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