added: new command "XBMC.RestartApp" for skinners to restart only the application
[xbmc:xbmc-antiquated.git] / xbmc / Util.cpp
1
2 #include "stdafx.h"
3 #include "application.h"
4 #include "util.h"
5 #include "xbox/iosupport.h"
6 #include "xbox/xbeheader.h"
7 #include "crc32.h"
8 #include "settings.h"
9 #include "utils/log.h"
10 #include "xbox/undocumented.h"
11 #include "url.h"
12 #include "shortcut.h"
13 #include "xbresource.h"
14 #include "graphiccontext.h"
15 #include "sectionloader.h"
16 #include "lib/cximage/ximage.h"
17 #include "filesystem/file.h"
18 #include "DetectDVDType.h"
19 #include "autoptrhandle.h"
20 #include "playlistfactory.h"
21 #include "ThumbnailCache.h"
22 #include "picture.h"
23 #include "filesystem/hddirectory.h"
24 #include "filesystem/DirectoryCache.h"
25 #include "Credits.h"
26 #include "utils/CharsetConverter.h"
27
28 bool CUtil::m_bNetworkUp = false;
29
30 struct SSortByLabel
31 {
32         bool operator()(CFileItem* pStart, CFileItem* pEnd)
33         {
34     CGUIListItem& rpStart=*pStart;
35     CGUIListItem& rpEnd=*pEnd;
36
37                 CStdString strLabel1=rpStart.GetLabel();
38                 strLabel1.ToLower();
39
40                 CStdString strLabel2=rpEnd.GetLabel();
41                 strLabel2.ToLower();
42
43                 if (m_bSortAscending)
44                         return (strcmp(strLabel1.c_str(),strLabel2.c_str())<0);
45                 else
46                         return (strcmp(strLabel1.c_str(),strLabel2.c_str())>=0);
47         }
48
49         bool m_bSortAscending;
50 };
51
52 using namespace AUTOPTR;
53 using namespace MEDIA_DETECT;
54 using namespace XFILE;
55 using namespace PLAYLIST;
56 char g_szTitleIP[32];
57 static D3DGAMMARAMP oldramp, flashramp;
58
59 CUtil::CUtil(void)
60 {
61   memset(g_szTitleIP,0,sizeof(g_szTitleIP));
62 }
63
64 CUtil::~CUtil(void)
65 {
66 }
67
68 char* CUtil::GetExtension(const CStdString& strFileName)
69 {
70   char* extension = strrchr(strFileName.c_str(),'.');
71   return extension ;
72 }
73
74 bool CUtil::IsXBE(const CStdString& strFileName)
75 {
76    char* pExtension=GetExtension(strFileName);
77    if (!pExtension) return false;
78    if (CUtil::cmpnocase(pExtension,".xbe")==0) return true;
79    return false;
80 }
81
82 bool CUtil::IsPythonScript(const CStdString& strFileName)
83 {
84    char* pExtension=GetExtension(strFileName);
85    if (!pExtension) return false;
86    if (CUtil::cmpnocase(pExtension,".py")==0) return true;
87    return false;
88 }
89
90 bool CUtil::IsDefaultXBE(const CStdString& strFileName)
91 {
92   char* pFileName=GetFileName(strFileName);
93   if (!pFileName) return false;
94   if (CUtil::cmpnocase(pFileName, "default.xbe")==0) return true;
95   return false;
96 }
97
98 bool CUtil::IsShortCut(const CStdString& strFileName)
99 {
100    char* pExtension=GetExtension(strFileName);
101    if (!pExtension) return false;
102    if (CUtil::cmpnocase(pExtension,".cut")==0) return true;
103    return false;
104 }
105
106 int CUtil::cmpnocase(const char* str1,const char* str2)
107 {
108   int iLen;
109   if ( strlen(str1) != strlen(str2) ) return 1;
110
111   iLen=strlen(str1);
112   for (int i=0; i < iLen;i++ )
113   {
114     if (tolower((unsigned char)str1[i]) != tolower((unsigned char)str2[i]) ) return 1;
115   }
116   return 0;
117 }
118
119
120 char* CUtil::GetFileName(const CStdString& strFileNameAndPath)
121 {
122
123   char* extension = strrchr(strFileNameAndPath.c_str(),'\\');
124   if (!extension)
125   {
126     extension = strrchr(strFileNameAndPath.c_str(),'/');
127     if (!extension) return (char*)strFileNameAndPath.c_str();
128   }
129
130   extension++;
131   return extension;
132
133 }
134
135 CStdString CUtil::GetTitleFromPath(const CStdString& strFileNameAndPath)
136 {
137         // use above to get the filename
138         CStdString strFilename = GetFileName(strFileNameAndPath);
139         // now remove the extension if needed
140         if (IsSmb(strFileNameAndPath)) {
141                 CStdString strTempFilename;
142                 g_charsetConverter.utf8ToStringCharset(strFilename,strTempFilename);
143                 strFilename = strTempFilename;
144         }
145         if (g_stSettings.m_bHideExtensions)
146         {
147                 RemoveExtension(strFilename);
148                 return strFilename;
149         }
150         return strFilename;
151 }
152
153 bool CUtil::GetVolumeFromFileName(const CStdString& strFileName, CStdString& strFileTitle, CStdString& strVolumePrefix, int& volumeNumber)
154 {
155   bool result = false;
156   CStdString strFileNameTemp = strFileName;
157
158   // remove any extension
159   int pos = strFileNameTemp.ReverseFind('.');
160   if (pos > 0)
161     strFileNameTemp = strFileNameTemp.Left(pos);
162
163   const CStdString & separatorsString = g_settings.m_szMyVideoStackSeparatorsString;
164   const CStdStringArray & tokens = g_settings.m_szMyVideoStackTokensArray;
165
166   CStdString strFileNameTempLower = strFileNameTemp;
167   strFileNameTempLower.MakeLower();
168
169   for (int i = 0; i < (int)tokens.size(); i++)
170   {
171     const CStdString & token = tokens[i];
172     pos = strFileNameTempLower.ReverseFind(token);
173     //CLog::Log(LOGERROR, "GetVolumeFromFileName : " + strFileNameTemp + " : " + token + " : 1");
174     if ((pos > 0) && (pos < (int)strFileNameTemp.size()))
175     {
176       //CLog::Log(LOGERROR, "GetVolumeFromFileName : " + strFileNameTemp + " : " + token + " : 2");
177       // token found at end
178       if (separatorsString.Find(strFileNameTemp.GetAt(pos - 1)) > -1)
179       {
180         // appropriate separator found between file title and token
181
182         CStdString volumeNumberString = strFileNameTemp.Mid(pos + token.size()).Trim();
183         //CLog::Log(LOGERROR, "GetVolumeFromFileName : " + strFileNameTemp + " : " + token + " : " + volumeNumberString + " : 3");
184         volumeNumber = atoi(volumeNumberString.c_str());
185         // the parsed result must be > 0
186         if (volumeNumber > 0)
187         {
188           //CLog::Log(LOGERROR, "GetVolumeFromFileName : " + strFileNameTemp + " : " + token + " : " + volumeNumberString + " : 4");
189           bool volumeNumberValid = true;
190           // make sure only numbers follow the token
191           for (int j = 1; j < (int)volumeNumberString.size(); j++)
192           {
193             char c = volumeNumberString.GetAt(j);
194             if ((c < '0') || (c > '9'))
195             {
196               volumeNumberValid = false;
197               break;
198             }
199           }
200
201           if (volumeNumberValid)
202           {
203             //CLog::Log(LOGERROR, "GetVolumeFromFileName : " + strFileNameTemp + " : " + token + " : " + volumeNumberString + " : 5");
204
205             result = true;
206             strFileTitle = strFileNameTemp.Left(pos-1);
207             // trim all additional separator characters
208             strFileTitle.TrimRight(separatorsString.c_str());
209             strVolumePrefix = token;
210             break;
211           }
212         }
213       }
214     }
215   }
216
217   return result;
218 }
219
220 void CUtil::RemoveExtension(CFileItem *pItem)
221 {
222         if (pItem->m_bIsFolder)
223                 return;
224         CStdString strLabel = pItem->GetLabel();
225         RemoveExtension(strLabel);
226         pItem->SetLabel(strLabel);
227 }
228
229 void CUtil::RemoveExtension(CStdString& strFileName)
230 {
231         int iPos = strFileName.ReverseFind(".");
232         //      Extension found
233         if (iPos>0)
234         {
235                 CStdString strExtension;
236                 CUtil::GetExtension(strFileName,strExtension);
237                 CUtil::Lower(strExtension);
238
239                 CStdString strFileMask;
240                 strFileMask=g_stSettings.m_szMyMusicExtensions;
241                 strFileMask+=g_stSettings.m_szMyPicturesExtensions;
242                 strFileMask+=g_stSettings.m_szMyVideoExtensions;
243
244                 //      Only remove if its a valid media extension
245                 if (strFileMask.Find(strExtension.c_str())>=0)
246                         strFileName=strFileName.Left(iPos);
247         }
248 }
249
250 // Remove the extensions from the filenames
251 void CUtil::RemoveExtensions(VECFILEITEMS &items)
252 {
253         for (int i=0; i < (int)items.size(); ++i)
254                 RemoveExtension(items[i]);
255 }
256
257 void CUtil::CleanFileName(CFileItem *pItem)
258 {
259         if (pItem->m_bIsFolder)
260                 return;
261         CStdString strLabel = pItem->GetLabel();
262         CleanFileName(strLabel);
263         pItem->SetLabel(strLabel);
264 }
265
266 void CUtil::CleanFileName(CStdString& strFileName)
267 {
268   bool result = false;
269
270   // assume extension has already been removed
271
272   // remove volume indicator
273
274   {
275     const CStdString & separatorsString = g_settings.m_szMyVideoStackSeparatorsString;
276     const CStdStringArray & tokens = g_settings.m_szMyVideoStackTokensArray;
277
278     CStdString strFileNameTempLower = strFileName;
279     strFileNameTempLower.MakeLower();
280
281     for (int i = 0; i < (int)tokens.size(); i++)
282     {
283       const CStdString & token = tokens[i];
284       int pos = strFileNameTempLower.ReverseFind(token);
285       if ((pos > 0) && (pos < (int)strFileName.size()))
286       {
287         // token found at end
288         if (separatorsString.Find(strFileName.GetAt(pos - 1)) > -1)
289         {
290           // appropriate separator found between file title and token
291
292           CStdString volumeNumberString = strFileName.Mid(pos + token.size()).Trim();
293           int volumeNumber = atoi(volumeNumberString.c_str());
294           // the parsed result must be > 0
295           if (volumeNumber > 0)
296           {
297             bool volumeNumberValid = true;
298             // make sure only numbers follow the token
299             for (int j = 1; j < (int)volumeNumberString.size(); j++)
300             {
301               char c = volumeNumberString.GetAt(j);
302               if ((c < '0') || (c > '9'))
303               {
304                 volumeNumberValid = false;
305                 break;
306               }
307             }
308
309             if (volumeNumberValid)
310             {
311               strFileName = strFileName.Left(pos-1);
312               // trim all additional separator characters
313               strFileName.TrimRight(separatorsString.c_str());
314               break;
315             }
316           }
317         }
318       }
319     }
320   }
321
322
323   // remove known tokens:      { "divx", "xvid", "3ivx", "ac3", "ac351", "mp3", "wma", "m4a", "mp4", "ogg", "SCR", "TS", "sharereactor" }
324   // including any separators: { ' ', '-', '_', '.', '[', ']', '(', ')' }
325   // logic is as follows:
326   //   - multiple tokens can be listed, separated by any combination of separators
327   //   - first token must follow a '-' token, potentially in addition to other separator tokens
328   //   - thus, something like "video_XviD_AC3" will not be parsed, but something like "video_-_XviD_AC3" will be parsed
329
330   // special logic - if a known token is found, try to group it with any 
331   // other tokens up to the dash separating the token group from the title. 
332   // thus, something like "The Godfather-DivX_503_2p_VBR-HQ_480x640_16x9" should 
333   // be fully cleaned up to "The Godfather"
334   // the problem with this logic is that it may clean out things we still 
335   // want to see, such as language codes.
336
337   {
338     //const CStdString separatorsString = " -_.[]()+";
339
340     //const CStdString tokensString = "divx|xvid|3ivx|ac3|ac351|mp3|wma|m4a|mp4|ogg|scr|ts|sharereactor";
341     //CStdStringArray tokens;
342     //StringUtils::SplitString(tokensString, "|", tokens);
343
344     const CStdString & separatorsString = g_settings.m_szMyVideoCleanSeparatorsString;
345     const CStdStringArray & tokens = g_settings.m_szMyVideoCleanTokensArray;
346
347     CStdString strFileNameTempLower = strFileName;
348     strFileNameTempLower.MakeLower();
349
350     int maxPos = 0;
351     bool tokenFoundWithSeparator = false;
352
353     while ((maxPos < (int)strFileName.size()) && (!tokenFoundWithSeparator))
354     {
355       bool tokenFound = false;
356
357       for (int i = 0; i < (int)tokens.size(); i++)
358       {
359         CStdString token = tokens[i];
360         int pos = strFileNameTempLower.Find(token, maxPos);
361         if (pos >= maxPos && pos>0)
362         {
363           tokenFound = tokenFound | true;
364           char separator = strFileName.GetAt(pos - 1);
365           char buffer[10];
366           itoa(pos, buffer, 10);
367           char buffer2[10];
368           itoa(maxPos, buffer2, 10);
369           //CLog::Log(LOGERROR, "CleanFileName : 1 : " + strFileName + " : " + token + " : " + buffer + " : " + separator + " : " + buffer2 + " : " + separatorsString);
370           if (separatorsString.Find(separator) > -1)
371           {
372             // token has some separator before it - now look for the 
373             // specific '-' separator, and trim any additional separators.
374
375             int pos2 = pos;
376             while (pos2 > 0)
377             {
378               separator = strFileName.GetAt(pos2 - 1);
379               if (separator == '-')
380                 tokenFoundWithSeparator = true;
381               else if (separatorsString.Find(separator) == -1)
382                 break;
383               pos2--;
384             }
385             if (tokenFoundWithSeparator)
386               pos = pos2;
387             //if (tokenFoundWithSeparator)
388             //  CLog::Log(LOGERROR, "CleanFileName : 2 : " + strFileName + " : " + token + " : " + buffer + " : " + separator + " : " + buffer2);
389             //else
390             //  CLog::Log(LOGERROR, "CleanFileName : 3 : " + strFileName + " : " + token + " : " + buffer + " : " + separator + " : " + buffer2);
391           }
392
393           if (tokenFoundWithSeparator)
394           {
395             if (pos > 0)
396               strFileName = strFileName.Left(pos);
397             break;
398           }
399           else
400           {
401             maxPos = max(maxPos, pos + 1);
402           }
403         }
404       }
405
406       if (!tokenFound)
407         break;
408
409       maxPos++;
410     }
411     
412   }
413   
414
415   // TODO: would be nice if we could remove years (i.e. "(1999)") from the 
416   // title, and put the year in a separate column instead
417
418   // TODO: would also be nice if we could do something with 
419   // languages (i.e. "[ITA]") - need to consider files with 
420   // multiple audio tracks
421
422
423   // final cleanup - special characters used instead of spaces:
424   // all '_' tokens should be replaced by spaces
425   // if the file contains no spaces, all '.' tokens should be replaced by 
426   // spaces - one possibility of a mistake here could be something like:
427   // "Dr..StrangeLove" - hopefully no one would have anything like this.
428
429   strFileName = strFileName.Trim();
430
431   {
432     bool alreadyContainsSpace = (strFileName.Find(' ') >= 0);
433
434     for (int i = 0; i < (int)strFileName.size(); i++)
435     {
436       char c = strFileName.GetAt(i);
437       if ((c == '_') || ((!alreadyContainsSpace) && (c == '.')))
438       {
439         strFileName.SetAt(i, ' ');
440       }
441     }
442   }
443
444   strFileName = strFileName.Trim();
445 }
446
447 void CUtil::CleanFileNames(VECFILEITEMS &items)
448 {
449         for (int i=0; i < (int)items.size(); ++i)
450                 CleanFileName(items[i]);
451 }
452
453 bool CUtil::GetParentPath(const CStdString& strPath, CStdString& strParent)
454 {
455   strParent="";
456
457   CURL url(strPath);
458   CStdString strFile=url.GetFileName();
459   if (strFile.size()==0)
460   {
461     if (url.GetProtocol() == "smb" && (url.GetHostName().size() > 0))
462     {
463       // we have an smb share with only server or workgroup name
464       // set hostname to "" and return true.
465       url.SetHostName("");
466       url.GetURL(strParent);
467       return true;
468     }
469     else if (url.GetProtocol() == "xbms" && (url.GetHostName().size() > 0))
470     {
471       // we have an xbms share with only server name
472       // set hostname to "" and return true.
473       url.SetHostName("");
474       url.GetURL(strParent);
475       return true;
476     }
477     return false;
478   }
479
480   if (HasSlashAtEnd(strFile) )
481   {
482     strFile=strFile.Left(strFile.size()-1);
483   }
484
485   int iPos=strFile.ReverseFind('/');
486   if (iPos < 0)
487   {
488     iPos=strFile.ReverseFind('\\');
489   }
490   if (iPos < 0)
491   {
492     url.SetFileName("");
493     url.GetURL(strParent);
494     return true;
495   }
496
497   strFile=strFile.Left(iPos);
498   url.SetFileName(strFile);
499   url.GetURL(strParent);
500   return true;
501 }
502
503 //Make sure you have a full path in the filename, otherwise adds the base path before.
504 void CUtil::GetQualifiedFilename(const CStdString &strBasePath, CStdString &strFilename)
505 {
506   CURL plItemUrl(strFilename);
507   CURL plBaseUrl(strBasePath);
508   int iDotDotLoc, iBeginCut, iEndCut;
509
510   if(plBaseUrl.GetProtocol().length()==0) //Base in local directory
511   {
512     if(plItemUrl.GetProtocol().length()==0 ) //Filename is local or not qualified
513     {
514       if (!( strFilename.c_str()[1] == ':')) //Filename not fully qualified
515       {
516         if (strFilename.c_str()[0] == '/' || strFilename.c_str()[0] == '\\')
517         {
518           strFilename = strBasePath + strFilename;
519           strFilename.Replace('/','\\');
520         }
521         else
522         {
523           strFilename = strBasePath + '\\' + strFilename;
524           strFilename.Replace('/','\\');
525         }
526       }
527     }
528     strFilename.Replace("\\.\\","\\");
529     while((iDotDotLoc = strFilename.Find("\\..\\")) > 0)
530     {
531         iEndCut = iDotDotLoc + 4;
532         iBeginCut = strFilename.Left(iDotDotLoc).ReverseFind('\\')+1;
533         strFilename.Delete(iBeginCut, iEndCut - iBeginCut);
534     }
535   }
536   else //Base is remote
537   {
538     if(plItemUrl.GetProtocol().length()==0 ) //Filename is local
539     {
540       if (strFilename.c_str()[0] == '/' || strFilename.c_str()[0] == '\\' ) //Begins with a slash.. not good.. but we try to make the best of it..
541       {
542         strFilename = strBasePath + strFilename;
543         strFilename.Replace('\\','/');
544       }
545       else
546       {
547         strFilename = strBasePath + '/' + strFilename;
548         strFilename.Replace('\\','/');
549       }
550     }
551     strFilename.Replace("/./","/");
552     while((iDotDotLoc = strFilename.Find("/../")) > 0)
553     {
554         iEndCut = iDotDotLoc + 4;
555         iBeginCut = strFilename.Left(iDotDotLoc).ReverseFind('/')+1;
556         strFilename.Delete(iBeginCut, iEndCut - iBeginCut);
557     }
558   }
559 }
560
561 /// \brief Runs an executable file
562 /// \param szPath1 Path of executeable to run
563 /// \param szParameters Any parameters to pass to the executeable being run
564 void CUtil::RunXBE(const char* szPath1, char* szParameters)
565 {
566         char szDevicePath[1024];
567         char szPath[1024];
568         char szXbePath[1024];
569         strcpy(szPath,szPath1);
570         char* szBackslash = strrchr(szPath,'\\');
571         *szBackslash=0x00;
572         char* szXbe = &szBackslash[1];
573
574         char* szColon = strrchr(szPath,':');
575         *szColon=0x00;
576         char* szDrive = szPath;
577         char* szDirectory = &szColon[1];
578
579         CIoSupport helper;
580         helper.GetPartition( (LPCSTR) szDrive, szDevicePath);
581
582         strcat(szDevicePath,szDirectory);
583         wsprintf(szXbePath,"d:\\%s",szXbe);
584
585         g_application.Stop();
586
587         CUtil::LaunchXbe(szDevicePath,szXbePath,szParameters);
588 }
589
590 //*********************************************************************************************
591 void CUtil::LaunchXbe(char* szPath, char* szXbe, char* szParameters)
592 {
593   CLog::Log(LOGINFO, "launch xbe:%s %s", szPath,szXbe);
594   CLog::Log(LOGINFO, " mount %s as D:", szPath);
595
596   CIoSupport helper;
597   helper.Unmount("D:");
598   helper.Mount("D:",szPath);
599
600   CLog::Log(LOGINFO, "launch xbe:%s", szXbe);
601
602   if (szParameters==NULL)
603   {
604     XLaunchNewImage(szXbe, NULL );
605   }
606   else
607   {
608     LAUNCH_DATA LaunchData;
609     strcpy((char*)LaunchData.Data,szParameters);
610
611     XLaunchNewImage(szXbe, &LaunchData );
612   }
613 }
614
615 bool CUtil::FileExists(const CStdString& strFileName)
616 {
617   if (strFileName.size()==0) return false;
618   CFile file;
619   if (!file.Exists(strFileName))
620     return false;
621
622   return true;
623 }
624
625 void CUtil::GetThumbnail(const CStdString& strFileName, CStdString& strThumb)
626 {
627   strThumb="";
628   CStdString strFile;
629   CUtil::ReplaceExtension(strFileName,".tbn",strFile);
630         if (CUtil::FileExists(strFile))
631         {
632     strThumb=strFile;
633     return;
634   }
635
636   if (CUtil::IsXBE(strFileName))
637   {
638     if (CUtil::GetXBEIcon(strFileName,strThumb) ) return ;
639     strThumb="defaultProgamIcon.png";
640     return;
641   }
642
643   if (CUtil::IsShortCut(strFileName) )
644   {
645     CShortcut shortcut;
646     if ( shortcut.Create( strFileName ) )
647     {
648       CStdString strFile=shortcut.m_strPath;
649
650       GetThumbnail(strFile,strThumb);
651       return;
652     }
653   }
654
655   char szThumbNail[1024];
656   Crc32 crc;
657   crc.Reset();
658   crc.Compute(strFileName.c_str(),strlen(strFileName.c_str()));
659   sprintf(szThumbNail,"%s\\%x.tbn",g_stSettings.szThumbnailsDirectory,crc);
660   strThumb= szThumbNail;
661 }
662
663 void CUtil::GetFileSize(__int64 dwFileSize, CStdString& strFileSize)
664 {
665   char szTemp[128];
666   // file < 1 kbyte?
667   if (dwFileSize < 1024)
668   {
669     //  substract the integer part of the float value
670     float fRemainder=(((float)dwFileSize)/1024.0f)-floor(((float)dwFileSize)/1024.0f);
671     float fToAdd=0.0f;
672     if (fRemainder < 0.01f)
673       fToAdd=0.1f;
674     sprintf(szTemp,"%2.1f KB", (((float)dwFileSize)/1024.0f)+fToAdd);
675     strFileSize=szTemp;
676     return;
677   }
678   __int64 iOneMeg=1024*1024;
679
680   // file < 1 megabyte?
681   if (dwFileSize < iOneMeg)
682   {
683     sprintf(szTemp,"%02.1f KB", ((float)dwFileSize)/1024.0f);
684     strFileSize=szTemp;
685     return;
686   }
687
688   // file < 1 GByte?
689   __int64 iOneGigabyte=iOneMeg;
690   iOneGigabyte *= (__int64)1000;
691   if (dwFileSize < iOneGigabyte)
692   {
693     sprintf(szTemp,"%02.1f MB", ((float)dwFileSize)/((float)iOneMeg));
694     strFileSize=szTemp;
695     return;
696   }
697   //file > 1 GByte
698   int iGigs=0;
699   while (dwFileSize >= iOneGigabyte)
700   {
701     dwFileSize -=iOneGigabyte;
702     iGigs++;
703   }
704   float fMegs=((float)dwFileSize)/((float)iOneMeg);
705   fMegs /=1000.0f;
706   fMegs+=iGigs;
707   sprintf(szTemp,"%02.1f GB", fMegs);
708   strFileSize=szTemp;
709   return;
710 }
711
712 void CUtil::GetDate(SYSTEMTIME stTime, CStdString& strDateTime)
713 {
714   char szTmp[128];
715   sprintf(szTmp,"%i-%i-%i %02.2i:%02.2i",
716           stTime.wDay,stTime.wMonth,stTime.wYear,
717           stTime.wHour,stTime.wMinute);
718   strDateTime=szTmp;
719 }
720
721 void CUtil::GetHomePath(CStdString& strPath)
722 {
723   char szXBEFileName[1024];
724   CIoSupport helper;
725   helper.GetXbePath(szXBEFileName);
726   char *szFileName = strrchr(szXBEFileName,'\\');
727   *szFileName=0;
728   strPath=szXBEFileName;
729 }
730
731 bool CUtil::IsEthernetConnected()
732 {
733   if (!(XNetGetEthernetLinkStatus() & XNET_ETHERNET_LINK_ACTIVE))
734     return false;
735
736   return true;
737 }
738
739 void CUtil::GetTitleIP(CStdString& ip)
740 {
741   ip = g_szTitleIP;
742 }
743
744 bool CUtil::InitializeNetwork(const char* szAssignment, const char* szLocalAddress, const char* szLocalSubnet, const char* szLocalGateway, const char* szNameServer)
745 {
746   if (!IsEthernetConnected())
747   {
748     CLog::Log(LOGWARNING, "network cable unplugged");
749     return false;
750   }
751
752   struct network_info networkinfo ;
753   memset(&networkinfo ,0,sizeof(networkinfo ));
754   bool bSetup(false);
755   if (CUtil::cmpnocase(szAssignment, "dhcp")==0 )
756   {
757     bSetup=true;
758     CLog::Log(LOGNOTICE, "use DHCP");
759     networkinfo.DHCP=true;
760   }
761   else if (CUtil::cmpnocase(szAssignment, "static")==0)
762   {
763     bSetup=true;
764     CLog::Log(LOGNOTICE, "use static ip");
765     networkinfo.DHCP=false;
766     strcpy(networkinfo.ip,szLocalAddress);
767     strcpy(networkinfo.subnet,szLocalSubnet);
768     strcpy(networkinfo.gateway,szLocalGateway);
769     strcpy(networkinfo.DNS1,szNameServer);
770   }
771   else
772   {
773     CLog::Log(LOGWARNING, "Not initializing network, using settings as they are setup by dashboard");
774   }
775
776   if (bSetup)
777   {
778     CLog::Log(LOGINFO, "setting up network...");
779     int iCount=0;
780     while (CUtil::SetUpNetwork( false, networkinfo )==1 && iCount < 100)
781     {
782       Sleep(50);
783       iCount++;
784     }
785   }
786   else
787   {
788     CLog::Log(LOGINFO, "init network");
789     XNetStartupParams xnsp;
790     memset(&xnsp, 0, sizeof(xnsp));
791     xnsp.cfgSizeOfStruct = sizeof(XNetStartupParams);
792
793     // Bypass security so that we may connect to 'untrusted' hosts
794     xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;
795     // create more memory for networking
796                 xnsp.cfgPrivatePoolSizeInPages = 64; // == 256kb, default = 12 (48kb)
797                 xnsp.cfgEnetReceiveQueueLength = 16; // == 32kb, default = 8 (16kb)
798                 xnsp.cfgIpFragMaxSimultaneous = 16; // default = 4
799                 xnsp.cfgIpFragMaxPacketDiv256 = 32; // == 8kb, default = 8 (2kb)
800                 xnsp.cfgSockMaxSockets = 64; // default = 64
801                 xnsp.cfgSockDefaultRecvBufsizeInK = 128; // default = 16
802                 xnsp.cfgSockDefaultSendBufsizeInK = 128; // default = 16
803     INT err = XNetStartup(&xnsp);
804   }
805
806   CLog::Log(LOGINFO, "get local ip address:");
807   XNADDR xna;
808   DWORD dwState;
809   do
810   {
811     dwState = XNetGetTitleXnAddr(&xna);
812     Sleep(50);
813   } while (dwState==XNET_GET_XNADDR_PENDING);
814
815   XNetInAddrToString(xna.ina,g_szTitleIP,32);
816
817   CLog::Log(LOGINFO, "ip adres:%s",g_szTitleIP);
818   WSADATA WsaData;
819   int err = WSAStartup( MAKEWORD(2,2), &WsaData );
820
821         if (err == NO_ERROR)
822         {
823                 m_bNetworkUp = true;
824                 return true;
825         }
826         return false;
827 }
828
829 static const __int64 SECS_BETWEEN_EPOCHS = 11644473600;
830 static const __int64 SECS_TO_100NS       = 10000000;
831
832 void CUtil::ConvertTimeTToFileTime(__int64 sec, long nsec, FILETIME &ftTime)
833 {
834   __int64 l64Result =((__int64)sec + SECS_BETWEEN_EPOCHS) + SECS_TO_100NS + (nsec / 100);
835   ftTime.dwLowDateTime = (DWORD)l64Result;
836   ftTime.dwHighDateTime = (DWORD)(l64Result>>32);
837 }
838
839
840 void CUtil::ReplaceExtension(const CStdString& strFile, const CStdString& strNewExtension, CStdString& strChangedFile)
841 {
842   CStdString strExtension;
843   GetExtension(strFile,strExtension);
844   if ( strExtension.size() )
845   {
846
847     strChangedFile=strFile.substr(0, strFile.size()-strExtension.size()) ;
848     strChangedFile+=strNewExtension;
849   }
850   else
851   {
852     strChangedFile=strFile;
853     strChangedFile+=strNewExtension;
854   }
855 }
856
857 void CUtil::GetExtension(const CStdString& strFile, CStdString& strExtension)
858 {
859   int iPos=strFile.ReverseFind(".");
860   if (iPos <0)
861   {
862     strExtension="";
863     return;
864   }
865   strExtension=strFile.Right( strFile.size()-iPos);
866 }
867
868 void CUtil::Lower(CStdString& strText)
869 {
870   char szText[1024];
871   strcpy(szText, strText.c_str());
872   //for multi-byte language, the strText.size() is not correct
873   for (int i=0; i < strlen(szText);++i)
874     szText[i]=tolower(szText[i]);
875   strText=szText;
876 };
877
878 void CUtil::Unicode2Ansi(const wstring& wstrText,CStdString& strName)
879 {
880   strName="";
881   char *pstr=(char*)wstrText.c_str();
882   for (int i=0; i < (int)wstrText.size();++i )
883   {
884     strName += pstr[i*2];
885   }
886 }
887 bool CUtil::HasSlashAtEnd(const CStdString& strFile)
888 {
889   if (strFile.size()==0) return false;
890   char kar=strFile.c_str()[strFile.size()-1];
891   if (kar=='/' || kar=='\\') return true;
892   return false;
893 }
894
895  bool CUtil::IsRemote(const CStdString& strFile)
896 {
897   CURL url(strFile);
898   CStdString strProtocol=url.GetProtocol();
899   strProtocol.ToLower();
900   if (strProtocol=="cdda" || strProtocol=="iso9660") return false;
901   if ( url.GetProtocol().size() ) return true;
902   return false;
903 }
904
905  bool CUtil::IsDVD(const CStdString& strFile)
906 {
907   if (strFile.Left(2)=="D:" || strFile.Left(2)=="d:")
908     return true;
909
910   if (strFile.Left(4)=="UDF:" || strFile.Left(4)=="udf:")
911     return true;
912
913   return false;
914 }
915 bool CUtil::IsCDDA(const CStdString& strFile)
916 {
917 CURL url(strFile);
918 if (url.GetProtocol()=="cdda")
919   return true;
920 return false;
921 }
922 bool CUtil::IsISO9660(const CStdString& strFile)
923 {
924   CStdString strLeft=strFile.Left(8);
925   strLeft.ToLower();
926   if (strLeft=="iso9660:")
927     return true;
928   return false;
929 }
930
931 bool CUtil::IsSmb(const CStdString& strFile)
932 {
933   CStdString strLeft = strFile.Left(4);
934   return (strLeft.CompareNoCase("smb:") == 0);
935 }
936
937 void CUtil::GetFileAndProtocol(const CStdString& strURL, CStdString& strDir)
938 {
939   strDir=strURL;
940   if (!IsRemote(strURL)) return;
941   if (IsDVD(strURL)) return;
942
943   CURL url(strURL);
944   strDir.Format("%s://%s", url.GetProtocol().c_str(), url.GetFileName().c_str());
945 }
946
947 void CUtil::RemoveCRLF(CStdString& strLine)
948 {
949   while ( strLine.size() && (strLine.Right(1)=="\n" || strLine.Right(1)=="\r") )
950   {
951     strLine=strLine.Left((int)strLine.size()-1);
952   }
953
954 }
955 bool CUtil::IsPicture(const CStdString& strFile)
956 {
957   CStdString strExtension;
958   CUtil::GetExtension(strFile,strExtension);
959   if (strExtension.size() < 2) return false;
960   CUtil::Lower(strExtension);
961   if ( strstr( g_stSettings.m_szMyPicturesExtensions, strExtension.c_str() ) )
962   {
963     return true;
964   }
965         if (strExtension == ".tbn")
966                 return true;
967   return false;
968 }
969
970 bool CUtil::IsShoutCast(const CStdString& strFileName)
971 {
972   if (strstr(strFileName.c_str(), "shout:") ) return true;
973   return false;
974 }
975
976 bool CUtil::IsCUESheet(const CStdString& strFileName)
977 {
978         CStdString strExtension;
979         GetExtension(strFileName, strExtension);
980         return (strExtension == ".cue");
981 }
982
983 bool CUtil::IsAudio(const CStdString& strFile)
984 {
985   CStdString strExtension;
986   CUtil::GetExtension(strFile,strExtension);
987   if (strExtension.size() < 2) return  false;
988   CUtil::Lower(strExtension);
989   if ( strstr( g_stSettings.m_szMyMusicExtensions, strExtension.c_str() ) )
990   {
991     return true;
992   }
993   if (strstr(strFile.c_str(), ".cdda") ) return true;
994   if (IsShoutCast(strFile) ) return true;
995
996   return false;
997 }
998 bool CUtil::IsVideo(const CStdString& strFile)
999 {
1000   CStdString strExtension;
1001   CUtil::GetExtension(strFile,strExtension);
1002   if (strExtension.size() < 2) return  false;
1003   CUtil::Lower(strExtension);
1004   if ( strstr( g_stSettings.m_szMyVideoExtensions, strExtension.c_str() ) )
1005   {
1006     return true;
1007   }
1008   return false;
1009 }
1010 bool CUtil::IsPlayList(const CStdString& strFile)
1011 {
1012   CStdString strExtension;
1013   CUtil::GetExtension(strFile,strExtension);
1014   strExtension.ToLower();
1015   if (strExtension==".m3u") return true;
1016   if (strExtension==".b4s") return true;
1017   if (strExtension==".pls") return true;
1018   if (strExtension==".strm") return true;
1019   return false;
1020 }
1021
1022 bool CUtil::IsDVDImage(const CStdString& strFile)
1023 {
1024   CStdString strExtension;
1025   CUtil::GetExtension(strFile,strExtension);
1026   if (strExtension.Equals(".img")) return true;
1027   return false;
1028 }
1029
1030 bool CUtil::IsDVDFile(const CStdString& strFile, bool bVobs /*= true*/, bool bIfos /*= true*/)
1031 {
1032         CStdString strFileName = GetFileName(strFile);
1033         if(bIfos)
1034         {
1035                 if(strFileName.Equals("video_ts.ifo")) return true;
1036                 if(strFileName.Left(4).Equals("vts_") && strFileName.Right(6).Equals("_0.ifo") && strFileName.length() == 12) return true;
1037         }
1038         if(bVobs)
1039         {
1040                 if(strFileName.Equals("video_ts.vob")) return true;
1041                 if(strFileName.Left(4).Equals("vts_") && strFileName.Right(4).Equals(".vob")) return true;
1042         }
1043
1044         return false;
1045 }
1046
1047 bool CUtil::IsRAR(const CStdString& strFile)
1048 {
1049   CStdString strExtension;
1050   CUtil::GetExtension(strFile,strExtension);
1051   if ( (strExtension.CompareNoCase(".rar") == 0) || (strExtension.Equals(".001")) ) return true; // sometimes the first rar is named .001
1052   return false;
1053 }
1054
1055 int CUtil::GetDVDIfoTitle(const CStdString& strFile)
1056 {
1057         CStdString strFilename = GetFileName(strFile);
1058         if (strFilename.Equals("video_ts.ifo")) return 0;
1059         //VTS_[TITLE]_0.IFO
1060         return atoi(strFilename.Mid(4,2).c_str());
1061 }
1062
1063  void CUtil::URLEncode(CStdString& strURLData)
1064 {
1065   CStdString strResult;
1066   for (int i=0; i < (int)strURLData.size(); ++i)
1067   {
1068       int kar=(unsigned char)strURLData[i];
1069       if (kar==' ') strResult+='+';
1070       else if (isalnum(kar) || kar=='&'  || kar=='=' ) strResult+=kar;
1071       else {
1072         CStdString strTmp;
1073         strTmp.Format("%%%02.2x", kar);
1074         strResult+=strTmp;
1075       }
1076   }
1077   strURLData=strResult;
1078 }
1079
1080 void CUtil::SaveString(const CStdString &strTxt, FILE *fd)
1081 {
1082   int iSize=strTxt.size();
1083   fwrite(&iSize,1,sizeof(int),fd);
1084   if (iSize > 0)
1085   {
1086     fwrite(&strTxt.c_str()[0],1,iSize,fd);
1087   }
1088 }
1089 int  CUtil::LoadString(CStdString &strTxt, byte* pBuffer)
1090 {
1091   strTxt="";
1092   int iSize;
1093   int iCount=sizeof(int);
1094   memcpy(&iSize,pBuffer,sizeof(int));
1095   if (iSize==0) return iCount;
1096   char *szTmp = new char [iSize+2];
1097   memcpy(szTmp ,&pBuffer[iCount], iSize);
1098   szTmp[iSize]=0;
1099   iCount+=iSize;
1100   strTxt=szTmp;
1101   delete [] szTmp;
1102   return iCount;
1103 }
1104 bool CUtil::LoadString(string &strTxt, FILE *fd)
1105 {
1106   strTxt="";
1107   int iSize;
1108   int iRead=fread(&iSize,1,sizeof(int),fd);
1109   if (iRead != sizeof(int) ) return false;
1110   if (feof(fd)) return false;
1111   if (iSize==0) return true;
1112   if (iSize > 0 && iSize < 16384)
1113   {
1114     char *szTmp = new char [iSize+2];
1115     iRead=fread(szTmp,1,iSize,fd);
1116     if (iRead != iSize)
1117     {
1118       delete [] szTmp;
1119       return false;
1120     }
1121     szTmp[iSize]=0;
1122     strTxt=szTmp;
1123     delete [] szTmp;
1124     return true;
1125   }
1126   return false;
1127 }
1128
1129 void CUtil::SaveInt(int iValue, FILE *fd)
1130 {
1131   fwrite(&iValue,1,sizeof(int),fd);
1132 }
1133
1134 int CUtil::LoadInt( FILE *fd)
1135 {
1136   int iValue;
1137   fread(&iValue,1,sizeof(int),fd);
1138   return iValue;
1139 }
1140
1141 void CUtil::LoadDateTime(SYSTEMTIME& dateTime, FILE *fd)
1142 {
1143   fread(&dateTime,1,sizeof(dateTime),fd);
1144 }
1145
1146 void CUtil::SaveDateTime(SYSTEMTIME& dateTime, FILE *fd)
1147 {
1148   fwrite(&dateTime,1,sizeof(dateTime),fd);
1149 }
1150
1151
1152 void CUtil::GetSongInfo(const CStdString& strFileName, CStdString& strSongCacheName)
1153 {
1154   Crc32 crc;
1155   crc.Reset();
1156   crc.Compute(strFileName.c_str(),strlen(strFileName.c_str()));
1157   strSongCacheName.Format("%s\\songinfo\\%x.si",g_stSettings.m_szAlbumDirectory,crc);
1158 }
1159
1160 void CUtil::GetAlbumFolderThumb(const CStdString& strFileName, CStdString& strThumb, bool bTempDir /*=false*/)
1161 {
1162   Crc32 crc;
1163   crc.Reset();
1164   crc.Compute(strFileName.c_str(),strlen(strFileName.c_str()));
1165   if (bTempDir)
1166     strThumb.Format("%s\\thumbs\\temp\\%x.tbn",g_stSettings.m_szAlbumDirectory,crc);
1167   else
1168     strThumb.Format("%s\\thumbs\\%x.tbn",g_stSettings.m_szAlbumDirectory,crc);
1169 }
1170
1171 void CUtil::GetAlbumThumb(const CStdString& strAlbumName, const CStdString& strFileName, CStdString& strThumb, bool bTempDir /*=false*/)
1172 {
1173   CStdString str;
1174   if (strAlbumName.IsEmpty())
1175   {
1176           str = "unknown" + strFileName;
1177   }
1178   else
1179   {
1180           str = strAlbumName + strFileName;
1181   }
1182
1183   GetAlbumFolderThumb(str, strThumb, bTempDir);
1184 }
1185
1186
1187 bool CUtil::GetXBEIcon(const CStdString& strFilePath, CStdString& strIcon)
1188 {
1189   // check if thumbnail already exists
1190   char szThumbNail[1024];
1191   Crc32 crc;
1192   crc.Reset();
1193   crc.Compute(strFilePath.c_str(),strlen(strFilePath.c_str()));
1194   sprintf(szThumbNail,"%s\\%x.tbn",g_stSettings.szThumbnailsDirectory,crc);
1195   strIcon= szThumbNail;
1196   if (CUtil::FileExists(strIcon) )
1197   {
1198     //yes, just return
1199     return true;
1200   }
1201
1202   // no, then create a new thumb
1203   // Locate file ID and get TitleImage.xbx E:\UDATA\<ID>\TitleImage.xbx
1204
1205   bool bFoundThumbnail=false;
1206   CStdString szFileName;
1207   szFileName.Format("E:\\UDATA\\%08x\\TitleImage.xbx", GetXbeID( strFilePath ) );
1208   if (!CUtil::FileExists(szFileName))
1209   {
1210     // extract icon from .xbe
1211     CXBE xbeReader;
1212     ::DeleteFile("T:\\1.xpr");
1213     if ( !xbeReader.ExtractIcon(strFilePath, "T:\\1.xpr"))
1214     {
1215       return false;
1216     }
1217     szFileName="T:\\1.xpr";
1218   }
1219
1220   CXBPackedResource* pPackedResource = new CXBPackedResource();
1221   if( SUCCEEDED( pPackedResource->Create( szFileName.c_str(), 1, NULL ) ) )
1222   {
1223     LPDIRECT3DTEXTURE8 pTexture;
1224     LPDIRECT3DTEXTURE8 m_pTexture;
1225     D3DSURFACE_DESC descSurface;
1226
1227     pTexture = pPackedResource->GetTexture((DWORD)0);
1228
1229     if ( pTexture )
1230     {
1231       if ( SUCCEEDED( pTexture->GetLevelDesc( 0, &descSurface ) ) )
1232       {
1233         int iHeight=descSurface.Height;
1234         int iWidth=descSurface.Width;
1235         DWORD dwFormat=descSurface.Format;
1236         g_graphicsContext.Get3DDevice()->CreateTexture( 128,
1237                                   128,
1238                                   1,
1239                                   0,
1240                                   D3DFMT_LIN_A8R8G8B8,
1241                                   0,
1242                                   &m_pTexture);
1243         LPDIRECT3DSURFACE8 pSrcSurface = NULL;
1244         LPDIRECT3DSURFACE8 pDestSurface = NULL;
1245
1246         pTexture->GetSurfaceLevel( 0, &pSrcSurface );
1247         m_pTexture->GetSurfaceLevel( 0, &pDestSurface );
1248
1249         D3DXLoadSurfaceFromSurface( pDestSurface, NULL, NULL,
1250                                     pSrcSurface, NULL, NULL,
1251                                     D3DX_DEFAULT, D3DCOLOR( 0 ) );
1252         D3DLOCKED_RECT rectLocked;
1253         if ( D3D_OK == m_pTexture->LockRect(0,&rectLocked,NULL,0L  ) )
1254         {
1255             BYTE *pBuff   = (BYTE*)rectLocked.pBits;
1256             if (pBuff)
1257             {
1258               DWORD strideScreen=rectLocked.Pitch;
1259               //mp_msg(0,0," strideScreen=%i\n", strideScreen);
1260
1261               CSectionLoader::Load("CXIMAGE");
1262               CxImage* pImage = new CxImage(iWidth, iHeight, 24, CXIMAGE_FORMAT_JPG);
1263               for (int y=0; y < iHeight; y++)
1264               {
1265                 byte *pPtr = pBuff+(y*(strideScreen));
1266                 for (int x=0; x < iWidth;x++)
1267                 {
1268                   byte Alpha=*(pPtr+3);
1269                   byte b=*(pPtr+0);
1270                   byte g=*(pPtr+1);
1271                   byte r=*(pPtr+2);
1272                   pPtr+=4;
1273                   pImage->SetPixelColor(x,y,RGB(r,g,b));
1274                 }
1275               }
1276
1277               m_pTexture->UnlockRect(0);
1278               pImage->Flip();
1279               pImage->Save(strIcon.c_str(),CXIMAGE_FORMAT_JPG);
1280               delete pImage;
1281               bFoundThumbnail=true;
1282               CSectionLoader::Unload("CXIMAGE");
1283             }
1284             else m_pTexture->UnlockRect(0);
1285         }
1286         pSrcSurface->Release();
1287         pDestSurface->Release();
1288         m_pTexture->Release();
1289       }
1290       pTexture->Release();
1291     }
1292   }
1293   delete pPackedResource;
1294   if (bFoundThumbnail) CUtil::ClearCache();
1295   return bFoundThumbnail;
1296 }
1297
1298
1299 bool CUtil::GetDirectoryName(const CStdString& strFileName, CStdString& strDescription)
1300 {
1301   CStdString strFName=CUtil::GetFileName(strFileName);
1302   strDescription=strFileName.Left(strFileName.size()-strFName.size());
1303   if (CUtil::HasSlashAtEnd(strDescription) )
1304   {
1305     strDescription=strDescription.Left(strDescription.size()-1);
1306   }
1307   int iPos=strDescription.ReverseFind("\\");
1308   if (iPos < 0)
1309     iPos=strDescription.ReverseFind("/");
1310   if (iPos >=0)
1311   {
1312     strDescription=strDescription.Right(strDescription.size()-iPos-1);
1313   }
1314
1315   else strDescription=strFName;
1316   return true;
1317 }
1318 bool CUtil::GetXBEDescription(const CStdString& strFileName, CStdString& strDescription)
1319 {
1320
1321     _XBE_CERTIFICATE HC;
1322     _XBE_HEADER HS;
1323
1324     FILE* hFile  = fopen(strFileName.c_str(),"rb");
1325     if (!hFile)
1326     {
1327       strDescription=CUtil::GetFileName(strFileName);
1328       return false;
1329     }
1330     fread(&HS,1,sizeof(HS),hFile);
1331     fseek(hFile,HS.XbeHeaderSize,SEEK_SET);
1332     fread(&HC,1,sizeof(HC),hFile);
1333     fclose(hFile);
1334
1335     CHAR TitleName[40];
1336     WideCharToMultiByte(CP_ACP,0,HC.TitleName,-1,TitleName,40,NULL,NULL);
1337     if (strlen(TitleName) > 0)
1338     {
1339       strDescription=TitleName;
1340       return true;
1341     }
1342     strDescription=CUtil::GetFileName(strFileName);
1343     return false;
1344 }
1345
1346 DWORD CUtil::GetXbeID( const CStdString& strFilePath)
1347 {
1348   DWORD dwReturn = 0;
1349
1350   DWORD dwCertificateLocation;
1351   DWORD dwLoadAddress;
1352   DWORD dwRead;
1353 //  WCHAR wcTitle[41];
1354
1355   CAutoPtrHandle  hFile( CreateFile( strFilePath.c_str(),
1356             GENERIC_READ,
1357             FILE_SHARE_READ,
1358             NULL,
1359             OPEN_EXISTING,
1360             FILE_ATTRIBUTE_NORMAL,
1361             NULL ));
1362   if ( hFile.isValid() )
1363   {
1364     if ( SetFilePointer(  (HANDLE)hFile,  0x104, NULL, FILE_BEGIN ) == 0x104 )
1365     {
1366       if ( ReadFile( (HANDLE)hFile, &dwLoadAddress, 4, &dwRead, NULL ) )
1367       {
1368         if ( SetFilePointer(  (HANDLE)hFile,  0x118, NULL, FILE_BEGIN ) == 0x118 )
1369         {
1370           if ( ReadFile( (HANDLE)hFile, &dwCertificateLocation, 4, &dwRead, NULL ) )
1371           {
1372             dwCertificateLocation -= dwLoadAddress;
1373             // Add offset into file
1374             dwCertificateLocation += 8;
1375             if ( SetFilePointer(  (HANDLE)hFile,  dwCertificateLocation, NULL, FILE_BEGIN ) == dwCertificateLocation )
1376             {
1377               dwReturn = 0;
1378               ReadFile( (HANDLE)hFile, &dwReturn, sizeof(DWORD), &dwRead, NULL );
1379               if ( dwRead != sizeof(DWORD) )
1380               {
1381                 dwReturn = 0;
1382               }
1383             }
1384
1385           }
1386         }
1387       }
1388     }
1389   }
1390   return dwReturn;
1391 }
1392
1393 void CUtil::FillInDefaultIcons(VECFILEITEMS &items)
1394 {
1395   for (int i=0; i < (int)items.size(); ++i)
1396   {
1397     CFileItem* pItem=items[i];
1398     FillInDefaultIcon(pItem);
1399
1400   }
1401 }
1402
1403 void CUtil::FillInDefaultIcon(CFileItem* pItem)
1404 {
1405   // find the default icon for a file or folder item
1406   // for files this can be the (depending on the file type)
1407   //   default picture for photo's
1408   //   default picture for songs
1409   //   default picture for videos
1410   //   default picture for shortcuts
1411   //   default picture for playlists
1412   //   or the icon embedded in an .xbe
1413   //
1414   // for folders
1415   //   for .. folders the default picture for parent folder
1416   //   for other folders the defaultFolder.png
1417
1418   CStdString strThumb;
1419   bool bOnlyDefaultXBE=g_stSettings.m_bMyProgramsDefaultXBE;
1420   if (!pItem->m_bIsFolder)
1421   {
1422     if (CUtil::IsPlayList(pItem->m_strPath) )
1423     {
1424       // playlist
1425       pItem->SetIconImage("defaultPlaylist.png");
1426
1427                         //      Save playlists to playlist directroy
1428       CStdString strDir;
1429       CStdString strFileName;
1430                         strFileName=CUtil::GetFileName(pItem->m_strPath);
1431                         strDir.Format("%s\\playlists\\%s",g_stSettings.m_szAlbumDirectory,strFileName.c_str());
1432                         if (strDir!=pItem->m_strPath)
1433                         {
1434                                 CPlayListFactory factory;
1435                                 auto_ptr<CPlayList> pPlayList (factory.Create(pItem->m_strPath));
1436                                 if (pPlayList.get()!=NULL)
1437                                 {
1438                                         if (pPlayList->Load(pItem->m_strPath) && pPlayList->size()>0)
1439                                         {
1440                                                 const CPlayList::CPlayListItem& item=(*pPlayList.get())[0];
1441                                                 CURL url(item.GetFileName());
1442                                                 if (!(url.GetProtocol() =="http" || url.GetProtocol()=="HTTP") &&
1443                                                                 !(url.GetProtocol() =="shout" || url.GetProtocol()=="SHOUT") &&
1444                                                                 !(url.GetProtocol() =="mms" || url.GetProtocol()=="MMS")  &&
1445                                                                 !(url.GetProtocol() =="rtp" || url.GetProtocol()=="RTP"))
1446                                                 {
1447                                                         pPlayList->Save(strDir);
1448                                                 }
1449                                         }
1450                                 }
1451                         }
1452     }
1453     else if (CUtil::IsPicture(pItem->m_strPath) )
1454     {
1455       // picture
1456       pItem->SetIconImage("defaultPicture.png");
1457     }
1458     else if ( bOnlyDefaultXBE ? CUtil::IsDefaultXBE(pItem->m_strPath) : CUtil::IsXBE(pItem->m_strPath) )
1459     {
1460       // xbe
1461       pItem->SetIconImage("defaultProgram.png");
1462     }
1463                 else if ( CUtil::IsAudio(pItem->m_strPath) )
1464     {
1465       // audio
1466       pItem->SetIconImage("defaultAudio.png");
1467     }
1468     else if (CUtil::IsVideo(pItem->m_strPath) )
1469     {
1470       // video
1471       pItem->SetIconImage("defaultVideo.png");
1472     }
1473     else if (CUtil::IsShortCut(pItem->m_strPath) )
1474     {
1475       // shortcut
1476       CStdString strDescription;
1477       CStdString strFName;
1478       strFName=CUtil::GetFileName(pItem->m_strPath);
1479
1480       int iPos=strFName.ReverseFind(".");
1481       strDescription=strFName.Left(iPos);
1482       pItem->SetLabel(strDescription);
1483       pItem->SetIconImage("defaultShortcut.png");
1484     }
1485                 //else
1486                 //{
1487                 //      // default icon for unknown file type
1488                 //      pItem->SetIconImage("defaultUnknown.png");
1489                 //}
1490   }
1491   else
1492   {
1493     if (pItem->GetLabel()=="..")
1494     {
1495       pItem->SetIconImage("defaultFolderBack.png");
1496     }
1497   }
1498
1499   if (pItem->GetIconImage()=="")
1500   {
1501     if (pItem->m_bIsFolder)
1502     {
1503       pItem->SetIconImage("defaultFolder.png");
1504     }
1505     if (!pItem->m_bIsFolder)
1506     {
1507       CStdString strExtension;
1508       CUtil::GetExtension(pItem->m_strPath,strExtension);
1509
1510       for (int i=0; i < (int)g_settings.m_vecIcons.size(); ++i)
1511       {
1512         CFileTypeIcon& icon=g_settings.m_vecIcons[i];
1513
1514         if (CUtil::cmpnocase(strExtension.c_str(), icon.m_strName)==0)
1515         {
1516           pItem->SetIconImage(icon.m_strIcon);
1517           break;
1518         }
1519       }
1520     }
1521   }
1522
1523   if (pItem->GetThumbnailImage()=="")
1524   {
1525     if (pItem->GetIconImage()!="")
1526     {
1527       CStdString strBig;
1528       int iPos=pItem->GetIconImage().Find(".");
1529       strBig=pItem->GetIconImage().Left(iPos);
1530       strBig+="Big";
1531       strBig+=pItem->GetIconImage().Right(pItem->GetIconImage().size()-(iPos));
1532       pItem->SetThumbnailImage(strBig);
1533     }
1534   }
1535 }
1536
1537 void CUtil::CreateShortcuts(VECFILEITEMS &items)
1538 {
1539         for (int i=0; i < (int)items.size(); ++i)
1540         {
1541                 CFileItem* pItem=items[i];
1542                 CreateShortcut(pItem);
1543
1544         }
1545 }
1546
1547 void CUtil::CreateShortcut(CFileItem* pItem)
1548 {
1549         bool bOnlyDefaultXBE=g_stSettings.m_bMyProgramsDefaultXBE;
1550         if ( bOnlyDefaultXBE ? CUtil::IsDefaultXBE(pItem->m_strPath) : CUtil::IsXBE(pItem->m_strPath) )
1551         {
1552                 // xbe
1553                 pItem->SetIconImage("defaultProgram.png");
1554                 if ( !CUtil::IsDVD(pItem->m_strPath) )
1555                 {
1556                         CStdString strDescription;
1557                         if (! CUtil::GetXBEDescription(pItem->m_strPath,strDescription))
1558                         {
1559                                 CUtil::GetDirectoryName(pItem->m_strPath, strDescription);
1560                         }
1561                         if (strDescription.size())
1562                         {
1563                                 CStdString strFname;
1564                                 strFname=CUtil::GetFileName(pItem->m_strPath);
1565                                 strFname.ToLower();
1566                                 if (strFname!="dashupdate.xbe" && strFname!="downloader.xbe" && strFname != "update.xbe")
1567                                 {
1568                                         CShortcut cut;
1569                                         cut.m_strPath=pItem->m_strPath;
1570                                         cut.Save(strDescription);
1571                                 }
1572                         }
1573                 }
1574         }
1575 }
1576
1577
1578 void CUtil::SetThumbs(VECFILEITEMS &items)
1579 {
1580   VECFILEITEMS qitems;
1581   CHDDirectory dir;
1582
1583   //cache thumbnails directory
1584   CStdString strThumb=g_stSettings.szThumbnailsDirectory;
1585   {
1586     CFileItemList itemlist(qitems); // will clean up everything
1587     dir.GetDirectory(strThumb.c_str(),qitems);          //      precache Q:\thumbs directory
1588   }
1589   {
1590     strThumb+="\\imdb";
1591     CFileItemList itemlist(qitems); // will clean up everything
1592     dir.GetDirectory(strThumb.c_str(),qitems);                  //      precache Q:\thumbs\imdb directory
1593   }
1594
1595
1596
1597   for (int i=0; i < (int)items.size(); ++i)
1598   {
1599     CFileItem* pItem=items[i];
1600     SetThumb(pItem);
1601   }
1602   CUtil::ClearCache();
1603 }
1604
1605 bool CUtil::GetFolderThumb(const CStdString& strFolder, CStdString& strThumb)
1606 {
1607   // get the thumbnail for the folder contained in strFolder
1608   // and return the filename of the thumbnail in strThumb
1609   //
1610   // if folder contains folder.jpg and is local on xbox HD then use it as the thumbnail
1611   // if folder contains folder.jpg but is located on a share then cache the folder.jpg
1612   // to q:\thumbs and return the cached image as a thumbnail
1613   CStdString strFolderImage;
1614   strThumb="";
1615   AddFileToFolder(strFolder, "folder.jpg", strFolderImage);
1616
1617   // remote or local file?
1618   if (CUtil::IsRemote(strFolder) || CUtil::IsDVD(strFolder) || CUtil::IsISO9660(strFolder) )
1619   {
1620     CURL url(strFolder);
1621     // dont try to locate a folder.jpg for streams &  shoutcast
1622     if (url.GetProtocol() =="http" || url.GetProtocol()=="HTTP") return false;
1623     if (url.GetProtocol() =="shout" || url.GetProtocol()=="SHOUT") return false;
1624     if (url.GetProtocol() =="mms" || url.GetProtocol()=="MMS") return false;
1625     if (url.GetProtocol() =="rtp" || url.GetProtocol()=="RTP") return false;
1626
1627     CUtil::GetThumbnail( strFolderImage,strThumb);
1628     // if local cache of thumb doesnt exists yet
1629     if (!CUtil::FileExists( strThumb) )
1630     {
1631       CFile file;
1632       // then cache folder.jpg to xbox HD
1633           if(file.Exists(strFolderImage))
1634           {
1635                 if ( file.Cache(strFolderImage.c_str(), strThumb.c_str(),NULL,NULL))
1636                 {
1637                         return true;
1638                 }
1639           }
1640     }
1641     else
1642     {
1643       // else used the cached version
1644       return true;
1645     }
1646   }
1647   else if (CUtil::FileExists(strFolderImage) )
1648   {
1649     // is local, and folder.jpg exists. Use it
1650     strThumb=strFolderImage;
1651     return true;
1652   }
1653
1654   // no thumb found
1655   strThumb="";
1656   return false;
1657 }
1658
1659 void CUtil::SetThumb(CFileItem* pItem)
1660 {
1661   CStdString strThumb;
1662   // set the thumbnail for an file item
1663
1664   // if it already has a thumbnail, then return
1665   if ( pItem->HasThumbnail() ) return;
1666
1667
1668   CStdString strFileName=pItem->m_strPath;
1669
1670         if (!CUtil::IsRemote(strFileName))
1671         {
1672                 CStdString strFile;
1673                 CUtil::ReplaceExtension(strFileName, ".tbn", strFile);
1674                 if (CUtil::FileExists(strFile))
1675                 {
1676                         pItem->SetThumbnailImage(strFile);
1677                         return;
1678                 }
1679         }
1680
1681   // if this is a shortcut, then get the real filename
1682   if (CUtil::IsShortCut(strFileName))
1683   {
1684     CShortcut shortcut;
1685     if ( shortcut.Create( strFileName ) )
1686     {
1687       strFileName=shortcut.m_strPath;
1688     }
1689   }
1690
1691   // get filename of cached thumbnail like Q:\thumbs\aed638.tbn
1692   CStdString strCachedThumbnail;
1693   Crc32 crc;
1694   crc.Reset();
1695   crc.Compute(strFileName.c_str(),strlen(strFileName.c_str()));
1696   strCachedThumbnail.Format("%s\\%x.tbn",g_stSettings.szThumbnailsDirectory,crc);
1697
1698   bool bGotIcon(false);
1699
1700   // does a cached thumbnail exists?
1701   if (!CUtil::FileExists(strCachedThumbnail) )
1702   {
1703                 // get the path for the  thumbnail
1704                 CUtil::GetThumbnail( strFileName,strThumb);
1705     // local cached thumb does not exists
1706     // check if strThumb exists
1707     if (CUtil::FileExists(strThumb))
1708     {
1709       // yes, is it a local or remote file
1710       if (CUtil::IsRemote(strThumb) || CUtil::IsDVD(strThumb) || CUtil::IsISO9660(strThumb) )
1711       {
1712         // remote file, then cache it...
1713         CFile file;
1714         if ( file.Cache(strThumb.c_str(), strCachedThumbnail.c_str(),NULL,NULL))
1715         {
1716           // cache ok, then use it
1717           pItem->SetThumbnailImage(strCachedThumbnail);
1718           bGotIcon=true;
1719         }
1720       }
1721       else
1722       {
1723         // local file, then use it
1724         pItem->SetThumbnailImage(strThumb);
1725         bGotIcon=true;
1726       }
1727     }
1728     else
1729     {
1730       // strThumb doesnt exists either
1731       // now check for filename.tbn or foldername.tbn
1732       CFile file;
1733       CStdString strThumbnailFileName;
1734                         if (pItem->m_bIsFolder)
1735                         {
1736                                 strThumbnailFileName=pItem->m_strPath;
1737                                 if (CUtil::HasSlashAtEnd(strThumbnailFileName))
1738                                         strThumbnailFileName.Delete(strThumbnailFileName.size()-1);
1739                                 strThumbnailFileName+=".tbn";
1740                         }
1741                         else
1742                                 CUtil::ReplaceExtension(strFileName,".tbn", strThumbnailFileName);
1743
1744                         if (file.Exists(strThumbnailFileName))
1745                         {
1746                                 //      local or remote ?
1747                                 if (CUtil::IsRemote(strFileName) || CUtil::IsDVD(strFileName) || CUtil::IsISO9660(strFileName))
1748                                 {
1749                                         //      remote, cache thumb to hdd
1750                                         if ( file.Cache(strThumbnailFileName.c_str(), strCachedThumbnail.c_str(),NULL,NULL))
1751                                         {
1752
1753                                                 pItem->SetThumbnailImage(strCachedThumbnail);
1754                                                 bGotIcon=true;
1755                                         }
1756                                 }
1757                                 else
1758                                 {
1759                                         //      local, just use it
1760                                         pItem->SetThumbnailImage(strThumbnailFileName);
1761                                         bGotIcon=true;
1762                                 }
1763       }
1764     }
1765                 // fill in the folder thumbs
1766                 if (!bGotIcon && pItem->GetLabel() != "..")
1767                 {
1768                         // this is a folder ?
1769                         if (pItem->m_bIsFolder)
1770                         {
1771                                 // yes, then get the folder thumbnail
1772                                 if ( CUtil::GetFolderThumb(strFileName, strThumb))
1773                                 {
1774                                         pItem->SetThumbnailImage(strThumb);
1775                                 }
1776                         }
1777                 }
1778   }
1779   else
1780   {
1781     // yes local cached thumbnail exists, use it
1782     pItem->SetThumbnailImage(strCachedThumbnail);
1783   }
1784 }
1785
1786 void CUtil::ShortenFileName(CStdString& strFileNameAndPath)
1787 {
1788   CStdString strFile=CUtil::GetFileName(strFileNameAndPath);
1789   if (strFile.size() > 42)
1790   {
1791     CStdString strExtension;
1792     CUtil::GetExtension(strFileNameAndPath, strExtension);
1793     CStdString strPath=strFileNameAndPath.Left( strFileNameAndPath.size() - strFile.size() );
1794
1795     strFile=strFile.Left(42-strExtension.size());
1796     strFile+=strExtension;
1797
1798     CStdString strNewFile=strPath;
1799     if (!CUtil::HasSlashAtEnd(strPath))
1800       strNewFile+="\\";
1801
1802     strNewFile+=strFile;
1803     strFileNameAndPath=strNewFile;
1804   }
1805 }
1806
1807 void CUtil::ConvertPathToUrl( const CStdString& strPath, const CStdString& strProtocol, CStdString& strOutUrl )
1808 {
1809   strOutUrl = strProtocol;
1810   CStdString temp = strPath;
1811   temp.Replace( '\\', '/' );
1812   temp.Delete( 0, 3 );
1813   strOutUrl += temp;
1814 }
1815
1816 void CUtil::GetDVDDriveIcon( const CStdString& strPath, CStdString& strIcon )
1817 {
1818   if ( !CDetectDVDMedia::IsDiscInDrive() ) {
1819     strIcon="defaultDVDEmpty.png";
1820     return;
1821   }
1822
1823   if ( IsDVD(strPath) ) {
1824     CCdInfo* pInfo = CDetectDVDMedia::GetCdInfo();
1825     //  xbox DVD
1826     if ( pInfo != NULL && pInfo->IsUDFX( 1 ) ) {
1827       strIcon="defaultXBOXDVD.png";
1828       return;
1829     }
1830     strIcon="defaultDVDRom.png";
1831     return;
1832   }
1833
1834   if ( IsISO9660(strPath) ) {
1835     CCdInfo* pInfo = CDetectDVDMedia::GetCdInfo();
1836     if ( pInfo != NULL && pInfo->IsVideoCd( 1 ) ) {
1837       strIcon="defaultVCD.png";
1838       return;
1839     }
1840     strIcon="defaultDVDRom.png";
1841     return;
1842   }
1843
1844   if ( IsCDDA(strPath) ) {
1845     strIcon="defaultCDDA.png";
1846     return;
1847   }
1848 }
1849
1850 void CUtil::RemoveTempFiles()
1851 {
1852   WIN32_FIND_DATA wfd;
1853
1854   CStdString strAlbumDir;
1855   strAlbumDir.Format("%s\\*.tmp",g_stSettings.m_szAlbumDirectory);
1856   memset(&wfd,0,sizeof(wfd));
1857
1858   CAutoPtrFind hFind( FindFirstFile(strAlbumDir.c_str(),&wfd));
1859   if (!hFind.isValid())
1860     return ;
1861   do
1862   {
1863     if ( !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
1864     {
1865       string strFile=g_stSettings.m_szAlbumDirectory;
1866           strFile += "\\";
1867       strFile += wfd.cFileName;
1868       DeleteFile(strFile.c_str());
1869     }
1870   } while (FindNextFile(hFind, &wfd));
1871
1872   //CStdString strTempThumbDir;
1873   //strTempThumbDir.Format("%s\\thumbs\\temp\\*.tbn",g_stSettings.m_szAlbumDirectory);
1874   //memset(&wfd,0,sizeof(wfd));
1875
1876   //CAutoPtrFind hFind1( FindFirstFile(strTempThumbDir.c_str(),&wfd));
1877   //if (!hFind1.isValid())
1878   //  return ;
1879   //do
1880   //{
1881   //  if ( !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
1882   //  {
1883   //    CStdString strFile;
1884   //    strFile.Format("%s\\thumbs\\temp\\",g_stSettings.m_szAlbumDirectory);
1885   //    strFile += wfd.cFileName;
1886   //    DeleteFile(strFile.c_str());
1887   //  }
1888   //} while (FindNextFile(hFind1, &wfd));
1889 }
1890
1891 void CUtil::DeleteTDATA()
1892 {
1893   WIN32_FIND_DATA wfd;
1894   CStdString strTDATADir;
1895   strTDATADir = "T:\\*.*";
1896   memset(&wfd,0,sizeof(wfd));
1897
1898   CAutoPtrFind hFind( FindFirstFile(strTDATADir.c_str(),&wfd));
1899   if (!hFind.isValid())
1900     return ;
1901   do
1902   {
1903     if ( !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
1904     {
1905           string strFile="T:\\";
1906       strFile += wfd.cFileName;
1907           CLog::Log(LOGINFO, "  DeleteFile(%s)", strFile.c_str());
1908           DeleteFile(strFile.c_str());
1909     }
1910   } while (FindNextFile(hFind, &wfd));
1911 }
1912
1913 bool CUtil::IsHD(const CStdString& strFileName)
1914 {
1915   if (strFileName.size()<=2) return false;
1916   char szDriveletter=tolower(strFileName.GetAt(0));
1917   if ( (szDriveletter >= 'c'&& szDriveletter <= 'g' && szDriveletter != 'd') || (szDriveletter=='q')  )
1918   {
1919     if (strFileName.GetAt(1)==':') return true;
1920   }
1921   return false;
1922 }
1923
1924 // Following 6 routines added by JM to determine (possible) source type based
1925 // on frame size
1926 bool CUtil::IsNTSC_VCD(int iWidth, int iHeight)
1927 {
1928   return (iWidth==352 && iHeight==240);
1929 }
1930
1931 bool CUtil::IsNTSC_SVCD(int iWidth, int iHeight)
1932 {
1933   return (iWidth==480 && iHeight==480);
1934 }
1935
1936 bool CUtil::IsNTSC_DVD(int iWidth, int iHeight)
1937 {
1938   return (iWidth==720 && iHeight==480);
1939 }
1940
1941 bool CUtil::IsPAL_VCD(int iWidth, int iHeight)
1942 {
1943   return (iWidth==352 && iHeight==488);
1944 }
1945
1946 bool CUtil::IsPAL_SVCD(int iWidth, int iHeight)
1947 {
1948   return (iWidth==480 && iHeight==576);
1949 }
1950
1951 bool CUtil::IsPAL_DVD(int iWidth, int iHeight)
1952 {
1953   return (iWidth==720 && iHeight==576);
1954 }
1955
1956
1957 void CUtil::RemoveIllegalChars( CStdString& strText)
1958 {
1959   char szRemoveIllegal [1024];
1960   strcpy(szRemoveIllegal ,strText.c_str());
1961   static char legalChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!#$%&'()-@[]^_`{}~ ";
1962   char *cursor;
1963   for (cursor = szRemoveIllegal; *(cursor += strspn(cursor, legalChars)); /**/ )
1964     *cursor = '_';
1965   strText=szRemoveIllegal;
1966 }
1967
1968 void CUtil::ClearSubtitles()
1969 {
1970         //delete cached subs
1971         WIN32_FIND_DATA wfd;
1972         CAutoPtrFind hFind ( FindFirstFile("Z:\\*.*",&wfd));
1973
1974         if (hFind.isValid())
1975         {
1976                 do
1977                 {
1978                         if (wfd.cFileName[0]!=0)
1979                         {
1980                                 if ( (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0 )
1981                                 {
1982                                         CStdString strFile;
1983                                         strFile.Format("Z:\\%s", wfd.cFileName);
1984                                         if (strFile.Find("subtitle")>=0 )
1985                                         {
1986                                                 ::DeleteFile(strFile.c_str());
1987                                         }
1988                                         else if (strFile.Find("vobsub_queue")>=0 )
1989                                         {
1990                                                 ::DeleteFile(strFile.c_str());
1991                                         }
1992                                 }
1993                         }
1994                 } while (FindNextFile((HANDLE)hFind, &wfd));
1995         }
1996 }
1997
1998 void CUtil::CacheSubtitles(const CStdString& strMovie, CStdString& strExtensionCached )
1999 {
2000   char * sub_exts[] = {  ".utf", ".utf8", ".utf-8", ".sub", ".srt", ".smi", ".rt", ".txt", ".ssa", ".aqt", ".jss", ".ass", ".idx",".ifo", NULL};
2001   strExtensionCached = "";
2002   int iPos=0;
2003   bool bFoundSubs=false;
2004   CStdString strPath,strFName;
2005   CUtil::Split(strMovie,strPath,strFName);
2006   if (CUtil::HasSlashAtEnd(strPath)) strPath=strPath.Left(strPath.size()-1);
2007
2008   g_directoryCache.ClearDirectory(strPath);
2009
2010         ClearSubtitles();
2011
2012   CURL url(strMovie);
2013   if (url.GetProtocol() =="http" || url.GetProtocol()=="HTTP") return ;
2014   if (url.GetProtocol() =="shout" || url.GetProtocol()=="SHOUT") return ;
2015   if (url.GetProtocol() =="mms" || url.GetProtocol()=="MMS") return ;
2016   if (url.GetProtocol() =="rtp" || url.GetProtocol()=="RTP") return ;
2017   if (CUtil::IsPlayList(strMovie)) return;
2018   if (!CUtil::IsVideo(strMovie)) return;
2019
2020   if (strlen(g_stSettings.m_szAlternateSubtitleDirectory)!=0)
2021   {
2022     // check alternate subtitle directory
2023     iPos=0;
2024     while (sub_exts[iPos])
2025     {
2026       CStdString strSource,strDest;
2027       strDest.Format("Z:\\subtitle%s", sub_exts[iPos]);
2028
2029       CStdString strFname;
2030       strFname=CUtil::GetFileName(strMovie);
2031       strSource.Format("%s\\%s", g_stSettings.m_szAlternateSubtitleDirectory,strFname.c_str());
2032       CUtil::ReplaceExtension(strSource,sub_exts[iPos],strSource);
2033       CFile file;
2034       if ( file.Cache(strSource.c_str(), strDest.c_str(),NULL,NULL))
2035       {
2036         CLog::Log(LOGINFO, " cached subtitle %s->%s\n", strSource.c_str(), strDest.c_str());
2037         strExtensionCached = (CStdString)sub_exts[iPos];
2038         bFoundSubs=true;
2039       }
2040       iPos++;
2041     }
2042   }
2043
2044   if (bFoundSubs) return;
2045
2046
2047   // check original movie directory
2048   iPos=0;
2049   while (sub_exts[iPos])
2050   {
2051     CStdString strSource,strDest;
2052     strDest.Format("Z:\\subtitle%s", sub_exts[iPos]);
2053
2054     ::DeleteFile(strDest);
2055     strSource=strMovie;
2056     CUtil::ReplaceExtension(strMovie,sub_exts[iPos],strSource);
2057     CFile file;
2058     if ( file.Cache(strSource.c_str(), strDest.c_str(),NULL,NULL))
2059     {
2060       CLog::Log(LOGINFO, " cached subtitle %s->%s\n", strSource.c_str(), strDest.c_str());
2061       strExtensionCached = (CStdString)sub_exts[iPos];
2062       bFoundSubs=true;
2063     }
2064     iPos++;
2065   }
2066
2067
2068 }
2069
2070 void CUtil::SecondsToHMSString(long lSeconds, CStdString& strHMS)
2071 {
2072   int hh = lSeconds / 3600;
2073   lSeconds = lSeconds%3600;
2074   int mm = lSeconds / 60;
2075   int ss = lSeconds % 60;
2076
2077   if (hh>=1)
2078     strHMS.Format("%2.2i:%02.2i:%02.2i",hh,mm,ss);
2079   else
2080     strHMS.Format("%i:%02.2i",mm,ss);
2081
2082 }
2083 void CUtil::PrepareSubtitleFonts()
2084 {
2085   if (strlen(g_stSettings.m_szSubtitleFont)==0) return;
2086   if (g_stSettings.m_iSubtitleHeight==0) return;
2087
2088   CStdString strPath,strHomePath,strSearchMask;
2089   strHomePath = "Q:";
2090   strPath.Format("%s\\mplayer\\font\\%s\\%i\\",
2091           strHomePath.c_str(),
2092           g_stSettings.m_szSubtitleFont,g_stSettings.m_iSubtitleHeight);
2093
2094   strSearchMask=strPath+"*.*";
2095   WIN32_FIND_DATA wfd;
2096   CAutoPtrFind hFind ( FindFirstFile(strSearchMask.c_str(),&wfd));
2097   if (hFind.isValid())
2098   {
2099     do
2100     {
2101       if (wfd.cFileName[0]!=0)
2102       {
2103         if ( (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0 )
2104         {
2105           CStdString strSource,strDest;
2106           strSource.Format("%s%s",strPath.c_str(),wfd.cFileName);
2107           strDest.Format("%s\\mplayer\\font\\%s",strHomePath.c_str(),  wfd.cFileName);
2108           ::CopyFile(strSource.c_str(),strDest.c_str(),FALSE);
2109         }
2110       }
2111     } while (FindNextFile((HANDLE)hFind, &wfd));
2112   }
2113 }
2114
2115 __int64 CUtil::ToInt64(DWORD dwHigh, DWORD dwLow)
2116 {
2117   __int64 n;
2118   n=dwHigh;
2119   n <<=32;
2120   n += dwLow;
2121   return n;
2122 }
2123
2124 void CUtil::AddFileToFolder(const CStdString& strFolder, const CStdString& strFile, CStdString& strResult)
2125 {
2126   strResult=strFolder;
2127   if (!CUtil::HasSlashAtEnd(strResult))
2128   {
2129     if (strResult.Find("//")>=0 )
2130       strResult+="/";
2131     else
2132       strResult+="\\";
2133   }
2134   strResult += strFile;
2135 }
2136
2137 bool CUtil::IsNFO(const CStdString& strFile)
2138 {
2139   char *pExtension=CUtil::GetExtension(strFile);
2140   if (!pExtension) return false;
2141   if (CUtil::cmpnocase(pExtension,".nfo")==0) return true;
2142   return false;
2143 }
2144
2145 void CUtil::GetPath(const CStdString& strFileName, CStdString& strPath)
2146 {
2147   int iPos1=strFileName.Find("/");
2148   int iPos2=strFileName.Find("\\");
2149   int iPos3=strFileName.Find(":");
2150   if (iPos2>iPos1) iPos1=iPos2;
2151   if (iPos3>iPos1) iPos1=iPos3;
2152
2153   strPath=strFileName.Left(iPos1-1);
2154 }
2155
2156 void CUtil::GetDirectory(const CStdString& strFilePath, CStdString& strDirectoryPath)
2157 {
2158         int iPos1=strFilePath.ReverseFind('/');
2159         int iPos2=strFilePath.ReverseFind('\\');
2160
2161         if (iPos2>iPos1)
2162         {
2163                 iPos1=iPos2;
2164         }
2165
2166         if (iPos1>0)
2167         {
2168                 strDirectoryPath = strFilePath.Left(iPos1);
2169         }
2170 }
2171
2172 void CUtil::Split(const CStdString& strFileNameAndPath, CStdString& strPath, CStdString& strFileName)
2173 {
2174   strFileName="";
2175   strPath="";
2176   int i=strFileNameAndPath.size()-1;
2177   while (i > 0)
2178   {
2179     char ch=strFileNameAndPath[i];
2180     if (ch==':' || ch=='/' || ch=='\\') break;
2181     else i--;
2182   }
2183   strPath     = strFileNameAndPath.Left(i);
2184   strFileName = strFileNameAndPath.Right(strFileNameAndPath.size() - i);
2185 }
2186
2187 int CUtil::GetFolderCount(VECFILEITEMS &items)
2188 {
2189   int nFolderCount=0;
2190   for (int i = 0; i < (int)items.size(); i++)
2191   {
2192     CFileItem* pItem = items[i];
2193     if (pItem->m_bIsFolder)
2194       nFolderCount++;
2195   }
2196
2197   return nFolderCount;
2198 }
2199
2200 int CUtil::GetFileCount(VECFILEITEMS &items)
2201 {
2202   int nFileCount=0;
2203   for (int i = 0; i < (int)items.size(); i++)
2204   {
2205     CFileItem* pItem = items[i];
2206     if (! pItem->m_bIsFolder)
2207       nFileCount++;
2208   }
2209
2210   return nFileCount;
2211 }
2212
2213 bool CUtil::ThumbExists(const CStdString& strFileName, bool bAddCache)
2214 {
2215   return CThumbnailCache::GetThumbnailCache()->ThumbExists(strFileName, bAddCache);
2216 }
2217
2218 void CUtil::ThumbCacheAdd(const CStdString& strFileName, bool bFileExists)
2219 {
2220   CThumbnailCache::GetThumbnailCache()->Add(strFileName, bFileExists);
2221 }
2222
2223 void CUtil::ThumbCacheClear()
2224 {
2225   CThumbnailCache::GetThumbnailCache()->Clear();
2226 }
2227
2228 bool CUtil::ThumbCached(const CStdString& strFileName)
2229 {
2230   return CThumbnailCache::GetThumbnailCache()->IsCached(strFileName);
2231 }
2232
2233 void CUtil::PlayDVD()
2234 {
2235   if (g_stSettings.m_szExternalDVDPlayer[0])
2236   {
2237     char szPath[1024];
2238     char szDevicePath[1024];
2239     char szXbePath[1024];
2240     char szParameters[1024];
2241     memset(szParameters,0,sizeof(szParameters));
2242     strcpy(szPath,g_stSettings.m_szExternalDVDPlayer);
2243     char* szBackslash = strrchr(szPath,'\\');
2244     *szBackslash=0x00;
2245     char* szXbe = &szBackslash[1];
2246     char* szColon = strrchr(szPath,':');
2247     *szColon=0x00;
2248     char* szDrive = szPath;
2249     char* szDirectory = &szColon[1];
2250     CIoSupport helper;
2251     helper.GetPartition( (LPCSTR) szDrive, szDevicePath);
2252     strcat(szDevicePath,szDirectory);
2253     wsprintf(szXbePath,"d:\\%s",szXbe);
2254
2255     g_application.Stop();
2256     CUtil::LaunchXbe(szDevicePath,szXbePath,NULL);
2257   }
2258   else
2259   {
2260     CIoSupport helper;
2261     helper.Remount("D:","Cdrom0");
2262         CFileItem item;
2263         item.m_strPath = "dvd://1";
2264     g_application.PlayFile(item);
2265   }
2266 }
2267
2268 DWORD CUtil::SetUpNetwork( bool resetmode, struct network_info& networkinfo )
2269 {
2270   static unsigned char params[512];
2271   static DWORD        vReturn;
2272   static XNADDR       sAddress;
2273   char temp_str[64];
2274   static char mode = 0;
2275   XNADDR xna;
2276   DWORD dwState;
2277
2278   if( resetmode )
2279   {
2280     resetmode = 0;
2281     mode = 0;
2282   }
2283
2284   if( !XNetGetEthernetLinkStatus() )
2285   {
2286     return 1;
2287   }
2288
2289   if( mode == 100 )
2290   {
2291     CLog::Log(LOGDEBUG, "  pending...");
2292     dwState = XNetGetTitleXnAddr(&xna);
2293     if(dwState==XNET_GET_XNADDR_PENDING)
2294       return 1;
2295     mode = 5;
2296     char  azIPAdd[256];
2297     memset( azIPAdd,0,256);
2298     XNetInAddrToString(xna.ina,azIPAdd,32);
2299     CLog::Log(LOGINFO, "ip address:%s",azIPAdd);
2300   }
2301
2302   // if local address is specified
2303   if( mode == 0 )
2304   {
2305     if ( !networkinfo.DHCP )
2306     {
2307       TXNetConfigParams configParams;
2308
2309       XNetLoadConfigParams( (LPBYTE) &configParams );
2310       BOOL bXboxVersion2 = (configParams.V2_Tag == 0x58425632 );  // "XBV2"
2311       BOOL bDirty = FALSE;
2312
2313       if (bXboxVersion2)
2314       {
2315         if (configParams.V2_IP != inet_addr(networkinfo.ip))
2316         {
2317           configParams.V2_IP = inet_addr(networkinfo.ip);
2318           bDirty = TRUE;
2319         }
2320       }
2321       else
2322       {
2323         if (configParams.V1_IP != inet_addr(networkinfo.ip))
2324         {
2325           configParams.V1_IP = inet_addr(networkinfo.ip);
2326           bDirty = TRUE;
2327         }
2328       }
2329
2330       if (bXboxVersion2)
2331       {
2332         if (configParams.V2_Subnetmask != inet_addr(networkinfo.subnet))
2333         {
2334           configParams.V2_Subnetmask = inet_addr(networkinfo.subnet);
2335           bDirty = TRUE;
2336         }
2337       }
2338       else
2339       {
2340         if (configParams.V1_Subnetmask != inet_addr(networkinfo.subnet))
2341         {
2342           configParams.V1_Subnetmask = inet_addr(networkinfo.subnet);
2343           bDirty = TRUE;
2344         }
2345       }
2346
2347       if (bXboxVersion2)
2348       {
2349         if (configParams.V2_Defaultgateway != inet_addr(networkinfo.gateway))
2350         {
2351           configParams.V2_Defaultgateway = inet_addr(networkinfo.gateway);
2352           bDirty = TRUE;
2353         }
2354       }
2355       else
2356       {
2357         if (configParams.V1_Defaultgateway != inet_addr(networkinfo.gateway))
2358         {
2359           configParams.V1_Defaultgateway = inet_addr(networkinfo.gateway);
2360           bDirty = TRUE;
2361         }
2362       }
2363
2364       if (bXboxVersion2)
2365       {
2366         if (configParams.V2_DNS1 != inet_addr(networkinfo.DNS1))
2367         {
2368           configParams.V2_DNS1 = inet_addr(networkinfo.DNS1);
2369           bDirty = TRUE;
2370         }
2371       }
2372       else
2373       {
2374         if (configParams.V1_DNS1 != inet_addr(networkinfo.DNS1))
2375         {
2376           configParams.V1_DNS1 = inet_addr(networkinfo.DNS1);
2377           bDirty = TRUE;
2378         }
2379       }
2380
2381       if (bXboxVersion2)
2382       {
2383         if (configParams.V2_DNS2 != inet_addr(networkinfo.DNS2))
2384         {
2385           configParams.V2_DNS2 = inet_addr(networkinfo.DNS2);
2386           bDirty = TRUE;
2387         }
2388       }
2389       else
2390       {
2391         if (configParams.V1_DNS2 != inet_addr(networkinfo.DNS2))
2392         {
2393           configParams.V1_DNS2 = inet_addr(networkinfo.DNS2);
2394           bDirty = TRUE;
2395         }
2396       }
2397
2398       if (configParams.Flag != (0x04|0x08) )
2399       {
2400         configParams.Flag = 0x04 | 0x08;
2401         bDirty = TRUE;
2402       }
2403
2404       XNetSaveConfigParams( (LPBYTE) &configParams );
2405
2406       XNetStartupParams xnsp;
2407       memset(&xnsp, 0, sizeof(xnsp));
2408       xnsp.cfgSizeOfStruct = sizeof(XNetStartupParams);
2409
2410       // Bypass security so that we may connect to 'untrusted' hosts
2411       xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;
2412     // create more memory for networking
2413                         xnsp.cfgPrivatePoolSizeInPages = 64; // == 256kb, default = 12 (48kb)
2414                         xnsp.cfgEnetReceiveQueueLength = 16; // == 32kb, default = 8 (16kb)
2415                         xnsp.cfgIpFragMaxSimultaneous = 16; // default = 4
2416                         xnsp.cfgIpFragMaxPacketDiv256 = 32; // == 8kb, default = 8 (2kb)
2417                         xnsp.cfgSockMaxSockets = 64; // default = 64
2418                         xnsp.cfgSockDefaultRecvBufsizeInK = 128; // default = 16
2419                         xnsp.cfgSockDefaultSendBufsizeInK = 128; // default = 16
2420       CLog::Log(LOGINFO, "requesting local ip adres");
2421       int err = XNetStartup(&xnsp);
2422       mode = 100;
2423       return 1;
2424     }
2425     else
2426     {
2427       /**     Set DHCP-flags from a known DHCP mode  (maybe some day we will fix this)  **/
2428       XNetLoadConfigParams(params);
2429       memset( params, 0, (sizeof(IN_ADDR) * 5) + 20 );
2430       params[40]=33;  params[41]=223; params[42]=196; params[43]=67;  params[44]=6;
2431       params[45]=145; params[46]=157; params[47]=118; params[48]=182; params[49]=239;
2432       params[50]=68;  params[51]=197; params[52]=133; params[53]=150; params[54]=118;
2433       params[55]=211; params[56]=38;  params[57]=87;  params[58]=222; params[59]=119;
2434       params[64]=0; params[72]=0; params[73]=0; params[74]=0; params[75]=0;
2435       params[340]=160;    params[341]=93;       params[342]=131;      params[343]=191;      params[344]=46;
2436
2437       XNetStartupParams xnsp;
2438
2439       memset(&xnsp, 0, sizeof(xnsp));
2440       xnsp.cfgSizeOfStruct = sizeof(XNetStartupParams);
2441       // Bypass security so that we may connect to 'untrusted' hosts
2442       xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;
2443
2444                         xnsp.cfgPrivatePoolSizeInPages = 64; // == 256kb, default = 12 (48kb)
2445                         xnsp.cfgEnetReceiveQueueLength = 16; // == 32kb, default = 8 (16kb)
2446                         xnsp.cfgIpFragMaxSimultaneous = 16; // default = 4
2447                         xnsp.cfgIpFragMaxPacketDiv256 = 32; // == 8kb, default = 8 (2kb)
2448                         xnsp.cfgSockMaxSockets = 64; // default = 64
2449                         xnsp.cfgSockDefaultRecvBufsizeInK = 128; // default = 16
2450                         xnsp.cfgSockDefaultSendBufsizeInK = 128; // default = 16
2451
2452       XNetSaveConfigParams(params);
2453       CLog::Log(LOGINFO, "requesting DHCP");
2454       int err = XNetStartup(&xnsp);
2455       mode = 5;
2456     }
2457
2458
2459   }
2460
2461   char g_szTitleIP[32];
2462
2463   WSADATA WsaData;
2464   int err;
2465
2466   char ftploop;
2467   if( mode == 5 )
2468   {
2469     XNADDR xna;
2470     DWORD dwState;
2471
2472     dwState = XNetGetTitleXnAddr(&xna);
2473
2474     if( dwState==XNET_GET_XNADDR_PENDING)
2475       return 1;
2476
2477     XNetInAddrToString(xna.ina,g_szTitleIP,32);
2478     err = WSAStartup( MAKEWORD(2,2), &WsaData );
2479     ftploop = 1;
2480     mode ++;
2481   }
2482
2483   if( mode == 6 )
2484   {
2485     vReturn = XNetGetTitleXnAddr(&sAddress);
2486
2487
2488     ftploop = 1;
2489
2490     if( vReturn != XNET_GET_XNADDR_PENDING )
2491     {
2492       char  azIPAdd[256];
2493       //char  azMessage[256];
2494
2495       memset(azIPAdd,0,sizeof(azIPAdd));
2496
2497       XNetInAddrToString(sAddress.ina,azIPAdd,sizeof(azIPAdd));
2498       //strcpy(NetworkStatus,azIPAdd);
2499       //strcpy( NetworkStatusInternal, NetworkStatus );
2500                         if (sAddress.ina.S_un.S_addr != 0)
2501       {
2502         DWORD temp = XNetGetEthernetLinkStatus();
2503         if(  temp & XNET_ETHERNET_LINK_ACTIVE )
2504         {
2505
2506           if ( temp & XNET_ETHERNET_LINK_FULL_DUPLEX )
2507           {
2508             // full duplex
2509             CLog::Log(LOGINFO, "  full duplex");
2510           }
2511
2512           if ( temp & XNET_ETHERNET_LINK_HALF_DUPLEX )
2513           {
2514             // half duplex
2515             CLog::Log(LOGINFO, "  half duplex");
2516           }
2517
2518           if ( temp & XNET_ETHERNET_LINK_100MBPS )
2519           {
2520             CLog::Log(LOGINFO, "  100 mbps");
2521           }
2522
2523           if ( temp & XNET_ETHERNET_LINK_10MBPS )
2524           {
2525             CLog::Log(LOGINFO, "  10bmps");
2526           }
2527
2528           if ( vReturn &  XNET_GET_XNADDR_STATIC )
2529           {
2530             CLog::Log(LOGINFO, "  static ip");
2531           }
2532
2533           if ( vReturn &  XNET_GET_XNADDR_DHCP )
2534           {
2535             CLog::Log(LOGINFO, "  Dynamic IP");
2536           }
2537
2538           if ( vReturn & XNET_GET_XNADDR_DNS )
2539           {
2540             CLog::Log(LOGINFO, "  DNS");
2541           }
2542
2543           if ( vReturn & XNET_GET_XNADDR_ETHERNET )
2544           {
2545             CLog::Log(LOGINFO, "  ethernet");
2546           }
2547
2548           if ( vReturn & XNET_GET_XNADDR_NONE )
2549           {
2550             CLog::Log(LOGINFO, "  none");
2551           }
2552
2553           if ( vReturn & XNET_GET_XNADDR_ONLINE )
2554           {
2555             CLog::Log(LOGINFO, "  online");
2556           }
2557
2558           if ( vReturn & XNET_GET_XNADDR_PENDING )
2559           {
2560             CLog::Log(LOGINFO, "  pending");
2561           }
2562
2563           if ( vReturn & XNET_GET_XNADDR_TROUBLESHOOT )
2564           {
2565             CLog::Log(LOGINFO, "  error");
2566           }
2567
2568           if ( vReturn & XNET_GET_XNADDR_PPPOE )
2569           {
2570             CLog::Log(LOGINFO, "  ppoe");
2571           }
2572
2573           sprintf(temp_str,"  IP: %s",azIPAdd);
2574           CLog::Log(LOGINFO, temp_str);
2575         }
2576         ftploop = 0;
2577         mode ++;
2578         return 0;
2579       }
2580                         return 2;
2581     }
2582
2583     Sleep(50);
2584     return 1;
2585   }
2586   return 1;
2587 }
2588
2589 void CUtil::GetVideoThumbnail(const CStdString& strIMDBID, CStdString& strThumb)
2590 {
2591   strThumb.Format("%s\\imdb\\imdb%s.jpg",g_stSettings.szThumbnailsDirectory,strIMDBID.c_str());
2592 }
2593
2594 void CUtil::SetMusicThumbs(VECFILEITEMS &items)
2595 {
2596   VECFILEITEMS qitems;
2597   CHDDirectory dir;
2598
2599
2600   CStdString strThumb=g_stSettings.m_szAlbumDirectory;
2601   strThumb+="\\thumbs";
2602   {
2603     CFileItemList itemlist(qitems); // will clean up everything
2604     dir.GetDirectory(strThumb.c_str(),qitems);                  //      precache Q:\albums\thumbs directory
2605   }
2606   {
2607     strThumb+="\\temp";
2608     CFileItemList itemlist(qitems); // will clean up everything
2609     dir.GetDirectory(strThumb.c_str(),qitems);                  //      precache Q:\albums\thumbs\temp directory
2610   }
2611
2612   for (int i=0; i < (int)items.size(); ++i)
2613   {
2614     CFileItem* pItem=items[i];
2615     SetMusicThumb(pItem);
2616   }
2617   CUtil::ClearCache();
2618
2619 }
2620
2621 void CUtil::SetMusicThumb(CFileItem* pItem)
2622 {
2623         //      Set the album thumb for a file or folder.
2624
2625         //      Sets thumb by album title or uses files in
2626         //      folder like folder.jpg or .tbn files.
2627
2628   // if it already has a thumbnail, then return
2629   if ( pItem->HasThumbnail() ) return;
2630
2631   if (CUtil::IsRemote(pItem->m_strPath))
2632   {
2633     CURL url(pItem->m_strPath);
2634     if (url.GetProtocol() =="http" || url.GetProtocol()=="HTTP") return ;
2635     if (url.GetProtocol() =="shout" || url.GetProtocol()=="SHOUT") return ;
2636     if (url.GetProtocol() =="mms" || url.GetProtocol()=="MMS") return ;
2637     if (url.GetProtocol() =="rtp" || url.GetProtocol()=="RTP") return ;
2638   }
2639   CStdString strThumb, strPath, strFileName;
2640
2641         //      If item is not a folder, extract its path
2642   if (!pItem->m_bIsFolder)
2643     CUtil::Split(pItem->m_strPath, strPath, strFileName);
2644   else
2645         {
2646     strPath=pItem->m_strPath;
2647                 if (CUtil::HasSlashAtEnd(strPath))
2648                         strPath.Delete(strPath.size()-1);
2649         }
2650
2651         //      Look if an album thumb is available,
2652         //      could be any file with tags loaded or
2653         //      a directory in album window
2654   CStdString strAlbum;
2655         if (pItem->m_musicInfoTag.Loaded())
2656                 strAlbum=pItem->m_musicInfoTag.GetAlbum();
2657
2658         if (!pItem->m_bIsFolder)
2659   {
2660     // look for a permanent thumb (Q:\albums\thumbs)
2661     CUtil::GetAlbumThumb(strAlbum, strPath, strThumb);
2662     if (CUtil::FileExists(strThumb))
2663     {
2664                         //      found it, we are finished.
2665       pItem->SetIconImage(strThumb);
2666       pItem->SetThumbnailImage(strThumb);
2667     }
2668     else
2669     {
2670       // look for a temporary thumb (Q:\albums\thumbs\temp)
2671       CUtil::GetAlbumThumb(strAlbum, strPath,strThumb, true);
2672       if (CUtil::FileExists(strThumb) )
2673       {
2674                                 //      found it
2675         pItem->SetIconImage(strThumb);
2676         pItem->SetThumbnailImage(strThumb);
2677       }
2678                         else
2679                         {
2680                                 //      no thumb found
2681                                 strThumb.Empty();
2682                         }
2683                 }
2684         }
2685
2686         //      If we have not found a thumb before, look for a .tbn if its a file
2687         if (strThumb.IsEmpty() && !pItem->m_bIsFolder)
2688         {
2689                 CUtil::ReplaceExtension(pItem->m_strPath, ".tbn", strThumb);
2690                 if( CUtil::IsRemote(pItem->m_strPath) || CUtil::IsDVD(pItem->m_strPath) || CUtil::IsISO9660(pItem->m_strPath))
2691                 {
2692                         //      Query local cache
2693                         CStdString strCached;
2694                         CUtil::GetAlbumFolderThumb(strThumb, strCached, true);
2695                         if (CUtil::FileExists(strCached))
2696                         {
2697                                 //      Remote thumb found in local cache
2698                                 pItem->SetIconImage(strCached);
2699                                 pItem->SetThumbnailImage(strCached);
2700                         }
2701                         else
2702                         {
2703                                 //      create cached thumb, if a .tbn file is found
2704                                 //      on a remote share
2705                                 if (CUtil::FileExists(strThumb))
2706                                 {
2707                                         //      found, save a thumb
2708                                         //      to the temp thumb dir.
2709                                         CPicture pic;
2710                                         if (pic.CreateAlbumThumbnail(strThumb, strThumb))
2711                                         {
2712                                                 pItem->SetIconImage(strCached);
2713                                                 pItem->SetThumbnailImage(strCached);
2714                                         }
2715                                         else
2716                                         {
2717                                                 //      save temp thumb failed,
2718                                                 //      no thumb available
2719                                                 strThumb.Empty();
2720                                         }
2721                                 }
2722                                 else
2723                                 {
2724                                         //      no thumb available
2725                                         strThumb.Empty();
2726                                 }
2727                         }
2728                 }
2729                 else
2730                 {
2731                         if (CUtil::FileExists(strThumb))
2732                         {
2733                                 //      use local .tbn file as thumb
2734                                 pItem->SetIconImage(strThumb);
2735                                 pItem->SetThumbnailImage(strThumb);
2736                         }
2737                         else
2738                         {
2739                                 //      No thumb found
2740                                 strThumb.Empty();
2741                         }
2742                 }
2743         }
2744
2745         //      If we have not found a thumb before, look for a folder thumb
2746   if (strThumb.IsEmpty() && pItem->GetLabel()!="..")
2747   {
2748                 CStdString strFolderThumb;
2749
2750                 //      Lookup permanent thumbs on HD, if a
2751                 //      thumb for this folder exists
2752     CUtil::GetAlbumFolderThumb(strPath,strFolderThumb);
2753                 if (!CUtil::FileExists(strFolderThumb))
2754                 {
2755                         //      No, lookup saved temp thumbs on HD, if a previously
2756                         //      cached thumb for this folder exists...
2757                         CUtil::GetAlbumFolderThumb(strPath,strFolderThumb, true);
2758                         if (!CUtil::FileExists(strFolderThumb))
2759                         {
2760                                 if (pItem->m_bIsFolder)
2761                                 {
2762                                         CStdString strFolderTbn=strPath;
2763                                         strFolderTbn+=".tbn";
2764                                         CUtil::AddFileToFolder(pItem->m_strPath, "folder.jpg", strThumb);
2765
2766                                         //      ...no, check for a folder.jpg
2767                                         if (CUtil::ThumbExists(strThumb, true))
2768                                         {
2769                                                 //      found, save a thumb for this folder
2770                                                 //      to the temp thumb dir.
2771                                                 CPicture pic;
2772                                                 if (!pic.CreateAlbumThumbnail(strThumb, strPath))
2773                                                 {
2774                                                         //      save temp thumb failed,
2775                                                         //      no thumb available
2776                                                         strFolderThumb.Empty();
2777                                                 }
2778                                         }       //      ...or maybe we have a "foldername".tbn
2779                                         else if (CUtil::ThumbExists(strFolderTbn, true))
2780                                         {
2781                                                 //      found, save a thumb for this folder
2782                                                 //      to the temp thumb dir.
2783                                                 CPicture pic;
2784                                                 if (!pic.CreateAlbumThumbnail(strFolderTbn, strPath))
2785                                                 {
2786                                                         //      save temp thumb failed,
2787                                                         //      no thumb available
2788                                                         strFolderThumb.Empty();
2789                                                 }
2790                                         }
2791                                         else
2792                                         {
2793                                                 //      no thumb exists, do we have a directory
2794                                                 //      from album window, use music.jpg as icon
2795                                                 if (!strAlbum.IsEmpty())
2796                                                         pItem->SetIconImage("music.jpg");
2797
2798                                                 strFolderThumb.Empty();
2799                                         }
2800                                 }
2801                                 else
2802                                 {
2803                                         //      No thumb found for file
2804                                         strFolderThumb.Empty();
2805                                 }
2806                         }
2807                 }       //      if (pItem->m_bIsFolder && strThumb.IsEmpty() && pItem->GetLabel()!="..")
2808
2809
2810                 //      Have we found a folder thumb
2811                 if (!strFolderThumb.IsEmpty())
2812                 {
2813                                 //      if we have a directory from album
2814                                 //      window, set the icon too.
2815                         if (pItem->m_bIsFolder && !strAlbum.IsEmpty())
2816                                 pItem->SetIconImage(strFolderThumb);
2817
2818                         pItem->SetThumbnailImage(strFolderThumb);
2819                 }
2820   }
2821 }
2822
2823 CStdString CUtil::GetNextFilename(const char* fn_template, int max)
2824 {
2825         // Open the file.
2826         char szName[1024];
2827
2828         INT i;
2829
2830         WIN32_FIND_DATA wfd;
2831         HANDLE hFind;
2832
2833
2834         if (NULL != strstr(fn_template, "%03d"))
2835         {
2836                 for(i = 0; i <= max; i++)
2837                 {
2838
2839                         wsprintf(szName, fn_template, i);
2840
2841                         memset(&wfd, 0, sizeof(wfd));
2842                         if ((hFind = FindFirstFile(szName, &wfd)) != INVALID_HANDLE_VALUE)
2843                                 FindClose(hFind);
2844                         else
2845                         {
2846                                 // FindFirstFile didn't find the file 'szName', return it
2847                                 return szName;
2848                         }
2849                 }
2850         }
2851
2852         return ""; // no fn generated
2853 }
2854
2855 void CUtil::InitGamma()
2856 {
2857   g_graphicsContext.Get3DDevice()->GetGammaRamp(&oldramp);
2858 }
2859 void CUtil::RestoreBrightnessContrastGamma()
2860 {
2861   g_graphicsContext.Lock();
2862   g_graphicsContext.Get3DDevice()->SetGammaRamp(D3DSGR_IMMEDIATE , &oldramp);
2863   g_graphicsContext.Unlock();
2864 }
2865
2866 void CUtil::SetBrightnessContrastGammaPercent(int iBrightNess, int iContrast, int iGamma, bool bImmediate)
2867 {
2868   if (iBrightNess < 0) iBrightNess=0;
2869   if (iBrightNess >100) iBrightNess=100;
2870   if (iContrast < 0) iContrast=0;
2871   if (iContrast >100) iContrast=100;
2872   if (iGamma < 0) iGamma=0;
2873   if (iGamma >100) iGamma=100;
2874
2875   float fBrightNess=(((float)iBrightNess)/50.0f) -1.0f;
2876   float fContrast=(((float)iContrast)/50.0f);
2877   float fGamma=(((float)iGamma)/40.0f)+0.5f;
2878   CUtil::SetBrightnessContrastGamma(fBrightNess, fContrast, fGamma, bImmediate);
2879 }
2880
2881 #define clamp(x) (x) > 255.f ? 255 : ((x) < 0 ? 0 : (BYTE)(x+0.5f))
2882 // Valid ranges:
2883 //  brightness -1 -> 1
2884 //  contrast    0 -> 2
2885 //  gamma     0.5 -> 3.5
2886 void CUtil::SetBrightnessContrastGamma(float Brightness, float Contrast, float Gamma, bool bImmediate)
2887 {
2888         // calculate ramp
2889         D3DGAMMARAMP ramp;
2890
2891         Gamma = 1.0f / Gamma;
2892         for (int i = 0; i < 256; ++i)
2893         {
2894                 float f = (powf((float)i / 255.f, Gamma) * Contrast + Brightness)*255.f;
2895                 ramp.blue[i] = ramp.green[i] = ramp.red[i] = clamp(f);
2896         }
2897
2898         // set ramp next v sync
2899         g_graphicsContext.Lock();
2900         g_graphicsContext.Get3DDevice()->SetGammaRamp(bImmediate ? D3DSGR_IMMEDIATE : 0, &ramp);
2901         g_graphicsContext.Unlock();
2902 }
2903
2904
2905 // Tokenize ripped from http://www.linuxselfhelp.com/HOWTO/C++Programming-HOWTO-7.html
2906 void CUtil::Tokenize(const CStdString& path, vector<CStdString>& tokens, const string& delimiters)
2907 {
2908         string str = path;
2909         // Skip delimiters at beginning.
2910         string::size_type lastPos = str.find_first_not_of(delimiters, 0);
2911         // Find first "non-delimiter".
2912         string::size_type pos     = str.find_first_of(delimiters, lastPos);
2913
2914         while (string::npos != pos || string::npos != lastPos)
2915         {
2916                 // Found a token, add it to the vector.
2917                 tokens.push_back(str.substr(lastPos, pos - lastPos));
2918                 // Skip delimiters.  Note the "not_of"
2919                 lastPos = str.find_first_not_of(delimiters, pos);
2920                 // Find next "non-delimiter"
2921                 pos = str.find_first_of(delimiters, lastPos);
2922         }
2923 }
2924
2925
2926 void CUtil::FlashScreen(bool bImmediate, bool bOn)
2927 {
2928         static bool bInFlash = false;
2929
2930         if (bInFlash == bOn)
2931                 return;
2932         bInFlash = bOn;
2933         g_graphicsContext.Lock();
2934         if (bOn)
2935         {
2936                 g_graphicsContext.Get3DDevice()->GetGammaRamp(&flashramp);
2937                 SetBrightnessContrastGamma(0.5f, 1.2f, 2.0f, bImmediate);
2938         }
2939         else
2940                 g_graphicsContext.Get3DDevice()->SetGammaRamp(bImmediate ? D3DSGR_IMMEDIATE : 0, &flashramp);
2941         g_graphicsContext.Unlock();
2942 }
2943
2944 void CUtil::TakeScreenshot()
2945 {
2946         LPDIRECT3DSURFACE8 lpSurface = NULL;
2947         char fn[1024];
2948         CStdString strDir = g_stSettings.m_szScreenshotsDirectory;
2949