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/>.
22 #include "ApplicationMessenger.h"
23 #include "Application.h"
26 #include "PlayListPlayer.h"
28 #include "pictures/GUIWindowSlideShow.h"
29 #include "interfaces/Builtins.h"
30 #include "interfaces/generic/ScriptInvocationManager.h"
31 #include "network/Network.h"
32 #include "utils/log.h"
33 #include "utils/URIUtils.h"
34 #include "utils/Variant.h"
35 #include "guilib/GUIWindowManager.h"
36 #include "settings/AdvancedSettings.h"
37 #include "settings/Settings.h"
39 #include "guilib/GUIDialog.h"
40 #include "guilib/Key.h"
41 #include "guilib/GUIKeyboardFactory.h"
42 #include "GUIInfoManager.h"
43 #include "utils/Splash.h"
44 #include "cores/IPlayer.h"
45 #include "cores/VideoRenderers/RenderManager.h"
46 #include "cores/AudioEngine/AEFactory.h"
47 #include "music/tags/MusicInfoTag.h"
49 #include "peripherals/Peripherals.h"
50 #include "powermanagement/PowerManager.h"
53 #include "WIN32Util.h"
54 #define CHalManager CWIN32Util
55 #elif defined(TARGET_DARWIN)
56 #include "osx/CocoaInterface.h"
58 #include "addons/AddonCallbacks.h"
59 #include "addons/AddonCallbacksGUI.h"
60 #include "storage/MediaManager.h"
61 #include "guilib/LocalizeStrings.h"
62 #include "threads/SingleLock.h"
64 #include "playlists/PlayList.h"
66 #include "pvr/PVRManager.h"
67 #include "windows/GUIWindowLoginScreen.h"
69 #include "utils/GlobalsHandling.h"
70 #if defined(TARGET_ANDROID)
71 #include "xbmc/android/activity/XBMCApp.h"
76 using namespace MUSIC_INFO;
77 using namespace PERIPHERALS;
79 CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) : CThread("DelayedMessage")
81 m_msg.dwMessage = msg.dwMessage;
82 m_msg.dwParam1 = msg.dwParam1;
83 m_msg.dwParam2 = msg.dwParam2;
84 m_msg.waitEvent = msg.waitEvent;
85 m_msg.lpVoid = msg.lpVoid;
86 m_msg.strParam = msg.strParam;
87 m_msg.params = msg.params;
92 void CDelayedMessage::Process()
97 CApplicationMessenger::Get().SendMessage(m_msg, false);
101 CApplicationMessenger& CApplicationMessenger::Get()
106 CApplicationMessenger::CApplicationMessenger()
110 CApplicationMessenger::~CApplicationMessenger()
115 void CApplicationMessenger::Cleanup()
117 CSingleLock lock (m_critSection);
119 while (m_vecMessages.size() > 0)
121 ThreadMessage* pMsg = m_vecMessages.front();
124 pMsg->waitEvent->Set();
130 while (m_vecWindowMessages.size() > 0)
132 ThreadMessage* pMsg = m_vecWindowMessages.front();
135 pMsg->waitEvent->Set();
138 m_vecWindowMessages.pop();
142 void CApplicationMessenger::SendMessage(ThreadMessage& message, bool wait)
144 message.waitEvent.reset();
145 boost::shared_ptr<CEvent> waitEvent;
147 { // check that we're not being called from our application thread, else we'll be waiting
149 if (!g_application.IsCurrentThread())
151 message.waitEvent.reset(new CEvent(true));
152 waitEvent = message.waitEvent;
156 //OutputDebugString("Attempting to wait on a SendMessage() from our application thread will cause lockup!\n");
157 //OutputDebugString("Sending immediately\n");
158 ProcessMessage(&message);
163 CSingleLock lock (m_critSection);
165 if (g_application.m_bStop)
167 if (message.waitEvent)
168 message.waitEvent.reset();
172 ThreadMessage* msg = new ThreadMessage();
173 msg->dwMessage = message.dwMessage;
174 msg->dwParam1 = message.dwParam1;
175 msg->dwParam2 = message.dwParam2;
176 msg->waitEvent = message.waitEvent;
177 msg->lpVoid = message.lpVoid;
178 msg->strParam = message.strParam;
179 msg->params = message.params;
181 if (msg->dwMessage == TMSG_DIALOG_DOMODAL)
182 m_vecWindowMessages.push(msg);
184 m_vecMessages.push(msg);
185 lock.Leave(); // this releases the lock on the vec of messages and
186 // allows the ProcessMessage to execute and therefore
187 // delete the message itself. Therefore any accesss
188 // of the message itself after this point consittutes
189 // a race condition (yarc - "yet another race condition")
191 if (waitEvent) // ... it just so happens we have a spare reference to the
192 // waitEvent ... just for such contingencies :)
194 // ensure the thread doesn't hold the graphics lock
195 CSingleExit exit(g_graphicsContext);
200 void CApplicationMessenger::ProcessMessages()
202 // process threadmessages
203 CSingleLock lock (m_critSection);
204 while (m_vecMessages.size() > 0)
206 ThreadMessage* pMsg = m_vecMessages.front();
207 //first remove the message from the queue, else the message could be processed more then once
210 //Leave here as the message might make another
211 //thread call processmessages or sendmessage
213 boost::shared_ptr<CEvent> waitEvent = pMsg->waitEvent;
214 lock.Leave(); // <- see the large comment in SendMessage ^
216 ProcessMessage(pMsg);
225 void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
227 switch (pMsg->dwMessage)
231 switch (CSettings::Get().GetInt("powermanagement.shutdownstate"))
233 case POWERSTATE_SHUTDOWN:
237 case POWERSTATE_SUSPEND:
241 case POWERSTATE_HIBERNATE:
245 case POWERSTATE_QUIT:
249 case POWERSTATE_MINIMIZE:
253 case TMSG_RENDERER_FLUSH:
254 g_renderManager.Flush();
262 g_application.Stop(EXITCODE_POWERDOWN);
263 g_powerManager.Powerdown();
269 g_application.Stop(EXITCODE_QUIT);
275 g_PVRManager.SetWakeupCommand();
276 g_powerManager.Hibernate();
282 g_PVRManager.SetWakeupCommand();
283 g_powerManager.Suspend();
290 g_application.Stop(EXITCODE_REBOOT);
291 g_powerManager.Reboot();
295 case TMSG_RESTARTAPP:
297 #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX)
298 g_application.Stop(EXITCODE_RESTARTAPP);
303 case TMSG_INHIBITIDLESHUTDOWN:
305 g_application.InhibitIdleShutdown(pMsg->dwParam1 != 0);
309 case TMSG_ACTIVATESCREENSAVER:
311 g_application.ActivateScreenSaver();
315 case TMSG_MEDIA_PLAY:
317 // first check if we were called from the PlayFile() function
318 if (pMsg->lpVoid && pMsg->dwParam2 == 0)
320 CFileItem *item = (CFileItem *)pMsg->lpVoid;
321 g_application.PlayFile(*item, pMsg->dwParam1 != 0);
325 // restore to previous window if needed
326 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW ||
327 g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
328 g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
329 g_windowManager.PreviousWindow();
331 g_application.ResetScreenSaver();
332 g_application.WakeUpScreenSaverAndDPMS();
334 //g_application.StopPlaying();
338 CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
340 if (list->Size() > 0)
342 int playlist = PLAYLIST_MUSIC;
343 for (int i = 0; i < list->Size(); i++)
345 if ((*list)[i]->IsVideo())
347 playlist = PLAYLIST_VIDEO;
352 g_playlistPlayer.ClearPlaylist(playlist);
353 g_playlistPlayer.SetCurrentPlaylist(playlist);
354 //For single item lists try PlayMedia. This covers some more cases where a playlist is not appropriate
355 //It will fall through to PlayFile
356 if (list->Size() == 1 && !(*list)[0]->IsPlayList())
357 g_application.PlayMedia(*((*list)[0]), playlist);
360 // Handle "shuffled" option if present
361 if (list->HasProperty("shuffled") && list->GetProperty("shuffled").isBoolean())
362 g_playlistPlayer.SetShuffle(playlist, list->GetProperty("shuffled").asBoolean(), false);
363 // Handle "repeat" option if present
364 if (list->HasProperty("repeat") && list->GetProperty("repeat").isInteger())
365 g_playlistPlayer.SetRepeat(playlist, (PLAYLIST::REPEAT_STATE)list->GetProperty("repeat").asInteger(), false);
367 g_playlistPlayer.Add(playlist, (*list));
368 g_playlistPlayer.Play(pMsg->dwParam1);
374 else if (pMsg->dwParam1 == PLAYLIST_MUSIC || pMsg->dwParam1 == PLAYLIST_VIDEO)
376 if (g_playlistPlayer.GetCurrentPlaylist() != (int)pMsg->dwParam1)
377 g_playlistPlayer.SetCurrentPlaylist(pMsg->dwParam1);
379 PlayListPlayerPlay(pMsg->dwParam2);
384 case TMSG_MEDIA_RESTART:
385 g_application.Restart(true);
388 case TMSG_PICTURE_SHOW:
390 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
391 if (!pSlideShow) return ;
394 if (g_application.m_pPlayer->IsPlayingVideo()) g_application.StopPlaying();
396 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
397 g_windowManager.PreviousWindow();
399 g_application.ResetScreenSaver();
400 g_application.WakeUpScreenSaverAndDPMS();
402 g_graphicsContext.Lock();
404 if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW)
405 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
406 if (URIUtils::IsZIP(pMsg->strParam) || URIUtils::IsRAR(pMsg->strParam)) // actually a cbz/cbr
410 if (URIUtils::IsZIP(pMsg->strParam))
411 URIUtils::CreateArchivePath(strPath, "zip", pMsg->strParam.c_str(), "");
413 URIUtils::CreateArchivePath(strPath, "rar", pMsg->strParam.c_str(), "");
415 CUtil::GetRecursiveListing(strPath, items, g_advancedSettings.m_pictureExtensions);
416 if (items.Size() > 0)
419 for (int i=0;i<items.Size();++i)
421 pSlideShow->Add(items[i].get());
423 pSlideShow->Select(items[0]->GetPath());
428 CFileItem item(pMsg->strParam, false);
430 pSlideShow->Add(&item);
431 pSlideShow->Select(pMsg->strParam);
433 g_graphicsContext.Unlock();
437 case TMSG_PICTURE_SLIDESHOW:
439 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
440 if (!pSlideShow) return ;
442 if (g_application.m_pPlayer->IsPlayingVideo())
443 g_application.StopPlaying();
445 g_graphicsContext.Lock();
449 CStdString strPath = pMsg->strParam;
450 CStdString extensions = g_advancedSettings.m_pictureExtensions;
452 extensions += "|.tbn";
453 CUtil::GetRecursiveListing(strPath, items, extensions);
455 if (items.Size() > 0)
457 for (int i=0;i<items.Size();++i)
458 pSlideShow->Add(items[i].get());
459 pSlideShow->StartSlideShow(); //Start the slideshow!
462 if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW)
464 if(items.Size() == 0)
466 CSettings::Get().SetString("screensaver.mode", "screensaver.xbmc.builtin.dim");
467 g_application.ActivateScreenSaver();
470 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
473 g_graphicsContext.Unlock();
477 case TMSG_SETLANGUAGE:
478 g_application.SetLanguage(pMsg->strParam);
480 case TMSG_MEDIA_STOP:
482 // restore to previous window if needed
483 bool stopSlideshow = true;
484 bool stopVideo = true;
485 bool stopMusic = true;
486 if (pMsg->dwParam1 >= PLAYLIST_MUSIC && pMsg->dwParam1 <= PLAYLIST_PICTURE)
488 stopSlideshow = (pMsg->dwParam1 == PLAYLIST_PICTURE);
489 stopVideo = (pMsg->dwParam1 == PLAYLIST_VIDEO);
490 stopMusic = (pMsg->dwParam1 == PLAYLIST_MUSIC);
493 if ((stopSlideshow && g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) ||
494 (stopVideo && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) ||
495 (stopMusic && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION))
496 g_windowManager.PreviousWindow();
498 g_application.ResetScreenSaver();
499 g_application.WakeUpScreenSaverAndDPMS();
502 if (g_application.m_pPlayer->IsPlaying()) g_application.StopPlaying();
506 case TMSG_MEDIA_PAUSE:
507 if (g_application.m_pPlayer->HasPlayer())
509 g_application.ResetScreenSaver();
510 g_application.WakeUpScreenSaverAndDPMS();
511 g_application.m_pPlayer->Pause();
515 case TMSG_MEDIA_UNPAUSE:
516 if (g_application.m_pPlayer->IsPausedPlayback())
518 g_application.ResetScreenSaver();
519 g_application.WakeUpScreenSaverAndDPMS();
520 g_application.m_pPlayer->Pause();
524 case TMSG_MEDIA_PAUSE_IF_PLAYING:
525 if (g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused())
527 g_application.ResetScreenSaver();
528 g_application.WakeUpScreenSaverAndDPMS();
529 g_application.m_pPlayer->Pause();
533 case TMSG_SWITCHTOFULLSCREEN:
534 if( g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
535 g_application.SwitchToFullScreen();
538 case TMSG_TOGGLEFULLSCREEN:
539 g_graphicsContext.Lock();
540 g_graphicsContext.ToggleFullScreenRoot();
541 g_graphicsContext.Unlock();
545 g_application.Minimize();
548 case TMSG_EXECUTE_OS:
549 /* Suspend AE temporarily so exclusive or hog-mode sinks */
550 /* don't block external player's access to audio device */
551 if (!CAEFactory::Suspend())
553 CLog::Log(LOGNOTICE, "%s: Failed to suspend AudioEngine before launching external program",__FUNCTION__);
555 #if defined( TARGET_POSIX) && !defined(TARGET_DARWIN)
556 CUtil::RunCommandLine(pMsg->strParam.c_str(), (pMsg->dwParam1 == 1));
557 #elif defined(TARGET_WINDOWS)
558 CWIN32Util::XBMCShellExecute(pMsg->strParam.c_str(), (pMsg->dwParam1 == 1));
560 /* Resume AE processing of XBMC native audio */
561 if (!CAEFactory::Resume())
563 CLog::Log(LOGFATAL, "%s: Failed to restart AudioEngine after return from external player",__FUNCTION__);
567 case TMSG_EXECUTE_SCRIPT:
568 CScriptInvocationManager::Get().Execute(pMsg->strParam);
571 case TMSG_EXECUTE_BUILT_IN:
572 CBuiltins::Execute(pMsg->strParam.c_str());
575 case TMSG_PLAYLISTPLAYER_PLAY:
576 if (pMsg->dwParam1 != (unsigned int) -1)
577 g_playlistPlayer.Play(pMsg->dwParam1);
579 g_playlistPlayer.Play();
582 case TMSG_PLAYLISTPLAYER_PLAY_SONG_ID:
583 if (pMsg->dwParam1 != (unsigned int) -1)
585 bool *result = (bool*)pMsg->lpVoid;
586 *result = g_playlistPlayer.PlaySongId(pMsg->dwParam1);
589 g_playlistPlayer.Play();
592 case TMSG_PLAYLISTPLAYER_NEXT:
593 g_playlistPlayer.PlayNext();
596 case TMSG_PLAYLISTPLAYER_PREV:
597 g_playlistPlayer.PlayPrevious();
600 case TMSG_PLAYLISTPLAYER_ADD:
603 CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
605 g_playlistPlayer.Add(pMsg->dwParam1, (*list));
610 case TMSG_PLAYLISTPLAYER_INSERT:
613 CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
614 g_playlistPlayer.Insert(pMsg->dwParam1, (*list), pMsg->dwParam2);
619 case TMSG_PLAYLISTPLAYER_REMOVE:
620 if (pMsg->dwParam1 != (unsigned int) -1)
621 g_playlistPlayer.Remove(pMsg->dwParam1,pMsg->dwParam2);
624 case TMSG_PLAYLISTPLAYER_CLEAR:
625 g_playlistPlayer.ClearPlaylist(pMsg->dwParam1);
628 case TMSG_PLAYLISTPLAYER_SHUFFLE:
629 g_playlistPlayer.SetShuffle(pMsg->dwParam1, pMsg->dwParam2 > 0);
632 case TMSG_PLAYLISTPLAYER_REPEAT:
633 g_playlistPlayer.SetRepeat(pMsg->dwParam1, (PLAYLIST::REPEAT_STATE)pMsg->dwParam2);
636 case TMSG_PLAYLISTPLAYER_GET_ITEMS:
639 PLAYLIST::CPlayList playlist = g_playlistPlayer.GetPlaylist(pMsg->dwParam1);
640 CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
642 for (int i = 0; i < playlist.size(); i++)
643 list->Add(CFileItemPtr(new CFileItem(*playlist[i])));
647 case TMSG_PLAYLISTPLAYER_SWAP:
650 vector<int> *indexes = (vector<int> *)pMsg->lpVoid;
651 if (indexes->size() == 2)
652 g_playlistPlayer.Swap(pMsg->dwParam1, indexes->at(0), indexes->at(1));
657 // Window messages below here...
658 case TMSG_DIALOG_DOMODAL: //doModel of window
660 CGUIDialog* pDialog = (CGUIDialog*)g_windowManager.GetWindow(pMsg->dwParam1);
661 if (!pDialog) return ;
666 case TMSG_NETWORKMESSAGE:
668 g_application.getNetwork().NetworkMessage((CNetwork::EMESSAGE)pMsg->dwParam1, (int)pMsg->dwParam2);
672 case TMSG_GUI_DO_MODAL:
674 CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid;
676 pDialog->DoModal((int)pMsg->dwParam1, pMsg->strParam);
682 CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid;
688 case TMSG_GUI_WINDOW_CLOSE:
690 CGUIWindow *window = (CGUIWindow *)pMsg->lpVoid;
692 window->Close(pMsg->dwParam2 & 0x1 ? true : false, pMsg->dwParam1, pMsg->dwParam2 & 0x2 ? true : false);
696 case TMSG_GUI_ACTIVATE_WINDOW:
698 g_windowManager.ActivateWindow(pMsg->dwParam1, pMsg->params, pMsg->dwParam2 > 0);
702 case TMSG_GUI_ADDON_DIALOG:
705 { // TODO: This is ugly - really these python dialogs should just be normal XBMC dialogs
706 ((ADDON::CGUIAddonWindowDialog *) pMsg->lpVoid)->Show_Internal(pMsg->dwParam2 > 0);
712 case TMSG_GUI_PYTHON_DIALOG:
714 // This hack is not much better but at least I don't need to make ApplicationMessenger
715 // know about Addon (Python) specific classes.
716 CAction caction(pMsg->dwParam1);
717 ((CGUIWindow*)pMsg->lpVoid)->OnAction(caction);
722 case TMSG_GUI_ACTION:
726 CAction *action = (CAction *)pMsg->lpVoid;
727 if (pMsg->dwParam1 == WINDOW_INVALID)
728 g_application.OnAction(*action);
731 CGUIWindow *pWindow = g_windowManager.GetWindow(pMsg->dwParam1);
733 pWindow->OnAction(*action);
735 CLog::Log(LOGWARNING, "Failed to get window with ID %i to send an action to", pMsg->dwParam1);
742 case TMSG_GUI_MESSAGE:
746 CGUIMessage *message = (CGUIMessage *)pMsg->lpVoid;
747 g_windowManager.SendMessage(*message, pMsg->dwParam1);
753 case TMSG_GUI_INFOLABEL:
757 vector<CStdString> *infoLabels = (vector<CStdString> *)pMsg->lpVoid;
758 for (unsigned int i = 0; i < pMsg->params.size(); i++)
759 infoLabels->push_back(g_infoManager.GetLabel(g_infoManager.TranslateString(pMsg->params[i])));
763 case TMSG_GUI_INFOBOOL:
767 vector<bool> *infoLabels = (vector<bool> *)pMsg->lpVoid;
768 for (unsigned int i = 0; i < pMsg->params.size(); i++)
769 infoLabels->push_back(g_infoManager.EvaluateBool(pMsg->params[i]));
776 ThreadMessageCallback *callback = (ThreadMessageCallback*)pMsg->lpVoid;
777 callback->callback(callback->userptr);
781 case TMSG_VOLUME_SHOW:
783 CAction action((int)pMsg->dwParam1);
784 g_application.ShowVolumeBar(&action);
788 case TMSG_SPLASH_MESSAGE:
790 if (g_application.GetSplash())
791 g_application.GetSplash()->Show(pMsg->strParam);
795 case TMSG_DISPLAY_SETUP:
797 *((bool*)pMsg->lpVoid) = g_application.InitWindow();
798 g_application.SetRenderGUI(true);
802 case TMSG_DISPLAY_DESTROY:
804 *((bool*)pMsg->lpVoid) = g_application.DestroyWindow();
805 g_application.SetRenderGUI(false);
809 case TMSG_UPDATE_CURRENT_ITEM:
811 CFileItem* item = (CFileItem*)pMsg->lpVoid;
814 if (pMsg->dwParam1 == 1 && item->HasMusicInfoTag()) // only grab music tag
815 g_infoManager.SetCurrentSongTag(*item->GetMusicInfoTag());
816 else if (pMsg->dwParam1 == 2 && item->HasVideoInfoTag()) // only grab video tag
817 g_infoManager.SetCurrentVideoTag(*item->GetVideoInfoTag());
819 g_infoManager.SetCurrentItem(*item);
824 case TMSG_LOADPROFILE:
826 CGUIWindowLoginScreen::LoadProfile(pMsg->dwParam1);
829 case TMSG_CECTOGGLESTATE:
831 *((bool*)pMsg->lpVoid) = g_peripherals.ToggleDeviceState(STATE_SWITCH_TOGGLE);
834 case TMSG_CECACTIVATESOURCE:
836 *((bool*)pMsg->lpVoid) = g_peripherals.ToggleDeviceState(STATE_ACTIVATE_SOURCE);
839 case TMSG_CECSTANDBY:
841 *((bool*)pMsg->lpVoid) = g_peripherals.ToggleDeviceState(STATE_STANDBY);
844 case TMSG_START_ANDROID_ACTIVITY:
846 #if defined(TARGET_ANDROID)
847 if (pMsg->params.size())
849 CXBMCApp::StartActivity(pMsg->params[0],
850 pMsg->params.size() > 1 ? pMsg->params[1] : "",
851 pMsg->params.size() > 2 ? pMsg->params[2] : "",
852 pMsg->params.size() > 3 ? pMsg->params[3] : "");
860 void CApplicationMessenger::ProcessWindowMessages()
862 CSingleLock lock (m_critSection);
863 //message type is window, process window messages
864 while (m_vecWindowMessages.size() > 0)
866 ThreadMessage* pMsg = m_vecWindowMessages.front();
867 //first remove the message from the queue, else the message could be processed more then once
868 m_vecWindowMessages.pop();
870 // leave here in case we make more thread messages from this one
872 boost::shared_ptr<CEvent> waitEvent = pMsg->waitEvent;
873 lock.Leave(); // <- see the large comment in SendMessage ^
875 ProcessMessage(pMsg);
884 int CApplicationMessenger::SetResponse(CStdString response)
886 CSingleLock lock (m_critBuffer);
887 bufferResponse=response;
892 CStdString CApplicationMessenger::GetResponse()
895 CSingleLock lock (m_critBuffer);
901 void CApplicationMessenger::ExecBuiltIn(const CStdString &command, bool wait)
903 ThreadMessage tMsg = {TMSG_EXECUTE_BUILT_IN};
904 tMsg.strParam = command;
905 SendMessage(tMsg, wait);
908 void CApplicationMessenger::MediaPlay(string filename)
910 CFileItem item(filename, false);
914 void CApplicationMessenger::MediaPlay(const CFileItem &item)
917 list.Add(CFileItemPtr(new CFileItem(item)));
922 void CApplicationMessenger::MediaPlay(const CFileItemList &list, int song)
924 ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
925 CFileItemList* listcopy = new CFileItemList();
926 listcopy->Copy(list);
927 tMsg.lpVoid = (void*)listcopy;
928 tMsg.dwParam1 = song;
930 SendMessage(tMsg, true);
933 void CApplicationMessenger::MediaPlay(int playlistid, int song /* = -1 */)
935 ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
937 tMsg.dwParam1 = playlistid;
938 tMsg.dwParam2 = song;
939 SendMessage(tMsg, true);
942 void CApplicationMessenger::PlayFile(const CFileItem &item, bool bRestart /*= false*/)
944 ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
945 CFileItem *pItem = new CFileItem(item);
946 tMsg.lpVoid = (void *)pItem;
947 tMsg.dwParam1 = bRestart ? 1 : 0;
949 SendMessage(tMsg, false);
952 void CApplicationMessenger::MediaStop(bool bWait /* = true */, int playlistid /* = -1 */)
954 ThreadMessage tMsg = {TMSG_MEDIA_STOP};
955 tMsg.dwParam1 = playlistid;
956 SendMessage(tMsg, bWait);
959 void CApplicationMessenger::MediaPause()
961 ThreadMessage tMsg = {TMSG_MEDIA_PAUSE};
962 SendMessage(tMsg, true);
965 void CApplicationMessenger::MediaUnPause()
967 ThreadMessage tMsg = {TMSG_MEDIA_UNPAUSE};
968 SendMessage(tMsg, true);
971 void CApplicationMessenger::MediaPauseIfPlaying()
973 ThreadMessage tMsg = {TMSG_MEDIA_PAUSE_IF_PLAYING};
974 SendMessage(tMsg, true);
977 void CApplicationMessenger::MediaRestart(bool bWait)
979 ThreadMessage tMsg = {TMSG_MEDIA_RESTART};
980 SendMessage(tMsg, bWait);
983 void CApplicationMessenger::PlayListPlayerPlay()
985 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY, (unsigned int) -1};
986 SendMessage(tMsg, true);
989 void CApplicationMessenger::PlayListPlayerPlay(int iSong)
991 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY, (unsigned int)iSong};
992 SendMessage(tMsg, true);
995 bool CApplicationMessenger::PlayListPlayerPlaySongId(int songId)
998 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY_SONG_ID, (unsigned int)songId};
999 tMsg.lpVoid = (void *)&returnState;
1000 SendMessage(tMsg, true);
1004 void CApplicationMessenger::PlayListPlayerNext()
1006 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_NEXT};
1007 SendMessage(tMsg, true);
1010 void CApplicationMessenger::PlayListPlayerPrevious()
1012 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PREV};
1013 SendMessage(tMsg, true);
1016 void CApplicationMessenger::PlayListPlayerAdd(int playlist, const CFileItem &item)
1019 list.Add(CFileItemPtr(new CFileItem(item)));
1021 PlayListPlayerAdd(playlist, list);
1024 void CApplicationMessenger::PlayListPlayerAdd(int playlist, const CFileItemList &list)
1026 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_ADD};
1027 CFileItemList* listcopy = new CFileItemList();
1028 listcopy->Copy(list);
1029 tMsg.lpVoid = (void*)listcopy;
1030 tMsg.dwParam1 = playlist;
1031 SendMessage(tMsg, true);
1034 void CApplicationMessenger::PlayListPlayerInsert(int playlist, const CFileItem &item, int index)
1037 list.Add(CFileItemPtr(new CFileItem(item)));
1038 PlayListPlayerInsert(playlist, list, index);
1041 void CApplicationMessenger::PlayListPlayerInsert(int playlist, const CFileItemList &list, int index)
1043 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_INSERT};
1044 CFileItemList* listcopy = new CFileItemList();
1045 listcopy->Copy(list);
1046 tMsg.lpVoid = (void *)listcopy;
1047 tMsg.dwParam1 = playlist;
1048 tMsg.dwParam2 = index;
1049 SendMessage(tMsg, true);
1052 void CApplicationMessenger::PlayListPlayerRemove(int playlist, int position)
1054 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_REMOVE, (unsigned int)playlist, (unsigned int)position};
1055 SendMessage(tMsg, true);
1058 void CApplicationMessenger::PlayListPlayerClear(int playlist)
1060 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_CLEAR};
1061 tMsg.dwParam1 = playlist;
1062 SendMessage(tMsg, true);
1065 void CApplicationMessenger::PlayListPlayerShuffle(int playlist, bool shuffle)
1067 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_SHUFFLE};
1068 tMsg.dwParam1 = playlist;
1069 tMsg.dwParam2 = shuffle ? 1 : 0;
1070 SendMessage(tMsg, true);
1073 void CApplicationMessenger::PlayListPlayerGetItems(int playlist, CFileItemList &list)
1075 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_GET_ITEMS};
1076 tMsg.dwParam1 = playlist;
1077 tMsg.lpVoid = (void *)&list;
1078 SendMessage(tMsg, true);
1081 void CApplicationMessenger::PlayListPlayerSwap(int playlist, int indexItem1, int indexItem2)
1083 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_SWAP};
1084 tMsg.dwParam1 = playlist;
1085 vector<int> *indexes = new vector<int>();
1086 indexes->push_back(indexItem1);
1087 indexes->push_back(indexItem2);
1088 tMsg.lpVoid = (void *)indexes;
1089 SendMessage(tMsg, true);
1092 void CApplicationMessenger::PlayListPlayerRepeat(int playlist, int repeatState)
1094 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_REPEAT};
1095 tMsg.dwParam1 = playlist;
1096 tMsg.dwParam2 = repeatState;
1097 SendMessage(tMsg, true);
1100 void CApplicationMessenger::PictureShow(string filename)
1102 ThreadMessage tMsg = {TMSG_PICTURE_SHOW};
1103 tMsg.strParam = filename;
1107 void CApplicationMessenger::PictureSlideShow(string pathname, bool addTBN /* = false */)
1109 unsigned int dwMessage = TMSG_PICTURE_SLIDESHOW;
1110 ThreadMessage tMsg = {dwMessage};
1111 tMsg.strParam = pathname;
1112 tMsg.dwParam1 = addTBN ? 1 : 0;
1116 void CApplicationMessenger::SetGUILanguage(const std::string &strLanguage)
1118 ThreadMessage tMsg = {TMSG_SETLANGUAGE};
1119 tMsg.strParam = strLanguage;
1123 void CApplicationMessenger::Shutdown()
1125 ThreadMessage tMsg = {TMSG_SHUTDOWN};
1129 void CApplicationMessenger::Powerdown()
1131 ThreadMessage tMsg = {TMSG_POWERDOWN};
1135 void CApplicationMessenger::Quit()
1137 ThreadMessage tMsg = {TMSG_QUIT};
1141 void CApplicationMessenger::Hibernate()
1143 ThreadMessage tMsg = {TMSG_HIBERNATE};
1147 void CApplicationMessenger::Suspend()
1149 ThreadMessage tMsg = {TMSG_SUSPEND};
1153 void CApplicationMessenger::Restart()
1155 ThreadMessage tMsg = {TMSG_RESTART};
1159 void CApplicationMessenger::Reset()
1161 ThreadMessage tMsg = {TMSG_RESET};
1165 void CApplicationMessenger::RestartApp()
1167 ThreadMessage tMsg = {TMSG_RESTARTAPP};
1171 void CApplicationMessenger::InhibitIdleShutdown(bool inhibit)
1173 ThreadMessage tMsg = {TMSG_INHIBITIDLESHUTDOWN, (unsigned int)inhibit};
1177 void CApplicationMessenger::ActivateScreensaver()
1179 ThreadMessage tMsg = {TMSG_ACTIVATESCREENSAVER};
1183 void CApplicationMessenger::NetworkMessage(unsigned int dwMessage, unsigned int dwParam)
1185 ThreadMessage tMsg = {TMSG_NETWORKMESSAGE, dwMessage, dwParam};
1189 void CApplicationMessenger::SwitchToFullscreen()
1191 /* FIXME: ideally this call should return upon a successfull switch but currently
1192 is causing deadlocks between the dvdplayer destructor and the rendermanager
1194 ThreadMessage tMsg = {TMSG_SWITCHTOFULLSCREEN};
1195 SendMessage(tMsg, false);
1198 void CApplicationMessenger::Minimize(bool wait)
1200 ThreadMessage tMsg = {TMSG_MINIMIZE};
1201 SendMessage(tMsg, wait);
1204 void CApplicationMessenger::DoModal(CGUIDialog *pDialog, int iWindowID, const CStdString ¶m)
1206 ThreadMessage tMsg = {TMSG_GUI_DO_MODAL};
1207 tMsg.lpVoid = pDialog;
1208 tMsg.dwParam1 = (unsigned int)iWindowID;
1209 tMsg.strParam = param;
1210 SendMessage(tMsg, true);
1213 void CApplicationMessenger::ExecOS(const CStdString &command, bool waitExit)
1215 ThreadMessage tMsg = {TMSG_EXECUTE_OS};
1216 tMsg.strParam = command;
1217 tMsg.dwParam1 = (unsigned int)waitExit;
1218 SendMessage(tMsg, false);
1221 void CApplicationMessenger::UserEvent(int code)
1223 ThreadMessage tMsg = {(unsigned int)code};
1224 SendMessage(tMsg, false);
1227 void CApplicationMessenger::Show(CGUIDialog *pDialog)
1229 ThreadMessage tMsg = {TMSG_GUI_SHOW};
1230 tMsg.lpVoid = pDialog;
1231 SendMessage(tMsg, true);
1234 void CApplicationMessenger::Close(CGUIWindow *window, bool forceClose, bool waitResult /*= true*/, int nextWindowID /*= 0*/, bool enableSound /*= true*/)
1236 ThreadMessage tMsg = {TMSG_GUI_WINDOW_CLOSE, (unsigned int)nextWindowID};
1237 tMsg.dwParam2 = (unsigned int)((forceClose ? 0x01 : 0) | (enableSound ? 0x02 : 0));
1238 tMsg.lpVoid = window;
1239 SendMessage(tMsg, waitResult);
1242 void CApplicationMessenger::ActivateWindow(int windowID, const vector<CStdString> ¶ms, bool swappingWindows)
1244 ThreadMessage tMsg = {TMSG_GUI_ACTIVATE_WINDOW, (unsigned int)windowID, swappingWindows ? 1u : 0u};
1245 tMsg.params = params;
1246 SendMessage(tMsg, true);
1249 void CApplicationMessenger::SendAction(const CAction &action, int windowID, bool waitResult)
1251 ThreadMessage tMsg = {TMSG_GUI_ACTION};
1252 tMsg.dwParam1 = windowID;
1253 tMsg.lpVoid = new CAction(action);
1254 SendMessage(tMsg, waitResult);
1257 void CApplicationMessenger::SendGUIMessage(const CGUIMessage &message, int windowID, bool waitResult)
1259 ThreadMessage tMsg = {TMSG_GUI_MESSAGE};
1260 tMsg.dwParam1 = windowID == WINDOW_INVALID ? 0 : windowID;
1261 tMsg.lpVoid = new CGUIMessage(message);
1262 SendMessage(tMsg, waitResult);
1265 void CApplicationMessenger::SendText(const std::string &aTextString, bool closeKeyboard /* = false */)
1267 if (CGUIKeyboardFactory::SendTextToActiveKeyboard(aTextString, closeKeyboard))
1270 CGUIWindow *window = g_windowManager.GetWindow(g_windowManager.GetFocusedWindow());
1274 CGUIMessage msg(GUI_MSG_SET_TEXT, 0, 0);
1275 msg.SetLabel(aTextString);
1276 msg.SetParam1(closeKeyboard ? 1 : 0);
1277 SendGUIMessage(msg, window->GetID());
1280 vector<CStdString> CApplicationMessenger::GetInfoLabels(const vector<CStdString> &properties)
1282 vector<CStdString> infoLabels;
1284 ThreadMessage tMsg = {TMSG_GUI_INFOLABEL};
1285 tMsg.params = properties;
1286 tMsg.lpVoid = (void*)&infoLabels;
1287 SendMessage(tMsg, true);
1291 vector<bool> CApplicationMessenger::GetInfoBooleans(const vector<CStdString> &properties)
1293 vector<bool> infoLabels;
1295 ThreadMessage tMsg = {TMSG_GUI_INFOBOOL};
1296 tMsg.params = properties;
1297 tMsg.lpVoid = (void*)&infoLabels;
1298 SendMessage(tMsg, true);
1302 void CApplicationMessenger::ShowVolumeBar(bool up)
1304 ThreadMessage tMsg = {TMSG_VOLUME_SHOW};
1305 tMsg.dwParam1 = up ? ACTION_VOLUME_UP : ACTION_VOLUME_DOWN;
1306 SendMessage(tMsg, false);
1309 void CApplicationMessenger::SetSplashMessage(const CStdString& message)
1311 ThreadMessage tMsg = {TMSG_SPLASH_MESSAGE};
1312 tMsg.strParam = message;
1313 SendMessage(tMsg, true);
1316 void CApplicationMessenger::SetSplashMessage(int stringID)
1318 SetSplashMessage(g_localizeStrings.Get(stringID));
1321 bool CApplicationMessenger::SetupDisplay()
1325 ThreadMessage tMsg = {TMSG_DISPLAY_SETUP};
1326 tMsg.lpVoid = (void*)&result;
1327 SendMessage(tMsg, true);
1332 bool CApplicationMessenger::DestroyDisplay()
1336 ThreadMessage tMsg = {TMSG_DISPLAY_DESTROY};
1337 tMsg.lpVoid = (void*)&result;
1338 SendMessage(tMsg, true);
1343 void CApplicationMessenger::SetCurrentSongTag(const CMusicInfoTag& tag)
1345 CFileItem* item = new CFileItem(tag);
1346 ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1348 tMsg.lpVoid = (void*)item;
1349 SendMessage(tMsg, false);
1352 void CApplicationMessenger::SetCurrentVideoTag(const CVideoInfoTag& tag)
1354 CFileItem* item = new CFileItem(tag);
1355 ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1357 tMsg.lpVoid = (void*)item;
1358 SendMessage(tMsg, false);
1361 void CApplicationMessenger::SetCurrentItem(const CFileItem& item)
1363 CFileItem* item2 = new CFileItem(item);
1364 ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1365 tMsg.lpVoid = (void*)item2;
1366 SendMessage(tMsg, false);
1369 void CApplicationMessenger::LoadProfile(unsigned int idx)
1371 ThreadMessage tMsg = {TMSG_LOADPROFILE};
1372 tMsg.dwParam1 = idx;
1373 SendMessage(tMsg, false);
1376 void CApplicationMessenger::StartAndroidActivity(const vector<CStdString> ¶ms)
1378 ThreadMessage tMsg = {TMSG_START_ANDROID_ACTIVITY};
1379 tMsg.params = params;
1380 SendMessage(tMsg, false);
1383 bool CApplicationMessenger::CECToggleState()
1387 ThreadMessage tMsg = {TMSG_CECTOGGLESTATE};
1388 tMsg.lpVoid = (void*)&result;
1389 SendMessage(tMsg, false);
1394 bool CApplicationMessenger::CECActivateSource()
1398 ThreadMessage tMsg = {TMSG_CECACTIVATESOURCE};
1399 tMsg.lpVoid = (void*)&result;
1400 SendMessage(tMsg, false);
1405 bool CApplicationMessenger::CECStandby()
1409 ThreadMessage tMsg = {TMSG_CECSTANDBY};
1410 tMsg.lpVoid = (void*)&result;
1411 SendMessage(tMsg, false);