[droid] splash: adjust progressbar color
[vuplus_xbmc] / xbmc / Autorun.cpp
1 /*
2  *      Copyright (C) 2005-2012 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "system.h"
22
23 #ifdef HAS_DVD_DRIVE
24
25 #include "Autorun.h"
26 #include "Application.h"
27 #include "GUIPassword.h"
28 #include "GUIUserMessages.h"
29 #include "PlayListPlayer.h"
30 #include "filesystem/StackDirectory.h"
31 #include "filesystem/Directory.h"
32 #include "filesystem/DirectoryFactory.h"
33 #include "filesystem/File.h"
34 #include "settings/GUISettings.h"
35 #include "settings/Settings.h"
36 #include "playlists/PlayList.h"
37 #include "guilib/GUIWindowManager.h"
38 #include "storage/MediaManager.h"
39 #include "video/VideoDatabase.h"
40 #include "dialogs/GUIDialogYesNo.h"
41 #include "utils/URIUtils.h"
42 #include "utils/log.h"
43 #ifdef HAS_CDDA_RIPPER
44 #include "cdrip/CDDARipper.h"
45 #endif
46
47 using namespace std;
48 using namespace XFILE;
49 using namespace PLAYLIST;
50 using namespace MEDIA_DETECT;
51
52 CAutorun::CAutorun()
53 {
54   m_bEnable = true;
55 }
56
57 CAutorun::~CAutorun()
58 {}
59
60 void CAutorun::ExecuteAutorun(const CStdString& path, bool bypassSettings, bool ignoreplaying, bool startFromBeginning )
61 {
62   if ((!ignoreplaying && (g_application.IsPlayingAudio() || g_application.IsPlayingVideo() || g_windowManager.HasModalDialog())) || g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN)
63     return ;
64
65   CCdInfo* pInfo = g_mediaManager.GetCdInfo(path);
66
67   if ( pInfo == NULL )
68     return ;
69
70   g_application.ResetScreenSaver();
71   g_application.WakeUpScreenSaverAndDPMS();  // turn off the screensaver if it's active
72 #ifdef HAS_CDDA_RIPPER
73   if (g_guiSettings.GetInt("audiocds.autoaction") == AUTOCD_RIP && 
74       pInfo->IsAudio(1) && !g_settings.GetCurrentProfile().musicLocked())
75   {
76     CCDDARipper::GetInstance().RipCD();
77   }
78   else
79 #endif
80   PlayDisc(path, bypassSettings, startFromBeginning);
81 }
82
83 bool CAutorun::PlayDisc(const CStdString& path, bool bypassSettings, bool startFromBeginning)
84 {
85   if ( !bypassSettings && !g_guiSettings.GetInt("audiocds.autoaction") == AUTOCD_PLAY && !g_guiSettings.GetBool("dvds.autorun"))
86     return false;
87
88   int nSize = g_playlistPlayer.GetPlaylist( PLAYLIST_MUSIC ).size();
89   int nAddedToPlaylist = 0;
90
91   CStdString mediaPath;
92
93   CCdInfo* pInfo = g_mediaManager.GetCdInfo(path);
94   if (pInfo == NULL)
95     return false;
96
97   if (mediaPath.IsEmpty() && pInfo->IsAudio(1))
98     mediaPath = "cdda://local/";
99
100   if (mediaPath.IsEmpty() && (pInfo->IsISOUDF(1) || pInfo->IsISOHFS(1) || pInfo->IsIso9660(1) || pInfo->IsIso9660Interactive(1)))
101     mediaPath = "iso9660://";
102
103   if (mediaPath.IsEmpty())
104     mediaPath = path;
105
106 #ifdef _WIN32
107   if (mediaPath.IsEmpty() || mediaPath.CompareNoCase("iso9660://") == 0)
108     mediaPath = g_mediaManager.TranslateDevicePath("");
109 #endif
110
111   auto_ptr<IDirectory> pDir ( CDirectoryFactory::Create( mediaPath ));
112   bool bPlaying = RunDisc(pDir.get(), mediaPath, nAddedToPlaylist, true, bypassSettings, startFromBeginning);
113
114   if ( !bPlaying && nAddedToPlaylist > 0 )
115   {
116     CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
117     g_windowManager.SendMessage( msg );
118     g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_MUSIC);
119     // Start playing the items we inserted
120     return g_playlistPlayer.Play(nSize);
121   }
122
123   return bPlaying;
124 }
125
126 /**
127  * This method tries to determine what type of disc is located in the given drive and starts to play the content appropriately.
128  */
129 bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAddedToPlaylist, bool bRoot, bool bypassSettings /* = false */, bool startFromBeginning /* = false */)
130 {
131   bool bPlaying(false);
132   CFileItemList vecItems;
133
134   if ( !pDir->GetDirectory( strDrive, vecItems ) )
135   {
136     return false;
137   }
138
139   // Sorting necessary for easier HDDVD handling
140   vecItems.Sort(SORT_METHOD_LABEL, SortOrderAscending);
141
142   bool bAllowVideo = true;
143 //  bool bAllowPictures = true;
144   bool bAllowMusic = true;
145   if (!g_passwordManager.IsMasterLockUnlocked(false))
146   {
147     bAllowVideo = !g_settings.GetCurrentProfile().videoLocked();
148 //    bAllowPictures = !g_settings.GetCurrentProfile().picturesLocked();
149     bAllowMusic = !g_settings.GetCurrentProfile().musicLocked();
150   }
151
152   // is this a root folder we have to check the content to determine a disc type
153   if( bRoot )
154   {
155     CStdString hddvdname = "";
156     CFileItemPtr phddvdItem;
157
158     // check root folders next, for normal structured dvd's
159     for (int i = 0; i < vecItems.Size(); i++)
160     {
161       CFileItemPtr pItem = vecItems[i];
162
163       // is the current item a (non system) folder?
164       if (pItem->m_bIsFolder && pItem->GetPath() != "." && pItem->GetPath() != "..")
165       {
166         CStdString name = pItem->GetPath();
167         URIUtils::RemoveSlashAtEnd(name);
168         name = URIUtils::GetFileName(name);
169
170         // Check if the current foldername indicates a DVD structure (name is "VIDEO_TS")
171         if (name.Equals("VIDEO_TS") && bAllowVideo
172         && (bypassSettings || g_guiSettings.GetBool("dvds.autorun")))
173         {
174           CStdString path = URIUtils::AddFileToFolder(pItem->GetPath(), "VIDEO_TS.IFO");
175           if(!CFile::Exists(path))
176             path = URIUtils::AddFileToFolder(pItem->GetPath(), "video_ts.ifo");
177           CFileItem item(path, false);
178           item.SetLabel(g_mediaManager.GetDiskLabel(strDrive));
179           item.GetVideoInfoTag()->m_strFileNameAndPath = g_mediaManager.GetDiskUniqueId(strDrive);
180
181           if (!startFromBeginning && !item.GetVideoInfoTag()->m_strFileNameAndPath.IsEmpty())
182             item.m_lStartOffset = STARTOFFSET_RESUME;
183
184           g_application.PlayFile(item, false);
185           bPlaying = true;
186           return true;
187         }
188
189         // Check if the current foldername indicates a Blu-Ray structure (default is "BDMV").
190         // A BR should also include an "AACS" folder for encryption, Sony-BRs can also include update folders for PS3 (PS3_UPDATE / PS3_VPRM).
191         // ToDo: for the time beeing, the DVD autorun settings are used to determine if the BR should be started automatically.
192         if (name.Equals("BDMV") && bAllowVideo
193         && (bypassSettings || g_guiSettings.GetBool("dvds.autorun")))
194         {
195           CFileItem item(URIUtils::AddFileToFolder(pItem->GetPath(), "index.bdmv"), false);
196           item.SetLabel(g_mediaManager.GetDiskLabel(strDrive));
197           item.GetVideoInfoTag()->m_strFileNameAndPath = g_mediaManager.GetDiskUniqueId(strDrive);
198
199           if (!startFromBeginning && !item.GetVideoInfoTag()->m_strFileNameAndPath.IsEmpty())
200             item.m_lStartOffset = STARTOFFSET_RESUME;
201
202           g_application.PlayFile(item, false);
203           bPlaying = true;
204           return true;
205         }
206
207         // Check if the current foldername indicates a HD DVD structure (default is "HVDVD_TS").
208         // Most HD DVD will also include an "ADV_OBJ" folder for advanced content. This folder should be handled first.
209         // ToDo: for the time beeing, the DVD autorun settings are used to determine if the HD DVD should be started automatically.
210         CFileItemList items, sitems;
211         
212         // Advanced Content HD DVD (most discs?)
213         if (name.Equals("ADV_OBJ"))
214         {
215           CLog::Log(LOGINFO,"HD DVD: Checking for playlist.");
216           // find playlist file
217           CDirectory::GetDirectory(pItem->GetPath(), items, "*.xpl");
218           if (items.Size())
219           {
220             // HD DVD Standard says the highest numbered playlist has to be handled first.
221             CLog::Log(LOGINFO,"HD DVD: Playlist found. Set filetypes to *.xpl for external player.");
222             items.Sort(SORT_METHOD_LABEL, SortOrderDescending);
223             phddvdItem = pItem; 
224             hddvdname = URIUtils::GetFileName(items[0]->GetPath());
225             CLog::Log(LOGINFO,"HD DVD: %s", items[0]->GetPath().c_str());
226           }
227         }
228
229         // Standard Content HD DVD (few discs?)
230         if (name.Equals("HVDVD_TS") && bAllowVideo
231         && (bypassSettings || g_guiSettings.GetBool("dvds.autorun")))
232         {
233           if (hddvdname == "")
234           {
235             CLog::Log(LOGINFO,"HD DVD: Checking for ifo.");
236             // find Video Manager or Title Set Information
237             CDirectory::GetDirectory(pItem->GetPath(), items, "HV*.ifo");
238             if (items.Size())
239             {
240               // HD DVD Standard says the lowest numbered ifo has to be handled first.
241               CLog::Log(LOGINFO,"HD DVD: IFO found. Set filename to HV* and filetypes to *.ifo for external player.");
242               items.Sort(SORT_METHOD_LABEL, SortOrderAscending);
243               phddvdItem = pItem; 
244               hddvdname = URIUtils::GetFileName(items[0]->GetPath());
245               CLog::Log(LOGINFO,"HD DVD: %s",items[0]->GetPath().c_str());
246             }
247           }
248           // Find and sort *.evo files for internal playback.
249           // While this algorithm works for all of my HD DVDs, it may fail on other discs. If there are very large extras which are
250           // alphabetically before the main movie they will be sorted to the top of the playlist and get played first.
251           CDirectory::GetDirectory(pItem->GetPath(), items, "*.evo");
252           if (items.Size())
253           {
254             // Sort *.evo files in alphabetical order.
255             items.Sort(SORT_METHOD_LABEL, SortOrderAscending);
256             int64_t asize = 0;
257             int ecount = 0;
258             // calculate average size of elements above 1gb
259             for (int j = 0; j < items.Size(); j++)
260               if (items[j]->m_dwSize > 1000000000)
261               {
262                 ecount++;
263                 asize = asize + items[j]->m_dwSize;
264               }
265             asize = asize / ecount;
266             // Put largest files in alphabetical order to top of new list.
267             for (int j = 0; j < items.Size(); j++)
268               if (items[j]->m_dwSize >= asize)
269                 sitems.Add (items[j]);
270             // Sort *.evo files by size.
271             items.Sort(SORT_METHOD_SIZE, SortOrderDescending);
272             // Add other files with descending size to bottom of new list.
273             for (int j = 0; j < items.Size(); j++)
274               if (items[j]->m_dwSize < asize)
275                 sitems.Add (items[j]);
276             // Replace list with optimized list.
277             items.Clear();
278             items.Copy (sitems);
279             sitems.Clear();
280           }
281           if (hddvdname != "")
282           {
283             CFileItem item(URIUtils::AddFileToFolder(phddvdItem->GetPath(), hddvdname), false);
284             item.SetLabel(g_mediaManager.GetDiskLabel(strDrive));
285             item.GetVideoInfoTag()->m_strFileNameAndPath = g_mediaManager.GetDiskUniqueId(strDrive);
286
287             if (!startFromBeginning && !item.GetVideoInfoTag()->m_strFileNameAndPath.IsEmpty())
288             item.m_lStartOffset = STARTOFFSET_RESUME;
289
290             // get playername
291             CStdString hddvdplayer = CPlayerCoreFactory::GetPlayerName(CPlayerCoreFactory::GetDefaultPlayer(item));
292             
293             // Single *.xpl or *.ifo files require an external player to handle playback.
294             // If no matching rule was found, DVDPlayer will be default player.
295             if (hddvdplayer != "DVDPlayer")
296             {
297               CLog::Log(LOGINFO,"HD DVD: External singlefile playback initiated: %s",hddvdname.c_str());
298               g_application.PlayFile(item, false);
299               bPlaying = true;
300               return true;
301             } else
302               CLog::Log(LOGINFO,"HD DVD: No external player found. Fallback to internal one.");
303           }
304
305           //  internal *.evo playback.
306           CLog::Log(LOGINFO,"HD DVD: Internal multifile playback initiated.");
307           g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO);
308           g_playlistPlayer.SetShuffle (PLAYLIST_VIDEO, false);
309           g_playlistPlayer.Add(PLAYLIST_VIDEO, items);
310           g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO);
311           g_playlistPlayer.Play(0);
312           bPlaying = true;
313           return true;
314         }
315                                 
316         // Video CDs can have multiple file formats. First we need to determine which one is used on the CD
317         CStdString strExt;
318         if (name.Equals("MPEGAV"))
319           strExt = ".dat";
320         if (name.Equals("MPEG2"))
321           strExt = ".mpg";
322
323         // If a file format was extracted we are sure this is a VCD. Autoplay if settings indicate we should.
324         if (!strExt.IsEmpty() && bAllowVideo
325              && (bypassSettings || g_guiSettings.GetBool("dvds.autorun")))
326         {
327           CFileItemList items;
328           CDirectory::GetDirectory(pItem->GetPath(), items, strExt);
329           if (items.Size())
330           {
331             items.Sort(SORT_METHOD_LABEL, SortOrderAscending);
332             g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO);
333             g_playlistPlayer.Add(PLAYLIST_VIDEO, items);
334             g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO);
335             g_playlistPlayer.Play(0);
336             bPlaying = true;
337             return true;
338           }
339         }
340         /* Probably want this if/when we add some automedia action dialog...
341         else if (pItem->GetPath().Find("PICTURES") != -1 && bAllowPictures
342               && (bypassSettings))
343         {
344           bPlaying = true;
345           CStdString strExec;
346           strExec.Format("XBMC.RecursiveSlideShow(%s)", pItem->GetPath().c_str());
347           CBuiltins::Execute(strExec);
348           return true;
349         }
350         */
351       }
352     }
353   }
354
355   // check video first
356   if (!nAddedToPlaylist && !bPlaying && (bypassSettings || g_guiSettings.GetBool("dvds.autorun")))
357   {
358     // stack video files
359     CFileItemList tempItems;
360     tempItems.Append(vecItems);
361     if (g_settings.m_videoStacking)
362       tempItems.Stack();
363     CFileItemList itemlist;
364
365     for (int i = 0; i < tempItems.Size(); i++)
366     {
367       CFileItemPtr pItem = tempItems[i];
368       if (!pItem->m_bIsFolder && pItem->IsVideo())
369       {
370         bPlaying = true;
371         if (pItem->IsStack())
372         {
373           // TODO: remove this once the app/player is capable of handling stacks immediately
374           CStackDirectory dir;
375           CFileItemList items;
376           dir.GetDirectory(pItem->GetPath(), items);
377           itemlist.Append(items);
378         }
379         else
380           itemlist.Add(pItem);
381       }
382     }
383     if (itemlist.Size())
384     {
385       if (!bAllowVideo)
386       {
387         if (!bypassSettings)
388           return false;
389
390         if (g_windowManager.GetActiveWindow() != WINDOW_VIDEO_FILES)
391           if (!g_passwordManager.IsMasterLockUnlocked(true))
392             return false;
393       }
394       g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO);
395       g_playlistPlayer.Add(PLAYLIST_VIDEO, itemlist);
396       g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO);
397       g_playlistPlayer.Play(0);
398     }
399   }
400   // then music
401   if (!bPlaying && (bypassSettings || g_guiSettings.GetInt("audiocds.autoaction") == AUTOCD_PLAY) && bAllowMusic)
402   {
403     for (int i = 0; i < vecItems.Size(); i++)
404     {
405       CFileItemPtr pItem = vecItems[i];
406       if (!pItem->m_bIsFolder && pItem->IsAudio())
407       {
408         nAddedToPlaylist++;
409         g_playlistPlayer.Add(PLAYLIST_MUSIC, pItem);
410       }
411     }
412   }
413   /* Probably want this if/when we add some automedia action dialog...
414   // and finally pictures
415   if (!nAddedToPlaylist && !bPlaying && bypassSettings && bAllowPictures)
416   {
417     for (int i = 0; i < vecItems.Size(); i++)
418     {
419       CFileItemPtr pItem = vecItems[i];
420       if (!pItem->m_bIsFolder && pItem->IsPicture())
421       {
422         bPlaying = true;
423         CStdString strExec;
424         strExec.Format("XBMC.RecursiveSlideShow(%s)", strDrive.c_str());
425         CBuiltins::Execute(strExec);
426         break;
427       }
428     }
429   }
430   */
431
432   // check subdirs if we are not playing yet
433   if (!bPlaying)
434   {
435     for (int i = 0; i < vecItems.Size(); i++)
436     {
437       CFileItemPtr  pItem = vecItems[i];
438       if (pItem->m_bIsFolder)
439       {
440         if (pItem->GetPath() != "." && pItem->GetPath() != ".." )
441         {
442           if (RunDisc(pDir, pItem->GetPath(), nAddedToPlaylist, false, bypassSettings, startFromBeginning))
443           {
444             bPlaying = true;
445             break;
446           }
447         }
448       } // if (non system) folder
449     } // for all items in directory
450   } // if root folder
451
452   return bPlaying;
453 }
454
455 void CAutorun::HandleAutorun()
456 {
457 #ifndef _WIN32
458   if (!m_bEnable)
459   {
460     CDetectDVDMedia::m_evAutorun.Reset();
461     return ;
462   }
463
464   if (CDetectDVDMedia::m_evAutorun.WaitMSec(0))
465   {
466     ExecuteAutorun();
467     CDetectDVDMedia::m_evAutorun.Reset();
468   }
469 #endif
470 }
471
472 void CAutorun::Enable()
473 {
474   m_bEnable = true;
475 }
476
477 void CAutorun::Disable()
478 {
479   m_bEnable = false;
480 }
481
482 bool CAutorun::IsEnabled() const
483 {
484   return m_bEnable;
485 }
486
487 bool CAutorun::PlayDiscAskResume(const CStdString& path)
488 {
489   return PlayDisc(path, true, !CanResumePlayDVD(path) || CGUIDialogYesNo::ShowAndGetInput(341, -1, -1, -1, 13404, 12021));
490 }
491
492 bool CAutorun::CanResumePlayDVD(const CStdString& path)
493 {
494   CStdString strUniqueId = g_mediaManager.GetDiskUniqueId(path);
495   if (!strUniqueId.IsEmpty())
496   {
497     CVideoDatabase dbs;
498     dbs.Open();
499     CBookmark bookmark;
500     if (dbs.GetResumeBookMark(strUniqueId, bookmark))
501       return true;
502   }
503   return false;
504 }
505
506 #endif