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 "GUIInfoManager.h"
42 #include "utils/Splash.h"
43 #include "cores/IPlayer.h"
44 #include "cores/VideoRenderers/RenderManager.h"
45 #include "cores/AudioEngine/AEFactory.h"
46 #include "music/tags/MusicInfoTag.h"
48 #include "peripherals/Peripherals.h"
49 #include "powermanagement/PowerManager.h"
52 #include "WIN32Util.h"
53 #define CHalManager CWIN32Util
54 #elif defined(TARGET_DARWIN)
55 #include "osx/CocoaInterface.h"
57 #include "addons/AddonCallbacks.h"
58 #include "addons/AddonCallbacksGUI.h"
59 #include "storage/MediaManager.h"
60 #include "guilib/LocalizeStrings.h"
61 #include "threads/SingleLock.h"
63 #include "playlists/PlayList.h"
65 #include "pvr/PVRManager.h"
66 #include "windows/GUIWindowLoginScreen.h"
68 #include "utils/GlobalsHandling.h"
69 #if defined(TARGET_ANDROID)
70 #include "xbmc/android/activity/XBMCApp.h"
75 using namespace MUSIC_INFO;
76 using namespace PERIPHERALS;
78 CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) : CThread("DelayedMessage")
80 m_msg.dwMessage = msg.dwMessage;
81 m_msg.dwParam1 = msg.dwParam1;
82 m_msg.dwParam2 = msg.dwParam2;
83 m_msg.waitEvent = msg.waitEvent;
84 m_msg.lpVoid = msg.lpVoid;
85 m_msg.strParam = msg.strParam;
86 m_msg.params = msg.params;
91 void CDelayedMessage::Process()
96 CApplicationMessenger::Get().SendMessage(m_msg, false);
100 CApplicationMessenger& CApplicationMessenger::Get()
105 CApplicationMessenger::CApplicationMessenger()
109 CApplicationMessenger::~CApplicationMessenger()
114 void CApplicationMessenger::Cleanup()
116 CSingleLock lock (m_critSection);
118 while (m_vecMessages.size() > 0)
120 ThreadMessage* pMsg = m_vecMessages.front();
123 pMsg->waitEvent->Set();
129 while (m_vecWindowMessages.size() > 0)
131 ThreadMessage* pMsg = m_vecWindowMessages.front();
134 pMsg->waitEvent->Set();
137 m_vecWindowMessages.pop();
141 void CApplicationMessenger::SendMessage(ThreadMessage& message, bool wait)
143 message.waitEvent.reset();
144 boost::shared_ptr<CEvent> waitEvent;
146 { // check that we're not being called from our application thread, else we'll be waiting
148 if (!g_application.IsCurrentThread())
150 message.waitEvent.reset(new CEvent(true));
151 waitEvent = message.waitEvent;
155 //OutputDebugString("Attempting to wait on a SendMessage() from our application thread will cause lockup!\n");
156 //OutputDebugString("Sending immediately\n");
157 ProcessMessage(&message);
162 CSingleLock lock (m_critSection);
164 if (g_application.m_bStop)
166 if (message.waitEvent)
167 message.waitEvent.reset();
171 ThreadMessage* msg = new ThreadMessage();
172 msg->dwMessage = message.dwMessage;
173 msg->dwParam1 = message.dwParam1;
174 msg->dwParam2 = message.dwParam2;
175 msg->waitEvent = message.waitEvent;
176 msg->lpVoid = message.lpVoid;
177 msg->strParam = message.strParam;
178 msg->params = message.params;
180 if (msg->dwMessage == TMSG_DIALOG_DOMODAL)
181 m_vecWindowMessages.push(msg);
183 m_vecMessages.push(msg);
184 lock.Leave(); // this releases the lock on the vec of messages and
185 // allows the ProcessMessage to execute and therefore
186 // delete the message itself. Therefore any accesss
187 // of the message itself after this point consittutes
188 // a race condition (yarc - "yet another race condition")
190 if (waitEvent) // ... it just so happens we have a spare reference to the
191 // waitEvent ... just for such contingencies :)
193 // ensure the thread doesn't hold the graphics lock
194 CSingleExit exit(g_graphicsContext);
199 void CApplicationMessenger::ProcessMessages()
201 // process threadmessages
202 CSingleLock lock (m_critSection);
203 while (m_vecMessages.size() > 0)
205 ThreadMessage* pMsg = m_vecMessages.front();
206 //first remove the message from the queue, else the message could be processed more then once
209 //Leave here as the message might make another
210 //thread call processmessages or sendmessage
212 boost::shared_ptr<CEvent> waitEvent = pMsg->waitEvent;
213 lock.Leave(); // <- see the large comment in SendMessage ^
215 ProcessMessage(pMsg);
224 void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
226 switch (pMsg->dwMessage)
230 switch (CSettings::Get().GetInt("powermanagement.shutdownstate"))
232 case POWERSTATE_SHUTDOWN:
236 case POWERSTATE_SUSPEND:
240 case POWERSTATE_HIBERNATE:
244 case POWERSTATE_QUIT:
248 case POWERSTATE_MINIMIZE:
252 case TMSG_RENDERER_FLUSH:
253 g_renderManager.Flush();
261 g_application.Stop(EXITCODE_POWERDOWN);
262 g_powerManager.Powerdown();
268 g_application.Stop(EXITCODE_QUIT);
274 g_PVRManager.SetWakeupCommand();
275 g_powerManager.Hibernate();
281 g_PVRManager.SetWakeupCommand();
282 g_powerManager.Suspend();
289 g_application.Stop(EXITCODE_REBOOT);
290 g_powerManager.Reboot();
294 case TMSG_RESTARTAPP:
296 #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX)
297 g_application.Stop(EXITCODE_RESTARTAPP);
302 case TMSG_INHIBITIDLESHUTDOWN:
304 g_application.InhibitIdleShutdown(pMsg->dwParam1 != 0);
308 case TMSG_ACTIVATESCREENSAVER:
310 g_application.ActivateScreenSaver();
314 case TMSG_MEDIA_PLAY:
316 // first check if we were called from the PlayFile() function
317 if (pMsg->lpVoid && pMsg->dwParam2 == 0)
319 CFileItem *item = (CFileItem *)pMsg->lpVoid;
320 g_application.PlayFile(*item, pMsg->dwParam1 != 0);
324 // restore to previous window if needed
325 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW ||
326 g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
327 g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
328 g_windowManager.PreviousWindow();
330 g_application.ResetScreenSaver();
331 g_application.WakeUpScreenSaverAndDPMS();
333 //g_application.StopPlaying();
337 CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
339 if (list->Size() > 0)
341 int playlist = PLAYLIST_MUSIC;
342 for (int i = 0; i < list->Size(); i++)
344 if ((*list)[i]->IsVideo())
346 playlist = PLAYLIST_VIDEO;
351 g_playlistPlayer.ClearPlaylist(playlist);
352 g_playlistPlayer.SetCurrentPlaylist(playlist);
353 //For single item lists try PlayMedia. This covers some more cases where a playlist is not appropriate
354 //It will fall through to PlayFile
355 if (list->Size() == 1 && !(*list)[0]->IsPlayList())
356 g_application.PlayMedia(*((*list)[0]), playlist);
359 // Handle "shuffled" option if present
360 if (list->HasProperty("shuffled") && list->GetProperty("shuffled").isBoolean())
361 g_playlistPlayer.SetShuffle(playlist, list->GetProperty("shuffled").asBoolean(), false);
362 // Handle "repeat" option if present
363 if (list->HasProperty("repeat") && list->GetProperty("repeat").isInteger())
364 g_playlistPlayer.SetRepeat(playlist, (PLAYLIST::REPEAT_STATE)list->GetProperty("repeat").asInteger(), false);
366 g_playlistPlayer.Add(playlist, (*list));
367 g_playlistPlayer.Play(pMsg->dwParam1);
373 else if (pMsg->dwParam1 == PLAYLIST_MUSIC || pMsg->dwParam1 == PLAYLIST_VIDEO)
375 if (g_playlistPlayer.GetCurrentPlaylist() != (int)pMsg->dwParam1)
376 g_playlistPlayer.SetCurrentPlaylist(pMsg->dwParam1);
378 PlayListPlayerPlay(pMsg->dwParam2);
383 case TMSG_MEDIA_RESTART:
384 g_application.Restart(true);
387 case TMSG_PICTURE_SHOW:
389 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
390 if (!pSlideShow) return ;
393 if (g_application.m_pPlayer->IsPlayingVideo()) g_application.StopPlaying();
395 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
396 g_windowManager.PreviousWindow();
398 g_application.ResetScreenSaver();
399 g_application.WakeUpScreenSaverAndDPMS();
401 g_graphicsContext.Lock();
403 if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW)
404 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
405 if (URIUtils::IsZIP(pMsg->strParam) || URIUtils::IsRAR(pMsg->strParam)) // actually a cbz/cbr
409 if (URIUtils::IsZIP(pMsg->strParam))
410 URIUtils::CreateArchivePath(strPath, "zip", pMsg->strParam.c_str(), "");
412 URIUtils::CreateArchivePath(strPath, "rar", pMsg->strParam.c_str(), "");
414 CUtil::GetRecursiveListing(strPath, items, g_advancedSettings.m_pictureExtensions);
415 if (items.Size() > 0)
418 for (int i=0;i<items.Size();++i)
420 pSlideShow->Add(items[i].get());
422 pSlideShow->Select(items[0]->GetPath());
427 CFileItem item(pMsg->strParam, false);
429 pSlideShow->Add(&item);
430 pSlideShow->Select(pMsg->strParam);
432 g_graphicsContext.Unlock();
436 case TMSG_PICTURE_SLIDESHOW:
438 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
439 if (!pSlideShow) return ;
441 if (g_application.m_pPlayer->IsPlayingVideo())
442 g_application.StopPlaying();
444 g_graphicsContext.Lock();
448 CStdString strPath = pMsg->strParam;
449 CStdString extensions = g_advancedSettings.m_pictureExtensions;
451 extensions += "|.tbn";
452 CUtil::GetRecursiveListing(strPath, items, extensions);
454 if (items.Size() > 0)
456 for (int i=0;i<items.Size();++i)
457 pSlideShow->Add(items[i].get());
458 pSlideShow->StartSlideShow(); //Start the slideshow!
461 if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW)
463 if(items.Size() == 0)
465 CSettings::Get().SetString("screensaver.mode", "screensaver.xbmc.builtin.dim");
466 g_application.ActivateScreenSaver();
469 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
472 g_graphicsContext.Unlock();
476 case TMSG_SETLANGUAGE:
477 g_application.SetLanguage(pMsg->strParam);
479 case TMSG_MEDIA_STOP:
481 // restore to previous window if needed
482 bool stopSlideshow = true;
483 bool stopVideo = true;
484 bool stopMusic = true;
485 if (pMsg->dwParam1 >= PLAYLIST_MUSIC && pMsg->dwParam1 <= PLAYLIST_PICTURE)
487 stopSlideshow = (pMsg->dwParam1 == PLAYLIST_PICTURE);
488 stopVideo = (pMsg->dwParam1 == PLAYLIST_VIDEO);
489 stopMusic = (pMsg->dwParam1 == PLAYLIST_MUSIC);
492 if ((stopSlideshow && g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) ||
493 (stopVideo && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) ||
494 (stopMusic && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION))
495 g_windowManager.PreviousWindow();
497 g_application.ResetScreenSaver();
498 g_application.WakeUpScreenSaverAndDPMS();
501 if (g_application.m_pPlayer->IsPlaying()) g_application.StopPlaying();
505 case TMSG_MEDIA_PAUSE:
506 if (g_application.m_pPlayer->HasPlayer())
508 g_application.ResetScreenSaver();
509 g_application.WakeUpScreenSaverAndDPMS();
510 g_application.m_pPlayer->Pause();
514 case TMSG_MEDIA_UNPAUSE:
515 if (g_application.m_pPlayer->IsPausedPlayback())
517 g_application.ResetScreenSaver();
518 g_application.WakeUpScreenSaverAndDPMS();
519 g_application.m_pPlayer->Pause();
523 case TMSG_MEDIA_PAUSE_IF_PLAYING:
524 if (g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused())
526 g_application.ResetScreenSaver();
527 g_application.WakeUpScreenSaverAndDPMS();
528 g_application.m_pPlayer->Pause();
532 case TMSG_SWITCHTOFULLSCREEN:
533 if( g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
534 g_application.SwitchToFullScreen();
537 case TMSG_TOGGLEFULLSCREEN:
538 g_graphicsContext.Lock();
539 g_graphicsContext.ToggleFullScreenRoot();
540 g_graphicsContext.Unlock();
544 g_application.Minimize();
547 case TMSG_EXECUTE_OS:
548 /* Suspend AE temporarily so exclusive or hog-mode sinks */
549 /* don't block external player's access to audio device */
550 if (!CAEFactory::Suspend())
552 CLog::Log(LOGNOTICE, "%s: Failed to suspend AudioEngine before launching external program",__FUNCTION__);
554 #if defined( TARGET_POSIX) && !defined(TARGET_DARWIN)
555 CUtil::RunCommandLine(pMsg->strParam.c_str(), (pMsg->dwParam1 == 1));
556 #elif defined(TARGET_WINDOWS)
557 CWIN32Util::XBMCShellExecute(pMsg->strParam.c_str(), (pMsg->dwParam1 == 1));
559 /* Resume AE processing of XBMC native audio */
560 if (!CAEFactory::Resume())
562 CLog::Log(LOGFATAL, "%s: Failed to restart AudioEngine after return from external player",__FUNCTION__);
566 case TMSG_EXECUTE_SCRIPT:
567 CScriptInvocationManager::Get().Execute(pMsg->strParam);
570 case TMSG_EXECUTE_BUILT_IN:
571 CBuiltins::Execute(pMsg->strParam.c_str());
574 case TMSG_PLAYLISTPLAYER_PLAY:
575 if (pMsg->dwParam1 != (unsigned int) -1)
576 g_playlistPlayer.Play(pMsg->dwParam1);
578 g_playlistPlayer.Play();
581 case TMSG_PLAYLISTPLAYER_PLAY_SONG_ID:
582 if (pMsg->dwParam1 != (unsigned int) -1)
584 bool *result = (bool*)pMsg->lpVoid;
585 *result = g_playlistPlayer.PlaySongId(pMsg->dwParam1);
588 g_playlistPlayer.Play();
591 case TMSG_PLAYLISTPLAYER_NEXT:
592 g_playlistPlayer.PlayNext();
595 case TMSG_PLAYLISTPLAYER_PREV:
596 g_playlistPlayer.PlayPrevious();
599 case TMSG_PLAYLISTPLAYER_ADD:
602 CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
604 g_playlistPlayer.Add(pMsg->dwParam1, (*list));
609 case TMSG_PLAYLISTPLAYER_INSERT:
612 CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
613 g_playlistPlayer.Insert(pMsg->dwParam1, (*list), pMsg->dwParam2);
618 case TMSG_PLAYLISTPLAYER_REMOVE:
619 if (pMsg->dwParam1 != (unsigned int) -1)
620 g_playlistPlayer.Remove(pMsg->dwParam1,pMsg->dwParam2);
623 case TMSG_PLAYLISTPLAYER_CLEAR:
624 g_playlistPlayer.ClearPlaylist(pMsg->dwParam1);
627 case TMSG_PLAYLISTPLAYER_SHUFFLE:
628 g_playlistPlayer.SetShuffle(pMsg->dwParam1, pMsg->dwParam2 > 0);
631 case TMSG_PLAYLISTPLAYER_REPEAT:
632 g_playlistPlayer.SetRepeat(pMsg->dwParam1, (PLAYLIST::REPEAT_STATE)pMsg->dwParam2);
635 case TMSG_PLAYLISTPLAYER_GET_ITEMS:
638 PLAYLIST::CPlayList playlist = g_playlistPlayer.GetPlaylist(pMsg->dwParam1);
639 CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
641 for (int i = 0; i < playlist.size(); i++)
642 list->Add(CFileItemPtr(new CFileItem(*playlist[i])));
646 case TMSG_PLAYLISTPLAYER_SWAP:
649 vector<int> *indexes = (vector<int> *)pMsg->lpVoid;
650 if (indexes->size() == 2)
651 g_playlistPlayer.Swap(pMsg->dwParam1, indexes->at(0), indexes->at(1));
656 // Window messages below here...
657 case TMSG_DIALOG_DOMODAL: //doModel of window
659 CGUIDialog* pDialog = (CGUIDialog*)g_windowManager.GetWindow(pMsg->dwParam1);
660 if (!pDialog) return ;
665 case TMSG_NETWORKMESSAGE:
667 g_application.getNetwork().NetworkMessage((CNetwork::EMESSAGE)pMsg->dwParam1, (int)pMsg->dwParam2);
671 case TMSG_GUI_DO_MODAL:
673 CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid;
675 pDialog->DoModal((int)pMsg->dwParam1, pMsg->strParam);
681 CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid;
687 case TMSG_GUI_WINDOW_CLOSE:
689 CGUIWindow *window = (CGUIWindow *)pMsg->lpVoid;
691 window->Close(pMsg->dwParam2 & 0x1 ? true : false, pMsg->dwParam1, pMsg->dwParam2 & 0x2 ? true : false);
695 case TMSG_GUI_ACTIVATE_WINDOW:
697 g_windowManager.ActivateWindow(pMsg->dwParam1, pMsg->params, pMsg->dwParam2 > 0);
701 case TMSG_GUI_ADDON_DIALOG:
704 { // TODO: This is ugly - really these python dialogs should just be normal XBMC dialogs
705 ((ADDON::CGUIAddonWindowDialog *) pMsg->lpVoid)->Show_Internal(pMsg->dwParam2 > 0);
711 case TMSG_GUI_PYTHON_DIALOG:
713 // This hack is not much better but at least I don't need to make ApplicationMessenger
714 // know about Addon (Python) specific classes.
715 CAction caction(pMsg->dwParam1);
716 ((CGUIWindow*)pMsg->lpVoid)->OnAction(caction);
721 case TMSG_GUI_ACTION:
725 CAction *action = (CAction *)pMsg->lpVoid;
726 if (pMsg->dwParam1 == WINDOW_INVALID)
727 g_application.OnAction(*action);
730 CGUIWindow *pWindow = g_windowManager.GetWindow(pMsg->dwParam1);
732 pWindow->OnAction(*action);
734 CLog::Log(LOGWARNING, "Failed to get window with ID %i to send an action to", pMsg->dwParam1);
741 case TMSG_GUI_MESSAGE:
745 CGUIMessage *message = (CGUIMessage *)pMsg->lpVoid;
746 g_windowManager.SendMessage(*message, pMsg->dwParam1);
752 case TMSG_GUI_INFOLABEL:
756 vector<CStdString> *infoLabels = (vector<CStdString> *)pMsg->lpVoid;
757 for (unsigned int i = 0; i < pMsg->params.size(); i++)
758 infoLabels->push_back(g_infoManager.GetLabel(g_infoManager.TranslateString(pMsg->params[i])));
762 case TMSG_GUI_INFOBOOL:
766 vector<bool> *infoLabels = (vector<bool> *)pMsg->lpVoid;
767 for (unsigned int i = 0; i < pMsg->params.size(); i++)
768 infoLabels->push_back(g_infoManager.EvaluateBool(pMsg->params[i]));
775 ThreadMessageCallback *callback = (ThreadMessageCallback*)pMsg->lpVoid;
776 callback->callback(callback->userptr);
780 case TMSG_VOLUME_SHOW:
782 CAction action((int)pMsg->dwParam1);
783 g_application.ShowVolumeBar(&action);
787 case TMSG_SPLASH_MESSAGE:
789 if (g_application.GetSplash())
790 g_application.GetSplash()->Show(pMsg->strParam);
794 case TMSG_DISPLAY_SETUP:
796 *((bool*)pMsg->lpVoid) = g_application.InitWindow();
797 g_application.SetRenderGUI(true);
801 case TMSG_DISPLAY_DESTROY:
803 *((bool*)pMsg->lpVoid) = g_application.DestroyWindow();
804 g_application.SetRenderGUI(false);
808 case TMSG_UPDATE_CURRENT_ITEM:
810 CFileItem* item = (CFileItem*)pMsg->lpVoid;
813 if (pMsg->dwParam1 == 1 && item->HasMusicInfoTag()) // only grab music tag
814 g_infoManager.SetCurrentSongTag(*item->GetMusicInfoTag());
815 else if (pMsg->dwParam1 == 2 && item->HasVideoInfoTag()) // only grab video tag
816 g_infoManager.SetCurrentVideoTag(*item->GetVideoInfoTag());
818 g_infoManager.SetCurrentItem(*item);
823 case TMSG_LOADPROFILE:
825 CGUIWindowLoginScreen::LoadProfile(pMsg->dwParam1);
828 case TMSG_CECTOGGLESTATE:
830 *((bool*)pMsg->lpVoid) = g_peripherals.ToggleDeviceState(STATE_SWITCH_TOGGLE);
833 case TMSG_CECACTIVATESOURCE:
835 *((bool*)pMsg->lpVoid) = g_peripherals.ToggleDeviceState(STATE_ACTIVATE_SOURCE);
838 case TMSG_CECSTANDBY:
840 *((bool*)pMsg->lpVoid) = g_peripherals.ToggleDeviceState(STATE_STANDBY);
843 case TMSG_START_ANDROID_ACTIVITY:
845 #if defined(TARGET_ANDROID)
846 if (pMsg->params.size())
848 CXBMCApp::StartActivity(pMsg->params[0],
849 pMsg->params.size() > 1 ? pMsg->params[1] : "",
850 pMsg->params.size() > 2 ? pMsg->params[2] : "",
851 pMsg->params.size() > 3 ? pMsg->params[3] : "");
859 void CApplicationMessenger::ProcessWindowMessages()
861 CSingleLock lock (m_critSection);
862 //message type is window, process window messages
863 while (m_vecWindowMessages.size() > 0)
865 ThreadMessage* pMsg = m_vecWindowMessages.front();
866 //first remove the message from the queue, else the message could be processed more then once
867 m_vecWindowMessages.pop();
869 // leave here in case we make more thread messages from this one
871 boost::shared_ptr<CEvent> waitEvent = pMsg->waitEvent;
872 lock.Leave(); // <- see the large comment in SendMessage ^
874 ProcessMessage(pMsg);
883 int CApplicationMessenger::SetResponse(CStdString response)
885 CSingleLock lock (m_critBuffer);
886 bufferResponse=response;
891 CStdString CApplicationMessenger::GetResponse()
894 CSingleLock lock (m_critBuffer);
900 void CApplicationMessenger::ExecBuiltIn(const CStdString &command, bool wait)
902 ThreadMessage tMsg = {TMSG_EXECUTE_BUILT_IN};
903 tMsg.strParam = command;
904 SendMessage(tMsg, wait);
907 void CApplicationMessenger::MediaPlay(string filename)
909 CFileItem item(filename, false);
913 void CApplicationMessenger::MediaPlay(const CFileItem &item)
916 list.Add(CFileItemPtr(new CFileItem(item)));
921 void CApplicationMessenger::MediaPlay(const CFileItemList &list, int song)
923 ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
924 CFileItemList* listcopy = new CFileItemList();
925 listcopy->Copy(list);
926 tMsg.lpVoid = (void*)listcopy;
927 tMsg.dwParam1 = song;
929 SendMessage(tMsg, true);
932 void CApplicationMessenger::MediaPlay(int playlistid, int song /* = -1 */)
934 ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
936 tMsg.dwParam1 = playlistid;
937 tMsg.dwParam2 = song;
938 SendMessage(tMsg, true);
941 void CApplicationMessenger::PlayFile(const CFileItem &item, bool bRestart /*= false*/)
943 ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
944 CFileItem *pItem = new CFileItem(item);
945 tMsg.lpVoid = (void *)pItem;
946 tMsg.dwParam1 = bRestart ? 1 : 0;
948 SendMessage(tMsg, false);
951 void CApplicationMessenger::MediaStop(bool bWait /* = true */, int playlistid /* = -1 */)
953 ThreadMessage tMsg = {TMSG_MEDIA_STOP};
954 tMsg.dwParam1 = playlistid;
955 SendMessage(tMsg, bWait);
958 void CApplicationMessenger::MediaPause()
960 ThreadMessage tMsg = {TMSG_MEDIA_PAUSE};
961 SendMessage(tMsg, true);
964 void CApplicationMessenger::MediaUnPause()
966 ThreadMessage tMsg = {TMSG_MEDIA_UNPAUSE};
967 SendMessage(tMsg, true);
970 void CApplicationMessenger::MediaPauseIfPlaying()
972 ThreadMessage tMsg = {TMSG_MEDIA_PAUSE_IF_PLAYING};
973 SendMessage(tMsg, true);
976 void CApplicationMessenger::MediaRestart(bool bWait)
978 ThreadMessage tMsg = {TMSG_MEDIA_RESTART};
979 SendMessage(tMsg, bWait);
982 void CApplicationMessenger::PlayListPlayerPlay()
984 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY, (unsigned int) -1};
985 SendMessage(tMsg, true);
988 void CApplicationMessenger::PlayListPlayerPlay(int iSong)
990 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY, (unsigned int)iSong};
991 SendMessage(tMsg, true);
994 bool CApplicationMessenger::PlayListPlayerPlaySongId(int songId)
997 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY_SONG_ID, (unsigned int)songId};
998 tMsg.lpVoid = (void *)&returnState;
999 SendMessage(tMsg, true);
1003 void CApplicationMessenger::PlayListPlayerNext()
1005 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_NEXT};
1006 SendMessage(tMsg, true);
1009 void CApplicationMessenger::PlayListPlayerPrevious()
1011 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PREV};
1012 SendMessage(tMsg, true);
1015 void CApplicationMessenger::PlayListPlayerAdd(int playlist, const CFileItem &item)
1018 list.Add(CFileItemPtr(new CFileItem(item)));
1020 PlayListPlayerAdd(playlist, list);
1023 void CApplicationMessenger::PlayListPlayerAdd(int playlist, const CFileItemList &list)
1025 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_ADD};
1026 CFileItemList* listcopy = new CFileItemList();
1027 listcopy->Copy(list);
1028 tMsg.lpVoid = (void*)listcopy;
1029 tMsg.dwParam1 = playlist;
1030 SendMessage(tMsg, true);
1033 void CApplicationMessenger::PlayListPlayerInsert(int playlist, const CFileItem &item, int index)
1036 list.Add(CFileItemPtr(new CFileItem(item)));
1037 PlayListPlayerInsert(playlist, list, index);
1040 void CApplicationMessenger::PlayListPlayerInsert(int playlist, const CFileItemList &list, int index)
1042 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_INSERT};
1043 CFileItemList* listcopy = new CFileItemList();
1044 listcopy->Copy(list);
1045 tMsg.lpVoid = (void *)listcopy;
1046 tMsg.dwParam1 = playlist;
1047 tMsg.dwParam2 = index;
1048 SendMessage(tMsg, true);
1051 void CApplicationMessenger::PlayListPlayerRemove(int playlist, int position)
1053 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_REMOVE, (unsigned int)playlist, (unsigned int)position};
1054 SendMessage(tMsg, true);
1057 void CApplicationMessenger::PlayListPlayerClear(int playlist)
1059 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_CLEAR};
1060 tMsg.dwParam1 = playlist;
1061 SendMessage(tMsg, true);
1064 void CApplicationMessenger::PlayListPlayerShuffle(int playlist, bool shuffle)
1066 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_SHUFFLE};
1067 tMsg.dwParam1 = playlist;
1068 tMsg.dwParam2 = shuffle ? 1 : 0;
1069 SendMessage(tMsg, true);
1072 void CApplicationMessenger::PlayListPlayerGetItems(int playlist, CFileItemList &list)
1074 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_GET_ITEMS};
1075 tMsg.dwParam1 = playlist;
1076 tMsg.lpVoid = (void *)&list;
1077 SendMessage(tMsg, true);
1080 void CApplicationMessenger::PlayListPlayerSwap(int playlist, int indexItem1, int indexItem2)
1082 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_SWAP};
1083 tMsg.dwParam1 = playlist;
1084 vector<int> *indexes = new vector<int>();
1085 indexes->push_back(indexItem1);
1086 indexes->push_back(indexItem2);
1087 tMsg.lpVoid = (void *)indexes;
1088 SendMessage(tMsg, true);
1091 void CApplicationMessenger::PlayListPlayerRepeat(int playlist, int repeatState)
1093 ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_REPEAT};
1094 tMsg.dwParam1 = playlist;
1095 tMsg.dwParam2 = repeatState;
1096 SendMessage(tMsg, true);
1099 void CApplicationMessenger::PictureShow(string filename)
1101 ThreadMessage tMsg = {TMSG_PICTURE_SHOW};
1102 tMsg.strParam = filename;
1106 void CApplicationMessenger::PictureSlideShow(string pathname, bool addTBN /* = false */)
1108 unsigned int dwMessage = TMSG_PICTURE_SLIDESHOW;
1109 ThreadMessage tMsg = {dwMessage};
1110 tMsg.strParam = pathname;
1111 tMsg.dwParam1 = addTBN ? 1 : 0;
1115 void CApplicationMessenger::SetGUILanguage(const std::string &strLanguage)
1117 ThreadMessage tMsg = {TMSG_SETLANGUAGE};
1118 tMsg.strParam = strLanguage;
1122 void CApplicationMessenger::Shutdown()
1124 ThreadMessage tMsg = {TMSG_SHUTDOWN};
1128 void CApplicationMessenger::Powerdown()
1130 ThreadMessage tMsg = {TMSG_POWERDOWN};
1134 void CApplicationMessenger::Quit()
1136 ThreadMessage tMsg = {TMSG_QUIT};
1140 void CApplicationMessenger::Hibernate()
1142 ThreadMessage tMsg = {TMSG_HIBERNATE};
1146 void CApplicationMessenger::Suspend()
1148 ThreadMessage tMsg = {TMSG_SUSPEND};
1152 void CApplicationMessenger::Restart()
1154 ThreadMessage tMsg = {TMSG_RESTART};
1158 void CApplicationMessenger::Reset()
1160 ThreadMessage tMsg = {TMSG_RESET};
1164 void CApplicationMessenger::RestartApp()
1166 ThreadMessage tMsg = {TMSG_RESTARTAPP};
1170 void CApplicationMessenger::InhibitIdleShutdown(bool inhibit)
1172 ThreadMessage tMsg = {TMSG_INHIBITIDLESHUTDOWN, (unsigned int)inhibit};
1176 void CApplicationMessenger::ActivateScreensaver()
1178 ThreadMessage tMsg = {TMSG_ACTIVATESCREENSAVER};
1182 void CApplicationMessenger::NetworkMessage(unsigned int dwMessage, unsigned int dwParam)
1184 ThreadMessage tMsg = {TMSG_NETWORKMESSAGE, dwMessage, dwParam};
1188 void CApplicationMessenger::SwitchToFullscreen()
1190 /* FIXME: ideally this call should return upon a successfull switch but currently
1191 is causing deadlocks between the dvdplayer destructor and the rendermanager
1193 ThreadMessage tMsg = {TMSG_SWITCHTOFULLSCREEN};
1194 SendMessage(tMsg, false);
1197 void CApplicationMessenger::Minimize(bool wait)
1199 ThreadMessage tMsg = {TMSG_MINIMIZE};
1200 SendMessage(tMsg, wait);
1203 void CApplicationMessenger::DoModal(CGUIDialog *pDialog, int iWindowID, const CStdString ¶m)
1205 ThreadMessage tMsg = {TMSG_GUI_DO_MODAL};
1206 tMsg.lpVoid = pDialog;
1207 tMsg.dwParam1 = (unsigned int)iWindowID;
1208 tMsg.strParam = param;
1209 SendMessage(tMsg, true);
1212 void CApplicationMessenger::ExecOS(const CStdString &command, bool waitExit)
1214 ThreadMessage tMsg = {TMSG_EXECUTE_OS};
1215 tMsg.strParam = command;
1216 tMsg.dwParam1 = (unsigned int)waitExit;
1217 SendMessage(tMsg, false);
1220 void CApplicationMessenger::UserEvent(int code)
1222 ThreadMessage tMsg = {(unsigned int)code};
1223 SendMessage(tMsg, false);
1226 void CApplicationMessenger::Show(CGUIDialog *pDialog)
1228 ThreadMessage tMsg = {TMSG_GUI_SHOW};
1229 tMsg.lpVoid = pDialog;
1230 SendMessage(tMsg, true);
1233 void CApplicationMessenger::Close(CGUIWindow *window, bool forceClose, bool waitResult /*= true*/, int nextWindowID /*= 0*/, bool enableSound /*= true*/)
1235 ThreadMessage tMsg = {TMSG_GUI_WINDOW_CLOSE, (unsigned int)nextWindowID};
1236 tMsg.dwParam2 = (unsigned int)((forceClose ? 0x01 : 0) | (enableSound ? 0x02 : 0));
1237 tMsg.lpVoid = window;
1238 SendMessage(tMsg, waitResult);
1241 void CApplicationMessenger::ActivateWindow(int windowID, const vector<CStdString> ¶ms, bool swappingWindows)
1243 ThreadMessage tMsg = {TMSG_GUI_ACTIVATE_WINDOW, (unsigned int)windowID, swappingWindows ? 1u : 0u};
1244 tMsg.params = params;
1245 SendMessage(tMsg, true);
1248 void CApplicationMessenger::SendAction(const CAction &action, int windowID, bool waitResult)
1250 ThreadMessage tMsg = {TMSG_GUI_ACTION};
1251 tMsg.dwParam1 = windowID;
1252 tMsg.lpVoid = new CAction(action);
1253 SendMessage(tMsg, waitResult);
1256 void CApplicationMessenger::SendGUIMessage(const CGUIMessage &message, int windowID, bool waitResult)
1258 ThreadMessage tMsg = {TMSG_GUI_MESSAGE};
1259 tMsg.dwParam1 = windowID == WINDOW_INVALID ? 0 : windowID;
1260 tMsg.lpVoid = new CGUIMessage(message);
1261 SendMessage(tMsg, waitResult);
1264 vector<CStdString> CApplicationMessenger::GetInfoLabels(const vector<CStdString> &properties)
1266 vector<CStdString> infoLabels;
1268 ThreadMessage tMsg = {TMSG_GUI_INFOLABEL};
1269 tMsg.params = properties;
1270 tMsg.lpVoid = (void*)&infoLabels;
1271 SendMessage(tMsg, true);
1275 vector<bool> CApplicationMessenger::GetInfoBooleans(const vector<CStdString> &properties)
1277 vector<bool> infoLabels;
1279 ThreadMessage tMsg = {TMSG_GUI_INFOBOOL};
1280 tMsg.params = properties;
1281 tMsg.lpVoid = (void*)&infoLabels;
1282 SendMessage(tMsg, true);
1286 void CApplicationMessenger::ShowVolumeBar(bool up)
1288 ThreadMessage tMsg = {TMSG_VOLUME_SHOW};
1289 tMsg.dwParam1 = up ? ACTION_VOLUME_UP : ACTION_VOLUME_DOWN;
1290 SendMessage(tMsg, false);
1293 void CApplicationMessenger::SetSplashMessage(const CStdString& message)
1295 ThreadMessage tMsg = {TMSG_SPLASH_MESSAGE};
1296 tMsg.strParam = message;
1297 SendMessage(tMsg, true);
1300 void CApplicationMessenger::SetSplashMessage(int stringID)
1302 SetSplashMessage(g_localizeStrings.Get(stringID));
1305 bool CApplicationMessenger::SetupDisplay()
1309 ThreadMessage tMsg = {TMSG_DISPLAY_SETUP};
1310 tMsg.lpVoid = (void*)&result;
1311 SendMessage(tMsg, true);
1316 bool CApplicationMessenger::DestroyDisplay()
1320 ThreadMessage tMsg = {TMSG_DISPLAY_DESTROY};
1321 tMsg.lpVoid = (void*)&result;
1322 SendMessage(tMsg, true);
1327 void CApplicationMessenger::SetCurrentSongTag(const CMusicInfoTag& tag)
1329 CFileItem* item = new CFileItem(tag);
1330 ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1332 tMsg.lpVoid = (void*)item;
1333 SendMessage(tMsg, false);
1336 void CApplicationMessenger::SetCurrentVideoTag(const CVideoInfoTag& tag)
1338 CFileItem* item = new CFileItem(tag);
1339 ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1341 tMsg.lpVoid = (void*)item;
1342 SendMessage(tMsg, false);
1345 void CApplicationMessenger::SetCurrentItem(const CFileItem& item)
1347 CFileItem* item2 = new CFileItem(item);
1348 ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1349 tMsg.lpVoid = (void*)item2;
1350 SendMessage(tMsg, false);
1353 void CApplicationMessenger::LoadProfile(unsigned int idx)
1355 ThreadMessage tMsg = {TMSG_LOADPROFILE};
1356 tMsg.dwParam1 = idx;
1357 SendMessage(tMsg, false);
1360 void CApplicationMessenger::StartAndroidActivity(const vector<CStdString> ¶ms)
1362 ThreadMessage tMsg = {TMSG_START_ANDROID_ACTIVITY};
1363 tMsg.params = params;
1364 SendMessage(tMsg, false);
1367 bool CApplicationMessenger::CECToggleState()
1371 ThreadMessage tMsg = {TMSG_CECTOGGLESTATE};
1372 tMsg.lpVoid = (void*)&result;
1373 SendMessage(tMsg, false);
1378 bool CApplicationMessenger::CECActivateSource()
1382 ThreadMessage tMsg = {TMSG_CECACTIVATESOURCE};
1383 tMsg.lpVoid = (void*)&result;
1384 SendMessage(tMsg, false);
1389 bool CApplicationMessenger::CECStandby()
1393 ThreadMessage tMsg = {TMSG_CECSTANDBY};
1394 tMsg.lpVoid = (void*)&result;
1395 SendMessage(tMsg, false);