2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "network/Network.h"
23 #include "utils/AlarmClock.h"
24 #include "utils/Screenshot.h"
25 #include "Application.h"
26 #include "ApplicationMessenger.h"
29 #include "input/ButtonTranslator.h"
31 #include "addons/GUIDialogAddonSettings.h"
32 #include "dialogs/GUIDialogFileBrowser.h"
33 #include "guilib/GUIKeyboardFactory.h"
34 #include "guilib/Key.h"
35 #include "guilib/StereoscopicsManager.h"
36 #include "dialogs/GUIDialogKaiToast.h"
37 #include "dialogs/GUIDialogNumeric.h"
38 #include "dialogs/GUIDialogProgress.h"
39 #include "dialogs/GUIDialogYesNo.h"
40 #include "GUIUserMessages.h"
41 #include "windows/GUIWindowLoginScreen.h"
42 #include "video/windows/GUIWindowVideoBase.h"
43 #include "addons/GUIWindowAddonBrowser.h"
44 #include "addons/Addon.h" // for TranslateType, TranslateContent
45 #include "addons/AddonInstaller.h"
46 #include "addons/AddonManager.h"
47 #include "addons/PluginSource.h"
48 #include "interfaces/generic/ScriptInvocationManager.h"
49 #include "interfaces/AnnouncementManager.h"
50 #include "network/NetworkServices.h"
51 #include "utils/log.h"
52 #include "storage/MediaManager.h"
53 #include "utils/RssManager.h"
54 #include "utils/JSONVariantParser.h"
55 #include "PartyModeManager.h"
56 #include "profiles/ProfilesManager.h"
57 #include "settings/DisplaySettings.h"
58 #include "settings/Settings.h"
59 #include "settings/MediaSettings.h"
60 #include "settings/MediaSourceSettings.h"
61 #include "settings/SkinSettings.h"
62 #include "utils/StringUtils.h"
63 #include "utils/URIUtils.h"
66 #include "music/MusicDatabase.h"
67 #include "cores/IPlayer.h"
69 #include "filesystem/PluginDirectory.h"
70 #ifdef HAS_FILESYSTEM_RAR
71 #include "filesystem/RarManager.h"
73 #include "filesystem/ZipManager.h"
75 #include "guilib/GUIWindowManager.h"
76 #include "guilib/LocalizeStrings.h"
79 #include "input/linux/LIRC.h"
81 #ifdef HAS_IRSERVERSUITE
83 #include "input/windows/IRServerSuite.h"
87 #if defined(TARGET_DARWIN)
88 #include "filesystem/SpecialProtocol.h"
89 #include "osx/CocoaInterface.h"
92 #ifdef HAS_CDDA_RIPPER
93 #include "cdrip/CDDARipper.h"
97 #include "settings/AdvancedSettings.h"
98 #include "settings/DisplaySettings.h"
101 using namespace XFILE;
102 using namespace ADDON;
105 using namespace MEDIA_DETECT;
111 bool needsParameters;
112 const char* description;
115 const BUILT_IN commands[] = {
116 { "Help", false, "This help message" },
117 { "Reboot", false, "Reboot the system" },
118 { "Restart", false, "Restart the system (same as reboot)" },
119 { "ShutDown", false, "Shutdown the system" },
120 { "Powerdown", false, "Powerdown system" },
121 { "Quit", false, "Quit XBMC" },
122 { "Hibernate", false, "Hibernates the system" },
123 { "Suspend", false, "Suspends the system" },
124 { "InhibitIdleShutdown", false, "Inhibit idle shutdown" },
125 { "AllowIdleShutdown", false, "Allow idle shutdown" },
126 { "ActivateScreensaver", false, "Activate Screensaver" },
127 { "RestartApp", false, "Restart XBMC" },
128 { "Minimize", false, "Minimize XBMC" },
129 { "Reset", false, "Reset the system (same as reboot)" },
130 { "Mastermode", false, "Control master mode" },
131 { "SetGUILanguage", true, "Set GUI Language" },
132 { "ActivateWindow", true, "Activate the specified window" },
133 { "ActivateWindowAndFocus", true, "Activate the specified window and sets focus to the specified id" },
134 { "ReplaceWindowAndFocus", true, "Replaces the current window with the new one and sets focus to the specified id" },
135 { "ReplaceWindow", true, "Replaces the current window with the new one" },
136 { "TakeScreenshot", false, "Takes a Screenshot" },
137 { "RunScript", true, "Run the specified script" },
138 { "StopScript", true, "Stop the script by ID or path, if running" },
139 #if defined(TARGET_DARWIN)
140 { "RunAppleScript", true, "Run the specified AppleScript command" },
142 { "RunPlugin", true, "Run the specified plugin" },
143 { "RunAddon", true, "Run the specified plugin/script" },
144 { "NotifyAll", true, "Notify all connected clients" },
145 { "Extract", true, "Extracts the specified archive" },
146 { "PlayMedia", true, "Play the specified media file (or playlist)" },
147 { "SlideShow", true, "Run a slideshow from the specified directory" },
148 { "RecursiveSlideShow", true, "Run a slideshow from the specified directory, including all subdirs" },
149 { "ReloadSkin", false, "Reload XBMC's skin" },
150 { "UnloadSkin", false, "Unload XBMC's skin" },
151 { "RefreshRSS", false, "Reload RSS feeds from RSSFeeds.xml"},
152 { "PlayerControl", true, "Control the music or video player" },
153 { "Playlist.PlayOffset", true, "Start playing from a particular offset in the playlist" },
154 { "Playlist.Clear", false, "Clear the current playlist" },
155 { "EjectTray", false, "Close or open the DVD tray" },
156 { "AlarmClock", true, "Prompt for a length of time and start an alarm clock" },
157 { "CancelAlarm", true, "Cancels an alarm" },
158 { "Action", true, "Executes an action for the active window (same as in keymap)" },
159 { "Notification", true, "Shows a notification on screen, specify header, then message, and optionally time in milliseconds and a icon." },
160 { "PlayDVD", false, "Plays the inserted CD or DVD media from the DVD-ROM Drive!" },
161 { "RipCD", false, "Rip the currently inserted audio CD"},
162 { "Skin.ToggleSetting", true, "Toggles a skin setting on or off" },
163 { "Skin.SetString", true, "Prompts and sets skin string" },
164 { "Skin.SetNumeric", true, "Prompts and sets numeric input" },
165 { "Skin.SetPath", true, "Prompts and sets a skin path" },
166 { "Skin.Theme", true, "Control skin theme" },
167 { "Skin.SetImage", true, "Prompts and sets a skin image" },
168 { "Skin.SetLargeImage", true, "Prompts and sets a large skin images" },
169 { "Skin.SetFile", true, "Prompts and sets a file" },
170 { "Skin.SetAddon", true, "Prompts and set an addon" },
171 { "Skin.SetBool", true, "Sets a skin setting on" },
172 { "Skin.Reset", true, "Resets a skin setting to default" },
173 { "Skin.ResetSettings", false, "Resets all skin settings" },
174 { "Mute", false, "Mute the player" },
175 { "SetVolume", true, "Set the current volume" },
176 { "Dialog.Close", true, "Close a dialog" },
177 { "System.LogOff", false, "Log off current user" },
178 { "System.Exec", true, "Execute shell commands" },
179 { "System.ExecWait", true, "Execute shell commands and freezes XBMC until shell is closed" },
180 { "Resolution", true, "Change XBMC's Resolution" },
181 { "SetFocus", true, "Change current focus to a different control id" },
182 { "UpdateLibrary", true, "Update the selected library (music or video)" },
183 { "CleanLibrary", true, "Clean the video/music library" },
184 { "ExportLibrary", true, "Export the video/music library" },
185 { "PageDown", true, "Send a page down event to the pagecontrol with given id" },
186 { "PageUp", true, "Send a page up event to the pagecontrol with given id" },
187 { "Container.Refresh", false, "Refresh current listing" },
188 { "Container.Update", false, "Update current listing. Send Container.Update(path,replace) to reset the path history" },
189 { "Container.NextViewMode", false, "Move to the next view type (and refresh the listing)" },
190 { "Container.PreviousViewMode", false, "Move to the previous view type (and refresh the listing)" },
191 { "Container.SetViewMode", true, "Move to the view with the given id" },
192 { "Container.NextSortMethod", false, "Change to the next sort method" },
193 { "Container.PreviousSortMethod",false, "Change to the previous sort method" },
194 { "Container.SetSortMethod", true, "Change to the specified sort method" },
195 { "Container.SortDirection", false, "Toggle the sort direction" },
196 { "Control.Move", true, "Tells the specified control to 'move' to another entry specified by offset" },
197 { "Control.SetFocus", true, "Change current focus to a different control id" },
198 { "Control.Message", true, "Send a given message to a control within a given window" },
199 { "SendClick", true, "Send a click message from the given control to the given window" },
200 { "LoadProfile", true, "Load the specified profile (note; if locks are active it won't work)" },
201 { "SetProperty", true, "Sets a window property for the current focused window/dialog (key,value)" },
202 { "ClearProperty", true, "Clears a window property for the current focused window/dialog (key,value)" },
203 { "PlayWith", true, "Play the selected item with the specified core" },
204 { "WakeOnLan", true, "Sends the wake-up packet to the broadcast address for the specified MAC address" },
205 { "Addon.Default.OpenSettings", true, "Open a settings dialog for the default addon of the given type" },
206 { "Addon.Default.Set", true, "Open a select dialog to allow choosing the default addon of the given type" },
207 { "Addon.OpenSettings", true, "Open a settings dialog for the addon of the given id" },
208 { "UpdateAddonRepos", false, "Check add-on repositories for updates" },
209 { "UpdateLocalAddons", false, "Check for local add-on changes" },
210 { "ToggleDPMS", false, "Toggle DPMS mode manually"},
211 { "CECToggleState", false, "Toggle state of playing device via a CEC peripheral"},
212 { "CECActivateSource", false, "Wake up playing device via a CEC peripheral"},
213 { "CECStandby", false, "Put playing device on standby via a CEC peripheral"},
214 { "Weather.Refresh", false, "Force weather data refresh"},
215 { "Weather.LocationNext", false, "Switch to next weather location"},
216 { "Weather.LocationPrevious", false, "Switch to previous weather location"},
217 { "Weather.LocationSet", true, "Switch to given weather location (parameter can be 1-3)"},
218 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
219 { "LIRC.Stop", false, "Removes XBMC as LIRC client" },
220 { "LIRC.Start", false, "Adds XBMC as LIRC client" },
221 { "LIRC.Send", true, "Sends a command to LIRC" },
223 { "VideoLibrary.Search", false, "Brings up a search dialog which will search the library" },
224 { "ToggleDebug", false, "Enables/disables debug mode" },
225 { "StartPVRManager", false, "(Re)Starts the PVR manager" },
226 { "StopPVRManager", false, "Stops the PVR manager" },
227 #if defined(TARGET_ANDROID)
228 { "StartAndroidActivity", true, "Launch an Android native app with the given package name. Optional parms (in order): intent, dataType, dataURI." },
230 { "SetStereoMode", true, "Changes the stereo mode of the GUI. Params can be: toggle, next, previous, select, tomono or any of the supported stereomodes (off, split_vertical, split_horizontal, row_interleaved, hardware_based, anaglyph_cyan_red, anaglyph_green_magenta, monoscopic)" }
233 bool CBuiltins::HasCommand(const CStdString& execString)
236 vector<CStdString> parameters;
237 CUtil::SplitExecFunction(execString, function, parameters);
238 for (unsigned int i = 0; i < sizeof(commands)/sizeof(BUILT_IN); i++)
240 if (StringUtils::EqualsNoCase(function, commands[i].command) && (!commands[i].needsParameters || parameters.size()))
246 void CBuiltins::GetHelp(CStdString &help)
249 for (unsigned int i = 0; i < sizeof(commands)/sizeof(BUILT_IN); i++)
251 help += commands[i].command;
253 help += commands[i].description;
258 int CBuiltins::Execute(const CStdString& execString)
260 // Get the text after the "XBMC."
262 vector<CStdString> params;
263 CUtil::SplitExecFunction(execString, execute, params);
264 StringUtils::ToLower(execute);
265 CStdString parameter = params.size() ? params[0] : "";
266 CStdString strParameterCaseIntact = parameter;
268 if (execute.Equals("reboot") || execute.Equals("restart") || execute.Equals("reset")) //Will reboot the system
270 CApplicationMessenger::Get().Restart();
272 else if (execute.Equals("shutdown"))
274 CApplicationMessenger::Get().Shutdown();
276 else if (execute.Equals("powerdown"))
278 CApplicationMessenger::Get().Powerdown();
280 else if (execute.Equals("restartapp"))
282 CApplicationMessenger::Get().RestartApp();
284 else if (execute.Equals("hibernate"))
286 CApplicationMessenger::Get().Hibernate();
288 else if (execute.Equals("suspend"))
290 CApplicationMessenger::Get().Suspend();
292 else if (execute.Equals("quit"))
294 CApplicationMessenger::Get().Quit();
296 else if (execute.Equals("inhibitidleshutdown"))
298 bool inhibit = (params.size() == 1 && params[0].Equals("true"));
299 CApplicationMessenger::Get().InhibitIdleShutdown(inhibit);
301 else if (execute.Equals("activatescreensaver"))
303 CApplicationMessenger::Get().ActivateScreensaver();
305 else if (execute.Equals("minimize"))
307 CApplicationMessenger::Get().Minimize();
309 else if (execute.Equals("loadprofile"))
311 int index = CProfilesManager::Get().GetProfileIndex(parameter);
312 bool prompt = (params.size() == 2 && params[1].Equals("prompt"));
315 && (CProfilesManager::Get().GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE
316 || g_passwordManager.IsProfileLockUnlocked(index,bCanceled,prompt)))
318 CApplicationMessenger::Get().LoadProfile(index);
321 else if (execute.Equals("mastermode"))
323 if (g_passwordManager.bMasterUser)
325 g_passwordManager.bMasterUser = false;
326 g_passwordManager.LockSources(true);
327 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(20052),g_localizeStrings.Get(20053));
329 else if (g_passwordManager.IsMasterLockUnlocked(true))
331 g_passwordManager.LockSources(false);
332 g_passwordManager.bMasterUser = true;
333 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(20052),g_localizeStrings.Get(20054));
336 CUtil::DeleteVideoDatabaseDirectoryCache();
337 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE);
338 g_windowManager.SendMessage(msg);
340 else if (execute.Equals("setguilanguage"))
344 CApplicationMessenger::Get().SetGUILanguage(params[0]);
347 else if (execute.Equals("takescreenshot"))
351 // get the parameters
352 CStdString strSaveToPath = params[0];
354 if (params.size() >= 2)
355 sync = params[1].Equals("sync");
357 if (!strSaveToPath.empty())
359 if (CDirectory::Exists(strSaveToPath))
361 CStdString file = CUtil::GetNextFilename(URIUtils::AddFileToFolder(strSaveToPath, "screenshot%03d.png"), 999);
365 CScreenShot::TakeScreenshot(file, sync);
369 CLog::Log(LOGWARNING, "Too many screen shots or invalid folder %s", strSaveToPath.c_str());
373 CScreenShot::TakeScreenshot(strSaveToPath, sync);
377 CScreenShot::TakeScreenshot();
379 else if (execute.Equals("activatewindow") || execute.Equals("replacewindow"))
381 // get the parameters
382 CStdString strWindow;
385 strWindow = params[0];
386 params.erase(params.begin());
389 // confirm the window destination is valid prior to switching
390 int iWindow = CButtonTranslator::TranslateWindow(strWindow);
391 if (iWindow != WINDOW_INVALID)
393 // disable the screensaver
394 g_application.WakeUpScreenSaverAndDPMS();
395 g_windowManager.ActivateWindow(iWindow, params, !execute.Equals("activatewindow"));
399 CLog::Log(LOGERROR, "Activate/ReplaceWindow called with invalid destination window: %s", strWindow.c_str());
403 else if ((execute.Equals("setfocus") || execute.Equals("control.setfocus")) && params.size())
405 int controlID = atol(params[0].c_str());
406 int subItem = (params.size() > 1) ? atol(params[1].c_str())+1 : 0;
407 CGUIMessage msg(GUI_MSG_SETFOCUS, g_windowManager.GetFocusedWindow(), controlID, subItem);
408 g_windowManager.SendMessage(msg);
410 else if ((execute.Equals("activatewindowandfocus") || execute.Equals("replacewindowandfocus")) && params.size())
412 CStdString strWindow = params[0];
414 // confirm the window destination is valid prior to switching
415 int iWindow = CButtonTranslator::TranslateWindow(strWindow);
416 if (iWindow != WINDOW_INVALID)
418 // disable the screensaver
419 g_application.WakeUpScreenSaverAndDPMS();
420 vector<CStdString> dummy;
421 g_windowManager.ActivateWindow(iWindow, dummy, !execute.Equals("activatewindowandfocus"));
423 unsigned int iPtr = 1;
424 while (params.size() > iPtr + 1)
426 CGUIMessage msg(GUI_MSG_SETFOCUS, g_windowManager.GetFocusedWindow(),
427 atol(params[iPtr].c_str()),
428 (params.size() >= iPtr + 2) ? atol(params[iPtr + 1].c_str())+1 : 0);
429 g_windowManager.SendMessage(msg);
435 CLog::Log(LOGERROR, "Replace/ActivateWindowAndFocus called with invalid destination window: %s", strWindow.c_str());
439 else if (execute.Equals("runscript") && params.size())
441 #if defined(TARGET_DARWIN_OSX)
442 if (URIUtils::HasExtension(strParameterCaseIntact, ".applescript|.scpt"))
444 CStdString osxPath = CSpecialProtocol::TranslatePath(strParameterCaseIntact);
445 Cocoa_DoAppleScriptFile(osxPath.c_str());
451 for (vector<CStdString>::const_iterator param = params.begin(); param != params.end(); ++param)
452 argv.push_back(*param);
454 vector<CStdString> path;
455 //split the path up to find the filename
456 StringUtils::SplitString(params[0],"\\",path);
458 argv[0] = path[path.size() - 1];
461 CStdString scriptpath(params[0]);
462 if (CAddonMgr::Get().GetAddon(params[0], script))
463 scriptpath = script->LibPath();
465 CScriptInvocationManager::Get().Execute(scriptpath, script, argv);
468 #if defined(TARGET_DARWIN_OSX)
469 else if (execute.Equals("runapplescript"))
471 Cocoa_DoAppleScript(strParameterCaseIntact.c_str());
474 else if (execute.Equals("stopscript"))
476 CStdString scriptpath(params[0]);
478 // Test to see if the param is an addon ID
480 if (CAddonMgr::Get().GetAddon(params[0], script))
481 scriptpath = script->LibPath();
483 CScriptInvocationManager::Get().Stop(scriptpath);
485 else if (execute.Equals("system.exec"))
487 CApplicationMessenger::Get().Minimize();
488 CApplicationMessenger::Get().ExecOS(parameter, false);
490 else if (execute.Equals("system.execwait"))
492 CApplicationMessenger::Get().Minimize();
493 CApplicationMessenger::Get().ExecOS(parameter, true);
495 else if (execute.Equals("resolution"))
497 RESOLUTION res = RES_PAL_4x3;
498 if (parameter.Equals("pal")) res = RES_PAL_4x3;
499 else if (parameter.Equals("pal16x9")) res = RES_PAL_16x9;
500 else if (parameter.Equals("ntsc")) res = RES_NTSC_4x3;
501 else if (parameter.Equals("ntsc16x9")) res = RES_NTSC_16x9;
502 else if (parameter.Equals("720p")) res = RES_HDTV_720p;
503 else if (parameter.Equals("720pSBS")) res = RES_HDTV_720pSBS;
504 else if (parameter.Equals("720pTB")) res = RES_HDTV_720pTB;
505 else if (parameter.Equals("1080pSBS")) res = RES_HDTV_1080pSBS;
506 else if (parameter.Equals("1080pTB")) res = RES_HDTV_1080pTB;
507 else if (parameter.Equals("1080i")) res = RES_HDTV_1080i;
508 if (g_graphicsContext.IsValidResolution(res))
510 CDisplaySettings::Get().SetCurrentResolution(res, true);
511 g_application.ReloadSkin();
514 else if (execute.Equals("extract") && params.size())
516 // Detects if file is zip or rar then extracts
517 CStdString strDestDirect;
518 if (params.size() < 2)
519 strDestDirect = URIUtils::GetDirectory(params[0]);
521 strDestDirect = params[1];
523 URIUtils::AddSlashAtEnd(strDestDirect);
525 if (URIUtils::IsZIP(params[0]))
526 g_ZipManager.ExtractArchive(params[0],strDestDirect);
527 #ifdef HAS_FILESYSTEM_RAR
528 else if (URIUtils::IsRAR(params[0]))
529 g_RarManager.ExtractArchive(params[0],strDestDirect);
532 CLog::Log(LOGERROR, "XBMC.Extract, No archive given");
534 else if (execute.Equals("runplugin"))
538 CFileItem item(params[0]);
539 if (!item.m_bIsFolder)
541 item.SetPath(params[0]);
542 CPluginDirectory::RunScriptWithParams(item.GetPath());
547 CLog::Log(LOGERROR, "XBMC.RunPlugin called with no arguments.");
550 else if (execute.Equals("runaddon"))
555 if (CAddonMgr::Get().GetAddon(params[0],addon) && addon)
557 PluginPtr plugin = boost::dynamic_pointer_cast<CPluginSource>(addon);
559 if (plugin && addon->Type() == ADDON_PLUGIN)
561 CStdString addonid = params[0];
562 CStdString urlParameters;
563 CStdStringArray parameters;
564 if (params.size() == 2 &&
565 (StringUtils::StartsWith(params[1], "/") || StringUtils::StartsWith(params[1], "?")))
566 urlParameters = params[1];
567 else if (params.size() > 1)
569 parameters.insert(parameters.begin(), params.begin() + 1, params.end());
570 urlParameters = "?" + StringUtils::JoinString(parameters, "&");
573 if (plugin->Provides(CPluginSource::VIDEO))
574 cmd = StringUtils::Format("ActivateWindow(Video,plugin://%s%s,return)", addonid.c_str(), urlParameters.c_str());
575 else if (plugin->Provides(CPluginSource::AUDIO))
576 cmd = StringUtils::Format("ActivateWindow(Music,plugin://%s%s,return)", addonid.c_str(), urlParameters.c_str());
577 else if (plugin->Provides(CPluginSource::EXECUTABLE))
578 cmd = StringUtils::Format("ActivateWindow(Programs,plugin://%s%s,return)", addonid.c_str(), urlParameters.c_str());
579 else if (plugin->Provides(CPluginSource::IMAGE))
580 cmd = StringUtils::Format("ActivateWindow(Pictures,plugin://%s%s,return)", addonid.c_str(), urlParameters.c_str());
582 // Pass the script name (params[0]) and all the parameters
583 // (params[1] ... params[x]) separated by a comma to RunPlugin
584 cmd = StringUtils::Format("RunPlugin(%s)", StringUtils::JoinString(params, ",").c_str());
586 else if (addon->Type() >= ADDON_SCRIPT && addon->Type() <= ADDON_SCRIPT_LYRICS)
587 // Pass the script name (params[0]) and all the parameters
588 // (params[1] ... params[x]) separated by a comma to RunScript
589 cmd = StringUtils::Format("RunScript(%s)", StringUtils::JoinString(params, ",").c_str());
596 CLog::Log(LOGERROR, "XBMC.RunAddon called with no arguments.");
599 else if (execute.Equals("notifyall"))
601 if (params.size() > 1)
604 if (params.size() > 2)
605 data = CJSONVariantParser::Parse((const unsigned char *)params[2].c_str(), params[2].size());
607 ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Other, params[0], params[1], data);
610 CLog::Log(LOGERROR, "XBMC.NotifyAll needs two parameters");
612 else if (execute.Equals("playmedia"))
616 CLog::Log(LOGERROR, "XBMC.PlayMedia called with empty parameter");
620 CFileItem item(params[0], false);
621 if (URIUtils::HasSlashAtEnd(params[0]))
622 item.m_bIsFolder = true;
624 // restore to previous window if needed
625 if( g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW ||
626 g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
627 g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION )
628 g_windowManager.PreviousWindow();
631 g_application.ResetScreenSaver();
632 g_application.WakeUpScreenSaverAndDPMS();
634 // ask if we need to check guisettings to resume
635 bool askToResume = true;
637 for (unsigned int i = 1 ; i < params.size() ; i++)
639 if (params[i].Equals("isdir"))
640 item.m_bIsFolder = true;
641 else if (params[i].Equals("1")) // set fullscreen or windowed
642 CMediaSettings::Get().SetVideoStartWindowed(true);
643 else if (params[i].Equals("resume"))
645 // force the item to resume (if applicable) (see CApplication::PlayMedia)
646 item.m_lStartOffset = STARTOFFSET_RESUME;
649 else if (params[i].Equals("noresume"))
651 // force the item to start at the beginning (m_lStartOffset is initialized to 0)
654 else if (StringUtils::StartsWithNoCase(params[i], "playoffset=")) {
655 playOffset = atoi(params[i].substr(11).c_str()) - 1;
656 item.SetProperty("playlist_starting_track", playOffset);
660 if (!item.m_bIsFolder && item.IsPlugin())
661 item.SetProperty("IsPlayable", true);
663 if ( askToResume == true )
665 if ( CGUIWindowVideoBase::ShowResumeMenu(item) == false )
668 if (item.m_bIsFolder)
671 CStdString extensions = g_advancedSettings.m_videoExtensions + "|" + g_advancedSettings.m_musicExtensions;
672 CDirectory::GetDirectory(item.GetPath(),items,extensions);
674 bool containsMusic = false, containsVideo = false;
675 for (int i = 0; i < items.Size(); i++)
677 bool isVideo = items[i]->IsVideo();
678 containsMusic |= !isVideo;
679 containsVideo |= isVideo;
681 if (containsMusic && containsVideo)
685 int playlist = containsVideo? PLAYLIST_VIDEO : PLAYLIST_MUSIC;;
686 if (containsMusic && containsVideo) //mixed content found in the folder
688 for (int i = items.Size() - 1; i >= 0; i--) //remove music entries
690 if (!items[i]->IsVideo())
695 g_playlistPlayer.ClearPlaylist(playlist);
696 g_playlistPlayer.Add(playlist, items);
697 g_playlistPlayer.SetCurrentPlaylist(playlist);
698 g_playlistPlayer.Play(playOffset);
702 int playlist = item.IsAudio() ? PLAYLIST_MUSIC : PLAYLIST_VIDEO;
703 g_playlistPlayer.ClearPlaylist(playlist);
704 g_playlistPlayer.SetCurrentPlaylist(playlist);
707 if (!g_application.PlayMedia(item, playlist))
709 CLog::Log(LOGERROR, "XBMC.PlayMedia could not play media: %s", params[0].c_str());
714 else if (execute.Equals("showPicture"))
718 CLog::Log(LOGERROR, "XBMC.ShowPicture called with empty parameter");
721 CGUIMessage msg(GUI_MSG_SHOW_PICTURE, 0, 0);
722 msg.SetStringParam(params[0]);
723 CGUIWindow *pWindow = g_windowManager.GetWindow(WINDOW_SLIDESHOW);
724 if (pWindow) pWindow->OnMessage(msg);
726 else if (execute.Equals("slideShow") || execute.Equals("recursiveslideShow"))
730 CLog::Log(LOGERROR, "XBMC.SlideShow called with empty parameter");
733 std::string beginSlidePath;
734 // leave RecursiveSlideShow command as-is
735 unsigned int flags = 0;
736 if (execute.Equals("RecursiveSlideShow"))
739 // SlideShow(dir[,recursive][,[not]random][,pause][,beginslide="/path/to/start/slide.jpg"])
740 // the beginslide value need be escaped (for '"' or '\' in it, by backslash)
741 // and then quoted, or not. See CUtil::SplitParams()
744 for (unsigned int i = 1 ; i < params.size() ; i++)
746 if (params[i].Equals("recursive"))
748 else if (params[i].Equals("random")) // set fullscreen or windowed
750 else if (params[i].Equals("notrandom"))
752 else if (params[i].Equals("pause"))
754 else if (StringUtils::StartsWithNoCase(params[i], "beginslide="))
755 beginSlidePath = params[i].substr(11);
759 CGUIMessage msg(GUI_MSG_START_SLIDESHOW, 0, 0, flags);
760 vector<CStdString> strParams;
761 strParams.push_back(params[0]);
762 strParams.push_back(beginSlidePath);
763 msg.SetStringParams(strParams);
764 CGUIWindow *pWindow = g_windowManager.GetWindow(WINDOW_SLIDESHOW);
765 if (pWindow) pWindow->OnMessage(msg);
767 else if (execute.Equals("reloadskin"))
770 g_application.ReloadSkin(!params.empty() && StringUtils::EqualsNoCase(params[0], "confirm"));
772 else if (execute.Equals("unloadskin"))
774 g_application.UnloadSkin(true); // we're reloading the skin after this
776 else if (execute.Equals("refreshrss"))
778 CRssManager::Get().Reload();
780 else if (execute.Equals("playercontrol"))
782 g_application.ResetScreenSaver();
783 g_application.WakeUpScreenSaverAndDPMS();
786 CLog::Log(LOGERROR, "XBMC.PlayerControl called with empty parameter");
789 if (parameter.Equals("play"))
791 // either resume playing, or pause
792 if (g_application.m_pPlayer->IsPlaying())
794 if (g_application.m_pPlayer->GetPlaySpeed() != 1)
795 g_application.m_pPlayer->SetPlaySpeed(1, g_application.IsMutedInternal());
797 g_application.m_pPlayer->Pause();
800 else if (parameter.Equals("stop"))
802 g_application.StopPlaying();
804 else if (parameter.Equals("rewind") || parameter.Equals("forward"))
806 if (g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused())
808 int iPlaySpeed = g_application.m_pPlayer->GetPlaySpeed();
809 if (parameter.Equals("rewind") && iPlaySpeed == 1) // Enables Rewinding
811 else if (parameter.Equals("rewind") && iPlaySpeed > 1) //goes down a notch if you're FFing
813 else if (parameter.Equals("forward") && iPlaySpeed < 1) //goes up a notch if you're RWing
816 if (iPlaySpeed == -1) iPlaySpeed = 1;
821 if (iPlaySpeed > 32 || iPlaySpeed < -32)
824 g_application.m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.IsMutedInternal());
827 else if (parameter.Equals("next"))
829 g_application.OnAction(CAction(ACTION_NEXT_ITEM));
831 else if (parameter.Equals("previous"))
833 g_application.OnAction(CAction(ACTION_PREV_ITEM));
835 else if (parameter.Equals("bigskipbackward"))
837 if (g_application.m_pPlayer->IsPlaying())
838 g_application.m_pPlayer->Seek(false, true);
840 else if (parameter.Equals("bigskipforward"))
842 if (g_application.m_pPlayer->IsPlaying())
843 g_application.m_pPlayer->Seek(true, true);
845 else if (parameter.Equals("smallskipbackward"))
847 if (g_application.m_pPlayer->IsPlaying())
848 g_application.m_pPlayer->Seek(false, false);
850 else if (parameter.Equals("smallskipforward"))
852 if (g_application.m_pPlayer->IsPlaying())
853 g_application.m_pPlayer->Seek(true, false);
855 else if (StringUtils::StartsWithNoCase(parameter, "seekpercentage"))
857 CStdString offset = "";
858 if (parameter.size() == 14)
859 CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) called with no argument");
860 else if (parameter.size() < 17) // arg must be at least "(N)"
861 CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) called with invalid argument: \"%s\"", parameter.substr(14).c_str());
864 // Don't bother checking the argument: an invalid arg will do seek(0)
865 offset = parameter.substr(15);
866 StringUtils::TrimRight(offset, ")");
867 float offsetpercent = (float) atof(offset.c_str());
868 if (offsetpercent < 0 || offsetpercent > 100)
869 CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) argument, %f, must be 0-100", offsetpercent);
870 else if (g_application.m_pPlayer->IsPlaying())
871 g_application.SeekPercentage(offsetpercent);
874 else if( parameter.Equals("showvideomenu") )
876 if( g_application.m_pPlayer->IsPlaying() )
877 g_application.m_pPlayer->OnAction(CAction(ACTION_SHOW_VIDEOMENU));
879 else if( parameter.Equals("record") )
881 if( g_application.m_pPlayer->IsPlaying() && g_application.m_pPlayer->CanRecord())
882 g_application.m_pPlayer->Record(!g_application.m_pPlayer->IsRecording());
884 else if (StringUtils::StartsWithNoCase(parameter, "partymode"))
886 CStdString strXspPath = "";
887 //empty param=music, "music"=music, "video"=video, else xsp path
888 PartyModeContext context = PARTYMODECONTEXT_MUSIC;
889 if (parameter.size() > 9)
891 if (parameter.size() == 16 && StringUtils::EndsWithNoCase(parameter, "video)"))
892 context = PARTYMODECONTEXT_VIDEO;
893 else if (parameter.size() != 16 || !StringUtils::EndsWithNoCase(parameter, "music)"))
895 strXspPath = parameter.substr(10);
896 StringUtils::TrimRight(strXspPath, ")");
897 context = PARTYMODECONTEXT_UNKNOWN;
900 if (g_partyModeManager.IsEnabled())
901 g_partyModeManager.Disable();
903 g_partyModeManager.Enable(context, strXspPath);
905 else if (parameter.Equals("random") ||
906 parameter.Equals("randomoff") ||
907 parameter.Equals("randomon"))
909 // get current playlist
910 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
912 // reverse the current setting
913 bool shuffled = g_playlistPlayer.IsShuffled(iPlaylist);
914 if ((shuffled && parameter.Equals("randomon")) || (!shuffled && parameter.Equals("randomoff")))
917 // check to see if we should notify the user
918 bool notify = (params.size() == 2 && params[1].Equals("notify"));
919 g_playlistPlayer.SetShuffle(iPlaylist, !shuffled, notify);
921 // save settings for now playing windows
925 CMediaSettings::Get().SetMusicPlaylistShuffled(g_playlistPlayer.IsShuffled(iPlaylist));
926 CSettings::Get().Save();
929 CMediaSettings::Get().SetVideoPlaylistShuffled(g_playlistPlayer.IsShuffled(iPlaylist));
930 CSettings::Get().Save();
934 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_RANDOM, 0, 0, iPlaylist, g_playlistPlayer.IsShuffled(iPlaylist));
935 g_windowManager.SendThreadMessage(msg);
938 else if (StringUtils::StartsWithNoCase(parameter, "repeat"))
940 // get current playlist
941 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
942 PLAYLIST::REPEAT_STATE previous_state = g_playlistPlayer.GetRepeat(iPlaylist);
944 PLAYLIST::REPEAT_STATE state;
945 if (parameter.Equals("repeatall"))
946 state = PLAYLIST::REPEAT_ALL;
947 else if (parameter.Equals("repeatone"))
948 state = PLAYLIST::REPEAT_ONE;
949 else if (parameter.Equals("repeatoff"))
950 state = PLAYLIST::REPEAT_NONE;
951 else if (previous_state == PLAYLIST::REPEAT_NONE)
952 state = PLAYLIST::REPEAT_ALL;
953 else if (previous_state == PLAYLIST::REPEAT_ALL)
954 state = PLAYLIST::REPEAT_ONE;
956 state = PLAYLIST::REPEAT_NONE;
958 if (state == previous_state)
961 // check to see if we should notify the user
962 bool notify = (params.size() == 2 && params[1].Equals("notify"));
963 g_playlistPlayer.SetRepeat(iPlaylist, state, notify);
965 // save settings for now playing windows
969 CMediaSettings::Get().SetMusicPlaylistRepeat(state == PLAYLIST::REPEAT_ALL);
970 CSettings::Get().Save();
973 CMediaSettings::Get().SetVideoPlaylistRepeat(state == PLAYLIST::REPEAT_ALL);
974 CSettings::Get().Save();
977 // send messages so now playing window can get updated
978 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_REPEAT, 0, 0, iPlaylist, (int)state);
979 g_windowManager.SendThreadMessage(msg);
982 else if (execute.Equals("playwith"))
984 g_application.m_eForcedNextPlayer = CPlayerCoreFactory::Get().GetPlayerCore(parameter);
985 g_application.OnAction(CAction(ACTION_PLAYER_PLAY));
987 else if (execute.Equals("mute"))
989 g_application.ToggleMute();
991 else if (execute.Equals("setvolume"))
993 float oldVolume = g_application.GetVolume();
994 float volume = (float)strtod(parameter.c_str(), NULL);
996 g_application.SetVolume(volume);
997 if(oldVolume != volume)
999 if(params.size() > 1 && params[1].Equals("showVolumeBar"))
1001 CApplicationMessenger::Get().ShowVolumeBar(oldVolume < volume);
1005 else if (execute.Equals("playlist.playoffset"))
1007 // playlist.playoffset(offset)
1008 // playlist.playoffset(music|video,offset)
1009 CStdString strPos = parameter;
1010 if (params.size() > 1)
1012 // ignore any other parameters if present
1013 CStdString strPlaylist = params[0];
1016 int iPlaylist = PLAYLIST_NONE;
1017 if (strPlaylist.Equals("music"))
1018 iPlaylist = PLAYLIST_MUSIC;
1019 else if (strPlaylist.Equals("video"))
1020 iPlaylist = PLAYLIST_VIDEO;
1023 if (iPlaylist == PLAYLIST_NONE)
1025 CLog::Log(LOGERROR,"Playlist.PlayOffset called with unknown playlist: %s", strPlaylist.c_str());
1029 // user wants to play the 'other' playlist
1030 if (iPlaylist != g_playlistPlayer.GetCurrentPlaylist())
1032 g_application.StopPlaying();
1033 g_playlistPlayer.Reset();
1034 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
1037 // play the desired offset
1038 int pos = atol(strPos.c_str());
1039 // playlist is already playing
1040 if (g_application.m_pPlayer->IsPlaying())
1041 g_playlistPlayer.PlayNext(pos);
1042 // we start playing the 'other' playlist so we need to use play to initialize the player state
1044 g_playlistPlayer.Play(pos);
1046 else if (execute.Equals("playlist.clear"))
1048 g_playlistPlayer.Clear();
1050 #ifdef HAS_DVD_DRIVE
1051 else if (execute.Equals("ejecttray"))
1053 g_mediaManager.ToggleTray();
1056 else if( execute.Equals("alarmclock") && params.size() > 1 )
1058 // format is alarmclock(name,command[,seconds,true]);
1060 if (params.size() > 2)
1062 if (params[2].find(':') == std::string::npos)
1063 seconds = static_cast<float>(atoi(params[2].c_str())*60);
1065 seconds = (float)StringUtils::TimeStringToSeconds(params[2]);
1068 { // check if shutdown is specified in particular, and get the time for it
1069 CStdString strHeading;
1070 if (StringUtils::EqualsNoCase(parameter, "shutdowntimer"))
1071 strHeading = g_localizeStrings.Get(20145);
1073 strHeading = g_localizeStrings.Get(13209);
1075 if( CGUIDialogNumeric::ShowAndGetNumber(strTime, strHeading) )
1076 seconds = static_cast<float>(atoi(strTime.c_str())*60);
1080 bool silent = false;
1082 for (unsigned int i = 3; i < params.size() ; i++)
1084 // check "true" for backward comp
1085 if (StringUtils::EqualsNoCase(params[i], "true") || StringUtils::EqualsNoCase(params[i], "silent"))
1087 else if (StringUtils::EqualsNoCase(params[i], "loop"))
1091 if( g_alarmClock.IsRunning() )
1092 g_alarmClock.Stop(params[0],silent);
1093 // no negative times not allowed, loop must have a positive time
1094 if (seconds < 0 || (seconds == 0 && loop))
1096 g_alarmClock.Start(params[0], seconds, params[1], silent, loop);
1098 else if (execute.Equals("notification"))
1100 if (params.size() < 2)
1102 if (params.size() == 4)
1103 CGUIDialogKaiToast::QueueNotification(params[3],params[0],params[1],atoi(params[2].c_str()));
1104 else if (params.size() == 3)
1105 CGUIDialogKaiToast::QueueNotification("",params[0],params[1],atoi(params[2].c_str()));
1107 CGUIDialogKaiToast::QueueNotification(params[0],params[1]);
1109 else if (execute.Equals("cancelalarm"))
1111 bool silent = false;
1112 if (params.size() > 1 && StringUtils::EqualsNoCase(params[1], "true"))
1114 g_alarmClock.Stop(params[0],silent);
1116 else if (execute.Equals("playdvd"))
1118 #ifdef HAS_DVD_DRIVE
1119 bool restart = false;
1120 if (params.size() > 0 && StringUtils::EqualsNoCase(params[0], "restart"))
1122 CAutorun::PlayDisc(g_mediaManager.GetDiscPath(), true, restart);
1125 else if (execute.Equals("ripcd"))
1127 #ifdef HAS_CDDA_RIPPER
1128 CCDDARipper::GetInstance().RipCD();
1131 else if (execute.Equals("skin.togglesetting"))
1133 int setting = CSkinSettings::Get().TranslateBool(parameter);
1134 CSkinSettings::Get().SetBool(setting, !CSkinSettings::Get().GetBool(setting));
1135 CSettings::Get().Save();
1137 else if (execute.Equals("skin.setbool") && params.size())
1139 if (params.size() > 1)
1141 int string = CSkinSettings::Get().TranslateBool(params[0]);
1142 CSkinSettings::Get().SetBool(string, StringUtils::EqualsNoCase(params[1], "true"));
1143 CSettings::Get().Save();
1146 // default is to set it to true
1147 int setting = CSkinSettings::Get().TranslateBool(params[0]);
1148 CSkinSettings::Get().SetBool(setting, true);
1149 CSettings::Get().Save();
1151 else if (execute.Equals("skin.reset"))
1153 CSkinSettings::Get().Reset(parameter);
1154 CSettings::Get().Save();
1156 else if (execute.Equals("skin.resetsettings"))
1158 CSkinSettings::Get().Reset();
1159 CSettings::Get().Save();
1161 else if (execute.Equals("skin.theme"))
1164 vector<CStdString> vecTheme;
1165 CUtil::GetSkinThemes(vecTheme);
1169 // find current theme
1170 if (!StringUtils::EqualsNoCase(CSettings::Get().GetString("lookandfeel.skintheme"), "SKINDEFAULT"))
1172 for (unsigned int i=0;i<vecTheme.size();++i)
1174 CStdString strTmpTheme(CSettings::Get().GetString("lookandfeel.skintheme"));
1175 URIUtils::RemoveExtension(strTmpTheme);
1176 if (vecTheme[i].Equals(strTmpTheme))
1184 int iParam = atoi(parameter.c_str());
1185 if (iParam == 0 || iParam == 1)
1187 else if (iParam == -1)
1189 if (iTheme > (int)vecTheme.size()-1)
1192 iTheme = vecTheme.size()-1;
1194 CStdString strSkinTheme = "SKINDEFAULT";
1195 if (iTheme != -1 && iTheme < (int)vecTheme.size())
1196 strSkinTheme = vecTheme[iTheme];
1198 CSettings::Get().SetString("lookandfeel.skintheme", strSkinTheme);
1199 // also set the default color theme
1200 CStdString colorTheme(URIUtils::ReplaceExtension(strSkinTheme, ".xml"));
1201 if (colorTheme.Equals("Textures.xml"))
1202 colorTheme = "defaults.xml";
1203 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1204 g_application.ReloadSkin();
1206 else if (execute.Equals("skin.setstring") || execute.Equals("skin.setimage") || execute.Equals("skin.setfile") ||
1207 execute.Equals("skin.setpath") || execute.Equals("skin.setnumeric") || execute.Equals("skin.setlargeimage"))
1209 // break the parameter up if necessary
1211 if (params.size() > 1)
1213 string = CSkinSettings::Get().TranslateString(params[0]);
1214 if (execute.Equals("skin.setstring"))
1216 CSkinSettings::Get().SetString(string, params[1]);
1217 CSettings::Get().Save();
1222 string = CSkinSettings::Get().TranslateString(params[0]);
1223 CStdString value = CSkinSettings::Get().GetString(string);
1224 VECSOURCES localShares;
1225 g_mediaManager.GetLocalDrives(localShares);
1226 if (execute.Equals("skin.setstring"))
1228 if (CGUIKeyboardFactory::ShowAndGetInput(value, g_localizeStrings.Get(1029), true))
1229 CSkinSettings::Get().SetString(string, value);
1231 else if (execute.Equals("skin.setnumeric"))
1233 if (CGUIDialogNumeric::ShowAndGetNumber(value, g_localizeStrings.Get(611)))
1234 CSkinSettings::Get().SetString(string, value);
1236 else if (execute.Equals("skin.setimage"))
1238 if (CGUIDialogFileBrowser::ShowAndGetImage(localShares, g_localizeStrings.Get(1030), value))
1239 CSkinSettings::Get().SetString(string, value);
1241 else if (execute.Equals("skin.setlargeimage"))
1243 VECSOURCES *shares = CMediaSourceSettings::Get().GetSources("pictures");
1244 if (!shares) shares = &localShares;
1245 if (CGUIDialogFileBrowser::ShowAndGetImage(*shares, g_localizeStrings.Get(1030), value))
1246 CSkinSettings::Get().SetString(string, value);
1248 else if (execute.Equals("skin.setfile"))
1250 // Note. can only browse one addon type from here
1251 // if browsing for addons, required param[1] is addontype string, with optional param[2]
1252 // as contenttype string see IAddon.h & ADDON::TranslateXX
1253 CStdString strMask = (params.size() > 1) ? params[1] : "";
1254 StringUtils::ToLower(strMask);
1256 if ((type = TranslateType(strMask)) != ADDON_UNKNOWN)
1259 url.SetProtocol("addons");
1260 url.SetHostName("enabled");
1261 url.SetFileName(strMask+"/");
1262 localShares.clear();
1263 CStdString content = (params.size() > 2) ? params[2] : "";
1264 StringUtils::ToLower(content);
1265 url.SetPassword(content);
1267 if (type == ADDON_SCRIPT)
1270 if (CGUIDialogFileBrowser::ShowAndGetFile(url.Get(), strMask, TranslateType(type, true), replace, true, true, true))
1272 if (StringUtils::StartsWithNoCase(replace, "addons://"))
1273 CSkinSettings::Get().SetString(string, URIUtils::GetFileName(replace));
1275 CSkinSettings::Get().SetString(string, replace);
1280 if (params.size() > 2)
1283 URIUtils::AddSlashAtEnd(value);
1285 if (CUtil::GetMatchingSource(value,localShares,bIsSource) < 0) // path is outside shares - add it as a separate one
1288 share.strName = g_localizeStrings.Get(13278);
1289 share.strPath = value;
1290 localShares.push_back(share);
1293 if (CGUIDialogFileBrowser::ShowAndGetFile(localShares, strMask, g_localizeStrings.Get(1033), value))
1294 CSkinSettings::Get().SetString(string, value);
1297 else // execute.Equals("skin.setpath"))
1299 g_mediaManager.GetNetworkLocations(localShares);
1300 if (params.size() > 1)
1303 URIUtils::AddSlashAtEnd(value);
1305 if (CUtil::GetMatchingSource(value,localShares,bIsSource) < 0) // path is outside shares - add it as a separate one
1308 share.strName = g_localizeStrings.Get(13278);
1309 share.strPath = value;
1310 localShares.push_back(share);
1313 if (CGUIDialogFileBrowser::ShowAndGetDirectory(localShares, g_localizeStrings.Get(1031), value))
1314 CSkinSettings::Get().SetString(string, value);
1316 CSettings::Get().Save();
1318 else if (execute.Equals("skin.setaddon") && params.size() > 1)
1320 int string = CSkinSettings::Get().TranslateString(params[0]);
1321 vector<ADDON::TYPE> types;
1322 for (unsigned int i = 1 ; i < params.size() ; i++)
1324 ADDON::TYPE type = TranslateType(params[i]);
1325 if (type != ADDON_UNKNOWN)
1326 types.push_back(type);
1329 if (types.size() > 0 && CGUIWindowAddonBrowser::SelectAddonID(types, result, true) == 1)
1331 CSkinSettings::Get().SetString(string, result);
1332 CSettings::Get().Save();
1335 else if (execute.Equals("dialog.close") && params.size())
1337 bool bForce = false;
1338 if (params.size() > 1 && StringUtils::EqualsNoCase(params[1], "true"))
1340 if (StringUtils::EqualsNoCase(params[0], "all"))
1342 g_windowManager.CloseDialogs(bForce);
1346 int id = CButtonTranslator::TranslateWindow(params[0]);
1347 CGUIWindow *window = (CGUIWindow *)g_windowManager.GetWindow(id);
1348 if (window && window->IsDialog())
1349 ((CGUIDialog *)window)->Close(bForce);
1352 else if (execute.Equals("system.logoff"))
1354 // there was a commit from cptspiff here which was reverted
1355 // for keeping the behaviour from Eden in Frodo - see
1356 // git rev 9ee5f0047b
1357 if (g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN)
1360 g_application.StopPlaying();
1361 if (g_application.IsMusicScanning())
1362 g_application.StopMusicScan();
1364 if (g_application.IsVideoScanning())
1365 g_application.StopVideoScan();
1367 ADDON::CAddonMgr::Get().StopServices(true);
1369 g_application.getNetwork().NetworkMessage(CNetwork::SERVICES_DOWN,1);
1370 CProfilesManager::Get().LoadMasterProfileForLogin();
1371 g_passwordManager.bMasterUser = false;
1372 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1373 if (!CNetworkServices::Get().StartEventServer()) // event server could be needed in some situations
1374 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33102), g_localizeStrings.Get(33100));
1376 else if (execute.Equals("pagedown"))
1378 int id = atoi(parameter.c_str());
1379 CGUIMessage message(GUI_MSG_PAGE_DOWN, g_windowManager.GetFocusedWindow(), id);
1380 g_windowManager.SendMessage(message);
1382 else if (execute.Equals("pageup"))
1384 int id = atoi(parameter.c_str());
1385 CGUIMessage message(GUI_MSG_PAGE_UP, g_windowManager.GetFocusedWindow(), id);
1386 g_windowManager.SendMessage(message);
1388 else if (execute.Equals("updatelibrary") && params.size())
1390 if (params[0].Equals("music"))
1392 if (g_application.IsMusicScanning())
1393 g_application.StopMusicScan();
1395 g_application.StartMusicScan(params.size() > 1 ? params[1] : "");
1397 if (params[0].Equals("video"))
1399 if (g_application.IsVideoScanning())
1400 g_application.StopVideoScan();
1402 g_application.StartVideoScan(params.size() > 1 ? params[1] : "");
1405 else if (execute.Equals("cleanlibrary"))
1407 if (!params.size() || params[0].Equals("video"))
1409 if (!g_application.IsVideoScanning())
1410 g_application.StartVideoCleanup();
1412 CLog::Log(LOGERROR, "XBMC.CleanLibrary is not possible while scanning or cleaning");
1414 else if (params[0].Equals("music"))
1416 if (!g_application.IsMusicScanning())
1418 CMusicDatabase musicdatabase;
1420 musicdatabase.Open();
1421 musicdatabase.Cleanup();
1422 musicdatabase.Close();
1425 CLog::Log(LOGERROR, "XBMC.CleanLibrary is not possible while scanning for media info");
1428 else if (execute.Equals("exportlibrary"))
1431 if (params[0].Equals("music"))
1435 g_mediaManager.GetLocalDrives(shares);
1438 bool actorThumbs=false;
1439 bool overwrite=false;
1440 bool cancelled=false;
1442 if (params.size() > 1)
1443 singleFile = params[1].Equals("true");
1445 singleFile = CGUIDialogYesNo::ShowAndGetInput(iHeading,20426,20427,-1,20428,20429,cancelled);
1452 if (params.size() > 2)
1453 thumbs = params[2].Equals("true");
1455 thumbs = CGUIDialogYesNo::ShowAndGetInput(iHeading,20430,-1,-1,cancelled);
1461 if (thumbs && params[0].Equals("video"))
1463 if (params.size() > 4)
1464 actorThumbs = params[4].Equals("true");
1466 actorThumbs = CGUIDialogYesNo::ShowAndGetInput(iHeading,20436,-1,-1,cancelled);
1474 if (params.size() > 3)
1475 overwrite = params[3].Equals("true");
1477 overwrite = CGUIDialogYesNo::ShowAndGetInput(iHeading,20431,-1,-1,cancelled);
1483 if (params.size() > 2)
1485 if (singleFile || !path.empty() ||
1486 CGUIDialogFileBrowser::ShowAndGetDirectory(shares,
1487 g_localizeStrings.Get(661), path, true))
1489 if (params[0].Equals("video"))
1491 CVideoDatabase videodatabase;
1492 videodatabase.Open();
1493 videodatabase.ExportToXML(path, singleFile, thumbs, actorThumbs, overwrite);
1494 videodatabase.Close();
1498 if (URIUtils::HasSlashAtEnd(path))
1499 path = URIUtils::AddFileToFolder(path, "musicdb.xml");
1500 CMusicDatabase musicdatabase;
1501 musicdatabase.Open();
1502 musicdatabase.ExportToXML(path, singleFile, thumbs, overwrite);
1503 musicdatabase.Close();
1507 else if (execute.Equals("control.move") && params.size() > 1)
1509 CGUIMessage message(GUI_MSG_MOVE_OFFSET, g_windowManager.GetFocusedWindow(), atoi(params[0].c_str()), atoi(params[1].c_str()));
1510 g_windowManager.SendMessage(message);
1512 else if (execute.Equals("container.refresh"))
1513 { // NOTE: These messages require a media window, thus they're sent to the current activewindow.
1514 // This shouldn't stop a dialog intercepting it though.
1515 CGUIMessage message(GUI_MSG_NOTIFY_ALL, g_windowManager.GetActiveWindow(), 0, GUI_MSG_UPDATE, 1); // 1 to reset the history
1516 message.SetStringParam(parameter);
1517 g_windowManager.SendMessage(message);
1519 else if (execute.Equals("container.update") && params.size())
1521 CGUIMessage message(GUI_MSG_NOTIFY_ALL, g_windowManager.GetActiveWindow(), 0, GUI_MSG_UPDATE, 0);
1522 message.SetStringParam(params[0]);
1523 if (params.size() > 1 && StringUtils::EqualsNoCase(params[1], "replace"))
1524 message.SetParam2(1); // reset the history
1525 g_windowManager.SendMessage(message);
1527 else if (execute.Equals("container.nextviewmode"))
1529 CGUIMessage message(GUI_MSG_CHANGE_VIEW_MODE, g_windowManager.GetActiveWindow(), 0, 0, 1);
1530 g_windowManager.SendMessage(message);
1532 else if (execute.Equals("container.previousviewmode"))
1534 CGUIMessage message(GUI_MSG_CHANGE_VIEW_MODE, g_windowManager.GetActiveWindow(), 0, 0, -1);
1535 g_windowManager.SendMessage(message);
1537 else if (execute.Equals("container.setviewmode"))
1539 CGUIMessage message(GUI_MSG_CHANGE_VIEW_MODE, g_windowManager.GetActiveWindow(), 0, atoi(parameter.c_str()));
1540 g_windowManager.SendMessage(message);
1542 else if (execute.Equals("container.nextsortmethod"))
1544 CGUIMessage message(GUI_MSG_CHANGE_SORT_METHOD, g_windowManager.GetActiveWindow(), 0, 0, 1);
1545 g_windowManager.SendMessage(message);
1547 else if (execute.Equals("container.previoussortmethod"))
1549 CGUIMessage message(GUI_MSG_CHANGE_SORT_METHOD, g_windowManager.GetActiveWindow(), 0, 0, -1);
1550 g_windowManager.SendMessage(message);
1552 else if (execute.Equals("container.setsortmethod"))
1554 CGUIMessage message(GUI_MSG_CHANGE_SORT_METHOD, g_windowManager.GetActiveWindow(), 0, atoi(parameter.c_str()));
1555 g_windowManager.SendMessage(message);
1557 else if (execute.Equals("container.sortdirection"))
1559 CGUIMessage message(GUI_MSG_CHANGE_SORT_DIRECTION, g_windowManager.GetActiveWindow(), 0, 0);
1560 g_windowManager.SendMessage(message);
1562 else if (execute.Equals("control.message") && params.size() >= 2)
1564 int controlID = atoi(params[0].c_str());
1565 int windowID = (params.size() == 3) ? CButtonTranslator::TranslateWindow(params[2]) : g_windowManager.GetActiveWindow();
1566 if (params[1] == "moveup")
1567 g_windowManager.SendMessage(GUI_MSG_MOVE_OFFSET, windowID, controlID, 1);
1568 else if (params[1] == "movedown")
1569 g_windowManager.SendMessage(GUI_MSG_MOVE_OFFSET, windowID, controlID, -1);
1570 else if (params[1] == "pageup")
1571 g_windowManager.SendMessage(GUI_MSG_PAGE_UP, windowID, controlID);
1572 else if (params[1] == "pagedown")
1573 g_windowManager.SendMessage(GUI_MSG_PAGE_DOWN, windowID, controlID);
1574 else if (params[1] == "click")
1575 g_windowManager.SendMessage(GUI_MSG_CLICKED, controlID, windowID);
1577 else if (execute.Equals("sendclick") && params.size())
1579 if (params.size() == 2)
1581 // have a window - convert it
1582 int windowID = CButtonTranslator::TranslateWindow(params[0]);
1583 CGUIMessage message(GUI_MSG_CLICKED, atoi(params[1].c_str()), windowID);
1584 g_windowManager.SendMessage(message);
1587 { // single param - assume you meant the active window
1588 CGUIMessage message(GUI_MSG_CLICKED, atoi(params[0].c_str()), g_windowManager.GetActiveWindow());
1589 g_windowManager.SendMessage(message);
1592 else if (execute.Equals("action") && params.size())
1594 // try translating the action from our ButtonTranslator
1596 if (CButtonTranslator::TranslateActionString(params[0].c_str(), actionID))
1598 int windowID = params.size() == 2 ? CButtonTranslator::TranslateWindow(params[1]) : WINDOW_INVALID;
1599 CApplicationMessenger::Get().SendAction(CAction(actionID), windowID);
1602 else if (execute.Equals("setproperty") && params.size() >= 2)
1604 CGUIWindow *window = g_windowManager.GetWindow(params.size() > 2 ? CButtonTranslator::TranslateWindow(params[2]) : g_windowManager.GetFocusedWindow());
1606 window->SetProperty(params[0],params[1]);
1608 else if (execute.Equals("clearproperty") && params.size())
1610 CGUIWindow *window = g_windowManager.GetWindow(params.size() > 1 ? CButtonTranslator::TranslateWindow(params[1]) : g_windowManager.GetFocusedWindow());
1612 window->SetProperty(params[0],"");
1614 else if (execute.Equals("wakeonlan"))
1616 g_application.getNetwork().WakeOnLan((char*)params[0].c_str());
1618 else if (execute.Equals("addon.default.opensettings") && params.size() == 1)
1621 ADDON::TYPE type = TranslateType(params[0]);
1622 if (CAddonMgr::Get().GetDefault(type, addon))
1624 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1625 if (type == ADDON_VIZ)
1626 g_windowManager.SendMessage(GUI_MSG_VISUALISATION_RELOAD, 0, 0);
1629 else if (execute.Equals("addon.default.set") && params.size() == 1)
1632 TYPE type = TranslateType(params[0]);
1633 bool allowNone = false;
1634 if (type == ADDON_VIZ)
1637 if (type != ADDON_UNKNOWN &&
1638 CGUIWindowAddonBrowser::SelectAddonID(type,addonID,allowNone))
1640 CAddonMgr::Get().SetDefault(type,addonID);
1641 if (type == ADDON_VIZ)
1642 g_windowManager.SendMessage(GUI_MSG_VISUALISATION_RELOAD, 0, 0);
1645 else if (execute.Equals("addon.opensettings") && params.size() == 1)
1648 if (CAddonMgr::Get().GetAddon(params[0], addon))
1649 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1651 else if (execute.Equals("updateaddonrepos"))
1653 CAddonInstaller::Get().UpdateRepos(true);
1655 else if (execute.Equals("updatelocaladdons"))
1657 CAddonMgr::Get().FindAddons();
1659 else if (execute.Equals("toggledpms"))
1661 g_application.ToggleDPMS(true);
1663 else if (execute.Equals("cectogglestate"))
1665 CApplicationMessenger::Get().CECToggleState();
1667 else if (execute.Equals("cecactivatesource"))
1669 CApplicationMessenger::Get().CECActivateSource();
1671 else if (execute.Equals("cecstandby"))
1673 CApplicationMessenger::Get().CECStandby();
1675 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
1676 else if (execute.Equals("lirc.stop"))
1678 g_RemoteControl.Disconnect();
1679 g_RemoteControl.setUsed(false);
1681 else if (execute.Equals("lirc.start"))
1683 g_RemoteControl.setUsed(true);
1684 g_RemoteControl.Initialize();
1686 else if (execute.Equals("lirc.send"))
1689 for (int i = 0; i < (int)params.size(); i++)
1691 command += params[i];
1692 if (i < (int)params.size() - 1)
1695 g_RemoteControl.AddSendCommand(command);
1698 else if (execute.Equals("weather.locationset"))
1700 int loc = atoi(params[0]);
1701 CGUIMessage msg(GUI_MSG_ITEM_SELECT, 0, 0, loc);
1702 g_windowManager.SendMessage(msg, WINDOW_WEATHER);
1704 else if (execute.Equals("weather.locationnext"))
1706 CGUIMessage msg(GUI_MSG_MOVE_OFFSET, 0, 0, 1);
1707 g_windowManager.SendMessage(msg, WINDOW_WEATHER);
1709 else if (execute.Equals("weather.locationprevious"))
1711 CGUIMessage msg(GUI_MSG_MOVE_OFFSET, 0, 0, -1);
1712 g_windowManager.SendMessage(msg, WINDOW_WEATHER);
1714 else if (execute.Equals("weather.refresh"))
1716 CGUIMessage msg(GUI_MSG_MOVE_OFFSET, 0, 0, 0);
1717 g_windowManager.SendMessage(msg, WINDOW_WEATHER);
1719 else if (execute.Equals("videolibrary.search"))
1721 CGUIMessage msg(GUI_MSG_SEARCH, 0, 0, 0);
1722 g_windowManager.SendMessage(msg, WINDOW_VIDEO_NAV);
1724 else if (execute.Equals("toggledebug"))
1726 bool debug = CSettings::Get().GetBool("debug.showloginfo");
1727 CSettings::Get().SetBool("debug.showloginfo", !debug);
1728 g_advancedSettings.SetDebugMode(!debug);
1730 else if (execute.Equals("startpvrmanager"))
1732 g_application.StartPVRManager();
1734 else if (execute.Equals("stoppvrmanager"))
1736 g_application.StopPVRManager();
1738 else if (execute.Equals("StartAndroidActivity") && params.size() > 0)
1740 CApplicationMessenger::Get().StartAndroidActivity(params);
1742 else if (execute.Equals("SetStereoMode") && !parameter.empty())
1744 CAction action = CStereoscopicsManager::Get().ConvertActionCommandToAction(execute, parameter);
1745 if (action.GetID() != ACTION_NONE)
1746 CApplicationMessenger::Get().SendAction(action);
1749 CLog::Log(LOGERROR,"Builtin 'SetStereoMode' called with unknown parameter: %s", parameter.c_str());