changed: Music thumb caching no longer has the 4096 limit.
[xbmc:xbmc-antiquated.git] / XBMC / xbmc / Application.cpp
1 /*
2  *      Copyright (C) 2005-2007 Team XboxMediaCenter
3  *      http://www.xboxmediacenter.com
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 GNU Make; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "stdafx.h"
23 #include "application.h"
24 #ifdef HAS_XBOX_HARDWARE
25 #include "xbox/XKEEPROM.h"
26 #include "utils/lcd.h"
27 #include "xbox/iosupport.h"
28 #include "xbox/XKHDD.h"
29 #endif
30 #include "xbox/xbeheader.h"
31 #include "util.h"
32 #include "texturemanager.h"
33 #include "cores/playercorefactory.h"
34 #include "playlistplayer.h"
35 #include "musicdatabase.h"
36 #include "videodatabase.h"
37 #include "autorun.h"
38 #include "ActionManager.h"
39 #ifdef HAS_LCD
40 #include "utils/LCDFactory.h"
41 #else
42 #include "GUILabelControl.h"  // needed for CInfoPortion
43 #include "GUIImage.h"
44 #endif
45 #include "utils/KaiClient.h"
46 #ifdef HAS_XBOX_HARDWARE
47 #include "utils/MemoryUnitManager.h"
48 #include "utils/FanController.h"
49 #include "utils/LED.h"
50 #endif
51 #include "XBVideoConfig.h"
52 #include "LangCodeExpander.h"
53 #include "lib/libGoAhead/xbmchttp.h"
54 #include "utils/GUIInfoManager.h"
55 #include "PlaylistFactory.h"
56 #include "GUIFontManager.h"
57 #include "SkinInfo.h"
58 #include "lib/libPython/XBPython.h"
59 #include "ButtonTranslator.h"
60 #include "GUIAudioManager.h"
61 #include "lib/libscrobbler/scrobbler.h"
62 #include "GUIPassword.h"
63 #include "applicationmessenger.h"
64 #include "sectionloader.h"
65 #include "cores/DllLoader/DllLoaderContainer.h"
66 #include "guiusermessages.h"
67 #include "filesystem/directoryCache.h"
68 #include "filesystem/StackDirectory.h"
69 #include "FileSystem/DllLibCurl.h"
70 #include "utils/TuxBoxUtil.h"
71 #include "utils/SystemInfo.h"
72
73 #ifdef HAS_FILESYSTEM
74 #include "filesystem/filedaap.h"
75 #endif
76 #ifdef HAS_UPNP
77 #include "UPnP.h"
78 #include "FileSystem/UPnPDirectory.h"
79 #endif
80 #include "PartyModeManager.h"
81 #ifdef HAS_VIDEO_PLAYBACK
82 #include "cores/videorenderers/rendermanager.h"
83 #endif
84 #ifdef HAS_KARAOKE
85 #include "CdgParser.h"
86 #endif
87 #include "audiocontext.h"
88 #include "GUIFontTTF.h"
89 #include "xbox/network.h"
90 #include "utils/win32exception.h"
91 #include "lib/libGoAhead/webserver.h"
92 #ifdef HAS_FTP_SERVER
93 #include "lib/libfilezilla/xbfilezilla.h"
94 #endif
95 #ifdef HAS_TIME_SERVER
96 #include "utils/sntp.h"
97 #endif
98 #ifdef HAS_XFONT
99 #include <xfont.h>  // for textout functions
100 #endif
101
102 // Windows includes
103 #include "GUIWindowHome.h"
104 #include "GUIStandardWindow.h"
105 #include "GUIWindowSettings.h"
106 #include "GUIWindowFileManager.h"
107 #include "GUIWindowSettingsCategory.h"
108 #include "GUIWindowMusicPlaylist.h"
109 #include "GUIWindowMusicSongs.h"
110 #include "GUIWindowMusicNav.h"
111 #include "GUIWindowMusicPlaylistEditor.h"
112 #include "GUIWindowVideoPlaylist.h"
113 #include "GUIWindowMusicInfo.h"
114 #include "GUIWindowVideoInfo.h"
115 #include "GUIWindowVideoFiles.h"
116 #include "GUIWindowVideoNav.h"
117 #include "GUIWindowSettingsProfile.h"
118 #include "GUIWindowSettingsScreenCalibration.h"
119 #include "GUIWindowPrograms.h"
120 #include "GUIWindowPictures.h"
121 #include "GUIWindowScripts.h"
122 #include "GUIWindowWeather.h"
123 #include "GUIWindowGameSaves.h"
124 #include "GUIWindowLoginScreen.h"
125 #include "GUIWindowVisualisation.h"
126 #include "GUIWindowSystemInfo.h"
127 #include "GUIWindowScreensaver.h"
128 #include "GUIWindowSlideshow.h"
129 #include "GUIWindowBuddies.h"
130
131 #include "GUIWindowFullScreen.h"
132 #include "GUIWindowOSD.h"
133 #include "GUIWindowMusicOverlay.h"
134 #include "GUIWindowVideoOverlay.h"
135
136 // Dialog includes
137 #include "GUIDialogMusicOSD.h"
138 #include "GUIDialogVisualisationSettings.h"
139 #include "GUIDialogVisualisationPresetList.h"
140 #include "GUIDialogInvite.h"
141 #include "GUIDialogHost.h"
142 #include "GUIDialogTrainerSettings.h"
143 #include "GUIWindowScriptsInfo.h"
144 #include "GUIDialogNetworkSetup.h"
145 #include "GUIDialogMediaSource.h"
146 #include "GUIDialogVideoSettings.h"
147 #include "GUIDialogAudioSubtitleSettings.h"
148 #include "GUIDialogVideoBookmarks.h"
149 #include "GUIDialogProfileSettings.h"
150 #include "GUIDialogLockSettings.h"
151 #include "GUIDialogContentSettings.h"
152 #include "GUIDialogVideoScan.h"
153
154 #include "GUIDialogKeyboard.h"
155 #include "GUIDialogYesNo.h"
156 #include "GUIDialogOK.h"
157 #include "GUIDialogProgress.h"
158 #include "GUIDialogSelect.h"
159 #include "GUIDialogFileStacking.h"
160 #include "GUIDialogNumeric.h"
161 #include "GUIDialogGamepad.h"
162 #include "GUIDialogSubMenu.h"
163 #include "GUIDialogButtonMenu.h"
164 #include "GUIDialogContextMenu.h"
165 #include "GUIDialogMusicScan.h"
166 #include "GUIDialogPlayerControls.h"
167
168 using namespace XFILE;
169 using namespace DIRECTORY;
170 using namespace PLAYLIST;
171
172 // uncomment this if you want to use release libs in the debug build.
173 // Atm this saves you 7 mb of memory
174 #define USE_RELEASE_LIBS
175
176 #ifdef HAS_LCD
177 #pragma comment (lib,"xbmc/lib/libXenium/XeniumSPIg.lib")
178 #endif
179 #ifdef HAS_KAI_VOICE
180 #pragma comment (lib,"xbmc/lib/libSpeex/libSpeex.lib")
181 #endif
182
183 #if defined(_DEBUG) && !defined(USE_RELEASE_LIBS)
184  #ifdef HAS_FILESYSTEM
185   #pragma comment (lib,"xbmc/lib/libXBMS/libXBMSd.lib")    // SECTIONNAME=LIBXBMS
186   #pragma comment (lib,"xbmc/lib/libsmb/libsmbd.lib")      // SECTIONNAME=LIBSMB
187   #pragma comment (lib,"xbmc/lib/libxdaap/libxdaapd.lib") // SECTIONNAME=LIBXDAAP
188   #pragma comment (lib,"xbmc/lib/libRTV/libRTVd.lib")    // SECTIONNAME=LIBRTV
189  #endif
190  #ifdef _XBOX
191   #pragma comment (lib,"xbmc/lib/unrarXlib/unrarxlibd.lib")
192   #pragma comment (lib,"xbmc/lib/libGoAhead/goaheadd.lib") // SECTIONNAME=LIBHTTP
193   #pragma comment (lib,"xbmc/lib/sqlLite/libSQLite3d.lib")
194   #pragma comment (lib,"xbmc/lib/libshout/libshoutd.lib" )
195   #pragma comment (lib,"xbmc/lib/libcdio/libcdiod.lib" )
196   #pragma comment (lib,"xbmc/lib/libiconv/libiconvd.lib")
197   #pragma comment (lib,"xbmc/lib/libfribidi/libfribidid.lib")
198  #else
199   #pragma comment (lib,"../../xbmc/lib/unrarXlib/unrarxlibd.lib")
200   #pragma comment (lib,"../../xbmc/lib/libGoAhead/goahead_win32d.lib") // SECTIONNAME=LIBHTTP
201   #pragma comment (lib,"../../xbmc/lib/sqlLite/libSQLite3_win32d.lib")
202   #pragma comment (lib,"../../xbmc/lib/libshout/libshout_win32d.lib" )
203   #pragma comment (lib,"../../xbmc/lib/libcdio/libcdio_win32d.lib" )
204   #pragma comment (lib,"../../xbmc/lib/libiconv/libiconvd.lib")
205   #pragma comment (lib,"../../xbmc/lib/libfribidi/libfribidid.lib")
206  #endif
207  #ifdef HAS_MIKMOD
208   #pragma comment (lib,"xbmc/lib/mikxbox/mikxboxd.lib")  // SECTIONNAME=MOD_RW,MOD_RX
209  #endif
210 #else
211  #ifdef HAS_FILESYSTEM
212   #pragma comment (lib,"xbmc/lib/libXBMS/libXBMS.lib")
213   #pragma comment (lib,"xbmc/lib/libsmb/libsmb.lib")
214   #pragma comment (lib,"xbmc/lib/libxdaap/libxdaap.lib") // SECTIONNAME=LIBXDAAP
215   #pragma comment (lib,"xbmc/lib/libRTV/libRTV.lib")
216  #endif
217  #ifdef _XBOX
218   #pragma comment (lib,"xbmc/lib/unrarXlib/unrarxlib.lib")
219   #pragma comment (lib,"xbmc/lib/libGoAhead/goahead.lib")
220   #pragma comment (lib,"xbmc/lib/sqlLite/libSQLite3.lib")
221   #pragma comment (lib,"xbmc/lib/libcdio/libcdio.lib")
222   #pragma comment (lib,"xbmc/lib/libshout/libshout.lib")
223   #pragma comment (lib,"xbmc/lib/libiconv/libiconv.lib")
224   #pragma comment (lib,"xbmc/lib/libfribidi/libfribidi.lib")
225  #else
226   #pragma comment (lib,"../../xbmc/lib/unrarXlib/unrarxlib.lib")
227   #pragma comment (lib,"../../xbmc/lib/libGoAhead/goahead_win32.lib")
228   #pragma comment (lib,"../../xbmc/lib/sqlLite/libSQLite3_win32.lib")
229   #pragma comment (lib,"../../xbmc/lib/libshout/libshout_win32.lib" )
230   #pragma comment (lib,"../../xbmc/lib/libcdio/libcdio_win32.lib" )
231   #pragma comment (lib,"../../xbmc/lib/libiconv/libiconv.lib")
232   #pragma comment (lib,"../../xbmc/lib/libfribidi/libfribidi.lib")
233  #endif
234  #ifdef HAS_MIKMOD
235   #pragma comment (lib,"xbmc/lib/mikxbox/mikxbox.lib")
236  #endif
237 #endif
238
239 #define MAX_FFWD_SPEED 5
240
241 CStdString g_LoadErrorStr;
242
243 #ifdef HAS_XBOX_HARDWARE
244 extern "C"
245 {
246   extern bool WINAPI NtSetSystemTime(LPFILETIME SystemTime , LPFILETIME PreviousTime );
247 };
248 #endif
249
250 #ifdef HAS_XBOX_D3D
251 static void WaitCallback(DWORD flags)
252 {
253 #ifndef PROFILE
254   /* if cpu is far ahead of gpu, sleep instead of yield */
255   if(flags & D3DWAIT_PRESENT)
256     while(D3DDevice::GetPushDistance(D3DDISTANCE_FENCES_TOWAIT) > 0)
257       Sleep(1);
258 #endif
259 }
260 #endif
261
262 //extern IDirectSoundRenderer* m_pAudioDecoder;
263 CApplication::CApplication(void)
264     : m_ctrDpad(220, 220)
265 {
266   m_iPlaySpeed = 1;
267   m_bSpinDown = false;
268   m_bNetworkSpinDown = false;
269   m_dwSpinDownTime = timeGetTime();
270   m_pWebServer = NULL;
271   pXbmcHttp = NULL;
272   m_pFileZilla = NULL;
273   pXbmcHttp = NULL;
274   m_pPlayer = NULL;
275 #ifdef HAS_XBOX_HARDWARE
276   XSetProcessQuantumLength(5); //default=20msec
277   XSetFileCacheSize (256*1024); //default=64kb
278 #endif
279   m_bInactive = false;   // CB: SCREENSAVER PATCH
280   m_bScreenSave = false;   // CB: SCREENSAVER PATCH
281   m_iScreenSaveLock = 0;
282   m_dwSaverTick = timeGetTime(); // CB: SCREENSAVER PATCH
283   m_dwSkinTime = 0;
284
285   m_bInitializing = true;
286   m_eForcedNextPlayer = EPC_NONE;
287   m_strPlayListFile = "";
288   m_nextPlaylistItem = -1;
289   m_playCountUpdated = false;
290
291   //true while we in IsPaused mode! Workaround for OnPaused, which must be add. after v2.0
292   m_bIsPaused = false;
293
294   /* for now allways keep this around */
295 #ifdef HAS_KARAOKE
296   m_pCdgParser = new CCdgParser();
297 #endif
298 }
299
300 CApplication::~CApplication(void)
301 {}
302
303 // text out routine for below
304 #ifdef HAS_XFONT
305 static void __cdecl FEH_TextOut(XFONT* pFont, int iLine, const wchar_t* fmt, ...)
306 {
307   wchar_t buf[100];
308   va_list args;
309   va_start(args, fmt);
310   _vsnwprintf(buf, 100, fmt, args);
311   va_end(args);
312
313   if (!(iLine & 0x8000))
314     CLog::Log(LOGFATAL, "%S", buf);
315
316   bool Center = (iLine & 0x10000) > 0;
317   pFont->SetTextAlignment(Center ? XFONT_TOP | XFONT_CENTER : XFONT_TOP | XFONT_LEFT);
318
319   iLine &= 0x7fff;
320
321   for (int i = 0; i < 2; i++)
322   {
323     D3DRECT rc = { 0, 50 + 25 * iLine, 720, 50 + 25 * (iLine + 1) };
324     D3DDevice::Clear(1, &rc, D3DCLEAR_TARGET, 0, 0, 0);
325     pFont->TextOut(g_application.m_pBackBuffer, buf, -1, Center ? 360 : 80, 50 + 25*iLine);
326     D3DDevice::Present(0, 0, 0, 0);
327   }
328 }
329 #else
330 static void __cdecl FEH_TextOut(void* pFont, int iLine, const wchar_t* fmt, ...) {}
331 #endif
332
333 HWND g_hWnd = NULL;
334
335 void CApplication::InitBasicD3D()
336 {
337   bool bPal = g_videoConfig.HasPAL();
338   CLog::Log(LOGINFO, "Init display in default mode: %s", bPal ? "PAL" : "NTSC");
339   // init D3D with defaults (NTSC or PAL standard res)
340   m_d3dpp.BackBufferWidth = 720;
341   m_d3dpp.BackBufferHeight = bPal ? 576 : 480;
342   m_d3dpp.BackBufferFormat = D3DFMT_LIN_X8R8G8B8;
343   m_d3dpp.BackBufferCount = 1;
344   m_d3dpp.EnableAutoDepthStencil = FALSE;
345   m_d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
346 #ifdef HAS_XBOX_D3D
347   m_d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
348 #else
349   m_d3dpp.FullScreen_PresentationInterval = 0;
350   m_d3dpp.Windowed = TRUE;
351   m_d3dpp.hDeviceWindow = g_hWnd;
352 #endif
353
354   if (!(m_pD3D = Direct3DCreate8(D3D_SDK_VERSION)))
355   {
356     CLog::Log(LOGFATAL, "FATAL ERROR: Unable to create Direct3D!");
357     Sleep(INFINITE); // die
358   }
359
360   // Check if we have the required modes available
361   g_videoConfig.GetModes(m_pD3D);
362   if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
363   {
364     // Oh uh - doesn't look good for starting in their wanted screenmode
365     CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
366     g_guiSettings.m_LookAndFeelResolution = g_videoConfig.GetSafeMode();
367     CLog::Log(LOGERROR, "Resetting to mode %s", g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].strMode);
368     CLog::Log(LOGERROR, "Done reset");
369   }
370   // Transfer the resolution information to our graphics context
371   g_graphicsContext.SetD3DParameters(&m_d3dpp);
372   g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution, TRUE);
373
374   // Create the device
375 #ifdef HAS_XBOX_D3D
376   // Xbox MUST use HAL / Hardware Vertex Processing!
377   if (m_pD3D->CreateDevice(0, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_d3dpp, &m_pd3dDevice) != S_OK)
378   {
379     CLog::Log(LOGFATAL, "FATAL ERROR: Unable to create D3D Device!");
380     Sleep(INFINITE); // die
381   }
382   m_pd3dDevice->GetBackBuffer(0, 0, &m_pBackBuffer);
383 #else
384   if (m_pD3D->CreateDevice(0, D3DDEVTYPE_REF, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_d3dpp, &m_pd3dDevice) != S_OK)
385   {
386     CLog::Log(LOGFATAL, "FATAL ERROR: Unable to create D3D Device!");
387     Sleep(INFINITE); // die
388   }
389 #endif
390
391   if (m_splash)
392   {
393     m_splash->Stop();
394   }
395   m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0, 0, 0);
396   m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
397 }
398
399 // This function does not return!
400 void CApplication::FatalErrorHandler(bool InitD3D, bool MapDrives, bool InitNetwork)
401 {
402   // XBMC couldn't start for some reason...
403   // g_LoadErrorStr should contain the reason
404   CLog::Log(LOGWARNING, "Emergency recovery console starting...");
405
406   bool HaveGamepad = true; // should always have the gamepad when we get here
407   if (InitD3D)
408     InitBasicD3D();
409
410   if (m_splash)
411   {
412     m_splash->Stop();
413   }
414   m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0, 0, 0);
415   m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
416
417   // D3D is up, load default font
418 #ifdef HAS_XFONT
419   XFONT* pFont;
420   if (XFONT_OpenDefaultFont(&pFont) != S_OK)
421   {
422     CLog::Log(LOGFATAL, "FATAL ERROR: Unable to open default font!");
423     Sleep(INFINITE); // die
424   }
425
426   // defaults for text
427   pFont->SetBkMode(XFONT_OPAQUE);
428   pFont->SetBkColor(D3DCOLOR_XRGB(0, 0, 0));
429   pFont->SetTextColor(D3DCOLOR_XRGB(0xff, 0x20, 0x20));
430 #else
431   void *pFont = NULL;
432 #endif
433   int iLine = 0;
434   FEH_TextOut(pFont, iLine++, L"XBMC Fatal Error:");
435   char buf[500];
436   strncpy(buf, g_LoadErrorStr.c_str(), 500);
437   buf[499] = 0;
438   char* pNewline = strtok(buf, "\n");
439   while (pNewline)
440   {
441     FEH_TextOut(pFont, iLine++, L"%S", pNewline);
442     pNewline = strtok(NULL, "\n");
443   }
444   ++iLine;
445
446 #ifdef HAS_XBOX_HARDWARE
447   if (MapDrives)
448   {
449     // map in default drives
450     CIoSupport::RemapDriveLetter('C',"Harddisk0\\Partition2");
451     CIoSupport::RemapDriveLetter('D',"Cdrom0");
452     CIoSupport::RemapDriveLetter('E',"Harddisk0\\Partition1");
453
454     //Add. also Drive F/G
455     if (CIoSupport::PartitionExists(6)) 
456       CIoSupport::RemapDriveLetter('F',"Harddisk0\\Partition6");
457     if (CIoSupport::PartitionExists(7))
458       CIoSupport::RemapDriveLetter('G',"Harddisk0\\Partition7");
459   }
460 #endif
461   bool Pal = g_graphicsContext.GetVideoResolution() == PAL_4x3;
462
463   if (HaveGamepad)
464     FEH_TextOut(pFont, (Pal ? 16 : 12) | 0x18000, L"Press any button to reboot");
465
466   bool NetworkUp = false;
467
468   // Boot up the network for FTP
469   if (InitNetwork)
470   {
471     std::vector<int> netorder;
472     if (m_bXboxMediacenterLoaded)
473     {
474       if (g_guiSettings.GetInt("network.assignment") == NETWORK_DHCP)
475       {
476         netorder.push_back(NETWORK_DHCP);
477         netorder.push_back(NETWORK_STATIC);
478       }
479       else if (g_guiSettings.GetInt("network.assignment") == NETWORK_STATIC)
480       {
481         netorder.push_back(NETWORK_STATIC);
482         netorder.push_back(NETWORK_DHCP);
483       }
484       else
485       {
486         netorder.push_back(NETWORK_DASH);
487         netorder.push_back(NETWORK_DHCP);
488         netorder.push_back(NETWORK_STATIC);
489       }
490     }
491     else
492     {
493       netorder.push_back(NETWORK_DASH);
494       netorder.push_back(NETWORK_DHCP);
495       netorder.push_back(NETWORK_STATIC);
496     }
497
498     while(1)
499     {
500       std::vector<int>::iterator it;
501       for( it = netorder.begin();it != netorder.end(); it++)
502       {
503         g_network.Deinitialize();
504
505 #ifdef HAS_XBOX_NETWORK
506         if (!(XNetGetEthernetLinkStatus() & XNET_ETHERNET_LINK_ACTIVE))
507         {
508           FEH_TextOut(pFont, iLine, L"Network cable unplugged");
509           break;
510         }
511 #endif
512         switch( (*it) )
513         {
514           case NETWORK_DASH:
515             FEH_TextOut(pFont, iLine, L"Init network using dash settings...");
516             g_network.Initialize(NETWORK_DASH, "","","","");
517             break;
518           case NETWORK_DHCP:
519             FEH_TextOut(pFont, iLine, L"Init network using DHCP...");
520             g_network.Initialize(NETWORK_DHCP, "","","","");
521             break;
522           default:
523             FEH_TextOut(pFont, iLine, L"Init network using static ip...");
524             if( m_bXboxMediacenterLoaded )
525             {
526               g_network.Initialize(NETWORK_STATIC,
527                     g_guiSettings.GetString("network.ipaddress").c_str(),
528                     g_guiSettings.GetString("network.subnet").c_str(),
529                     g_guiSettings.GetString("network.gateway").c_str(),
530                     g_guiSettings.GetString("network.dns").c_str() );
531             }
532             else
533             {
534               g_network.Initialize(NETWORK_STATIC,
535                     "192.168.0.42",
536                     "255.255.255.0",
537                     "192.168.0.1",
538                     "192.168.0.1" );
539             }
540             break;
541         }
542
543         int count = 0;
544 #ifdef HAS_XBOX_NETWORK
545         DWORD dwState = XNET_GET_XNADDR_PENDING;
546
547         while(dwState == XNET_GET_XNADDR_PENDING)
548         {
549           dwState = g_network.UpdateState();
550
551           if( dwState != XNET_GET_XNADDR_PENDING )
552             break;
553
554           if (HaveGamepad && AnyButtonDown())
555             g_applicationMessenger.Restart();
556
557
558           Sleep(50);
559           ++count;
560         }
561
562         if( dwState != XNET_GET_XNADDR_PENDING && dwState != XNET_GET_XNADDR_NONE )
563         {
564           /* yay, we got network */
565           NetworkUp = true;
566           break;
567         }
568 #endif
569         /* increment line before next attempt */
570         ++iLine;
571       }
572
573       /* break out of the continous loop if we have network*/
574       if( NetworkUp )
575         break;
576       else
577       {
578         int n = 10;
579         while (n)
580         {
581           FEH_TextOut(pFont, (iLine + 1) | 0x8000, L"Unable to init network, retrying in %d seconds", n--);
582           for (int i = 0; i < 20; ++i)
583           {
584             Sleep(50);
585
586             if (HaveGamepad && AnyButtonDown())
587               g_applicationMessenger.Restart();
588           }
589         }
590       }
591     }
592   }
593
594   if( NetworkUp )
595   {
596     FEH_TextOut(pFont, iLine++, L"IP Address: %S", g_network.m_networkinfo.ip);
597     ++iLine;
598   }
599
600   if (NetworkUp)
601   {
602 #ifdef HAS_FTP_SERVER
603     if (!m_pFileZilla)
604     {
605       // Start FTP with default settings
606       FEH_TextOut(pFont, iLine++, L"Starting FTP server...");
607
608       m_pFileZilla = new CXBFileZilla(NULL);
609       m_pFileZilla->Start();
610
611       // Default settings
612       m_pFileZilla->mSettings.SetMaxUsers(0);
613       m_pFileZilla->mSettings.SetWelcomeMessage("XBMC emergency recovery console FTP.");
614
615       // default user
616       CXFUser* pUser;
617       m_pFileZilla->AddUser("xbox", pUser);
618       pUser->SetPassword("xbox");
619       pUser->SetShortcutsEnabled(false);
620       pUser->SetUseRelativePaths(false);
621       pUser->SetBypassUserLimit(false);
622       pUser->SetUserLimit(0);
623       pUser->SetIPLimit(0);
624       pUser->AddDirectory("/", XBFILE_READ | XBFILE_WRITE | XBFILE_DELETE | XBFILE_APPEND | XBDIR_DELETE | XBDIR_CREATE | XBDIR_LIST | XBDIR_SUBDIRS | XBDIR_HOME);
625       pUser->AddDirectory("C:\\", XBFILE_READ | XBFILE_WRITE | XBFILE_DELETE | XBFILE_APPEND | XBDIR_DELETE | XBDIR_CREATE | XBDIR_LIST | XBDIR_SUBDIRS);
626       pUser->AddDirectory("D:\\", XBFILE_READ | XBDIR_LIST | XBDIR_SUBDIRS);
627       pUser->AddDirectory("E:\\", XBFILE_READ | XBFILE_WRITE | XBFILE_DELETE | XBFILE_APPEND | XBDIR_DELETE | XBDIR_CREATE | XBDIR_LIST | XBDIR_SUBDIRS);
628       pUser->AddDirectory("Q:\\", XBFILE_READ | XBFILE_WRITE | XBFILE_DELETE | XBFILE_APPEND | XBDIR_DELETE | XBDIR_CREATE | XBDIR_LIST | XBDIR_SUBDIRS);
629       //Add. also Drive F/G
630       if (CIoSupport::DriveExists('F')){
631         pUser->AddDirectory("F:\\", XBFILE_READ | XBFILE_WRITE | XBFILE_DELETE | XBFILE_APPEND | XBDIR_DELETE | XBDIR_CREATE | XBDIR_LIST | XBDIR_SUBDIRS);
632       }
633       if (CIoSupport::DriveExists('G')){
634         pUser->AddDirectory("G:\\", XBFILE_READ | XBFILE_WRITE | XBFILE_DELETE | XBFILE_APPEND | XBDIR_DELETE | XBDIR_CREATE | XBDIR_LIST | XBDIR_SUBDIRS);
635       }
636       pUser->CommitChanges();
637     }
638
639     FEH_TextOut(pFont, iLine++, L"FTP server running on port %d, login: xbox/xbox", m_pFileZilla->mSettings.GetServerPort());
640 #endif
641     ++iLine;
642   }
643
644   if (HaveGamepad)
645   {
646     for (;;)
647     {
648       Sleep(50);
649       if (AnyButtonDown())
650       {
651         g_application.Stop();
652         Sleep(200);
653 #ifdef _XBOX
654 #ifdef _DEBUG  // don't actually shut off if debug build, it hangs VS for a long time
655         XKUtils::XBOXPowerCycle();
656 #endif
657 #else
658         SendMessage(g_hWnd, WM_CLOSE, 0, 0);
659 #endif
660       }
661     }
662   }
663   else
664 #ifdef _XBOX
665     Sleep(INFINITE);
666 #else
667     SendMessage(g_hWnd, WM_CLOSE, 0, 0);
668 #endif
669 }
670
671 LONG WINAPI CApplication::UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
672 {
673   PCSTR pExceptionString = "Unknown exception code";
674
675 #define STRINGIFY_EXCEPTION(code) case code: pExceptionString = #code; break
676
677   switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
678   {
679     STRINGIFY_EXCEPTION(EXCEPTION_ACCESS_VIOLATION);
680     STRINGIFY_EXCEPTION(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
681     STRINGIFY_EXCEPTION(EXCEPTION_BREAKPOINT);
682     STRINGIFY_EXCEPTION(EXCEPTION_FLT_DENORMAL_OPERAND);
683     STRINGIFY_EXCEPTION(EXCEPTION_FLT_DIVIDE_BY_ZERO);
684     STRINGIFY_EXCEPTION(EXCEPTION_FLT_INEXACT_RESULT);
685     STRINGIFY_EXCEPTION(EXCEPTION_FLT_INVALID_OPERATION);
686     STRINGIFY_EXCEPTION(EXCEPTION_FLT_OVERFLOW);
687     STRINGIFY_EXCEPTION(EXCEPTION_FLT_STACK_CHECK);
688     STRINGIFY_EXCEPTION(EXCEPTION_ILLEGAL_INSTRUCTION);
689     STRINGIFY_EXCEPTION(EXCEPTION_INT_DIVIDE_BY_ZERO);
690     STRINGIFY_EXCEPTION(EXCEPTION_INT_OVERFLOW);
691     STRINGIFY_EXCEPTION(EXCEPTION_INVALID_DISPOSITION);
692     STRINGIFY_EXCEPTION(EXCEPTION_NONCONTINUABLE_EXCEPTION);
693     STRINGIFY_EXCEPTION(EXCEPTION_SINGLE_STEP);
694   }
695 #undef STRINGIFY_EXCEPTION
696
697   g_LoadErrorStr.Format("%s (0x%08x)\n at 0x%08x",
698                         pExceptionString, ExceptionInfo->ExceptionRecord->ExceptionCode,
699                         ExceptionInfo->ExceptionRecord->ExceptionAddress);
700
701   CLog::Log(LOGFATAL, "%s", g_LoadErrorStr.c_str());
702
703   return ExceptionInfo->ExceptionRecord->ExceptionCode;
704 }
705 #ifdef _XBOX
706 #include "xbox/undocumented.h"
707 extern "C" HANDLE __stdcall KeGetCurrentThread(VOID);
708 #endif
709 extern "C" void __stdcall init_emu_environ();
710
711 HRESULT CApplication::Create(HWND hWnd)
712 {
713   g_hWnd = hWnd;
714
715   HRESULT hr;
716   //grab a handle to our thread to be used later in identifying the render thread
717   m_threadID = GetCurrentThreadId();
718
719   //floating point precision to 24 bits (faster performance)
720   _controlfp(_PC_24, _MCW_PC);
721
722   init_emu_environ();
723
724   /* install win32 exception translator, win32 exceptions
725    * can now be caught using c++ try catch */
726   win32_exception::install_handler();
727
728   CStdString strExecutablePath;
729   char szDevicePath[MAX_PATH];
730
731   // map Q to home drive of xbe to load the config file
732   CUtil::GetHomePath(strExecutablePath);
733   CIoSupport::GetPartition(strExecutablePath.c_str()[0], szDevicePath);
734   strcat(szDevicePath, &strExecutablePath.c_str()[2]);
735
736   CIoSupport::RemapDriveLetter('Q', szDevicePath);
737
738   // check logpath
739   CStdString strLogFile, strLogFileOld;
740   strLogFile.Format("%sxbmc.log", g_stSettings.m_logFolder);
741   strLogFileOld.Format("%sxbmc.old.log", g_stSettings.m_logFolder);
742
743   ::DeleteFile(strLogFileOld.c_str());
744   ::MoveFile(strLogFile.c_str(), strLogFileOld.c_str());
745
746   CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
747   CLog::Log(LOGNOTICE, "Starting XBoxMediaCenter.  Built on %s", __DATE__);
748   CLog::Log(LOGNOTICE, "Q is mapped to: %s", strExecutablePath.c_str());
749   char szXBEFileName[1024];
750   CIoSupport::GetXbePath(szXBEFileName);
751   CLog::Log(LOGNOTICE, "The executeable running is: %s", szXBEFileName);
752   CLog::Log(LOGNOTICE, "Log File is located: %s", strLogFile.c_str());
753   CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
754
755   g_settings.m_vecProfiles.clear();
756   g_settings.LoadProfiles("q:\\system\\profiles.xml");
757   if (g_settings.m_vecProfiles.size() == 0)
758   {
759     //no profiles yet, make one based on the default settings
760     CProfile profile;
761     profile.setDirectory("q:\\userdata");
762     profile.setName("Master user");
763     profile.setLockMode(LOCK_MODE_EVERYONE);
764     profile.setLockCode("");
765     profile.setDate("");
766     g_settings.m_vecProfiles.push_back(profile);
767   }
768
769   // if we are running from DVD our UserData location will be TDATA
770   if (CUtil::IsDVD(strExecutablePath))
771   {
772     // TODO: Should we copy over any UserData folder from the DVD?
773     if (!CFile::Exists("T:\\guisettings.xml")) // first run - cache userdata folder
774     {
775       CFileItemList items;
776       CUtil::GetRecursiveListing("q:\\userdata",items,"");
777       for (int i=0;i<items.Size();++i)
778           CFile::Cache(items[i]->m_strPath,"T:\\"+CUtil::GetFileName(items[i]->m_strPath));
779     }
780     g_settings.m_vecProfiles[0].setDirectory("T:\\");
781     g_stSettings.m_logFolder = "T:\\";
782   }
783   else
784   {
785     CStdString strMnt = g_settings.GetUserDataFolder();
786     if (g_settings.GetUserDataFolder().Left(2).Equals("Q:"))
787     {
788       CUtil::GetHomePath(strMnt);
789       strMnt += g_settings.GetUserDataFolder().substr(2);
790     }
791
792     CIoSupport::GetPartition(strMnt.c_str()[0], szDevicePath);
793     strcat(szDevicePath, &strMnt.c_str()[2]);
794     CIoSupport::RemapDriveLetter('T',szDevicePath);
795   }
796
797   CLog::Log(LOGNOTICE, "Setup DirectX");
798   // Create the Direct3D object
799   if ( NULL == ( m_pD3D = Direct3DCreate8(D3D_SDK_VERSION) ) )
800   {
801     CLog::Log(LOGFATAL, "XBAppEx: Unable to create Direct3D!" );
802     return E_FAIL;
803   }
804
805   //list available videomodes
806   g_videoConfig.GetModes(m_pD3D);
807   //init the present parameters with values that are supported
808   RESOLUTION initialResolution = g_videoConfig.GetInitialMode(m_pD3D, &m_d3dpp);
809   // Transfer the resolution information to our graphics context
810   g_graphicsContext.SetD3DParameters(&m_d3dpp);
811   g_graphicsContext.SetVideoResolution(initialResolution, TRUE);
812
813   // Initialize core peripheral port support. Note: If these parameters
814   // are 0 and NULL, respectively, then the default number and types of
815   // controllers will be initialized.
816 #ifdef HAS_XBOX_HARDWARE
817   XInitDevices( m_dwNumInputDeviceTypes, m_InputDeviceTypes );
818
819   // Create the gamepad devices
820   if ( FAILED(hr = XBInput_CreateGamepads(&m_Gamepad)) )
821   {
822     CLog::Log(LOGERROR, "XBAppEx: Call to CreateGamepads() failed!" );
823     return hr;
824   }
825
826   if ( FAILED(hr = XBInput_CreateIR_Remotes()) )
827   {
828     CLog::Log(LOGERROR, "XBAppEx: Call to CreateIRRemotes() failed!" );
829     return hr;
830   }
831 #endif
832
833   // Create the Mouse and Keyboard devices
834   g_Mouse.Initialize(hWnd);
835   g_Keyboard.Initialize(hWnd);
836
837 #ifdef HAS_XBOX_HARDWARE
838   // Wait for controller polling to finish. in an elegant way, instead of a Sleep(1000)
839   while (XGetDeviceEnumerationStatus() == XDEVICE_ENUMERATION_BUSY)
840   {
841     ReadInput();
842   }
843   Sleep(10); // needed or the readinput doesnt fetch anything
844   ReadInput();
845 #endif
846 #ifdef HAS_GAMEPAD
847   //Check for LTHUMBCLICK+RTHUMBCLICK and BLACK+WHITE, no LTRIGGER+RTRIGGER
848   if (((m_DefaultGamepad.wButtons & (XINPUT_GAMEPAD_LEFT_THUMB + XINPUT_GAMEPAD_RIGHT_THUMB)) && !(m_DefaultGamepad.wButtons & (KEY_BUTTON_LEFT_TRIGGER+KEY_BUTTON_RIGHT_TRIGGER))) ||
849       ((m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] && m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE]) && !(m_DefaultGamepad.wButtons & KEY_BUTTON_LEFT_TRIGGER+KEY_BUTTON_RIGHT_TRIGGER)))
850   {
851     CLog::Log(LOGINFO, "Key combination detected for userdata deletion (LTHUMB+RTHUMB or BLACK+WHITE)");
852     InitBasicD3D();
853     // D3D is up, load default font
854     XFONT* pFont;
855     if (XFONT_OpenDefaultFont(&pFont) != S_OK)
856     {
857       CLog::Log(LOGFATAL, "FATAL ERROR: Unable to open default font!");
858       Sleep(INFINITE); // die
859     }
860     // defaults for text
861     pFont->SetBkMode(XFONT_OPAQUE);
862     pFont->SetBkColor(D3DCOLOR_XRGB(0, 0, 0));
863     pFont->SetTextColor(D3DCOLOR_XRGB(0xff, 0x20, 0x20));
864     int iLine = 0;
865     FEH_TextOut(pFont, iLine++, L"Key combination for userdata deletion detected!");
866     FEH_TextOut(pFont, iLine++, L"Are you sure you want to proceed?");
867     iLine++;
868     FEH_TextOut(pFont, iLine++, L"A for yes, any other key for no");
869     bool bAnyAnalogKey = false;
870     while (m_DefaultGamepad.wPressedButtons != XBGAMEPAD_NONE) // wait for user to let go of lclick + rclick
871     {
872       ReadInput();
873     }
874     while (m_DefaultGamepad.wPressedButtons == XBGAMEPAD_NONE && !bAnyAnalogKey)
875     {
876       ReadInput();
877       bAnyAnalogKey = m_DefaultGamepad.bPressedAnalogButtons[0] || m_DefaultGamepad.bPressedAnalogButtons[1] || m_DefaultGamepad.bPressedAnalogButtons[2] || m_DefaultGamepad.bPressedAnalogButtons[3] || m_DefaultGamepad.bPressedAnalogButtons[4] || m_DefaultGamepad.bPressedAnalogButtons[5] || m_DefaultGamepad.bPressedAnalogButtons[6] || m_DefaultGamepad.bPressedAnalogButtons[7];
878     }
879     if (m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A])
880     {
881       CUtil::DeleteGUISettings();
882       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\database\\");
883       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\thumbnails\\");
884       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\playlists\\");
885       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\cache\\");
886       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\profiles\\");
887       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\visualisations\\");
888       CFile::Delete(g_settings.GetUserDataFolder()+"\\avpacksettings.xml");
889       g_settings.m_vecProfiles.erase(g_settings.m_vecProfiles.begin()+1,g_settings.m_vecProfiles.end());
890
891       g_settings.SaveProfiles("q:\\system\\profiles.xml");
892
893       char szXBEFileName[1024];
894
895       CIoSupport::GetXbePath(szXBEFileName);
896       CUtil::RunXBE(szXBEFileName);
897     }
898     m_pd3dDevice->Release();
899   }
900 #endif
901
902   CIoSupport::RemapDriveLetter('C', "Harddisk0\\Partition2");
903   CIoSupport::RemapDriveLetter('E', "Harddisk0\\Partition1");
904
905   CIoSupport::Dismount("Cdrom0");
906   CIoSupport::RemapDriveLetter('D', "Cdrom0");
907
908   // Attempt to read the LBA48 v3 patch partition table, if kernel supports the command and it exists.
909   CIoSupport::ReadPartitionTable();
910   if (CIoSupport::HasPartitionTable())
911   {
912     // Mount up to Partition15 (drive O:) if they are available.
913     for (int i=EXTEND_PARTITION_BEGIN; i <= EXTEND_PARTITION_END; i++)
914     {
915       char szDevice[32];
916       if (CIoSupport::PartitionExists(i))
917       {
918         char cDriveLetter = 'A' + i - 1;
919         sprintf(szDevice, "Harddisk0\\Partition%u", i);
920
921         CIoSupport::RemapDriveLetter(cDriveLetter, szDevice);
922       }
923     }
924   }
925   else
926   {
927     if (CIoSupport::DriveExists('F'))
928       CIoSupport::RemapDriveLetter('F', "Harddisk0\\Partition6");
929     if (CIoSupport::DriveExists('G'))
930       CIoSupport::RemapDriveLetter('G', "Harddisk0\\Partition7");
931   }
932
933   CIoSupport::RemapDriveLetter('X',"Harddisk0\\Partition3");
934   CIoSupport::RemapDriveLetter('Y',"Harddisk0\\Partition4");
935 #ifdef HAS_XBOX_HARDWARE
936   CIoSupport::RemapDriveLetter('Z',"Harddisk0\\Partition5");
937 #endif
938
939   CLog::Log(LOGINFO, "Drives are mapped");
940
941   CLog::Log(LOGNOTICE, "load settings...");
942   g_LoadErrorStr = "Unable to load settings";
943   g_settings.m_iLastUsedProfileIndex = g_settings.m_iLastLoadedProfileIndex;
944   if (g_settings.bUseLoginScreen && g_settings.m_iLastLoadedProfileIndex != 0)
945     g_settings.m_iLastLoadedProfileIndex = 0;
946
947   m_bAllSettingsLoaded = g_settings.Load(m_bXboxMediacenterLoaded, m_bSettingsLoaded);
948   if (!m_bAllSettingsLoaded)
949     FatalErrorHandler(true, true, true);
950
951   // Check for WHITE + Y for forced Error Handler (to recover if something screwy happens)
952 #ifdef HAS_GAMEPAD
953   if (m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_Y] && m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE])
954   {
955     g_LoadErrorStr = "Key code detected for Error Recovery mode";
956     FatalErrorHandler(true, true, true);
957   }
958 #endif
959
960   //Check for X+Y - if pressed, set debug log mode and mplayer debuging on
961   CheckForDebugButtonCombo();
962
963 #ifdef HAS_XBOX_HARDWARE
964   bool bNeedReboot = false;
965   char temp[1024];
966   CIoSupport::GetXbePath(temp);
967   char temp2[1024];
968   char temp3;
969   temp3 = temp[0];
970   CIoSupport::GetPartition(temp3,temp2);
971   CStdString strTemp(temp+2);
972   int iLastSlash = strTemp.rfind('\\');
973   strcat(temp2,strTemp.substr(0,iLastSlash).c_str());
974   F_VIDEO ForceVideo = VIDEO_NULL;
975   F_COUNTRY ForceCountry = COUNTRY_NULL;
976
977   if (CUtil::RemoveTrainer())
978     bNeedReboot = true;
979
980 // now check if we are switching video modes. if, are we in the wrong mode according to eeprom?
981   if (g_guiSettings.GetBool("myprograms.gameautoregion"))
982   {
983     bool fDoPatchTest = false;
984
985     // should use xkeeprom.h :/
986     EEPROMDATA EEPROM;
987     ZeroMemory(&EEPROM, sizeof(EEPROMDATA));
988
989     if( XKUtils::ReadEEPROMFromXBOX((LPBYTE)&EEPROM))
990     {
991       DWORD DWVideo = *(LPDWORD)(&EEPROM.VideoStandard[0]);
992       char temp[1024];
993       CIoSupport::GetXbePath(temp);
994       char temp2[1024];
995       char temp3;
996       temp3 = temp[0];
997       CIoSupport::GetPartition(temp3,temp2);
998       CStdString strTemp(temp+2);
999       int iLastSlash = strTemp.rfind('\\');
1000       strcat(temp2,strTemp.substr(0,iLastSlash).c_str());
1001
1002       if ((DWVideo == XKEEPROM::VIDEO_STANDARD::NTSC_M) && ((XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I) || (XGetVideoStandard() == XC_VIDEO_STANDARD_NTSC_J) || initialResolution > 5))
1003       {
1004         CLog::Log(LOGINFO, "Rebooting to change resolution from %s back to NTSC_M", (XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I) ? "PAL" : "NTSC_J");
1005         ForceVideo = VIDEO_NTSCM;
1006         ForceCountry = COUNTRY_USA;
1007         bNeedReboot = true;
1008         fDoPatchTest = true;
1009       }
1010       else if ((DWVideo == XKEEPROM::VIDEO_STANDARD::PAL_I) && ((XGetVideoStandard() == XC_VIDEO_STANDARD_NTSC_M) || (XGetVideoStandard() == XC_VIDEO_STANDARD_NTSC_J) || initialResolution < 6))
1011       {
1012         CLog::Log(LOGINFO, "Rebooting to change resolution from %s back to PAL_I", (XGetVideoStandard() == XC_VIDEO_STANDARD_NTSC_M) ? "NTSC_M" : "NTSC_J");
1013         ForceVideo = VIDEO_PAL50;
1014         ForceCountry = COUNTRY_EUR;
1015         bNeedReboot = true;
1016         fDoPatchTest = true;
1017       }
1018       else if ((DWVideo == XKEEPROM::VIDEO_STANDARD::NTSC_J) && ((XGetVideoStandard() == XC_VIDEO_STANDARD_NTSC_M) || (XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I) || initialResolution > 5))
1019       {
1020         CLog::Log(LOGINFO, "Rebooting to change resolution from %s back to NTSC_J", (XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I) ? "PAL" : "NTSC_M");
1021         ForceVideo = VIDEO_NTSCJ;
1022         ForceCountry = COUNTRY_JAP;
1023         bNeedReboot = true;
1024         fDoPatchTest = true;
1025       }
1026       else
1027         CUtil::RemoveKernelPatch(); // This removes the Resolution patch from the kernel if it is not needed (if actual resolution matches eeprom setting)
1028
1029       if (fDoPatchTest) // Is set if we have to test whether our patch is in the kernel & therefore responsible for the mismatch of resolution & eeprom setting
1030       {
1031         if (!CUtil::LookForKernelPatch()) // If our patch is not present we are not responsible for the mismatch of current resolution & eeprom setting
1032         {
1033           // We do a hard reset to come back to default resolution and avoid infinite reboots
1034           CLog::Log(LOGINFO, "No infinite reboot loop...");
1035           g_applicationMessenger.Reset();
1036         }
1037       }
1038     }
1039   }
1040
1041   if (bNeedReboot)
1042   {
1043     Destroy();
1044     CUtil::LaunchXbe(temp2,("D:\\"+strTemp.substr(iLastSlash+1)).c_str(),NULL,ForceVideo,ForceCountry);
1045   }
1046 #endif
1047
1048   CStdString strHomePath = "Q:";
1049   CLog::Log(LOGINFO, "Checking skinpath existance, and existence of keymap.xml:%s...", (strHomePath + "\\skin").c_str());
1050   CStdString keymapPath;
1051
1052   keymapPath = g_settings.GetUserDataItem("keymap.xml");
1053 #ifdef _XBOX
1054   if (access(strHomePath + "\\skin", 0) || access(keymapPath.c_str(), 0))
1055   {
1056     g_LoadErrorStr = "Unable to find skin or Keymap.xml.  Make sure you have UserData/Keymap.xml and Skin/ folder";
1057     FatalErrorHandler(true, false, true);
1058   }
1059 #endif
1060
1061   if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
1062   {
1063     // Oh uh - doesn't look good for starting in their wanted screenmode
1064     CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
1065     g_guiSettings.m_LookAndFeelResolution = initialResolution;
1066   }
1067   // Transfer the new resolution information to our graphics context
1068 #ifndef HAS_XBOX_D3D
1069   m_d3dpp.Windowed = TRUE;
1070   m_d3dpp.hDeviceWindow = g_hWnd;
1071 #else
1072 #define D3DCREATE_MULTITHREADED 0
1073 #endif
1074   g_graphicsContext.SetD3DParameters(&m_d3dpp);
1075   g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution, TRUE);
1076   if ( FAILED( hr = m_pD3D->CreateDevice(0, D3DDEVTYPE_HAL, NULL,
1077                                          D3DCREATE_MULTITHREADED | D3DCREATE_HARDWARE_VERTEXPROCESSING,
1078                                          &m_d3dpp, &m_pd3dDevice ) ) )
1079   {
1080     // try software vertex processing
1081     if ( FAILED( hr = m_pD3D->CreateDevice(0, D3DDEVTYPE_HAL, NULL,
1082                                           D3DCREATE_MULTITHREADED | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
1083                                           &m_d3dpp, &m_pd3dDevice ) ) )
1084     {
1085       // and slow as arse reference processing
1086       if ( FAILED( hr = m_pD3D->CreateDevice(0, D3DDEVTYPE_REF, NULL,
1087                                             D3DCREATE_MULTITHREADED | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
1088                                             &m_d3dpp, &m_pd3dDevice ) ) )
1089       {
1090
1091         CLog::Log(LOGFATAL, "XBAppEx: Could not create D3D device!" );
1092         CLog::Log(LOGFATAL, " width/height:(%ix%i)" , m_d3dpp.BackBufferWidth, m_d3dpp.BackBufferHeight);
1093         CLog::Log(LOGFATAL, " refreshrate:%i" , m_d3dpp.FullScreen_RefreshRateInHz);
1094         if (m_d3dpp.Flags & D3DPRESENTFLAG_WIDESCREEN)
1095           CLog::Log(LOGFATAL, " 16:9 widescreen");
1096         else
1097           CLog::Log(LOGFATAL, " 4:3");
1098
1099         if (m_d3dpp.Flags & D3DPRESENTFLAG_INTERLACED)
1100           CLog::Log(LOGFATAL, " interlaced");
1101         if (m_d3dpp.Flags & D3DPRESENTFLAG_PROGRESSIVE)
1102           CLog::Log(LOGFATAL, " progressive");
1103         return hr;
1104       }
1105     }
1106   }
1107   g_graphicsContext.SetD3DDevice(m_pd3dDevice);
1108   // set filters
1109   g_graphicsContext.Get3DDevice()->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR /*g_stSettings.m_minFilter*/ );
1110   g_graphicsContext.Get3DDevice()->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR /*g_stSettings.m_maxFilter*/ );
1111   CUtil::InitGamma();
1112   // set GUI res and force the clear of the screen
1113   g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution, TRUE, true);
1114
1115   // initialize our charset converter
1116   g_charsetConverter.reset();
1117
1118   // Load the langinfo to have user charset <-> utf-8 conversion
1119   CStdString strLangInfoPath;
1120   strLangInfoPath.Format("Q:\\language\\%s\\langinfo.xml", g_guiSettings.GetString("locale.language"));
1121
1122   CLog::Log(LOGINFO, "load language info file:%s", strLangInfoPath.c_str());
1123   g_langInfo.Load(strLangInfoPath);
1124
1125   m_splash = new CSplash("Q:\\media\\splash.png");
1126   m_splash->Start();
1127
1128   CStdString strLanguagePath;
1129   strLanguagePath.Format("Q:\\language\\%s\\strings.xml", g_guiSettings.GetString("locale.language"));
1130
1131   CLog::Log(LOGINFO, "load language file:%s", strLanguagePath.c_str());
1132   if (!g_localizeStrings.Load(strLanguagePath ))
1133     FatalErrorHandler(false, false, true);
1134
1135   CLog::Log(LOGINFO, "load keymapping");
1136   if (!g_buttonTranslator.Load())
1137     FatalErrorHandler(false, false, true);
1138
1139   // check the skin file for testing purposes
1140   CStdString strSkinBase = "Q:\\skin\\";
1141   CStdString strSkinPath = strSkinBase + g_guiSettings.GetString("lookandfeel.skin");
1142   CLog::Log(LOGINFO, "Checking skin version of: %s", g_guiSettings.GetString("lookandfeel.skin").c_str());
1143   if (!g_SkinInfo.Check(strSkinPath))
1144   {
1145     // reset to the default skin (Project Mayhem III)
1146     CLog::Log(LOGINFO, "The above skin isn't suitable - checking the version of the default: %s", "Project Mayhem III");
1147     strSkinPath = strSkinBase + "Project Mayhem III";
1148     if (!g_SkinInfo.Check(strSkinPath))
1149     {
1150       g_LoadErrorStr.Format("No suitable skin version found.\nWe require at least version %5.4f \n", g_SkinInfo.GetMinVersion());
1151       FatalErrorHandler(false, false, true);
1152     }
1153   }
1154   int iResolution = g_graphicsContext.GetVideoResolution();
1155   CLog::Log(LOGINFO, " GUI format %ix%i %s",
1156             g_settings.m_ResInfo[iResolution].iWidth,
1157             g_settings.m_ResInfo[iResolution].iHeight,
1158             g_settings.m_ResInfo[iResolution].strMode);
1159   m_gWindowManager.Initialize();
1160
1161   g_actionManager.SetScriptActionCallback(&g_pythonParser);
1162
1163   // show recovery console on fatal error instead of freezing
1164   CLog::Log(LOGINFO, "install unhandled exception filter");
1165   SetUnhandledExceptionFilter(UnhandledExceptionFilter);
1166
1167 #ifdef HAS_XBOX_D3D
1168   D3DDevice::SetWaitCallback(WaitCallback);
1169 #endif
1170
1171   return CXBApplicationEx::Create(hWnd);
1172 }
1173
1174 HRESULT CApplication::Initialize()
1175 {
1176   CLog::Log(LOGINFO, "creating subdirectories");
1177
1178   //CLog::Log(LOGINFO, "userdata folder: %s", g_stSettings.m_userDataFolder.c_str());
1179   CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
1180   CLog::Log(LOGINFO, "  recording folder:%s", g_guiSettings.GetString("mymusic.recordingpath",false).c_str());
1181   CLog::Log(LOGINFO, "  screenshots folder:%s", g_guiSettings.GetString("pictures.screenshotpath",false).c_str());
1182
1183   // UserData folder layout:
1184   // UserData/
1185   //   Database/
1186   //     CDDb/
1187   //   Thumbnails/
1188   //     Music/
1189   //       temp/
1190   //     0 .. F/
1191   //     XLinkKai/
1192
1193   CreateDirectory(g_settings.GetUserDataFolder().c_str(), NULL);
1194   CreateDirectory(g_settings.GetProfileUserDataFolder().c_str(), NULL);
1195   CreateDirectory(g_settings.GetDatabaseFolder().c_str(), NULL);
1196   CreateDirectory(g_settings.GetCDDBFolder().c_str(), NULL);
1197
1198   // Thumbnails/
1199   CreateDirectory(g_settings.GetThumbnailsFolder().c_str(), NULL);
1200   CreateDirectory(g_settings.GetMusicThumbFolder().c_str(), NULL);
1201   CreateDirectory(g_settings.GetMusicArtistThumbFolder().c_str(), NULL);
1202   CreateDirectory(g_settings.GetLastFMThumbFolder().c_str(), NULL);
1203   CreateDirectory(g_settings.GetVideoThumbFolder().c_str(), NULL);
1204   CreateDirectory(g_settings.GetBookmarksThumbFolder().c_str(), NULL);
1205   CreateDirectory(g_settings.GetProgramsThumbFolder().c_str(), NULL);
1206   CreateDirectory(g_settings.GetGameSaveThumbFolder().c_str(), NULL);
1207   CreateDirectory(g_settings.GetXLinkKaiThumbFolder().c_str(), NULL);
1208   CreateDirectory(g_settings.GetPicturesThumbFolder().c_str(), NULL);
1209   CreateDirectory(g_settings.GetProfilesThumbFolder().c_str(),NULL);
1210   CLog::Log(LOGINFO, "  thumbnails folder:%s", g_settings.GetThumbnailsFolder().c_str());
1211   for (unsigned int hex=0; hex < 16; hex++)
1212   {
1213     CStdString strHex;
1214     strHex.Format("%x",hex);
1215     CStdString strThumbLoc = g_settings.GetPicturesThumbFolder();
1216     strThumbLoc += "\\" + strHex;
1217     CreateDirectory(strThumbLoc.c_str(),NULL);
1218     strThumbLoc = g_settings.GetMusicThumbFolder();
1219     strThumbLoc += "\\" + strHex;
1220     CreateDirectory(strThumbLoc.c_str(),NULL);
1221   }
1222
1223   CreateDirectory("Z:\\temp", NULL); // temp directory for python and dllGetTempPathA
1224   CreateDirectory("Q:\\scripts", NULL);
1225   CreateDirectory("Q:\\language", NULL);
1226   CreateDirectory("Q:\\visualisations", NULL);
1227   CreateDirectory("Q:\\sounds", NULL);
1228   CreateDirectory(g_settings.GetUserDataFolder()+"\\visualisations",NULL);
1229
1230   // initialize network
1231   if (!m_bXboxMediacenterLoaded)
1232   {
1233     CLog::Log(LOGINFO, "using default network settings");
1234     g_guiSettings.SetString("network.ipaddress", "192.168.0.100");
1235     g_guiSettings.SetString("network.subnet", "255.255.255.0");
1236     g_guiSettings.SetString("network.gateway", "192.168.0.1");
1237     g_guiSettings.SetString("network.dns", "192.168.0.1");
1238     g_guiSettings.SetBool("servers.ftpserver", true);
1239     g_guiSettings.SetBool("servers.webserver", false);
1240     g_guiSettings.SetBool("locale.timeserver", false);
1241   }
1242
1243   StartServices();
1244
1245   m_gWindowManager.Add(new CGUIWindowHome);                     // window id = 0
1246
1247   CLog::Log(LOGNOTICE, "load default skin:[%s]", g_guiSettings.GetString("lookandfeel.skin").c_str());
1248   LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1249
1250   m_gWindowManager.Add(new CGUIWindowPrograms);                 // window id = 1
1251   m_gWindowManager.Add(new CGUIWindowPictures);                 // window id = 2
1252   m_gWindowManager.Add(new CGUIWindowFileManager);      // window id = 3
1253   m_gWindowManager.Add(new CGUIWindowVideoFiles);          // window id = 6
1254   m_gWindowManager.Add(new CGUIWindowSettings);                 // window id = 4
1255   m_gWindowManager.Add(new CGUIWindowSystemInfo);               // window id = 7
1256   m_gWindowManager.Add(new CGUIWindowSettingsScreenCalibration); // window id = 11
1257   m_gWindowManager.Add(new CGUIWindowSettingsCategory);         // window id = 12 slideshow:window id 2007
1258   m_gWindowManager.Add(new CGUIWindowScripts);                  // window id = 20
1259   m_gWindowManager.Add(new CGUIWindowVideoNav);                 // window id = 36
1260   m_gWindowManager.Add(new CGUIWindowVideoPlaylist);            // window id = 28
1261   m_gWindowManager.Add(new CGUIWindowLoginScreen);            // window id = 29
1262   m_gWindowManager.Add(new CGUIWindowSettingsProfile);          // window id = 34
1263   m_gWindowManager.Add(new CGUIWindowGameSaves);               // window id = 35
1264   m_gWindowManager.Add(new CGUIDialogYesNo);              // window id = 100
1265   m_gWindowManager.Add(new CGUIDialogProgress);           // window id = 101
1266   m_gWindowManager.Add(new CGUIDialogInvite);             // window id = 102
1267   m_gWindowManager.Add(new CGUIDialogKeyboard);           // window id = 103
1268   m_gWindowManager.Add(&m_guiDialogVolumeBar);          // window id = 104
1269   m_gWindowManager.Add(&m_guiDialogSeekBar);            // window id = 115
1270   m_gWindowManager.Add(new CGUIDialogSubMenu);            // window id = 105
1271   m_gWindowManager.Add(new CGUIDialogContextMenu);        // window id = 106
1272   m_gWindowManager.Add(&m_guiDialogKaiToast);           // window id = 107
1273   m_gWindowManager.Add(new CGUIDialogHost);               // window id = 108
1274   m_gWindowManager.Add(new CGUIDialogNumeric);            // window id = 109
1275   m_gWindowManager.Add(new CGUIDialogGamepad);            // window id = 110
1276   m_gWindowManager.Add(new CGUIDialogButtonMenu);         // window id = 111
1277   m_gWindowManager.Add(new CGUIDialogMusicScan);          // window id = 112
1278   m_gWindowManager.Add(new CGUIDialogPlayerControls);     // window id = 113
1279   m_gWindowManager.Add(new CGUIDialogMusicOSD);           // window id = 120
1280   m_gWindowManager.Add(new CGUIDialogVisualisationSettings);     // window id = 121
1281   m_gWindowManager.Add(new CGUIDialogVisualisationPresetList);   // window id = 122
1282   m_gWindowManager.Add(new CGUIDialogVideoSettings);             // window id = 123
1283   m_gWindowManager.Add(new CGUIDialogAudioSubtitleSettings);     // window id = 124
1284   m_gWindowManager.Add(new CGUIDialogVideoBookmarks);      // window id = 125
1285   // Don't add the filebrowser dialog - it's created and added when it's needed
1286   m_gWindowManager.Add(new CGUIDialogTrainerSettings);  // window id = 127
1287   m_gWindowManager.Add(new CGUIDialogNetworkSetup);  // window id = 128
1288   m_gWindowManager.Add(new CGUIDialogMediaSource);   // window id = 129
1289   m_gWindowManager.Add(new CGUIDialogProfileSettings); // window id = 130
1290   m_gWindowManager.Add(new CGUIDialogVideoScan);      // window id = 133
1291
1292   CGUIDialogLockSettings* pDialog = NULL;
1293   CStdString strPath;
1294   RESOLUTION res2;
1295   strPath = g_SkinInfo.GetSkinPath("LockSettings.xml", &res2);
1296   if (CFile::Exists(strPath))
1297     pDialog = new CGUIDialogLockSettings;
1298
1299   if (pDialog)
1300     m_gWindowManager.Add(pDialog); // window id = 131
1301
1302   m_gWindowManager.Add(new CGUIDialogContentSettings);        // window id = 132
1303
1304   m_gWindowManager.Add(new CGUIWindowMusicPlayList);          // window id = 500
1305   m_gWindowManager.Add(new CGUIWindowMusicSongs);             // window id = 501
1306   m_gWindowManager.Add(new CGUIWindowMusicNav);               // window id = 502
1307   m_gWindowManager.Add(new CGUIWindowMusicPlaylistEditor);    // window id = 503
1308
1309   m_gWindowManager.Add(new CGUIDialogSelect);             // window id = 2000
1310   m_gWindowManager.Add(new CGUIWindowMusicInfo);                // window id = 2001
1311   m_gWindowManager.Add(new CGUIDialogOK);                 // window id = 2002
1312   m_gWindowManager.Add(new CGUIWindowVideoInfo);                // window id = 2003
1313   m_gWindowManager.Add(new CGUIWindowScriptsInfo);              // window id = 2004
1314   m_gWindowManager.Add(new CGUIWindowFullScreen);         // window id = 2005
1315   m_gWindowManager.Add(new CGUIWindowVisualisation);      // window id = 2006
1316   m_gWindowManager.Add(new CGUIWindowSlideShow);          // window id = 2007
1317   m_gWindowManager.Add(new CGUIDialogFileStacking);       // window id = 2008
1318
1319   m_gWindowManager.Add(new CGUIWindowOSD);                // window id = 2901
1320   m_gWindowManager.Add(new CGUIWindowMusicOverlay);       // window id = 2903
1321   m_gWindowManager.Add(new CGUIWindowVideoOverlay);       // window id = 2904
1322   m_gWindowManager.Add(new CGUIWindowScreensaver);        // window id = 2900 Screensaver
1323   m_gWindowManager.Add(new CGUIWindowWeather);                // window id = 2600 WEATHER
1324   m_gWindowManager.Add(new CGUIWindowBuddies);                // window id = 2700 BUDDIES
1325   m_gWindowManager.Add(new CGUIWindow(WINDOW_STARTUP, "Startup.xml"));  // startup window (id 2999)
1326
1327   /* window id's 3000 - 3100 are reserved for python */
1328   g_DownloadManager.Initialize();
1329
1330   m_ctrDpad.SetDelays(100, 500); //g_stSettings.m_iMoveDelayController, g_stSettings.m_iRepeatDelayController);
1331
1332   SAFE_DELETE(m_splash);
1333
1334   if (g_guiSettings.GetBool("masterlock.startuplock") && g_settings.m_vecProfiles[0].getLockMode() != LOCK_MODE_EVERYONE && !g_settings.m_vecProfiles[0].getLockCode().IsEmpty())
1335     g_passwordManager.CheckStartUpLock();
1336
1337   // check if we should use the login screen
1338   if (g_settings.bUseLoginScreen)
1339   {
1340     m_gWindowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1341   }
1342   else
1343   {
1344     RESOLUTION res = INVALID;
1345     CStdString startupPath = g_SkinInfo.GetSkinPath("startup.xml", &res);
1346     int startWindow = g_guiSettings.GetInt("lookandfeel.startupwindow");
1347     // test for a startup window, and activate that instead of home
1348     if (CFile::Exists(startupPath) && (!g_SkinInfo.OnlyAnimateToHome() || startWindow == WINDOW_HOME))
1349     {
1350       m_gWindowManager.ActivateWindow(WINDOW_STARTUP);
1351     }
1352     else
1353     {
1354       // We need to Popup the WindowHome to initiate the GUIWindowManger for MasterCode popup dialog!
1355       // Then we can start the StartUpWindow! To prevent BlackScreen if the target Window is Protected with MasterCode!
1356       m_gWindowManager.ActivateWindow(WINDOW_HOME);
1357       if (startWindow != WINDOW_HOME)
1358         m_gWindowManager.ActivateWindow(startWindow);
1359     }
1360   }
1361   /* setup network based on our settings */
1362   /* network will start it's init procedure */
1363   g_network.Initialize(g_guiSettings.GetInt("network.assignment"),
1364     g_guiSettings.GetString("network.ipaddress").c_str(),
1365     g_guiSettings.GetString("network.subnet").c_str(),
1366     g_guiSettings.GetString("network.gateway").c_str(),
1367     g_guiSettings.GetString("network.dns").c_str());
1368
1369   g_pythonParser.bStartup = true;
1370   g_sysinfo.Refresh();
1371
1372   CLog::Log(LOGINFO, "removing tempfiles");
1373   CUtil::RemoveTempFiles();
1374
1375   if (!m_bAllSettingsLoaded)
1376   {
1377     CLog::Log(LOGWARNING, "settings not correct, show dialog");
1378     CStdString test;
1379     CUtil::GetHomePath(test);
1380     CGUIDialogOK *dialog = (CGUIDialogOK *)m_gWindowManager.GetWindow(WINDOW_DIALOG_OK);
1381     if (dialog)
1382     {
1383       dialog->SetHeading(279);
1384       dialog->SetLine(0, "Error while loading settings");
1385       dialog->SetLine(1, test);
1386       dialog->SetLine(2, "");;
1387       dialog->DoModal();
1388     }
1389   }
1390
1391   //  Show mute symbol
1392   if (g_stSettings.m_nVolumeLevel == VOLUME_MINIMUM)
1393     Mute();
1394
1395   // if the user shutoff the xbox during music scan
1396   // restore the settings
1397   if (g_stSettings.m_bMyMusicIsScanning)
1398   {
1399     CLog::Log(LOGWARNING,"System rebooted during music scan! ... restoring UseTags and FindRemoteThumbs");
1400     RestoreMusicScanSettings();
1401   }
1402
1403   m_slowTimer.StartZero();
1404
1405   CLog::Log(LOGNOTICE, "initialize done");
1406
1407   m_bInitializing = false;
1408
1409   // final check for debugging combo
1410   CheckForDebugButtonCombo();
1411   return S_OK;
1412 }
1413
1414 void CApplication::PrintXBEToLCD(const char* xbePath)
1415 {
1416 #ifdef HAS_LCD
1417   int pLine = 0;
1418   CStdString strXBEName;
1419   if (!CUtil::GetXBEDescription(xbePath, strXBEName))
1420   {
1421     CUtil::GetDirectoryName(xbePath, strXBEName);
1422     CUtil::ShortenFileName(strXBEName);
1423     CUtil::RemoveIllegalChars(strXBEName);
1424   }
1425   // crop to LCD screen size
1426   if ((int)strXBEName.size() > g_advancedSettings.m_lcdColumns)
1427     strXBEName = strXBEName.Left(g_advancedSettings.m_lcdColumns);
1428   if (g_lcd)
1429   {
1430     g_lcd->SetLine(pLine++, "");
1431     g_lcd->SetLine(pLine++, "Playing");
1432     g_lcd->SetLine(pLine++, strXBEName);
1433     g_lcd->SetLine(pLine++, "");
1434   }
1435 #endif
1436 }
1437
1438 void CApplication::StartIdleThread()
1439 {
1440   m_idleThread.Create(false, 0x100);
1441 }
1442
1443 void CApplication::StopIdleThread()
1444 {
1445   m_idleThread.StopThread();
1446 }
1447
1448 void CApplication::StartWebServer()
1449 {
1450   if (g_guiSettings.GetBool("servers.webserver") && g_network.IsAvailable() )
1451   {
1452     CLog::Log(LOGNOTICE, "Webserver: Starting...");
1453     CSectionLoader::Load("LIBHTTP");
1454     m_pWebServer = new CWebServer();
1455     m_pWebServer->Start(g_network.m_networkinfo.ip, atoi(g_guiSettings.GetString("servers.webserverport")), "Q:\\web", false);
1456         if (pXbmcHttp)
1457       pXbmcHttp->xbmcBroadcast("StartUp", 1);
1458   }
1459 }
1460
1461 void CApplication::StopWebServer()
1462 {
1463   if (m_pWebServer)
1464   {
1465     CLog::Log(LOGNOTICE, "Webserver: Stopping...");
1466     m_pWebServer->Stop();
1467     delete m_pWebServer;
1468     m_pWebServer = NULL;
1469     CSectionLoader::Unload("LIBHTTP");
1470     CLog::Log(LOGNOTICE, "Webserver: Stopped...");
1471   }
1472 }
1473
1474 void CApplication::StartFtpServer()
1475 {
1476 #ifdef HAS_FTP_SERVER
1477   if ( g_guiSettings.GetBool("servers.ftpserver") && g_network.IsAvailable() )
1478   {
1479     CLog::Log(LOGNOTICE, "XBFileZilla: Starting...");
1480     if (!m_pFileZilla)
1481     {
1482       // if user didn't upgrade properly...
1483       // check whether P:\\FileZilla Server.xml exists (UserData/FileZilla Server.xml)
1484       if (CFile::Exists(g_settings.GetUserDataItem("FileZilla Server.xml")))
1485         m_pFileZilla = new CXBFileZilla(g_settings.GetUserDataFolder());
1486       else
1487         m_pFileZilla = new CXBFileZilla("Q:\\System\\");
1488       m_pFileZilla->Start(false);
1489     }
1490     //CLog::Log(LOGNOTICE, "XBFileZilla: Started");
1491   }
1492 #endif
1493 }
1494
1495 void CApplication::StopFtpServer()
1496 {
1497 #ifdef HAS_FTP_SERVER
1498   if (m_pFileZilla)
1499   {
1500     CLog::Log(LOGINFO, "XBFileZilla: Stopping...");
1501
1502     std::vector<SXFConnection> mConnections;
1503     std::vector<SXFConnection>::iterator it;
1504
1505     m_pFileZilla->GetAllConnections(mConnections);
1506
1507     for(it = mConnections.begin();it != mConnections.end();it++)
1508     {
1509       m_pFileZilla->CloseConnection(it->mId);
1510     }
1511
1512     m_pFileZilla->Stop();
1513     delete m_pFileZilla;
1514     m_pFileZilla = NULL;
1515
1516     CLog::Log(LOGINFO, "XBFileZilla: Stopped");
1517   }
1518 #endif
1519 }
1520
1521 void CApplication::StartTimeServer()
1522 {
1523 #ifdef HAS_TIME_SERVER
1524   if (g_guiSettings.GetBool("locale.timeserver") && g_network.IsAvailable() )
1525   {
1526     if( !m_psntpClient )
1527     {
1528       CSectionLoader::Load("SNTP");
1529       CLog::Log(LOGNOTICE, "start timeserver client");
1530
1531       m_psntpClient = new CSNTPClient();
1532       m_psntpClient->Update();
1533     }
1534   }
1535 #endif
1536 }
1537
1538 void CApplication::StopTimeServer()
1539 {
1540 #ifdef HAS_TIME_SERVER
1541   if( m_psntpClient )
1542   {
1543     CLog::Log(LOGNOTICE, "stop time server client");
1544     SAFE_DELETE(m_psntpClient);
1545     CSectionLoader::Unload("SNTP");
1546   }
1547 #endif
1548 }
1549
1550 void CApplication::StartKai()
1551 {
1552   if (g_guiSettings.GetBool("xlinkkai.enabled"))
1553   {
1554     CGUIWindowBuddies *pKai = (CGUIWindowBuddies*)m_gWindowManager.GetWindow(WINDOW_BUDDIES);
1555     if (pKai)
1556     {
1557       CLog::Log(LOGNOTICE, "starting kai");
1558       CKaiClient::GetInstance()->SetObserver(pKai);
1559     }
1560   }
1561 }
1562
1563 void CApplication::StopKai()
1564 {
1565   if (CKaiClient::IsInstantiated())
1566   {
1567     CLog::Log(LOGNOTICE, "stopping kai");
1568     CKaiClient::GetInstance()->RemoveObserver();
1569     CKaiClient::RemoveInstance();
1570   }
1571 }
1572
1573 void CApplication::StartUPnP()
1574 {
1575 #ifdef HAS_UPNP
1576     StartUPnPClient();
1577     StartUPnPServer();
1578 #endif
1579 }
1580
1581 void CApplication::StopUPnP()
1582 {
1583 #ifdef HAS_UPNP
1584   if (CUPnP::IsInstantiated())
1585   {
1586     CLog::Log(LOGNOTICE, "stopping upnp");
1587     CUPnP::ReleaseInstance();
1588   }
1589 #endif
1590 }
1591
1592 void CApplication::StartUPnPClient()
1593 {
1594 #ifdef HAS_UPNP
1595   if (g_guiSettings.GetBool("upnp.client"))
1596   {
1597     CLog::Log(LOGNOTICE, "starting upnp client");
1598     CUPnP::GetInstance()->StartClient();
1599   }
1600 #endif
1601 }
1602
1603 void CApplication::StopUPnPClient()
1604 {
1605 #ifdef HAS_UPNP
1606   if (CUPnP::IsInstantiated())
1607   {
1608     CLog::Log(LOGNOTICE, "stopping upnp client");
1609     CUPnP::GetInstance()->StopClient();
1610   }
1611 #endif
1612 }
1613
1614 void CApplication::StartUPnPServer()
1615 {
1616 #ifdef HAS_UPNP
1617   if (g_guiSettings.GetBool("upnp.server"))
1618   {
1619     CLog::Log(LOGNOTICE, "starting upnp server");
1620     CUPnP::GetInstance()->StartServer();
1621   }
1622 #endif
1623 }
1624
1625 void CApplication::StopUPnPServer()
1626 {
1627 #ifdef HAS_UPNP
1628   if (CUPnP::IsInstantiated())
1629   {
1630     CLog::Log(LOGNOTICE, "stopping upnp server");
1631     CUPnP::GetInstance()->StopServer();
1632   }
1633 #endif
1634 }
1635
1636 void CApplication::StartLEDControl(bool switchoff)
1637 {
1638 #ifdef HAS_XBOX_HARDWARE
1639   if (switchoff && g_guiSettings.GetInt("system.ledcolour") != LED_COLOUR_NO_CHANGE)
1640   {
1641 #ifdef AFTER2_0
1642     if(CDetectDVDMedia::DriveReady() != DRIVE_NOT_READY)
1643     {
1644 #endif
1645       if ( IsPlayingVideo() && (g_guiSettings.GetInt("system.leddisableonplayback") == LED_PLAYBACK_VIDEO))
1646       {
1647         //CLog::Log(LOGNOTICE, "LED Control: Playing Video LED is switched OFF!");
1648         ILED::CLEDControl(LED_COLOUR_OFF);
1649       }
1650       if ( IsPlayingAudio() && (g_guiSettings.GetInt("system.leddisableonplayback") == LED_PLAYBACK_MUSIC))
1651       {
1652         //CLog::Log(LOGNOTICE, "LED Control: Playing Music LED is switched OFF!");
1653         ILED::CLEDControl(LED_COLOUR_OFF);
1654       }
1655       if ( ((IsPlayingVideo() || IsPlayingAudio())) && (g_guiSettings.GetInt("system.leddisableonplayback") == LED_PLAYBACK_VIDEO_MUSIC))
1656       {
1657         //CLog::Log(LOGNOTICE, "LED Control: Playing Video Or Music LED is switched OFF!");
1658         ILED::CLEDControl(LED_COLOUR_OFF);
1659       }
1660 #ifdef AFTER2_0
1661     }
1662 #endif
1663   }
1664   else if (!switchoff)
1665   {
1666     ILED::CLEDControl(g_guiSettings.GetInt("system.ledcolour"));
1667   }
1668 #endif
1669 }
1670
1671 void CApplication::DimLCDOnPlayback(bool dim)
1672 {
1673 #ifdef HAS_LCD
1674   if(g_lcd && dim && (g_guiSettings.GetInt("lcd.disableonplayback") != LED_PLAYBACK_OFF) && (g_guiSettings.GetInt("lcd.type") != LCD_TYPE_NONE))
1675   {
1676     if ( (IsPlayingVideo()) && g_guiSettings.GetInt("lcd.disableonplayback") == LED_PLAYBACK_VIDEO)
1677     {
1678       //CLog::Log(LOGNOTICE, "LCD Control: Playing Video LCD is switched OFF!");
1679       g_lcd->SetBackLight(0);
1680     }
1681     if ( (IsPlayingAudio()) && g_guiSettings.GetInt("lcd.disableonplayback") == LED_PLAYBACK_MUSIC)
1682     {
1683       //CLog::Log(LOGNOTICE, "LCD Control: Playing Music LCD is switched OFF!");
1684       g_lcd->SetBackLight(0);
1685     }
1686     if ( ((IsPlayingVideo() || IsPlayingAudio())) && g_guiSettings.GetInt("lcd.disableonplayback") == LED_PLAYBACK_VIDEO_MUSIC)
1687     {
1688       //CLog::Log(LOGNOTICE, "LCD Control: Playing Video Or Music LCD is switched OFF!");
1689       g_lcd->SetBackLight(0);
1690     }
1691   }
1692   else if(!dim)
1693   {
1694     g_lcd->SetBackLight(g_guiSettings.GetInt("lcd.backlight"));
1695   }
1696 #endif
1697 }
1698
1699 void CApplication::StartServices()
1700 {
1701   StartIdleThread();
1702
1703   CheckDate();
1704   StartLEDControl(false);
1705
1706   // Start Thread for DVD Mediatype detection
1707   CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1708   m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1709
1710   CLog::Log(LOGNOTICE, "initializing playlistplayer");
1711   g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, g_stSettings.m_bMyMusicPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1712   g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, g_stSettings.m_bMyMusicPlaylistShuffle);
1713   g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, g_stSettings.m_bMyVideoPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1714   g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, g_stSettings.m_bMyVideoPlaylistShuffle);
1715   CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1716
1717 #ifdef HAS_LCD
1718   CLCDFactory factory;
1719   g_lcd = factory.Create();
1720   if (g_lcd)
1721   {
1722     g_lcd->Initialize();
1723   }
1724 #endif
1725
1726 #ifdef HAS_XBOX_HARDWARE
1727   if (g_guiSettings.GetBool("system.autotemperature"))
1728   {
1729     CLog::Log(LOGNOTICE, "start fancontroller");
1730     CFanController::Instance()->Start(g_guiSettings.GetInt("system.targettemperature"));
1731   }
1732   else if (g_guiSettings.GetBool("system.fanspeedcontrol"))
1733   {
1734     CLog::Log(LOGNOTICE, "setting fanspeed");
1735     CFanController::Instance()->SetFanSpeed(g_guiSettings.GetInt("system.fanspeed"));
1736   }
1737   int setting_level = g_guiSettings.GetInt("harddisk.aamlevel");
1738   if (setting_level == AAM_QUIET)
1739     XKHDD::SetAAMLevel(0x80);
1740   else if (setting_level == AAM_FAST)
1741     XKHDD::SetAAMLevel(0xFE);
1742   setting_level = g_guiSettings.GetInt("harddisk.apmlevel");
1743   switch(setting_level)
1744   {
1745   case APM_LOPOWER:
1746     XKHDD::SetAPMLevel(0x80);
1747     break;
1748   case APM_HIPOWER:
1749     XKHDD::SetAPMLevel(0xFE);
1750     break;
1751   case APM_LOPOWER_STANDBY:
1752     XKHDD::SetAPMLevel(0x01);
1753     break;
1754   case APM_HIPOWER_STANDBY:
1755     XKHDD::SetAPMLevel(0x7F);
1756     break;
1757   }
1758 #endif
1759 }
1760
1761 void CApplication::CheckDate()
1762 {
1763   CLog::Log(LOGNOTICE, "Checking the Date!");
1764   // Check the Date: Year, if it is  above 2099 set to 2004!
1765   SYSTEMTIME CurTime;
1766   SYSTEMTIME NewTime;
1767   GetLocalTime(&CurTime);
1768   GetLocalTime(&NewTime);
1769   CLog::Log(LOGINFO, "- Current Date is: %i-%i-%i",CurTime.wDay, CurTime.wMonth, CurTime.wYear);
1770   if ((CurTime.wYear > 2099) || (CurTime.wYear < 2001) )        // XBOX MS Dashboard also uses min/max DateYear 2001/2099 !!
1771   {
1772     CLog::Log(LOGNOTICE, "- The Date is Wrong: Setting New Date!");
1773     NewTime.wYear               = 2004; // 2004
1774     NewTime.wMonth              = 1;    // January
1775     NewTime.wDayOfWeek  = 1;    // Monday
1776     NewTime.wDay                = 5;    // Monday 05.01.2004!!
1777     NewTime.wHour               = 12;
1778     NewTime.wMinute             = 0;
1779
1780     FILETIME stNewTime, stCurTime;
1781     SystemTimeToFileTime(&NewTime, &stNewTime);
1782     SystemTimeToFileTime(&CurTime, &stCurTime);
1783 #ifdef HAS_XBOX_HARDWARE
1784     NtSetSystemTime(&stNewTime, &stCurTime);    // Set a Default Year 2004!
1785 #endif
1786     CLog::Log(LOGNOTICE, "- New Date is now: %i-%i-%i",NewTime.wDay, NewTime.wMonth, NewTime.wYear);
1787   }
1788   return ;
1789 }
1790
1791 void CApplication::StopServices()
1792 {
1793   g_network.NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1794
1795   CLog::Log(LOGNOTICE, "stop dvd detect media");
1796   m_DetectDVDType.StopThread();
1797
1798 #ifdef HAS_XBOX_HARDWARE
1799   CLog::Log(LOGNOTICE, "stop fancontroller");
1800   CFanController::Instance()->Stop();
1801   CFanController::RemoveInstance();
1802 #endif
1803
1804   StopIdleThread();
1805 }
1806
1807 void CApplication::DelayLoadSkin()
1808 {
1809   m_dwSkinTime = timeGetTime() + 2000;
1810   return ;
1811 }
1812
1813 void CApplication::CancelDelayLoadSkin()
1814 {
1815   m_dwSkinTime = 0;
1816 }
1817
1818 void CApplication::ReloadSkin()
1819 {
1820   CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, m_gWindowManager.GetActiveWindow());
1821   g_graphicsContext.SendMessage(msg);
1822   // Reload the skin, restoring the previously focused control
1823   CGUIWindow* pWindow = m_gWindowManager.GetWindow(m_gWindowManager.GetActiveWindow());
1824   unsigned iCtrlID = pWindow->GetFocusedControlID();
1825   g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1826   CGUIMessage msg3(GUI_MSG_SETFOCUS, m_gWindowManager.GetActiveWindow(), iCtrlID, 0);
1827   pWindow->OnMessage(msg3);
1828 }
1829
1830 void CApplication::LoadSkin(const CStdString& strSkin)
1831 {
1832   bool bPreviousPlayingState=false;
1833   bool bPreviousRenderingState=false;
1834   if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1835   {
1836     bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1837     if (bPreviousPlayingState)
1838       g_application.m_pPlayer->Pause();
1839 #ifdef HAS_VIDEO_PLAYBACK
1840     if (!g_renderManager.Paused())
1841     {
1842       if (m_gWindowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1843      {
1844         m_gWindowManager.ActivateWindow(WINDOW_HOME);
1845         bPreviousRenderingState = true;
1846       }
1847     }
1848 #endif
1849   }
1850   // close the music and video overlays (they're re-opened automatically later)
1851   CSingleLock lock(g_graphicsContext);
1852
1853   m_dwSkinTime = 0;
1854
1855   CStdString strHomePath;
1856   CStdString strSkinPath = "Q:\\skin\\" + strSkin;
1857
1858   CLog::Log(LOGINFO, "  load skin from:%s", strSkinPath.c_str());
1859
1860   // save the current window details
1861   int currentWindow = m_gWindowManager.GetActiveWindow();
1862   vector<DWORD> currentModelessWindows;
1863   m_gWindowManager.GetActiveModelessWindows(currentModelessWindows);
1864
1865   //  When the app is started the instance of the
1866   //  kai client should not be created until the
1867   //  skin is loaded the first time, but we must
1868   //  disconnect from the engine when the skin is
1869   //  changed
1870   bool bKaiConnected = false;
1871   if (!m_bInitializing && g_guiSettings.GetBool("xlinkkai.enabled"))
1872   {
1873     bKaiConnected = CKaiClient::GetInstance()->IsEngineConnected();
1874     if (bKaiConnected)
1875     {
1876       CLog::Log(LOGINFO, " Disconnecting Kai...");
1877       CKaiClient::GetInstance()->RemoveObserver();
1878     }
1879   }
1880
1881   CLog::Log(LOGINFO, "  delete old skin...");
1882   UnloadSkin();
1883
1884   // Load in the skin.xml file if it exists
1885   g_SkinInfo.Load(strSkinPath);
1886
1887   CLog::Log(LOGINFO, "  load fonts for skin...");
1888   g_graphicsContext.SetMediaDir(strSkinPath);
1889   if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(g_guiSettings.GetString("lookandfeel.font")))
1890   {
1891     CLog::Log(LOGINFO, "    language needs a ttf font, loading first ttf font available");
1892     CStdString strFontSet;
1893     if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1894     {
1895       CLog::Log(LOGINFO, "    new font is '%s'", strFontSet.c_str());
1896       g_guiSettings.SetString("lookandfeel.font", strFontSet);
1897       g_settings.Save();
1898     }
1899     else
1900       CLog::Log(LOGERROR, "    no ttf font found, but needed for the language %s.", g_guiSettings.GetString("locale.language").c_str());
1901   }
1902   g_fontManager.LoadFonts(g_guiSettings.GetString("lookandfeel.font"));
1903
1904   LARGE_INTEGER start;
1905   QueryPerformanceCounter(&start);
1906
1907   CLog::Log(LOGINFO, "  load new skin...");
1908   CGUIWindowHome *pHome = (CGUIWindowHome *)m_gWindowManager.GetWindow(WINDOW_HOME);
1909   if (!g_SkinInfo.Check(strSkinPath) || !pHome || !pHome->Load("home.xml"))
1910   {
1911     // failed to load home.xml
1912     // fallback to default skin
1913     if ( strcmpi(strSkin.c_str(), "Project Mayhem III") != 0)
1914     {
1915       CLog::Log(LOGERROR, "failed to load home.xml for skin:%s, fallback to \"Project Mayhem III\" skin", strSkin.c_str());
1916       LoadSkin("Project Mayhem III");
1917       return ;
1918     }
1919   }
1920
1921   // Load the user windows
1922   LoadUserWindows(strSkinPath);
1923
1924   LARGE_INTEGER end, freq;
1925   QueryPerformanceCounter(&end);
1926   QueryPerformanceFrequency(&freq);
1927   CLog::DebugLog("Load Skin XML: %.2fms", 1000.f * (end.QuadPart - start.QuadPart) / freq.QuadPart);
1928
1929   CLog::Log(LOGINFO, "  initialize new skin...");
1930   m_guiPointer.AllocResources(true);
1931   m_guiDialogVolumeBar.AllocResources(true);
1932   m_guiDialogSeekBar.AllocResources(true);
1933   m_guiDialogKaiToast.AllocResources(true);
1934   m_guiDialogMuteBug.AllocResources(true);
1935   m_gWindowManager.AddMsgTarget(this);
1936   m_gWindowManager.AddMsgTarget(&g_playlistPlayer);
1937   m_gWindowManager.SetCallback(*this);
1938   m_gWindowManager.Initialize();
1939   g_audioManager.Initialize(CAudioContext::DEFAULT_DEVICE);
1940   g_audioManager.Load();
1941   CLog::Log(LOGINFO, "  skin loaded...");
1942
1943   if (bKaiConnected)
1944   {
1945     CLog::Log(LOGINFO, " Reconnecting Kai...");
1946
1947     CGUIWindowBuddies *pKai = (CGUIWindowBuddies *)m_gWindowManager.GetWindow(WINDOW_BUDDIES);
1948     CKaiClient::GetInstance()->SetObserver(pKai);
1949     Sleep(3000);  //  The client need some time to "resync"
1950   }
1951
1952   // leave the graphics lock
1953   lock.Leave();
1954
1955   // restore windows
1956   if (currentWindow != WINDOW_INVALID)
1957   {
1958     m_gWindowManager.ActivateWindow(currentWindow);
1959     for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1960     {
1961       CGUIDialog *dialog = (CGUIDialog *)m_gWindowManager.GetWindow(currentModelessWindows[i]);
1962       if (dialog) dialog->Show();
1963     }
1964   }
1965
1966   if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1967   {
1968     if (bPreviousPlayingState)
1969       g_application.m_pPlayer->Pause();
1970     if (bPreviousRenderingState)
1971       m_gWindowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1972   }
1973 }
1974
1975 void CApplication::UnloadSkin()
1976 {
1977   g_audioManager.DeInitialize(CAudioContext::DEFAULT_DEVICE);
1978
1979   m_gWindowManager.DeInitialize();
1980
1981   //These windows are not handled by the windowmanager (why not?) so we should unload them manually
1982   CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0);
1983   m_guiPointer.OnMessage(msg);
1984   m_guiPointer.ResetControlStates();
1985   m_guiPointer.FreeResources(true);
1986   m_guiDialogMuteBug.OnMessage(msg);
1987   m_guiDialogMuteBug.ResetControlStates();
1988   m_guiDialogMuteBug.FreeResources(true);
1989
1990   CGUIWindow::FlushReferenceCache(); // flush the cache
1991
1992   g_TextureManager.Cleanup();
1993
1994   g_fontManager.Clear();
1995
1996   g_charsetConverter.reset();
1997 }
1998
1999 bool CApplication::LoadUserWindows(const CStdString& strSkinPath)
2000 {
2001   WIN32_FIND_DATA FindFileData;
2002   WIN32_FIND_DATA NextFindFileData;
2003   HANDLE hFind;
2004   TiXmlDocument xmlDoc;
2005   RESOLUTION resToUse = INVALID;
2006
2007   // Start from wherever home.xml is
2008   g_SkinInfo.GetSkinPath("home.xml", &resToUse);
2009   std::vector<CStdString> vecSkinPath;
2010   if (resToUse == HDTV_1080i)
2011     vecSkinPath.push_back(strSkinPath+g_SkinInfo.GetDirFromRes(HDTV_1080i));
2012   if (resToUse == HDTV_720p)
2013     vecSkinPath.push_back(strSkinPath+g_SkinInfo.GetDirFromRes(HDTV_720p));
2014   if (resToUse == PAL_16x9 || resToUse == NTSC_16x9 || resToUse == HDTV_480p_16x9 || resToUse == HDTV_720p || resToUse == HDTV_1080i)
2015     vecSkinPath.push_back(strSkinPath+g_SkinInfo.GetDirFromRes(g_SkinInfo.GetDefaultWideResolution()));
2016   vecSkinPath.push_back(strSkinPath+g_SkinInfo.GetDirFromRes(g_SkinInfo.GetDefaultResolution()));
2017   for (unsigned int i=0;i<vecSkinPath.size();++i)
2018   {
2019     CStdString strPath;
2020     strPath.Format("%s\\%s", vecSkinPath[i], "custom*.xml");
2021     CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2022     hFind = FindFirstFile(strPath.c_str(), &NextFindFileData);
2023
2024     CStdString strFileName;
2025     while (hFind != INVALID_HANDLE_VALUE)
2026     {
2027       FindFileData = NextFindFileData;
2028
2029       if (!FindNextFile(hFind, &NextFindFileData))
2030       {
2031         FindClose(hFind);
2032         hFind = INVALID_HANDLE_VALUE;
2033       }
2034
2035       // skip "up" directories, which come in all queries
2036       if (!_tcscmp(FindFileData.cFileName, _T(".")) || !_tcscmp(FindFileData.cFileName, _T("..")))
2037         continue;
2038
2039       strFileName = vecSkinPath[i]+"\\"+FindFileData.cFileName;
2040       CLog::Log(LOGINFO, "Loading skin file: %s", strFileName.c_str());
2041       if (!xmlDoc.LoadFile(strFileName.c_str()))
2042       {
2043         CLog::Log(LOGERROR, "unable to load:%s, Line %d\n%s", strFileName.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2044         continue;
2045       }
2046
2047       // Root element should be <window>
2048       TiXmlElement* pRootElement = xmlDoc.RootElement();
2049       CStdString strValue = pRootElement->Value();
2050       if (!strValue.Equals("window"))
2051       {
2052         CLog::Log(LOGERROR, "file :%s doesnt contain <window>", strFileName.c_str());
2053         continue;
2054       }
2055
2056       // Read the <type> element to get the window type to create
2057       // If no type is specified, create a CGUIWindow as default
2058       CGUIWindow* pWindow = NULL;
2059       CStdString strType;
2060       if (pRootElement->Attribute("type"))
2061         strType = pRootElement->Attribute("type");
2062       else
2063       {
2064         const TiXmlNode *pType = pRootElement->FirstChild("type");
2065         if (pType && pType->FirstChild())
2066           strType = pType->FirstChild()->Value();
2067       }
2068       if (strType.Equals("dialog"))
2069         pWindow = new CGUIDialog(0, "");
2070       else if (strType.Equals("submenu"))
2071         pWindow = new CGUIDialogSubMenu();
2072       else if (strType.Equals("buttonmenu"))
2073         pWindow = new CGUIDialogButtonMenu();
2074       else
2075         pWindow = new CGUIStandardWindow();
2076
2077       int id = WINDOW_INVALID;
2078       if (!pRootElement->Attribute("id", &id))
2079       {
2080         const TiXmlNode *pType = pRootElement->FirstChild("id");
2081         if (pType && pType->FirstChild())
2082           id = atol(pType->FirstChild()->Value());
2083       }
2084       // Check to make sure the pointer isn't still null
2085       if (pWindow == NULL || id == WINDOW_INVALID)
2086       {
2087         CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2088         return false;
2089       }
2090       if (m_gWindowManager.GetWindow(WINDOW_HOME + id))
2091       {
2092         delete pWindow;
2093         continue;
2094       }
2095       // set the window's xml file, and add it to the window manager.
2096       pWindow->SetXMLFile(FindFileData.cFileName);
2097       pWindow->SetID(WINDOW_HOME + id);
2098       m_gWindowManager.AddCustomWindow(pWindow);
2099     }
2100     CloseHandle(hFind);
2101   }
2102   return true;
2103 }
2104
2105 #ifdef HAS_XBOX_D3D  // needed for screenshot
2106 void CApplication::Render()
2107 {
2108 #else
2109 void CApplication::RenderNoPresent()
2110 {
2111 #endif
2112   // update sound
2113   if (m_pPlayer)
2114   {
2115     m_pPlayer->DoAudioWork();
2116   }
2117   // process karaoke
2118 #ifdef HAS_KARAOKE
2119   if (m_pCdgParser)
2120     m_pCdgParser->ProcessVoice();
2121 #endif
2122
2123   // check if we haven't rewound past the start of the file
2124   if (IsPlaying())
2125   {
2126     int iSpeed = g_application.GetPlaySpeed();
2127     if (iSpeed < 1)
2128     {
2129       iSpeed *= -1;
2130       int iPower = 0;
2131       while (iSpeed != 1)
2132       {
2133         iSpeed >>= 1;
2134         iPower++;
2135       }
2136       if (g_infoManager.GetPlayTime() / 1000 < iPower)
2137       {
2138         g_application.SetPlaySpeed(1);
2139         g_application.SeekTime(0);
2140       }
2141     }
2142   }
2143
2144   // don't do anything that would require graphiccontext to be locked before here in fullscreen.
2145   // that stuff should go into renderfullscreen instead as that is called from the renderin thread
2146
2147   // dont show GUI when playing full screen video
2148   if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && !IsPaused())
2149   {
2150     Sleep(50);
2151     ResetScreenSaver();
2152     g_infoManager.ResetCache();
2153     return;
2154   }
2155
2156   // enable/disable video overlay window
2157   if (IsPlayingVideo() && m_gWindowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO && !m_bScreenSave)
2158   {
2159     g_graphicsContext.EnablePreviewWindow(true);
2160   }
2161   else
2162   {
2163     g_graphicsContext.EnablePreviewWindow(false);
2164   }
2165   // update our FPS
2166   g_infoManager.UpdateFPS();
2167
2168   if(!m_pd3dDevice)
2169     return;
2170
2171   g_graphicsContext.Lock();
2172
2173   m_pd3dDevice->BeginScene();
2174
2175   m_gWindowManager.UpdateModelessVisibility();
2176
2177   // draw GUI
2178   g_graphicsContext.Clear();
2179   //SWATHWIDTH of 4 improves fillrates (performance investigator)
2180 #ifdef HAS_XBOX_D3D
2181   m_pd3dDevice->SetRenderState(D3DRS_SWATHWIDTH, 4);
2182 #endif
2183   m_gWindowManager.Render();
2184
2185   // if we're recording an audio stream then show blinking REC
2186   if (IsPlayingAudio())
2187   {
2188     if (m_pPlayer->IsRecording() )
2189     {
2190       static iBlinkRecord = 0;
2191       CGUIFont* pFont = g_fontManager.GetFont("font13");
2192       if (pFont)
2193       {
2194         iBlinkRecord++;
2195         if (iBlinkRecord > 25)
2196           pFont->DrawText(60, 50, 0xffff0000, 0, L"REC"); //Draw REC in RED
2197         if (iBlinkRecord > 50)
2198           iBlinkRecord = 0;
2199       }
2200     }
2201   }
2202
2203   // Now render any dialogs
2204   m_gWindowManager.RenderDialogs();
2205
2206   // Render the mouse pointer
2207   if (g_Mouse.IsActive())
2208   {
2209     m_guiPointer.Render();
2210   }
2211
2212   {
2213     // free memory if we got les then 10megs free ram
2214     MEMORYSTATUS stat;
2215     GlobalMemoryStatus(&stat);
2216     DWORD dwMegFree = (DWORD)(stat.dwAvailPhys / (1024 * 1024));
2217     if (dwMegFree <= 10)
2218     {
2219       g_TextureManager.Flush();
2220     }
2221
2222     // reset image scaling and effect states
2223     g_graphicsContext.SetScalingResolution(g_graphicsContext.GetVideoResolution(), 0, 0, false);
2224
2225     // If we have the remote codes enabled, then show them
2226     if (g_advancedSettings.m_displayRemoteCodes)
2227     {
2228 #ifdef HAS_IR_REMOTE
2229       XBIR_REMOTE* pRemote = &m_DefaultIR_Remote;
2230       static iRemoteCode = 0;
2231       static iShowRemoteCode = 0;
2232       if (pRemote->wButtons)
2233       {
2234         iRemoteCode = 255 - pRemote->wButtons; // remote OBC code is 255-wButtons
2235         iShowRemoteCode = 50;
2236       }
2237       if (iShowRemoteCode > 0)
2238       {
2239         CStdStringW wszText;
2240         wszText.Format(L"Remote Code: %i", iRemoteCode);
2241         CGUIFont* pFont = g_fontManager.GetFont("font13");
2242         if (pFont)
2243         {
2244 #ifdef _DEBUG
2245           pFont->DrawOutlineText( 0.08f * g_graphicsContext.GetWidth(), 0.12f * g_graphicsContext.GetHeight(), 0xffffffff, 0xff000000, 2, wszText);
2246 #else
2247
2248           if (LOG_LEVEL_DEBUG_FREEMEM <= g_advancedSettings.m_logLevel)
2249             pFont->DrawOutlineText( 0.08f * g_graphicsContext.GetWidth(), 0.12f * g_graphicsContext.GetHeight(), 0xffffffff, 0xff000000, 2, wszText);
2250           else
2251             pFont->DrawOutlineText( 0.08f * g_graphicsContext.GetWidth(), 0.08f * g_graphicsContext.GetHeight(), 0xffffffff, 0xff000000, 2, wszText);
2252 #endif
2253         }
2254         iShowRemoteCode--;
2255       }
2256 #endif
2257     }
2258
2259     RenderMemoryStatus();
2260   }
2261
2262   m_pd3dDevice->EndScene();
2263 #ifdef HAS_XBOX_D3D
2264   m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
2265 #endif
2266   g_graphicsContext.Unlock();
2267
2268   // reset our info cache - we do this at the end of Render so that it is
2269   // fresh for the next process(), or after a windowclose animation (where process()
2270   // isn't called)
2271   g_infoManager.ResetCache();
2272 }
2273
2274 #ifndef HAS_XBOX_D3D
2275 void CApplication::Render()
2276 {
2277   g_graphicsContext.Lock();
2278   RenderNoPresent();
2279   // Present the backbuffer contents to the display
2280   if (m_pd3dDevice) m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
2281   g_graphicsContext.Unlock();
2282 }
2283 #endif
2284
2285 void CApplication::RenderMemoryStatus()
2286 {
2287 #if !defined(_DEBUG) && !defined(PROFILE)
2288   if (LOG_LEVEL_DEBUG_FREEMEM <= g_advancedSettings.m_logLevel)
2289 #endif
2290   {
2291     // reset the window scaling and fade status
2292     RESOLUTION res = g_graphicsContext.GetVideoResolution();
2293     g_graphicsContext.SetScalingResolution(res, 0, 0, false);
2294
2295     CStdStringW wszText;
2296     MEMORYSTATUS stat;
2297     GlobalMemoryStatus(&stat);
2298     wszText.Format(L"FreeMem %d/%d Kb, FPS %2.1f, CPU %2.0f%%", stat.dwAvailPhys/1024, stat.dwTotalPhys/1024, g_infoManager.GetFPS(), (1.0f - m_idleThread.GetRelativeUsage())*100);
2299
2300     CGUIFont* pFont = g_fontManager.GetFont("font13");
2301     if (pFont)
2302     {
2303       float x = 0.04f * g_graphicsContext.GetWidth() + g_settings.m_ResInfo[res].Overscan.left;
2304       float y = 0.04f * g_graphicsContext.GetHeight() + g_settings.m_ResInfo[res].Overscan.top;
2305       pFont->DrawOutlineText(x, y, 0xffffffff, 0xff000000, 2, wszText);
2306     }
2307   }
2308 }
2309
2310 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2311 // The window manager will return true if the event is processed, false otherwise.
2312 // If not already processed, this routine handles global keypresses.  It returns
2313 // true if the key has been processed, false otherwise.
2314
2315 bool CApplication::OnKey(CKey& key)
2316 {
2317   // Turn the mouse off, as we've just got a keypress from controller or remote
2318   g_Mouse.SetInactive();
2319   CAction action;
2320
2321   // a key has been pressed.
2322   // Reset the screensaver timer
2323   // but not for the analog thumbsticks/triggers
2324   if (!key.IsAnalogButton())
2325   {
2326     // reset harddisk spindown timer
2327     m_bSpinDown = false;
2328     m_bNetworkSpinDown = false;
2329
2330     // reset Idle Timer
2331     m_idleTimer.StartZero();
2332
2333     ResetScreenSaver();
2334     if (ResetScreenSaverWindow())
2335       return true;
2336   }
2337
2338   // get the current active window
2339   int iWin = m_gWindowManager.GetActiveWindow() & WINDOW_ID_MASK;
2340   // change this if we have a dialog up
2341   if (m_gWindowManager.HasModalDialog())
2342   {
2343     iWin = m_gWindowManager.GetTopMostDialogID() & WINDOW_ID_MASK;
2344   }
2345   if (iWin == WINDOW_FULLSCREEN_VIDEO)
2346   {
2347     // current active window is full screen video.
2348     if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2349     {
2350       // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2351       g_buttonTranslator.GetAction(WINDOW_VIDEO_MENU, key, action);
2352     }
2353     else
2354     {
2355       // no then use the fullscreen window section of keymap.xml to map key->action
2356       g_buttonTranslator.GetAction(iWin, key, action);
2357     }
2358   }
2359   else
2360   {
2361     // current active window isnt the fullscreen window
2362     // just use corresponding section from keymap.xml
2363     // to map key->action
2364     if (key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC || iWin == WINDOW_BUDDIES) )
2365     {
2366       if (key.GetFromHttpApi())
2367       {
2368         if (key.GetButtonCode() != KEY_INVALID)
2369           action.wID = (WORD) key.GetButtonCode();
2370       }
2371       else
2372       { // see if we've got an ascii key
2373         if (g_Keyboard.GetAscii() != 0)
2374           action.wID = (WORD)g_Keyboard.GetAscii() | KEY_ASCII;
2375         else
2376           action.wID = (WORD)g_Keyboard.GetKey() | KEY_VKEY;
2377       }
2378     }
2379     else
2380       g_buttonTranslator.GetAction(iWin, key, action);
2381   }
2382   if (!key.IsAnalogButton())
2383     CLog::Log(LOGDEBUG, __FUNCTION__": %i pressed, action is %i", key.GetButtonCode(), action.wID);
2384
2385   //  Play a sound based on the action
2386   g_audioManager.PlayActionSound(action);
2387
2388   return OnAction(action);
2389 }
2390
2391 bool CApplication::OnAction(const CAction &action)
2392 {
2393   // Let's tell the outside world about this action
2394   if (pXbmcHttp)
2395   {
2396     CStdString tmp;
2397     tmp.Format("%i",action.wID);
2398     pXbmcHttp->xbmcBroadcast("OnAction:"+tmp, 2);
2399   }
2400
2401   // special case for switching between GUI & fullscreen mode.
2402   if (action.wID == ACTION_SHOW_GUI)
2403   { // Switch to fullscreen mode if we can
2404     if (SwitchToFullScreen())
2405     {
2406       m_navigationTimer.StartZero();
2407       return true;
2408     }
2409   }
2410
2411   // in normal case
2412   // just pass the action to the current window and let it handle it
2413   if (m_gWindowManager.OnAction(action))
2414   {
2415     m_navigationTimer.StartZero();
2416     return true;
2417   }
2418
2419   // handle extra global presses
2420
2421   // screenshot : take a screenshot :)
2422   if (action.wID == ACTION_TAKE_SCREENSHOT)
2423   {
2424     CUtil::TakeScreenshot();
2425     return true;
2426   }
2427   // built in functions : execute the built-in
2428   if (action.wID == ACTION_BUILT_IN_FUNCTION)
2429   {
2430     CUtil::ExecBuiltIn(action.strAction);
2431     m_navigationTimer.StartZero();
2432     return true;
2433   }
2434
2435   // power down : turn off after 3 seconds of button down
2436   static bool PowerButtonDown = false;
2437   static DWORD PowerButtonCode;
2438   static DWORD MarkTime;
2439   if (action.wID == ACTION_POWERDOWN)
2440   {
2441     // Hold button for 3 secs to power down
2442     if (!PowerButtonDown)
2443     {
2444       MarkTime = GetTickCount();
2445       PowerButtonDown = true;
2446       PowerButtonCode = action.m_dwButtonCode;
2447     }
2448   }
2449   if (PowerButtonDown)
2450   {
2451     if (g_application.IsButtonDown(PowerButtonCode))
2452     {
2453       if (GetTickCount() >= MarkTime + 3000)
2454       {
2455         g_applicationMessenger.Shutdown();
2456         return true;
2457       }
2458     }
2459     else
2460       PowerButtonDown = false;
2461   }
2462   // show info : Shows the current video or song information
2463   if (action.wID == ACTION_SHOW_INFO)
2464   {
2465     g_infoManager.ToggleShowInfo();
2466     return true;
2467   }
2468
2469   // codec info : Shows the current song, video or picture codec information
2470   if (action.wID == ACTION_SHOW_CODEC)
2471   {
2472     g_infoManager.ToggleShowCodec();
2473     return true;
2474   }
2475
2476   // stop : stops playing current audio song
2477   if (action.wID == ACTION_STOP)
2478   {
2479     StopPlaying();
2480     return true;
2481   }
2482
2483   // previous : play previous song from playlist
2484   if (action.wID == ACTION_PREV_ITEM)
2485   {
2486     // first check whether we're within 3 seconds of the start of the track
2487     // if not, we just revert to the start of the track
2488     if (m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3)
2489       SeekTime(0);
2490     else
2491     {
2492       if (IsPlayingVideo() && g_stSettings.m_currentVideoSettings != g_stSettings.m_defaultVideoSettings)
2493       {
2494         // save video settings
2495         CVideoDatabase dbs;
2496         dbs.Open();
2497         dbs.SetVideoSettings(m_itemCurrentFile.m_strPath, g_stSettings.m_currentVideoSettings);
2498         dbs.Close();
2499       }
2500       g_playlistPlayer.PlayPrevious();
2501     }
2502     return true;
2503   }
2504
2505   // next : play next song from playlist
2506   if (action.wID == ACTION_NEXT_ITEM)
2507   {
2508     if (IsPlaying() && m_pPlayer->SkipNext())
2509       return true;
2510
2511     if (IsPlayingVideo() && g_stSettings.m_currentVideoSettings != g_stSettings.m_defaultVideoSettings)
2512     {
2513       // save video settings
2514       CVideoDatabase dbs;
2515       dbs.Open();
2516       dbs.SetVideoSettings(m_itemCurrentFile.m_strPath, g_stSettings.m_currentVideoSettings);
2517       dbs.Close();
2518     }
2519
2520     g_playlistPlayer.PlayNext();
2521
2522     return true;
2523   }
2524
2525   if ( IsPlaying())
2526   {
2527     // pause : pauses current audio song
2528     if (action.wID == ACTION_PAUSE)
2529     {
2530       m_pPlayer->Pause();
2531       if (!m_pPlayer->IsPaused())
2532       { // unpaused - set the playspeed back to normal
2533         SetPlaySpeed(1);
2534       }
2535       if (!g_guiSettings.GetBool("lookandfeel.soundsduringplayback"))
2536         g_audioManager.Enable(m_pPlayer->IsPaused());
2537       return true;
2538     }
2539     if (!m_pPlayer->IsPaused())
2540     {
2541       // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2542       // if we are playing at normal speed, then allow play to pause
2543       if (action.wID == ACTION_PLAYER_PLAY)
2544       {
2545         if (m_iPlaySpeed != 1)
2546         {
2547           SetPlaySpeed(1);
2548         }
2549         else
2550         {
2551           m_pPlayer->Pause();
2552         }
2553         return true;
2554       }
2555       if (action.wID == ACTION_PLAYER_FORWARD || action.wID == ACTION_PLAYER_REWIND)
2556       {
2557         int iPlaySpeed = m_iPlaySpeed;
2558         if (action.wID == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2559           iPlaySpeed *= -2;
2560         else if (action.wID == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2561           iPlaySpeed /= 2;
2562         else if (action.wID == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2563           iPlaySpeed /= 2;
2564         else
2565           iPlaySpeed *= 2;
2566
2567         if (action.wID == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2568           iPlaySpeed = 1;
2569         if (iPlaySpeed > 32 || iPlaySpeed < -32)
2570           iPlaySpeed = 1;
2571
2572         SetPlaySpeed(iPlaySpeed);
2573         return true;
2574       }
2575       else if ((action.fAmount1 || GetPlaySpeed() != 1) && (action.wID == ACTION_ANALOG_REWIND || action.wID == ACTION_ANALOG_FORWARD))
2576       {
2577         // calculate the speed based on the amount the button is held down
2578         int iPower = (int)(action.fAmount1 * MAX_FFWD_SPEED + 0.5f);
2579         // returns 0 -> MAX_FFWD_SPEED
2580         int iSpeed = 1 << iPower;
2581         if (iSpeed != 1 && action.wID == ACTION_ANALOG_REWIND)
2582           iSpeed = -iSpeed;
2583         g_application.SetPlaySpeed(iSpeed);
2584         if (iSpeed == 1)
2585           CLog::DebugLog("Resetting playspeed");
2586         return true;
2587       }
2588     }
2589     // allow play to unpause
2590     else
2591     {
2592       if (action.wID == ACTION_PLAYER_PLAY)
2593       {
2594         // unpause, and set the playspeed back to normal
2595         m_pPlayer->Pause();
2596         if (!g_guiSettings.GetBool("lookandfeel.soundsduringplayback"))
2597           g_audioManager.Enable(m_pPlayer->IsPaused());
2598
2599         g_application.SetPlaySpeed(1);
2600         return true;
2601       }
2602     }
2603   }
2604   if (action.wID == ACTION_MUTE)
2605   {
2606     Mute();
2607     return true;
2608   }
2609
2610   // Check for global volume control
2611   if (action.fAmount1 && (action.wID == ACTION_VOLUME_UP || action.wID == ACTION_VOLUME_DOWN))
2612   {
2613     // increase or decrease the volume
2614     int volume = g_stSettings.m_nVolumeLevel + g_stSettings.m_dynamicRangeCompressionLevel;
2615
2616     // calculate speed so that a full press will equal 1 second from min to max
2617     float speed = float(VOLUME_MAXIMUM - VOLUME_MINIMUM);
2618     if( action.fRepeat )
2619       speed *= action.fRepeat;
2620     else
2621       speed /= 50; //50 fps
2622
2623     if (action.wID == ACTION_VOLUME_UP)
2624       volume += (int)(action.fAmount1 * action.fAmount1 * speed);
2625     else
2626       volume -= (int)(action.fAmount1 * action.fAmount1 * speed);
2627
2628     SetHardwareVolume(volume);
2629
2630     // show visual feedback of volume change...
2631     m_guiDialogVolumeBar.Show();
2632     m_guiDialogVolumeBar.OnAction(action);
2633     return true;
2634   }
2635   // Check for global seek control
2636   if (IsPlaying() && action.fAmount1 && (action.wID == ACTION_ANALOG_SEEK_FORWARD || action.wID == ACTION_ANALOG_SEEK_BACK))
2637   {
2638     if (!m_pPlayer->CanSeek()) return false;
2639     CScrobbler::GetInstance()->SetSubmitSong(false);  // Do not submit songs to Audioscrobbler when seeking, see CheckAudioScrobblerStatus()
2640     m_guiDialogSeekBar.OnAction(action);
2641     return true;
2642   }
2643   return false;
2644 }
2645
2646 void CApplication::SetKaiNotification(const CStdString& aCaption, const CStdString& aDescription, CGUIImage* aIcon/*=NULL*/)
2647 {
2648   // queue toast notification
2649   if (g_guiSettings.GetBool("xlinkkai.enablenotifications"))
2650   {
2651     if (aIcon==NULL)
2652       m_guiDialogKaiToast.QueueNotification(aCaption, aDescription);
2653     else
2654       m_guiDialogKaiToast.QueueNotification(aIcon->GetFileName(), aCaption, aDescription);
2655   }
2656 }
2657
2658 void CApplication::UpdateLCD()
2659 {
2660 #ifdef HAS_LCD
2661   static lTickCount = 0;
2662
2663   if (!g_lcd || g_guiSettings.GetInt("lcd.type") == LCD_TYPE_NONE)
2664     return ;
2665   long lTimeOut = 1000;
2666   if ( m_iPlaySpeed != 1)
2667     lTimeOut = 0;
2668   if ( ((long)GetTickCount() - lTickCount) >= lTimeOut)
2669   {
2670     if (g_application.NavigationIdleTime() < 5)
2671       g_lcd->Render(ILCD::LCD_MODE_NAVIGATION);
2672     else if (IsPlayingVideo())
2673       g_lcd->Render(ILCD::LCD_MODE_VIDEO);
2674     else if (IsPlayingAudio())
2675       g_lcd->Render(ILCD::LCD_MODE_MUSIC);
2676     else
2677       g_lcd->Render(ILCD::LCD_MODE_GENERAL);
2678
2679     // reset tick count
2680     lTickCount = GetTickCount();
2681   }
2682 #endif
2683 }
2684
2685 void CApplication::FrameMove()
2686 {
2687   // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2688   float frameTime = m_frameTime.GetElapsedSeconds();
2689   m_frameTime.StartZero();
2690   // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2691   if( frameTime > 0.5 ) frameTime = 0.5;
2692
2693   if (g_guiSettings.GetBool("xlinkkai.enabled"))
2694   {
2695     CKaiClient::GetInstance()->DoWork();
2696   }
2697
2698   // check if there are notifications to display
2699   if (m_guiDialogKaiToast.DoWork())
2700   {
2701     if (!m_guiDialogKaiToast.IsDialogRunning())
2702     {
2703       m_guiDialogKaiToast.Show();
2704     }
2705   }
2706
2707   UpdateLCD();
2708
2709   // read raw input from controller, remote control, mouse and keyboard
2710   ReadInput();
2711   // process input actions
2712   ProcessMouse();
2713   ProcessHTTPApiButtons();
2714   ProcessKeyboard();
2715   ProcessRemote(frameTime);
2716   ProcessGamepad(frameTime);
2717 }
2718
2719 bool CApplication::ProcessGamepad(float frameTime)
2720 {
2721 #ifdef HAS_GAMEPAD
2722   // Handle the gamepad button presses.  We check for button down,
2723   // then call OnKey() which handles the translation to actions, and sends the
2724   // action to our window manager's OnAction() function, which filters the messages
2725   // to where they're supposed to end up, returning true if the message is successfully
2726   // processed.  If OnKey() returns false, then the key press wasn't processed at all,
2727   // and we can safely process the next key (or next check on the same key in the
2728   // case of the analog sticks which can produce more than 1 key event.)
2729
2730   WORD wButtons = m_DefaultGamepad.wButtons;
2731   WORD wDpad = wButtons & (XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_RIGHT);
2732
2733   BYTE bLeftTrigger = m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER];
2734   BYTE bRightTrigger = m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER];
2735   BYTE bButtonA = m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_A];
2736   BYTE bButtonB = m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_B];
2737   BYTE bButtonX = m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_X];
2738   BYTE bButtonY = m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_Y];
2739
2740   // pass them through the delay
2741   WORD wDir = m_ctrDpad.DpadInput(wDpad, 0 != bLeftTrigger, 0 != bRightTrigger);
2742
2743   // map all controller & remote actions to their keys
2744   if (m_DefaultGamepad.fX1 || m_DefaultGamepad.fY1)
2745   {
2746     CKey key(KEY_BUTTON_LEFT_THUMB_STICK, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2747     if (OnKey(key)) return true;
2748   }
2749   if (m_DefaultGamepad.fX2 || m_DefaultGamepad.fY2)
2750   {
2751     CKey key(KEY_BUTTON_RIGHT_THUMB_STICK, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2752     if (OnKey(key)) return true;
2753   }
2754   // direction specific keys (for defining different actions for each direction)
2755   // We need to be able to know when it last had a direction, so that we can
2756   // post the reset direction code the next time around (to reset scrolling,
2757   // fastforwarding and other analog actions)
2758
2759   // For the sticks, once it is pushed in one direction (eg up) it will only
2760   // detect movement in that direction of movement (eg up or down) - the other
2761   // direction (eg left and right) will not be registered until the stick has
2762   // been recentered for at least 2 frames.
2763
2764   // first the right stick
2765   static lastRightStickKey = 0;
2766   int newRightStickKey = 0;
2767   if (lastRightStickKey == KEY_BUTTON_RIGHT_THUMB_STICK_UP || lastRightStickKey == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
2768   {
2769     if (m_DefaultGamepad.fY2 > 0)
2770       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_UP;
2771     else if (m_DefaultGamepad.fY2 < 0)
2772       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_DOWN;
2773     else if (m_DefaultGamepad.fX2 != 0)
2774     {
2775       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_UP;
2776       //m_DefaultGamepad.fY2 = 0.00001f; // small amount of movement
2777     }
2778   }
2779   else if (lastRightStickKey == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT || lastRightStickKey == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
2780   {
2781     if (m_DefaultGamepad.fX2 > 0)
2782       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT;
2783     else if (m_DefaultGamepad.fX2 < 0)
2784       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_LEFT;
2785     else if (m_DefaultGamepad.fY2 != 0)
2786     {
2787       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT;
2788       //m_DefaultGamepad.fX2 = 0.00001f; // small amount of movement
2789     }
2790   }
2791   else
2792   {
2793     if (m_DefaultGamepad.fY2 > 0 && m_DefaultGamepad.fX2*2 < m_DefaultGamepad.fY2 && -m_DefaultGamepad.fX2*2 < m_DefaultGamepad.fY2)
2794       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_UP;
2795     else if (m_DefaultGamepad.fY2 < 0 && m_DefaultGamepad.fX2*2 < -m_DefaultGamepad.fY2 && -m_DefaultGamepad.fX2*2 < -m_DefaultGamepad.fY2)
2796       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_DOWN;
2797     else if (m_DefaultGamepad.fX2 > 0 && m_DefaultGamepad.fY2*2 < m_DefaultGamepad.fX2 && -m_DefaultGamepad.fY2*2 < m_DefaultGamepad.fX2)
2798       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT;
2799     else if (m_DefaultGamepad.fX2 < 0 && m_DefaultGamepad.fY2*2 < -m_DefaultGamepad.fX2 && -m_DefaultGamepad.fY2*2 < -m_DefaultGamepad.fX2)
2800       newRightStickKey = KEY_BUTTON_RIGHT_THUMB_STICK_LEFT;
2801   }
2802   if (lastRightStickKey && newRightStickKey != lastRightStickKey)
2803   { // was held down last time - and we have a new key now
2804     // post old key reset message...
2805     CKey key(lastRightStickKey, 0, 0, 0, 0, 0, 0);
2806     lastRightStickKey = newRightStickKey;
2807     if (OnKey(key)) return true;
2808   }
2809   lastRightStickKey = newRightStickKey;
2810   // post the new key's message
2811   if (newRightStickKey)
2812   {
2813     CKey key(newRightStickKey, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2814     if (OnKey(key)) return true;
2815   }
2816
2817   // now the left stick
2818   static lastLeftStickKey = 0;
2819   int newLeftStickKey = 0;
2820   if (lastLeftStickKey == KEY_BUTTON_LEFT_THUMB_STICK_UP || lastLeftStickKey == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
2821   {
2822     if (m_DefaultGamepad.fY1 > 0)
2823       newLeftStickKey = KEY_BUTTON_LEFT_THUMB_STICK_UP;
2824     else if (m_DefaultGamepad.fY1 < 0)
2825       newLeftStickKey = KEY_BUTTON_LEFT_THUMB_STICK_DOWN;
2826   }
2827   else if (lastLeftStickKey == KEY_BUTTON_LEFT_THUMB_STICK_LEFT || lastLeftStickKey == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
2828   {
2829     if (m_DefaultGamepad.fX1 > 0)
2830       newLeftStickKey = KEY_BUTTON_LEFT_THUMB_STICK_RIGHT;
2831     else if (m_DefaultGamepad.fX1 < 0)
2832       newLeftStickKey = KEY_BUTTON_LEFT_THUMB_STICK_LEFT;
2833   }
2834   else
2835   { // check for a new control movement
2836     if (m_DefaultGamepad.fY1 > 0 && m_DefaultGamepad.fX1 < m_DefaultGamepad.fY1 && -m_DefaultGamepad.fX1 < m_DefaultGamepad.fY1)
2837       newLeftStickKey = KEY_BUTTON_LEFT_THUMB_STICK_UP;
2838     else if (m_DefaultGamepad.fY1 < 0 && m_DefaultGamepad.fX1 < -m_DefaultGamepad.fY1 && -m_DefaultGamepad.fX1 < -m_DefaultGamepad.fY1)
2839       newLeftStickKey = KEY_BUTTON_LEFT_THUMB_STICK_DOWN;
2840     else if (m_DefaultGamepad.fX1 > 0 && m_DefaultGamepad.fY1 < m_DefaultGamepad.fX1 && -m_DefaultGamepad.fY1 < m_DefaultGamepad.fX1)
2841       newLeftStickKey = KEY_BUTTON_LEFT_THUMB_STICK_RIGHT;
2842     else if (m_DefaultGamepad.fX1 < 0 && m_DefaultGamepad.fY1 < -m_DefaultGamepad.fX1 && -m_DefaultGamepad.fY1 < -m_DefaultGamepad.fX1)
2843       newLeftStickKey = KEY_BUTTON_LEFT_THUMB_STICK_LEFT;
2844   }
2845
2846   if (lastLeftStickKey && newLeftStickKey != lastLeftStickKey)
2847   { // was held down last time - and we have a new key now
2848     // post old key reset message...
2849     CKey key(lastLeftStickKey, 0, 0, 0, 0, 0, 0);
2850     lastLeftStickKey = newLeftStickKey;
2851     if (OnKey(key)) return true;
2852   }
2853   lastLeftStickKey = newLeftStickKey;
2854   // post the new key's message
2855   if (newLeftStickKey)
2856   {
2857     CKey key(newLeftStickKey, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2858     if (OnKey(key)) return true;
2859   }
2860
2861   // Trigger detection
2862   static lastTriggerKey = 0;
2863   int newTriggerKey = 0;
2864   if (bLeftTrigger)
2865     newTriggerKey = KEY_BUTTON_LEFT_ANALOG_TRIGGER;
2866   else if (bRightTrigger)
2867     newTriggerKey = KEY_BUTTON_RIGHT_ANALOG_TRIGGER;
2868   if (lastTriggerKey && newTriggerKey != lastTriggerKey)
2869   { // was held down last time - and we have a new key now
2870     // post old key reset message...
2871     CKey key(lastTriggerKey, 0, 0, 0, 0, 0, 0);
2872     lastTriggerKey = newTriggerKey;
2873     if (OnKey(key)) return true;
2874   }
2875   lastTriggerKey = newTriggerKey;
2876   // post the new key's message
2877   if (newTriggerKey)
2878   {
2879     CKey key(newTriggerKey, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2880     if (OnKey(key)) return true;
2881   }
2882
2883   // Now the digital buttons...
2884   if ( wDir & DC_LEFTTRIGGER)
2885   {
2886     CKey key(KEY_BUTTON_LEFT_TRIGGER, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2887     if (OnKey(key)) return true;
2888   }
2889   if ( wDir & DC_RIGHTTRIGGER)
2890   {
2891     CKey key(KEY_BUTTON_RIGHT_TRIGGER, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2892     if (OnKey(key)) return true;
2893   }
2894   if ( wDir & DC_LEFT )
2895   {
2896     CKey key(KEY_BUTTON_DPAD_LEFT, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2897     if (OnKey(key)) return true;
2898   }
2899   if ( wDir & DC_RIGHT)
2900   {
2901     CKey key(KEY_BUTTON_DPAD_RIGHT, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2902     if (OnKey(key)) return true;
2903   }
2904   if ( wDir & DC_UP )
2905   {
2906     CKey key(KEY_BUTTON_DPAD_UP, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2907     if (OnKey(key)) return true;
2908   }
2909   if ( wDir & DC_DOWN )
2910   {
2911     CKey key(KEY_BUTTON_DPAD_DOWN, bLeftTrigger, bRightTrigger, m_DefaultGamepad.fX1, m_DefaultGamepad.fY1, m_DefaultGamepad.fX2, m_DefaultGamepad.fY2, frameTime);
2912     if (OnKey(key)) return true;
2913   }
2914
2915   if (m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_BACK )
2916   {
2917   &n