[PVR][Estuary] Timer settings dialog: Show client name in timer type selection dialog...
[xbmc.git] / xbmc / Autorun.cpp
blob7739ae5ceb404473da251625d52281eba87c04f6
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "Autorun.h"
11 #include "FileItem.h"
12 #include "GUIPassword.h"
13 #include "GUIUserMessages.h"
14 #include "PlayListPlayer.h"
15 #include "ServiceBroker.h"
16 #include "URL.h"
17 #include "application/Application.h"
18 #include "application/ApplicationComponents.h"
19 #include "application/ApplicationPowerHandling.h"
20 #include "cores/playercorefactory/PlayerCoreFactory.h"
21 #include "filesystem/Directory.h"
22 #include "filesystem/DirectoryFactory.h"
23 #include "filesystem/StackDirectory.h"
24 #include "guilib/GUIComponent.h"
25 #include "guilib/GUIWindowManager.h"
26 #include "guilib/LocalizeStrings.h"
27 #include "messaging/helpers/DialogHelper.h"
28 #include "playlists/PlayList.h"
29 #include "profiles/ProfileManager.h"
30 #include "settings/Settings.h"
31 #include "settings/SettingsComponent.h"
32 #include "settings/lib/Setting.h"
33 #include "settings/lib/SettingDefinitions.h"
35 #include <stdlib.h>
36 #ifndef TARGET_WINDOWS
37 #include "storage/DetectDVDType.h"
38 #endif
39 #include "storage/MediaManager.h"
40 #include "utils/FileUtils.h"
41 #include "utils/StringUtils.h"
42 #include "utils/URIUtils.h"
43 #include "utils/Variant.h"
44 #include "utils/log.h"
45 #include "video/VideoDatabase.h"
47 #ifdef HAS_CDDA_RIPPER
48 #include "cdrip/CDDARipper.h"
49 #endif
51 using namespace XFILE;
52 using namespace MEDIA_DETECT;
53 using namespace KODI::MESSAGING;
54 using namespace std::chrono_literals;
56 using KODI::MESSAGING::HELPERS::DialogResponse;
58 CAutorun::CAutorun()
60 m_bEnable = true;
63 CAutorun::~CAutorun() = default;
65 bool CAutorun::ExecuteAutorun(const std::string& path)
67 if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_LOGIN_SCREEN)
68 return false;
70 CCdInfo* pInfo = CServiceBroker::GetMediaManager().GetCdInfo(path);
72 if ( pInfo == NULL )
73 return false;
75 auto& components = CServiceBroker::GetAppComponents();
76 const auto appPower = components.GetComponent<CApplicationPowerHandling>();
77 appPower->ResetScreenSaver();
78 appPower->WakeUpScreenSaverAndDPMS(); // turn off the screensaver if it's active
80 bool success = false;
82 #ifdef HAS_CDDA_RIPPER
83 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_AUDIOCDS_AUTOACTION) == AUTOCD_RIP &&
84 pInfo->IsAudio(1) && !CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetCurrentProfile().musicLocked())
86 success = KODI::CDRIP::CCDDARipper::GetInstance().RipCD();
88 else
89 #endif
91 success = PlayDisc(path, false, false);
92 return success;
95 bool CAutorun::PlayDisc(const std::string& path, bool bypassSettings, bool startFromBeginning)
97 if ( !bypassSettings && CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_AUDIOCDS_AUTOACTION) != AUTOCD_PLAY && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_DVDS_AUTORUN))
98 return false;
100 int nSize = CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::TYPE_MUSIC).size();
101 int nAddedToPlaylist = 0;
103 std::string mediaPath;
105 CCdInfo* pInfo = CServiceBroker::GetMediaManager().GetCdInfo(path);
106 if (pInfo == NULL)
107 return false;
109 if (pInfo->IsAudio(1))
110 mediaPath = "cdda://local/";
112 if (mediaPath.empty() && (pInfo->IsISOUDF(1) || pInfo->IsISOHFS(1) || pInfo->IsIso9660(1) || pInfo->IsIso9660Interactive(1)))
113 mediaPath = "iso9660://";
115 if (mediaPath.empty())
116 mediaPath = path;
118 if (mediaPath.empty() || mediaPath == "iso9660://")
119 mediaPath = CServiceBroker::GetMediaManager().GetDiscPath();
121 const CURL pathToUrl(mediaPath);
122 std::unique_ptr<IDirectory> pDir ( CDirectoryFactory::Create( pathToUrl ));
123 bool bPlaying = RunDisc(pDir.get(), mediaPath, nAddedToPlaylist, true, bypassSettings, startFromBeginning);
125 if ( !bPlaying && nAddedToPlaylist > 0 )
127 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
128 CServiceBroker::GetGUI()->GetWindowManager().SendMessage( msg );
129 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::TYPE_MUSIC);
130 // Start playing the items we inserted
131 return CServiceBroker::GetPlaylistPlayer().Play(nSize, "");
134 return bPlaying;
138 * This method tries to determine what type of disc is located in the given drive and starts to play the content appropriately.
140 bool CAutorun::RunDisc(IDirectory* pDir, const std::string& strDrive, int& nAddedToPlaylist, bool bRoot, bool bypassSettings /* = false */, bool startFromBeginning /* = false */)
142 if (!pDir)
144 CLog::Log(LOGDEBUG, "CAutorun::{}: cannot run disc. is it properly mounted?", __FUNCTION__);
145 return false;
148 bool bPlaying(false);
149 CFileItemList vecItems;
151 const CURL pathToUrl(strDrive);
152 if ( !pDir->GetDirectory( pathToUrl, vecItems ) )
154 return false;
157 // Sorting necessary for easier HDDVD handling
158 vecItems.Sort(SortByLabel, SortOrderAscending);
160 bool bAllowVideo = true;
161 // bool bAllowPictures = true;
162 bool bAllowMusic = true;
163 if (!g_passwordManager.IsMasterLockUnlocked(false))
165 const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
167 bAllowVideo = !profileManager->GetCurrentProfile().videoLocked();
168 // bAllowPictures = !profileManager->GetCurrentProfile().picturesLocked();
169 bAllowMusic = !profileManager->GetCurrentProfile().musicLocked();
172 // is this a root folder we have to check the content to determine a disc type
173 if (bRoot)
175 std::string hddvdname = "";
176 CFileItemPtr phddvdItem;
177 bool bAutorunDVDs = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_DVDS_AUTORUN);
179 // check root folders next, for normal structured dvd's
180 for (const auto& pItem : vecItems)
182 // is the current item a (non system) folder?
183 if (pItem->m_bIsFolder && pItem->GetPath() != "." && pItem->GetPath() != "..")
185 std::string name = pItem->GetPath();
186 URIUtils::RemoveSlashAtEnd(name);
187 name = URIUtils::GetFileName(name);
189 // Check if the current foldername indicates a DVD structure (name is "VIDEO_TS")
190 if (StringUtils::EqualsNoCase(name, "VIDEO_TS") && bAllowVideo
191 && (bypassSettings || bAutorunDVDs))
193 std::string path = URIUtils::AddFileToFolder(pItem->GetPath(), "VIDEO_TS.IFO");
194 if (!CFileUtils::Exists(path))
195 path = URIUtils::AddFileToFolder(pItem->GetPath(), "video_ts.ifo");
196 CFileItemPtr item(new CFileItem(path, false));
197 item->SetLabel(CServiceBroker::GetMediaManager().GetDiskLabel(strDrive));
198 item->GetVideoInfoTag()->m_strFileNameAndPath =
199 CServiceBroker::GetMediaManager().GetDiskUniqueId(strDrive);
201 if (!startFromBeginning && !item->GetVideoInfoTag()->m_strFileNameAndPath.empty())
202 item->SetStartOffset(STARTOFFSET_RESUME);
204 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::TYPE_VIDEO);
205 CServiceBroker::GetPlaylistPlayer().SetShuffle(PLAYLIST::TYPE_VIDEO, false);
206 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::TYPE_VIDEO, item);
207 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::TYPE_VIDEO);
208 CServiceBroker::GetPlaylistPlayer().Play(0, "");
209 return true;
212 // Check if the current foldername indicates a Blu-Ray structure (default is "BDMV").
213 // A BR should also include an "AACS" folder for encryption, Sony-BRs can also include update folders for PS3 (PS3_UPDATE / PS3_VPRM).
214 //! @todo for the time being, the DVD autorun settings are used to determine if the BR should be started automatically.
215 if (StringUtils::EqualsNoCase(name, "BDMV") && bAllowVideo
216 && (bypassSettings || bAutorunDVDs))
218 CFileItemPtr item(new CFileItem(URIUtils::AddFileToFolder(pItem->GetPath(), "index.bdmv"), false));
219 item->SetLabel(CServiceBroker::GetMediaManager().GetDiskLabel(strDrive));
220 item->GetVideoInfoTag()->m_strFileNameAndPath =
221 CServiceBroker::GetMediaManager().GetDiskUniqueId(strDrive);
223 if (!startFromBeginning && !item->GetVideoInfoTag()->m_strFileNameAndPath.empty())
224 item->SetStartOffset(STARTOFFSET_RESUME);
226 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::TYPE_VIDEO);
227 CServiceBroker::GetPlaylistPlayer().SetShuffle(PLAYLIST::TYPE_VIDEO, false);
228 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::TYPE_VIDEO, item);
229 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::TYPE_VIDEO);
230 CServiceBroker::GetPlaylistPlayer().Play(0, "");
231 return true;
234 // Check if the current foldername indicates a HD DVD structure (default is "HVDVD_TS").
235 // Most HD DVD will also include an "ADV_OBJ" folder for advanced content. This folder should be handled first.
236 //! @todo for the time being, the DVD autorun settings are used to determine if the HD DVD should be started automatically.
237 CFileItemList items, sitems;
239 // Advanced Content HD DVD (most discs?)
240 if (StringUtils::EqualsNoCase(name, "ADV_OBJ"))
242 CLog::Log(LOGINFO,"HD DVD: Checking for playlist.");
243 // find playlist file
244 CDirectory::GetDirectory(pItem->GetPath(), items, "*.xpl", DIR_FLAG_DEFAULTS);
245 if (items.Size())
247 // HD DVD Standard says the highest numbered playlist has to be handled first.
248 CLog::Log(LOGINFO,"HD DVD: Playlist found. Set filetypes to *.xpl for external player.");
249 items.Sort(SortByLabel, SortOrderDescending);
250 phddvdItem = pItem;
251 hddvdname = URIUtils::GetFileName(items[0]->GetPath());
252 CLog::Log(LOGINFO, "HD DVD: {}", items[0]->GetPath());
256 // Standard Content HD DVD (few discs?)
257 if (StringUtils::EqualsNoCase(name, "HVDVD_TS") && bAllowVideo
258 && (bypassSettings || bAutorunDVDs))
260 if (hddvdname == "")
262 CLog::Log(LOGINFO,"HD DVD: Checking for ifo.");
263 // find Video Manager or Title Set Information
264 CDirectory::GetDirectory(pItem->GetPath(), items, "HV*.ifo", DIR_FLAG_DEFAULTS);
265 if (items.Size())
267 // HD DVD Standard says the lowest numbered ifo has to be handled first.
268 CLog::Log(LOGINFO,"HD DVD: IFO found. Set filename to HV* and filetypes to *.ifo for external player.");
269 items.Sort(SortByLabel, SortOrderAscending);
270 phddvdItem = pItem;
271 hddvdname = URIUtils::GetFileName(items[0]->GetPath());
272 CLog::Log(LOGINFO, "HD DVD: {}", items[0]->GetPath());
275 // Find and sort *.evo files for internal playback.
276 // While this algorithm works for all of my HD DVDs, it may fail on other discs. If there are very large extras which are
277 // alphabetically before the main movie they will be sorted to the top of the playlist and get played first.
278 CDirectory::GetDirectory(pItem->GetPath(), items, "*.evo", DIR_FLAG_DEFAULTS);
279 if (items.Size())
281 // Sort *.evo files in alphabetical order.
282 items.Sort(SortByLabel, SortOrderAscending);
283 int64_t asize = 0;
284 int ecount = 0;
285 // calculate average size of elements above 1gb
286 for (int j = 0; j < items.Size(); j++)
287 if (items[j]->m_dwSize > 1000000000)
289 ecount++;
290 asize = asize + items[j]->m_dwSize;
292 if (ecount > 0)
293 asize = asize / ecount;
294 // Put largest files in alphabetical order to top of new list.
295 for (int j = 0; j < items.Size(); j++)
296 if (items[j]->m_dwSize >= asize)
297 sitems.Add (items[j]);
298 // Sort *.evo files by size.
299 items.Sort(SortBySize, SortOrderDescending);
300 // Add other files with descending size to bottom of new list.
301 for (int j = 0; j < items.Size(); j++)
302 if (items[j]->m_dwSize < asize)
303 sitems.Add (items[j]);
304 // Replace list with optimized list.
305 items.Clear();
306 items.Copy (sitems);
307 sitems.Clear();
309 if (hddvdname != "")
311 CFileItem item(URIUtils::AddFileToFolder(phddvdItem->GetPath(), hddvdname), false);
312 item.SetLabel(CServiceBroker::GetMediaManager().GetDiskLabel(strDrive));
313 item.GetVideoInfoTag()->m_strFileNameAndPath =
314 CServiceBroker::GetMediaManager().GetDiskUniqueId(strDrive);
316 if (!startFromBeginning && !item.GetVideoInfoTag()->m_strFileNameAndPath.empty())
317 item.SetStartOffset(STARTOFFSET_RESUME);
319 // get playername
320 std::string hdVideoPlayer = CServiceBroker::GetPlayerCoreFactory().GetDefaultPlayer(item);
322 // Single *.xpl or *.ifo files require an external player to handle playback.
323 // If no matching rule was found, VideoPlayer will be default player.
324 if (hdVideoPlayer != "VideoPlayer")
326 CLog::Log(LOGINFO, "HD DVD: External singlefile playback initiated: {}", hddvdname);
327 g_application.PlayFile(item, hdVideoPlayer, false);
328 return true;
329 } else
330 CLog::Log(LOGINFO,"HD DVD: No external player found. Fallback to internal one.");
333 // internal *.evo playback.
334 CLog::Log(LOGINFO,"HD DVD: Internal multifile playback initiated.");
335 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::TYPE_VIDEO);
336 CServiceBroker::GetPlaylistPlayer().SetShuffle(PLAYLIST::TYPE_VIDEO, false);
337 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::TYPE_VIDEO, items);
338 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::TYPE_VIDEO);
339 CServiceBroker::GetPlaylistPlayer().Play(0, "");
340 return true;
343 // Video CDs can have multiple file formats. First we need to determine which one is used on the CD
344 std::string strExt;
345 if (StringUtils::EqualsNoCase(name, "MPEGAV"))
346 strExt = ".dat";
347 if (StringUtils::EqualsNoCase(name, "MPEG2"))
348 strExt = ".mpg";
350 // If a file format was extracted we are sure this is a VCD. Autoplay if settings indicate we should.
351 if (!strExt.empty() && bAllowVideo
352 && (bypassSettings || bAutorunDVDs))
354 CFileItemList items;
355 CDirectory::GetDirectory(pItem->GetPath(), items, strExt, DIR_FLAG_DEFAULTS);
356 if (items.Size())
358 items.Sort(SortByLabel, SortOrderAscending);
359 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::TYPE_VIDEO);
360 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::TYPE_VIDEO, items);
361 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::TYPE_VIDEO);
362 CServiceBroker::GetPlaylistPlayer().Play(0, "");
363 return true;
366 /* Probably want this if/when we add some automedia action dialog...
367 else if (pItem->GetPath().Find("PICTURES") != -1 && bAllowPictures
368 && (bypassSettings))
370 bPlaying = true;
371 std::string strExec = StringUtils::Format("RecursiveSlideShow({})", pItem->GetPath());
372 CBuiltins::Execute(strExec);
373 return true;
380 // check video first
381 if (!nAddedToPlaylist && !bPlaying && (bypassSettings || CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_DVDS_AUTORUN)))
383 // stack video files
384 CFileItemList tempItems;
385 tempItems.Append(vecItems);
386 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MYVIDEOS_STACKVIDEOS))
387 tempItems.Stack();
388 CFileItemList itemlist;
390 for (int i = 0; i < tempItems.Size(); i++)
392 CFileItemPtr pItem = tempItems[i];
393 if (!pItem->m_bIsFolder && pItem->IsVideo())
395 bPlaying = true;
396 if (pItem->IsStack())
398 //! @todo remove this once the app/player is capable of handling stacks immediately
399 CStackDirectory dir;
400 CFileItemList items;
401 dir.GetDirectory(pItem->GetURL(), items);
402 itemlist.Append(items);
404 else
405 itemlist.Add(pItem);
408 if (itemlist.Size())
410 if (!bAllowVideo)
412 if (!bypassSettings)
413 return false;
415 if (!g_passwordManager.IsMasterLockUnlocked(true))
416 return false;
418 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::TYPE_VIDEO);
419 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::TYPE_VIDEO, itemlist);
420 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::TYPE_VIDEO);
421 CServiceBroker::GetPlaylistPlayer().Play(0, "");
424 // then music
425 if (!bPlaying && (bypassSettings || CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_AUDIOCDS_AUTOACTION) == AUTOCD_PLAY) && bAllowMusic)
427 for (int i = 0; i < vecItems.Size(); i++)
429 CFileItemPtr pItem = vecItems[i];
430 if (!pItem->m_bIsFolder && pItem->IsAudio())
432 nAddedToPlaylist++;
433 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::TYPE_MUSIC, pItem);
437 /* Probably want this if/when we add some automedia action dialog...
438 // and finally pictures
439 if (!nAddedToPlaylist && !bPlaying && bypassSettings && bAllowPictures)
441 for (int i = 0; i < vecItems.Size(); i++)
443 CFileItemPtr pItem = vecItems[i];
444 if (!pItem->m_bIsFolder && pItem->IsPicture())
446 bPlaying = true;
447 std::string strExec = StringUtils::Format("RecursiveSlideShow({})", strDrive);
448 CBuiltins::Execute(strExec);
449 break;
455 // check subdirs if we are not playing yet
456 if (!bPlaying)
458 for (int i = 0; i < vecItems.Size(); i++)
460 CFileItemPtr pItem = vecItems[i];
461 if (pItem->m_bIsFolder)
463 if (pItem->GetPath() != "." && pItem->GetPath() != ".." )
465 if (RunDisc(pDir, pItem->GetPath(), nAddedToPlaylist, false, bypassSettings, startFromBeginning))
467 bPlaying = true;
468 break;
471 } // if (non system) folder
472 } // for all items in directory
473 } // if root folder
475 return bPlaying;
478 void CAutorun::HandleAutorun()
480 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
481 const CDetectDVDMedia& mediadetect = CServiceBroker::GetDetectDVDMedia();
483 if (!m_bEnable)
485 mediadetect.m_evAutorun.Reset();
486 return ;
489 if (mediadetect.m_evAutorun.Wait(0ms))
491 if (!ExecuteAutorun(""))
492 CLog::Log(LOGDEBUG, "{}: Could not execute autorun", __func__);
493 mediadetect.m_evAutorun.Reset();
495 #endif
498 void CAutorun::Enable()
500 m_bEnable = true;
503 void CAutorun::Disable()
505 m_bEnable = false;
508 bool CAutorun::IsEnabled() const
510 return m_bEnable;
513 bool CAutorun::PlayDiscAskResume(const std::string& path)
515 return PlayDisc(path, true,
516 !CanResumePlayDVD(path) ||
517 HELPERS::ShowYesNoDialogText(CVariant{341}, CVariant{""}, CVariant{13404},
518 CVariant{12021}) == DialogResponse::CHOICE_YES);
521 bool CAutorun::CanResumePlayDVD(const std::string& path)
523 std::string strUniqueId = CServiceBroker::GetMediaManager().GetDiskUniqueId(path);
524 if (!strUniqueId.empty())
526 CVideoDatabase dbs;
527 dbs.Open();
528 CBookmark bookmark;
529 if (dbs.GetResumeBookMark(strUniqueId, bookmark))
530 return true;
532 return false;
535 void CAutorun::SettingOptionAudioCdActionsFiller(const SettingConstPtr& setting,
536 std::vector<IntegerSettingOption>& list,
537 int& current,
538 void* data)
540 list.emplace_back(g_localizeStrings.Get(16018), AUTOCD_NONE);
541 list.emplace_back(g_localizeStrings.Get(14098), AUTOCD_PLAY);
542 #ifdef HAS_CDDA_RIPPER
543 list.emplace_back(g_localizeStrings.Get(14096), AUTOCD_RIP);
544 #endif