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