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