[droid] Do not show any ui if pre-checks are OK
[vuplus_xbmc] / xbmc / ApplicationMessenger.cpp
1 /*
2  *      Copyright (C) 2005-2012 Team XBMC
3  *      http://www.xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 #include "system.h"
22 #include "ApplicationMessenger.h"
23 #include "Application.h"
24
25 #include "PlayListPlayer.h"
26 #include "Util.h"
27 #ifdef HAS_PYTHON
28 #include "interfaces/python/XBPython.h"
29 #endif
30 #include "pictures/GUIWindowSlideShow.h"
31 #include "interfaces/Builtins.h"
32 #include "network/Network.h"
33 #include "utils/log.h"
34 #include "utils/URIUtils.h"
35 #include "utils/Variant.h"
36 #include "guilib/GUIWindowManager.h"
37 #include "settings/Settings.h"
38 #include "settings/GUISettings.h"
39 #include "FileItem.h"
40 #include "guilib/GUIDialog.h"
41 #include "GUIInfoManager.h"
42 #include "utils/Splash.h"
43 #include "cores/VideoRenderers/RenderManager.h"
44 #include "cores/AudioEngine/AEFactory.h"
45 #include "music/tags/MusicInfoTag.h"
46
47 #include "powermanagement/PowerManager.h"
48
49 #ifdef _WIN32
50 #include "WIN32Util.h"
51 #define CHalManager CWIN32Util
52 #elif defined(TARGET_DARWIN)
53 #include "osx/CocoaInterface.h"
54 #endif
55 #include "addons/AddonCallbacks.h"
56 #include "addons/AddonCallbacksGUI.h"
57 #include "storage/MediaManager.h"
58 #include "guilib/LocalizeStrings.h"
59 #include "threads/SingleLock.h"
60
61 #include "playlists/PlayList.h"
62 #include "FileItem.h"
63
64 #include "pvr/PVRManager.h"
65 #include "windows/GUIWindowLoginScreen.h"
66
67 using namespace PVR;
68 using namespace std;
69 using namespace MUSIC_INFO;
70
71 CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) : CThread("CDelayedMessage")
72 {
73   m_msg.dwMessage  = msg.dwMessage;
74   m_msg.dwParam1   = msg.dwParam1;
75   m_msg.dwParam2   = msg.dwParam2;
76   m_msg.waitEvent  = msg.waitEvent;
77   m_msg.lpVoid     = msg.lpVoid;
78   m_msg.strParam   = msg.strParam;
79   m_msg.params     = msg.params;
80
81   m_delay = delay;
82 }
83
84 void CDelayedMessage::Process()
85 {
86   Sleep(m_delay);
87
88   if (!m_bStop)
89     CApplicationMessenger::Get().SendMessage(m_msg, false);
90 }
91
92 CApplicationMessenger& CApplicationMessenger::Get()
93 {
94   static CApplicationMessenger s_messenger;
95   return s_messenger;
96 }
97
98 CApplicationMessenger::CApplicationMessenger()
99 {
100 }
101
102 CApplicationMessenger::~CApplicationMessenger()
103 {
104   Cleanup();
105 }
106
107 void CApplicationMessenger::Cleanup()
108 {
109   CSingleLock lock (m_critSection);
110
111   while (m_vecMessages.size() > 0)
112   {
113     ThreadMessage* pMsg = m_vecMessages.front();
114
115     if (pMsg->waitEvent)
116       pMsg->waitEvent->Set();
117
118     delete pMsg;
119     m_vecMessages.pop();
120   }
121
122   while (m_vecWindowMessages.size() > 0)
123   {
124     ThreadMessage* pMsg = m_vecWindowMessages.front();
125
126     if (pMsg->waitEvent)
127       pMsg->waitEvent->Set();
128
129     delete pMsg;
130     m_vecWindowMessages.pop();
131   }
132 }
133
134 void CApplicationMessenger::SendMessage(ThreadMessage& message, bool wait)
135 {
136   message.waitEvent.reset();
137   boost::shared_ptr<CEvent> waitEvent;
138   if (wait)
139   { // check that we're not being called from our application thread, else we'll be waiting
140     // forever!
141     if (!g_application.IsCurrentThread())
142     {
143       message.waitEvent.reset(new CEvent(true));
144       waitEvent = message.waitEvent;
145     }
146     else
147     {
148       //OutputDebugString("Attempting to wait on a SendMessage() from our application thread will cause lockup!\n");
149       //OutputDebugString("Sending immediately\n");
150       ProcessMessage(&message);
151       return;
152     }
153   }
154
155   CSingleLock lock (m_critSection);
156
157   if (g_application.m_bStop)
158   {
159     if (message.waitEvent)
160       message.waitEvent.reset();
161     return;
162   }
163
164   ThreadMessage* msg = new ThreadMessage();
165   msg->dwMessage = message.dwMessage;
166   msg->dwParam1 = message.dwParam1;
167   msg->dwParam2 = message.dwParam2;
168   msg->waitEvent = message.waitEvent;
169   msg->lpVoid = message.lpVoid;
170   msg->strParam = message.strParam;
171   msg->params = message.params;
172
173   if (msg->dwMessage == TMSG_DIALOG_DOMODAL)
174     m_vecWindowMessages.push(msg);
175   else
176     m_vecMessages.push(msg);
177   lock.Leave();  // this releases the lock on the vec of messages and
178                  //   allows the ProcessMessage to execute and therefore
179                  //   delete the message itself. Therefore any accesss
180                  //   of the message itself after this point consittutes
181                  //   a race condition (yarc - "yet another race condition")
182                  //
183   if (waitEvent) // ... it just so happens we have a spare reference to the
184                  //  waitEvent ... just for such contingencies :)
185   { 
186     // ensure the thread doesn't hold the graphics lock
187     CSingleExit exit(g_graphicsContext);
188     waitEvent->Wait();
189   }
190 }
191
192 void CApplicationMessenger::ProcessMessages()
193 {
194   // process threadmessages
195   CSingleLock lock (m_critSection);
196   while (m_vecMessages.size() > 0)
197   {
198     ThreadMessage* pMsg = m_vecMessages.front();
199     //first remove the message from the queue, else the message could be processed more then once
200     m_vecMessages.pop();
201
202     //Leave here as the message might make another
203     //thread call processmessages or sendmessage
204
205     boost::shared_ptr<CEvent> waitEvent = pMsg->waitEvent; 
206     lock.Leave(); // <- see the large comment in SendMessage ^
207
208     ProcessMessage(pMsg);
209     if (waitEvent)
210       waitEvent->Set();
211     delete pMsg;
212
213     lock.Enter();
214   }
215 }
216
217 void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
218 {
219   switch (pMsg->dwMessage)
220   {
221     case TMSG_SHUTDOWN:
222       {
223         switch (g_guiSettings.GetInt("powermanagement.shutdownstate"))
224         {
225           case POWERSTATE_SHUTDOWN:
226             Powerdown();
227             break;
228
229           case POWERSTATE_SUSPEND:
230             Suspend();
231             break;
232
233           case POWERSTATE_HIBERNATE:
234             Hibernate();
235             break;
236
237           case POWERSTATE_QUIT:
238             Quit();
239             break;
240
241           case POWERSTATE_MINIMIZE:
242             Minimize();
243             break;
244
245           case TMSG_RENDERER_FLUSH:
246             g_renderManager.Flush();
247             break;
248         }
249       }
250       break;
251
252     case TMSG_POWERDOWN:
253       {
254         g_application.Stop(EXITCODE_POWERDOWN);
255         g_powerManager.Powerdown();
256       }
257       break;
258
259     case TMSG_QUIT:
260       {
261         g_application.Stop(EXITCODE_QUIT);
262       }
263       break;
264
265     case TMSG_HIBERNATE:
266       {
267         g_PVRManager.SetWakeupCommand();
268         g_powerManager.Hibernate();
269       }
270       break;
271
272     case TMSG_SUSPEND:
273       {
274         g_PVRManager.SetWakeupCommand();
275         g_powerManager.Suspend();
276       }
277       break;
278
279     case TMSG_RESTART:
280     case TMSG_RESET:
281       {
282         g_application.Stop(EXITCODE_REBOOT);
283         g_powerManager.Reboot();
284       }
285       break;
286
287     case TMSG_RESTARTAPP:
288       {
289 #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX)
290         g_application.Stop(EXITCODE_RESTARTAPP);
291 #endif
292       }
293       break;
294
295     case TMSG_INHIBITIDLESHUTDOWN:
296       {
297         g_application.InhibitIdleShutdown(pMsg->dwParam1 != 0);
298       }
299       break;
300
301     case TMSG_MEDIA_PLAY:
302       {
303         // first check if we were called from the PlayFile() function
304         if (pMsg->lpVoid && pMsg->dwParam2 == 0)
305         {
306           CFileItem *item = (CFileItem *)pMsg->lpVoid;
307           g_application.PlayFile(*item, pMsg->dwParam1 != 0);
308           delete item;
309           return;
310         }
311         // restore to previous window if needed
312         if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW ||
313             g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
314             g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
315           g_windowManager.PreviousWindow();
316
317         g_application.ResetScreenSaver();
318         g_application.WakeUpScreenSaverAndDPMS();
319
320         //g_application.StopPlaying();
321         // play file
322         if(pMsg->lpVoid)
323         {
324           CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
325
326           if (list->Size() > 0)
327           {
328             int playlist = PLAYLIST_MUSIC;
329             for (int i = 0; i < list->Size(); i++)
330             {
331               if ((*list)[i]->IsVideo())
332               {
333                 playlist = PLAYLIST_VIDEO;
334                 break;
335               }
336             }
337
338             g_playlistPlayer.ClearPlaylist(playlist);
339             g_playlistPlayer.SetCurrentPlaylist(playlist);
340             //For single item lists try PlayMedia. This covers some more cases where a playlist is not appropriate
341             //It will fall through to PlayFile
342             if (list->Size() == 1 && !(*list)[0]->IsPlayList())
343               g_application.PlayMedia(*((*list)[0]), playlist);
344             else
345             {
346               // Handle "shuffled" option if present
347               if (list->HasProperty("shuffled") && list->GetProperty("shuffled").isBoolean())
348                 g_playlistPlayer.SetShuffle(playlist, list->GetProperty("shuffled").asBoolean(), false);
349               // Handle "repeat" option if present
350               if (list->HasProperty("repeat") && list->GetProperty("repeat").isInteger())
351                 g_playlistPlayer.SetRepeat(playlist, (PLAYLIST::REPEAT_STATE)list->GetProperty("repeat").asInteger(), false);
352
353               g_playlistPlayer.Add(playlist, (*list));
354               g_playlistPlayer.Play(pMsg->dwParam1);
355             }
356           }
357
358           delete list;
359         }
360         else if (pMsg->dwParam1 == PLAYLIST_MUSIC || pMsg->dwParam1 == PLAYLIST_VIDEO)
361         {
362           if (g_playlistPlayer.GetCurrentPlaylist() != (int)pMsg->dwParam1)
363             g_playlistPlayer.SetCurrentPlaylist(pMsg->dwParam1);
364
365           PlayListPlayerPlay(pMsg->dwParam2);
366         }
367       }
368       break;
369
370     case TMSG_MEDIA_RESTART:
371       g_application.Restart(true);
372       break;
373
374     case TMSG_PICTURE_SHOW:
375       {
376         CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
377         if (!pSlideShow) return ;
378
379         // stop playing file
380         if (g_application.IsPlayingVideo()) g_application.StopPlaying();
381
382         if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
383           g_windowManager.PreviousWindow();
384
385         g_application.ResetScreenSaver();
386         g_application.WakeUpScreenSaverAndDPMS();
387
388         g_graphicsContext.Lock();
389
390         if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW)
391           g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
392         if (URIUtils::IsZIP(pMsg->strParam) || URIUtils::IsRAR(pMsg->strParam)) // actually a cbz/cbr
393         {
394           CFileItemList items;
395           CStdString strPath;
396           if (URIUtils::IsZIP(pMsg->strParam))
397             URIUtils::CreateArchivePath(strPath, "zip", pMsg->strParam.c_str(), "");
398           else
399             URIUtils::CreateArchivePath(strPath, "rar", pMsg->strParam.c_str(), "");
400
401           CUtil::GetRecursiveListing(strPath, items, g_settings.m_pictureExtensions);
402           if (items.Size() > 0)
403           {
404             pSlideShow->Reset();
405             for (int i=0;i<items.Size();++i)
406             {
407               pSlideShow->Add(items[i].get());
408             }
409             pSlideShow->Select(items[0]->GetPath());
410           }
411         }
412         else
413         {
414           CFileItem item(pMsg->strParam, false);
415           pSlideShow->Reset();
416           pSlideShow->Add(&item);
417           pSlideShow->Select(pMsg->strParam);
418         }
419         g_graphicsContext.Unlock();
420       }
421       break;
422
423     case TMSG_PICTURE_SLIDESHOW:
424       {
425         CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
426         if (!pSlideShow) return ;
427
428         if (g_application.IsPlayingVideo())
429           g_application.StopPlaying();
430
431         g_graphicsContext.Lock();
432         pSlideShow->Reset();
433
434         CFileItemList items;
435         CStdString strPath = pMsg->strParam;
436         CStdString extensions = g_settings.m_pictureExtensions;
437         if (pMsg->dwParam1)
438           extensions += "|.tbn";
439         CUtil::GetRecursiveListing(strPath, items, extensions);
440
441         if (items.Size() > 0)
442         {
443           for (int i=0;i<items.Size();++i)
444             pSlideShow->Add(items[i].get());
445           pSlideShow->StartSlideShow(); //Start the slideshow!
446         }
447
448         if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW)
449         {
450           if(items.Size() == 0)
451           {
452             g_guiSettings.SetString("screensaver.mode", "screensaver.xbmc.builtin.dim");
453             g_application.ActivateScreenSaver();
454           }
455           else
456             g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
457         }
458
459         g_graphicsContext.Unlock();
460       }
461       break;
462
463     case TMSG_SETLANGUAGE:
464       g_guiSettings.SetLanguage(pMsg->strParam);
465       break;
466     case TMSG_MEDIA_STOP:
467       {
468         // restore to previous window if needed
469         if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW ||
470             g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
471             g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
472           g_windowManager.PreviousWindow();
473
474         g_application.ResetScreenSaver();
475         g_application.WakeUpScreenSaverAndDPMS();
476
477         // stop playing file
478         if (g_application.IsPlaying()) g_application.StopPlaying();
479       }
480       break;
481
482     case TMSG_MEDIA_PAUSE:
483       if (g_application.m_pPlayer)
484       {
485         g_application.ResetScreenSaver();
486         g_application.WakeUpScreenSaverAndDPMS();
487         g_application.m_pPlayer->Pause();
488       }
489       break;
490
491     case TMSG_MEDIA_UNPAUSE:
492       if (g_application.IsPaused())
493       {
494         g_application.ResetScreenSaver();
495         g_application.WakeUpScreenSaverAndDPMS();
496         g_application.m_pPlayer->Pause();
497       }
498       break;
499
500     case TMSG_SWITCHTOFULLSCREEN:
501       if( g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
502         g_application.SwitchToFullScreen();
503       break;
504
505     case TMSG_TOGGLEFULLSCREEN:
506       g_graphicsContext.Lock();
507       g_graphicsContext.ToggleFullScreenRoot();
508       g_graphicsContext.Unlock();
509       break;
510
511     case TMSG_MINIMIZE:
512       g_application.Minimize();
513       break;
514
515     case TMSG_EXECUTE_OS:
516       /* Suspend AE temporarily so exclusive or hog-mode sinks */
517       /* don't block external player's access to audio device  */
518       if (!CAEFactory::Suspend())
519       {
520         CLog::Log(LOGNOTICE, "%s: Failed to suspend AudioEngine before launching external program",__FUNCTION__);
521       }
522 #if defined( _LINUX) && !defined(TARGET_DARWIN)
523       CUtil::RunCommandLine(pMsg->strParam.c_str(), (pMsg->dwParam1 == 1));
524 #elif defined(_WIN32)
525       CWIN32Util::XBMCShellExecute(pMsg->strParam.c_str(), (pMsg->dwParam1 == 1));
526 #endif
527       /* Resume AE processing of XBMC native audio */
528       if (!CAEFactory::Resume())
529       {
530         CLog::Log(LOGFATAL, "%s: Failed to restart AudioEngine after return from external player",__FUNCTION__);
531       }
532       break;
533
534     case TMSG_EXECUTE_SCRIPT:
535 #ifdef HAS_PYTHON
536       g_pythonParser.evalFile(pMsg->strParam.c_str(),ADDON::AddonPtr());
537 #endif
538       break;
539
540     case TMSG_EXECUTE_BUILT_IN:
541       CBuiltins::Execute(pMsg->strParam.c_str());
542       break;
543
544     case TMSG_PLAYLISTPLAYER_PLAY:
545       if (pMsg->dwParam1 != (DWORD) -1)
546         g_playlistPlayer.Play(pMsg->dwParam1);
547       else
548         g_playlistPlayer.Play();
549       break;
550
551     case TMSG_PLAYLISTPLAYER_PLAY_SONG_ID:
552       if (pMsg->dwParam1 != (DWORD) -1)
553       {
554         bool *result = (bool*)pMsg->lpVoid;
555         *result = g_playlistPlayer.PlaySongId(pMsg->dwParam1);
556       }
557       else
558         g_playlistPlayer.Play();
559       break;
560
561     case TMSG_PLAYLISTPLAYER_NEXT:
562       g_playlistPlayer.PlayNext();
563       break;
564
565     case TMSG_PLAYLISTPLAYER_PREV:
566       g_playlistPlayer.PlayPrevious();
567       break;
568
569     case TMSG_PLAYLISTPLAYER_ADD:
570       if(pMsg->lpVoid)
571       {
572         CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
573
574         g_playlistPlayer.Add(pMsg->dwParam1, (*list));
575         delete list;
576       }
577       break;
578
579     case TMSG_PLAYLISTPLAYER_INSERT:
580       if (pMsg->lpVoid)
581       {
582         CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
583         g_playlistPlayer.Insert(pMsg->dwParam1, (*list), pMsg->dwParam2);
584         delete list;
585       }
586       break;
587
588     case TMSG_PLAYLISTPLAYER_REMOVE:
589       if (pMsg->dwParam1 != (DWORD) -1)
590         g_playlistPlayer.Remove(pMsg->dwParam1,pMsg->dwParam2);
591       break;
592
593     case TMSG_PLAYLISTPLAYER_CLEAR:
594       g_playlistPlayer.ClearPlaylist(pMsg->dwParam1);
595       break;
596
597     case TMSG_PLAYLISTPLAYER_SHUFFLE:
598       g_playlistPlayer.SetShuffle(pMsg->dwParam1, pMsg->dwParam2 > 0);
599       break;
600
601     case TMSG_PLAYLISTPLAYER_REPEAT:
602       g_playlistPlayer.SetRepeat(pMsg->dwParam1, (PLAYLIST::REPEAT_STATE)pMsg->dwParam2);
603       break;
604
605     case TMSG_PLAYLISTPLAYER_GET_ITEMS:
606       if (pMsg->lpVoid)
607       {
608         PLAYLIST::CPlayList playlist = g_playlistPlayer.GetPlaylist(pMsg->dwParam1);
609         CFileItemList *list = (CFileItemList *)pMsg->lpVoid;
610
611         for (int i = 0; i < playlist.size(); i++)
612           list->Add(CFileItemPtr(new CFileItem(*playlist[i])));
613       }
614       break;
615
616     case TMSG_PLAYLISTPLAYER_SWAP:
617       if (pMsg->lpVoid)
618       {
619         vector<int> *indexes = (vector<int> *)pMsg->lpVoid;
620         if (indexes->size() == 2)
621           g_playlistPlayer.Swap(pMsg->dwParam1, indexes->at(0), indexes->at(1));
622         delete indexes;
623       }
624       break;
625
626     // Window messages below here...
627     case TMSG_DIALOG_DOMODAL:  //doModel of window
628       {
629         CGUIDialog* pDialog = (CGUIDialog*)g_windowManager.GetWindow(pMsg->dwParam1);
630         if (!pDialog) return ;
631         pDialog->DoModal();
632       }
633       break;
634
635     case TMSG_NETWORKMESSAGE:
636       {
637         g_application.getNetwork().NetworkMessage((CNetwork::EMESSAGE)pMsg->dwParam1, (int)pMsg->dwParam2);
638       }
639       break;
640
641     case TMSG_GUI_DO_MODAL:
642       {
643         CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid;
644         if (pDialog)
645           pDialog->DoModal((int)pMsg->dwParam1, pMsg->strParam);
646       }
647       break;
648
649     case TMSG_GUI_SHOW:
650       {
651         CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid;
652         if (pDialog)
653           pDialog->Show();
654       }
655       break;
656
657     case TMSG_GUI_WINDOW_CLOSE:
658       {
659         CGUIWindow *window = (CGUIWindow *)pMsg->lpVoid;
660         if (window)
661           window->Close(pMsg->dwParam2 & 0x1 ? true : false, pMsg->dwParam1, pMsg->dwParam2 & 0x2 ? true : false);
662       }
663       break;
664
665     case TMSG_GUI_ACTIVATE_WINDOW:
666       {
667         g_windowManager.ActivateWindow(pMsg->dwParam1, pMsg->params, pMsg->dwParam2 > 0);
668       }
669       break;
670
671     case TMSG_GUI_ADDON_DIALOG:
672       {
673         if (pMsg->lpVoid)
674         { // TODO: This is ugly - really these python dialogs should just be normal XBMC dialogs
675           ((ADDON::CGUIAddonWindowDialog *) pMsg->lpVoid)->Show_Internal(pMsg->dwParam2 > 0);
676         }
677       }
678       break;
679
680     case TMSG_GUI_PYTHON_DIALOG:
681       {
682         // This hack is not much better but at least I don't need to make ApplicationMessenger
683         //  know about Addon (Python) specific classes.
684         CAction caction(pMsg->dwParam1);
685         ((CGUIWindow*)pMsg->lpVoid)->OnAction(caction);
686       }
687       break;
688
689     case TMSG_GUI_ACTION:
690       {
691         if (pMsg->lpVoid)
692         {
693           CAction *action = (CAction *)pMsg->lpVoid;
694           if (pMsg->dwParam1 == WINDOW_INVALID)
695             g_application.OnAction(*action);
696           else
697           {
698             CGUIWindow *pWindow = g_windowManager.GetWindow(pMsg->dwParam1);  
699             if (pWindow)
700               pWindow->OnAction(*action);
701             else
702               CLog::Log(LOGWARNING, "Failed to get window with ID %i to send an action to", pMsg->dwParam1);
703           }
704           delete action;
705         }
706       }
707       break;
708
709     case TMSG_GUI_MESSAGE:
710       {
711         if (pMsg->lpVoid)
712         {
713           CGUIMessage *message = (CGUIMessage *)pMsg->lpVoid;
714           g_windowManager.SendMessage(*message, pMsg->dwParam1);
715           delete message;
716         }
717       }
718       break;
719
720     case TMSG_GUI_INFOLABEL:
721       {
722         if (pMsg->lpVoid)
723         {
724           vector<CStdString> *infoLabels = (vector<CStdString> *)pMsg->lpVoid;
725           for (unsigned int i = 0; i < pMsg->params.size(); i++)
726             infoLabels->push_back(g_infoManager.GetLabel(g_infoManager.TranslateString(pMsg->params[i])));
727         }
728       }
729       break;
730     case TMSG_GUI_INFOBOOL:
731       {
732         if (pMsg->lpVoid)
733         {
734           vector<bool> *infoLabels = (vector<bool> *)pMsg->lpVoid;
735           for (unsigned int i = 0; i < pMsg->params.size(); i++)
736             infoLabels->push_back(g_infoManager.EvaluateBool(pMsg->params[i]));
737         }
738       }
739       break;
740
741     case TMSG_CALLBACK:
742       {
743         ThreadMessageCallback *callback = (ThreadMessageCallback*)pMsg->lpVoid;
744         callback->callback(callback->userptr);
745       }
746       break;
747
748     case TMSG_VOLUME_SHOW:
749       {
750         CAction action((int)pMsg->dwParam1);
751         g_application.ShowVolumeBar(&action);
752       }
753       break;
754
755     case TMSG_SPLASH_MESSAGE:
756       {
757         if (g_application.GetSplash())
758           g_application.GetSplash()->Show(pMsg->strParam);
759       }
760       break;
761       
762     case TMSG_DISPLAY_SETUP:
763     {
764       *((bool*)pMsg->lpVoid) = g_application.InitWindow();
765       g_application.SetRenderGUI(true);
766     }
767     break;
768     
769     case TMSG_DISPLAY_DESTROY:
770     {
771       *((bool*)pMsg->lpVoid) = g_application.DestroyWindow();
772       g_application.SetRenderGUI(false);
773     }
774     break;
775
776     case TMSG_UPDATE_CURRENT_ITEM:
777     {
778       CFileItem* item = (CFileItem*)pMsg->lpVoid;
779       if (!item)
780         return;
781       if (pMsg->dwParam1 == 1 && item->HasMusicInfoTag()) // only grab music tag
782         g_infoManager.SetCurrentSongTag(*item->GetMusicInfoTag());
783       else if (pMsg->dwParam1 == 2 && item->HasVideoInfoTag()) // only grab video tag
784         g_infoManager.SetCurrentVideoTag(*item->GetVideoInfoTag());
785       else
786         g_infoManager.SetCurrentItem(*item);
787       delete item;
788       break;
789     }
790
791     case TMSG_LOADPROFILE:
792     {
793       CGUIWindowLoginScreen::LoadProfile(pMsg->dwParam1);
794       break;
795     }
796   }
797 }
798
799 void CApplicationMessenger::ProcessWindowMessages()
800 {
801   CSingleLock lock (m_critSection);
802   //message type is window, process window messages
803   while (m_vecWindowMessages.size() > 0)
804   {
805     ThreadMessage* pMsg = m_vecWindowMessages.front();
806     //first remove the message from the queue, else the message could be processed more then once
807     m_vecWindowMessages.pop();
808
809     // leave here in case we make more thread messages from this one
810
811     boost::shared_ptr<CEvent> waitEvent = pMsg->waitEvent;
812     lock.Leave(); // <- see the large comment in SendMessage ^
813
814     ProcessMessage(pMsg);
815     if (waitEvent)
816       waitEvent->Set();
817     delete pMsg;
818
819     lock.Enter();
820   }
821 }
822
823 int CApplicationMessenger::SetResponse(CStdString response)
824 {
825   CSingleLock lock (m_critBuffer);
826   bufferResponse=response;
827   lock.Leave();
828   return 0;
829 }
830
831 CStdString CApplicationMessenger::GetResponse()
832 {
833   CStdString tmp;
834   CSingleLock lock (m_critBuffer);
835   tmp=bufferResponse;
836   lock.Leave();
837   return tmp;
838 }
839
840 void CApplicationMessenger::ExecBuiltIn(const CStdString &command, bool wait)
841 {
842   ThreadMessage tMsg = {TMSG_EXECUTE_BUILT_IN};
843   tMsg.strParam = command;
844   SendMessage(tMsg, wait);
845 }
846
847 void CApplicationMessenger::MediaPlay(string filename)
848 {
849   CFileItem item(filename, false);
850   MediaPlay(item);
851 }
852
853 void CApplicationMessenger::MediaPlay(const CFileItem &item)
854 {
855   CFileItemList list;
856   list.Add(CFileItemPtr(new CFileItem(item)));
857
858   MediaPlay(list);
859 }
860
861 void CApplicationMessenger::MediaPlay(const CFileItemList &list, int song)
862 {
863   ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
864   CFileItemList* listcopy = new CFileItemList();
865   listcopy->Copy(list);
866   tMsg.lpVoid = (void*)listcopy;
867   tMsg.dwParam1 = song;
868   tMsg.dwParam2 = 1;
869   SendMessage(tMsg, true);
870 }
871
872 void CApplicationMessenger::MediaPlay(int playlistid, int song /* = -1 */)
873 {
874   ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
875   tMsg.lpVoid = NULL;
876   tMsg.dwParam1 = playlistid;
877   tMsg.dwParam2 = song;
878   SendMessage(tMsg, true);
879 }
880
881 void CApplicationMessenger::PlayFile(const CFileItem &item, bool bRestart /*= false*/)
882 {
883   ThreadMessage tMsg = {TMSG_MEDIA_PLAY};
884   CFileItem *pItem = new CFileItem(item);
885   tMsg.lpVoid = (void *)pItem;
886   tMsg.dwParam1 = bRestart ? 1 : 0;
887   tMsg.dwParam2 = 0;
888   SendMessage(tMsg, false);
889 }
890
891 void CApplicationMessenger::MediaStop(bool bWait /* = true */)
892 {
893   ThreadMessage tMsg = {TMSG_MEDIA_STOP};
894   SendMessage(tMsg, bWait);
895 }
896
897 void CApplicationMessenger::MediaPause()
898 {
899   ThreadMessage tMsg = {TMSG_MEDIA_PAUSE};
900   SendMessage(tMsg, true);
901 }
902
903 void CApplicationMessenger::MediaRestart(bool bWait)
904 {
905   ThreadMessage tMsg = {TMSG_MEDIA_RESTART};
906   SendMessage(tMsg, bWait);
907 }
908
909 void CApplicationMessenger::PlayListPlayerPlay()
910 {
911   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY, (DWORD) -1};
912   SendMessage(tMsg, true);
913 }
914
915 void CApplicationMessenger::PlayListPlayerPlay(int iSong)
916 {
917   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY, (DWORD)iSong};
918   SendMessage(tMsg, true);
919 }
920
921 bool CApplicationMessenger::PlayListPlayerPlaySongId(int songId)
922 {
923   bool returnState;
924   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY_SONG_ID, (DWORD)songId};
925   tMsg.lpVoid = (void *)&returnState;
926   SendMessage(tMsg, true);
927   return returnState;
928 }
929
930 void CApplicationMessenger::PlayListPlayerNext()
931 {
932   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_NEXT};
933   SendMessage(tMsg, true);
934 }
935
936 void CApplicationMessenger::PlayListPlayerPrevious()
937 {
938   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PREV};
939   SendMessage(tMsg, true);
940 }
941
942 void CApplicationMessenger::PlayListPlayerAdd(int playlist, const CFileItem &item)
943 {
944   CFileItemList list;
945   list.Add(CFileItemPtr(new CFileItem(item)));
946
947   PlayListPlayerAdd(playlist, list);
948 }
949
950 void CApplicationMessenger::PlayListPlayerAdd(int playlist, const CFileItemList &list)
951 {
952   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_ADD};
953   CFileItemList* listcopy = new CFileItemList();
954   listcopy->Copy(list);
955   tMsg.lpVoid = (void*)listcopy;
956   tMsg.dwParam1 = playlist;
957   SendMessage(tMsg, true);
958 }
959
960 void CApplicationMessenger::PlayListPlayerInsert(int playlist, const CFileItem &item, int index)
961 {
962   CFileItemList list;
963   list.Add(CFileItemPtr(new CFileItem(item)));
964   PlayListPlayerInsert(playlist, list, index);
965 }
966
967 void CApplicationMessenger::PlayListPlayerInsert(int playlist, const CFileItemList &list, int index)
968 {
969   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_INSERT};
970   CFileItemList* listcopy = new CFileItemList();
971   listcopy->Copy(list);
972   tMsg.lpVoid = (void *)listcopy;
973   tMsg.dwParam1 = playlist;
974   tMsg.dwParam2 = index;
975   SendMessage(tMsg, true);
976 }
977
978 void CApplicationMessenger::PlayListPlayerRemove(int playlist, int position)
979 {
980   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_REMOVE, (DWORD)playlist, (DWORD)position};
981   SendMessage(tMsg, true);
982 }
983
984 void CApplicationMessenger::PlayListPlayerClear(int playlist)
985 {
986   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_CLEAR};
987   tMsg.dwParam1 = playlist;
988   SendMessage(tMsg, true);
989 }
990
991 void CApplicationMessenger::PlayListPlayerShuffle(int playlist, bool shuffle)
992 {
993   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_SHUFFLE};
994   tMsg.dwParam1 = playlist;
995   tMsg.dwParam2 = shuffle ? 1 : 0;
996   SendMessage(tMsg, true);
997 }
998
999 void CApplicationMessenger::PlayListPlayerGetItems(int playlist, CFileItemList &list)
1000 {
1001   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_GET_ITEMS};
1002   tMsg.dwParam1 = playlist;
1003   tMsg.lpVoid = (void *)&list;
1004   SendMessage(tMsg, true);
1005 }
1006
1007 void CApplicationMessenger::PlayListPlayerSwap(int playlist, int indexItem1, int indexItem2)
1008 {
1009   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_SWAP};
1010   tMsg.dwParam1 = playlist;
1011   vector<int> *indexes = new vector<int>();
1012   indexes->push_back(indexItem1);
1013   indexes->push_back(indexItem2);
1014   tMsg.lpVoid = (void *)indexes;
1015   SendMessage(tMsg, true);
1016 }
1017
1018 void CApplicationMessenger::PlayListPlayerRepeat(int playlist, int repeatState)
1019 {
1020   ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_REPEAT};
1021   tMsg.dwParam1 = playlist;
1022   tMsg.dwParam2 = repeatState;
1023   SendMessage(tMsg, true);
1024 }
1025
1026 void CApplicationMessenger::PictureShow(string filename)
1027 {
1028   ThreadMessage tMsg = {TMSG_PICTURE_SHOW};
1029   tMsg.strParam = filename;
1030   SendMessage(tMsg);
1031 }
1032
1033 void CApplicationMessenger::PictureSlideShow(string pathname, bool addTBN /* = false */)
1034 {
1035   DWORD dwMessage = TMSG_PICTURE_SLIDESHOW;
1036   ThreadMessage tMsg = {dwMessage};
1037   tMsg.strParam = pathname;
1038   tMsg.dwParam1 = addTBN ? 1 : 0;
1039   SendMessage(tMsg);
1040 }
1041
1042 void CApplicationMessenger::SetGUILanguage(const std::string &strLanguage)
1043 {
1044   ThreadMessage tMsg = {TMSG_SETLANGUAGE};
1045   tMsg.strParam = strLanguage;
1046   SendMessage(tMsg);
1047 }
1048
1049 void CApplicationMessenger::Shutdown()
1050 {
1051   ThreadMessage tMsg = {TMSG_SHUTDOWN};
1052   SendMessage(tMsg);
1053 }
1054
1055 void CApplicationMessenger::Powerdown()
1056 {
1057   ThreadMessage tMsg = {TMSG_POWERDOWN};
1058   SendMessage(tMsg);
1059 }
1060
1061 void CApplicationMessenger::Quit()
1062 {
1063   ThreadMessage tMsg = {TMSG_QUIT};
1064   SendMessage(tMsg);
1065 }
1066
1067 void CApplicationMessenger::Hibernate()
1068 {
1069   ThreadMessage tMsg = {TMSG_HIBERNATE};
1070   SendMessage(tMsg);
1071 }
1072
1073 void CApplicationMessenger::Suspend()
1074 {
1075   ThreadMessage tMsg = {TMSG_SUSPEND};
1076   SendMessage(tMsg);
1077 }
1078
1079 void CApplicationMessenger::Restart()
1080 {
1081   ThreadMessage tMsg = {TMSG_RESTART};
1082   SendMessage(tMsg);
1083 }
1084
1085 void CApplicationMessenger::Reset()
1086 {
1087   ThreadMessage tMsg = {TMSG_RESET};
1088   SendMessage(tMsg);
1089 }
1090
1091 void CApplicationMessenger::RestartApp()
1092 {
1093   ThreadMessage tMsg = {TMSG_RESTARTAPP};
1094   SendMessage(tMsg);
1095 }
1096
1097 void CApplicationMessenger::InhibitIdleShutdown(bool inhibit)
1098 {
1099   ThreadMessage tMsg = {TMSG_INHIBITIDLESHUTDOWN, (DWORD)inhibit};
1100   SendMessage(tMsg);
1101 }
1102
1103 void CApplicationMessenger::NetworkMessage(DWORD dwMessage, DWORD dwParam)
1104 {
1105   ThreadMessage tMsg = {TMSG_NETWORKMESSAGE, dwMessage, dwParam};
1106   SendMessage(tMsg);
1107 }
1108
1109 void CApplicationMessenger::SwitchToFullscreen()
1110 {
1111   /* FIXME: ideally this call should return upon a successfull switch but currently
1112      is causing deadlocks between the dvdplayer destructor and the rendermanager
1113   */
1114   ThreadMessage tMsg = {TMSG_SWITCHTOFULLSCREEN};
1115   SendMessage(tMsg, false);
1116 }
1117
1118 void CApplicationMessenger::Minimize(bool wait)
1119 {
1120   ThreadMessage tMsg = {TMSG_MINIMIZE};
1121   SendMessage(tMsg, wait);
1122 }
1123
1124 void CApplicationMessenger::DoModal(CGUIDialog *pDialog, int iWindowID, const CStdString &param)
1125 {
1126   ThreadMessage tMsg = {TMSG_GUI_DO_MODAL};
1127   tMsg.lpVoid = pDialog;
1128   tMsg.dwParam1 = (DWORD)iWindowID;
1129   tMsg.strParam = param;
1130   SendMessage(tMsg, true);
1131 }
1132
1133 void CApplicationMessenger::ExecOS(const CStdString command, bool waitExit)
1134 {
1135   ThreadMessage tMsg = {TMSG_EXECUTE_OS};
1136   tMsg.strParam = command;
1137   tMsg.dwParam1 = (DWORD)waitExit;
1138   SendMessage(tMsg, false);
1139 }
1140
1141 void CApplicationMessenger::UserEvent(int code)
1142 {
1143   ThreadMessage tMsg = {(DWORD)code};
1144   SendMessage(tMsg, false);
1145 }
1146
1147 void CApplicationMessenger::Show(CGUIDialog *pDialog)
1148 {
1149   ThreadMessage tMsg = {TMSG_GUI_SHOW};
1150   tMsg.lpVoid = pDialog;
1151   SendMessage(tMsg, true);
1152 }
1153
1154 void CApplicationMessenger::Close(CGUIWindow *window, bool forceClose, bool waitResult /*= true*/, int nextWindowID /*= 0*/, bool enableSound /*= true*/)
1155 {
1156   ThreadMessage tMsg = {TMSG_GUI_WINDOW_CLOSE, (DWORD)nextWindowID};
1157   tMsg.dwParam2 = (DWORD)((forceClose ? 0x01 : 0) | (enableSound ? 0x02 : 0));
1158   tMsg.lpVoid = window;
1159   SendMessage(tMsg, waitResult);
1160 }
1161
1162 void CApplicationMessenger::ActivateWindow(int windowID, const vector<CStdString> &params, bool swappingWindows)
1163 {
1164   ThreadMessage tMsg = {TMSG_GUI_ACTIVATE_WINDOW, (DWORD)windowID, swappingWindows ? 1u : 0u};
1165   tMsg.params = params;
1166   SendMessage(tMsg, true);
1167 }
1168
1169 void CApplicationMessenger::SendAction(const CAction &action, int windowID, bool waitResult)
1170 {
1171   ThreadMessage tMsg = {TMSG_GUI_ACTION};
1172   tMsg.dwParam1 = windowID;
1173   tMsg.lpVoid = new CAction(action);
1174   SendMessage(tMsg, waitResult);
1175 }
1176
1177 void CApplicationMessenger::SendGUIMessage(const CGUIMessage &message, int windowID, bool waitResult)
1178 {
1179   ThreadMessage tMsg = {TMSG_GUI_MESSAGE};
1180   tMsg.dwParam1 = windowID == WINDOW_INVALID ? 0 : windowID;
1181   tMsg.lpVoid = new CGUIMessage(message);
1182   SendMessage(tMsg, waitResult);
1183 }
1184
1185 vector<CStdString> CApplicationMessenger::GetInfoLabels(const vector<CStdString> &properties)
1186 {
1187   vector<CStdString> infoLabels;
1188
1189   ThreadMessage tMsg = {TMSG_GUI_INFOLABEL};
1190   tMsg.params = properties;
1191   tMsg.lpVoid = (void*)&infoLabels;
1192   SendMessage(tMsg, true);
1193   return infoLabels;
1194 }
1195
1196 vector<bool> CApplicationMessenger::GetInfoBooleans(const vector<CStdString> &properties)
1197 {
1198   vector<bool> infoLabels;
1199
1200   ThreadMessage tMsg = {TMSG_GUI_INFOBOOL};
1201   tMsg.params = properties;
1202   tMsg.lpVoid = (void*)&infoLabels;
1203   SendMessage(tMsg, true);
1204   return infoLabels;
1205 }
1206
1207 void CApplicationMessenger::ShowVolumeBar(bool up)
1208 {
1209   ThreadMessage tMsg = {TMSG_VOLUME_SHOW};
1210   tMsg.dwParam1 = up ? ACTION_VOLUME_UP : ACTION_VOLUME_DOWN;
1211   SendMessage(tMsg, false);
1212 }
1213
1214 void CApplicationMessenger::SetSplashMessage(const CStdString& message)
1215 {
1216   ThreadMessage tMsg = {TMSG_SPLASH_MESSAGE};
1217   tMsg.strParam = message;
1218   SendMessage(tMsg, true);
1219 }
1220
1221 void CApplicationMessenger::SetSplashMessage(int stringID)
1222 {
1223   SetSplashMessage(g_localizeStrings.Get(stringID));
1224 }
1225
1226 bool CApplicationMessenger::SetupDisplay()
1227 {
1228   bool result;
1229   
1230   ThreadMessage tMsg = {TMSG_DISPLAY_SETUP};
1231   tMsg.lpVoid = (void*)&result;
1232   SendMessage(tMsg, true);
1233   
1234   return result;
1235 }
1236
1237 bool CApplicationMessenger::DestroyDisplay()
1238 {
1239   bool result;
1240   
1241   ThreadMessage tMsg = {TMSG_DISPLAY_DESTROY};
1242   tMsg.lpVoid = (void*)&result;
1243   SendMessage(tMsg, true);
1244   
1245   return result;
1246 }
1247
1248 void CApplicationMessenger::SetCurrentSongTag(const CMusicInfoTag& tag)
1249 {
1250   CFileItem* item = new CFileItem(tag);
1251   ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1252   tMsg.dwParam1 = 1;
1253   tMsg.lpVoid = (void*)item;
1254   SendMessage(tMsg, false);
1255 }
1256
1257 void CApplicationMessenger::SetCurrentVideoTag(const CVideoInfoTag& tag)
1258 {
1259   CFileItem* item = new CFileItem(tag);
1260   ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1261   tMsg.dwParam1 = 2;
1262   tMsg.lpVoid = (void*)item;
1263   SendMessage(tMsg, false);
1264 }
1265
1266 void CApplicationMessenger::SetCurrentItem(const CFileItem& item)
1267 {
1268   CFileItem* item2 = new CFileItem(item);
1269   ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM};
1270   tMsg.lpVoid = (void*)item2;
1271   SendMessage(tMsg, false);
1272 }
1273
1274 void CApplicationMessenger::LoadProfile(unsigned int idx)
1275 {
1276   ThreadMessage tMsg = {TMSG_LOADPROFILE};
1277   tMsg.dwParam1 = idx;
1278   SendMessage(tMsg, false);
1279 }