[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / Autorun.cpp
blob78aa9583a5f17a8748e21d90651ec96c449e563a
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 "FileItemList.h"
13 #include "GUIPassword.h"
14 #include "GUIUserMessages.h"
15 #include "PlayListPlayer.h"
16 #include "ServiceBroker.h"
17 #include "URL.h"
18 #include "application/Application.h"
19 #include "application/ApplicationComponents.h"
20 #include "application/ApplicationPowerHandling.h"
21 #include "cores/playercorefactory/PlayerCoreFactory.h"
22 #include "filesystem/Directory.h"
23 #include "filesystem/DirectoryFactory.h"
24 #include "filesystem/StackDirectory.h"
25 #include "guilib/GUIComponent.h"
26 #include "guilib/GUIWindowManager.h"
27 #include "guilib/LocalizeStrings.h"
28 #include "messaging/helpers/DialogHelper.h"
29 #include "music/MusicFileItemClassify.h"
30 #include "playlists/PlayList.h"
31 #include "profiles/ProfileManager.h"
32 #include "settings/Settings.h"
33 #include "settings/SettingsComponent.h"
34 #include "settings/lib/Setting.h"
35 #include "settings/lib/SettingDefinitions.h"
36 #include "video/VideoFileItemClassify.h"
38 #include <stdlib.h>
39 #ifndef TARGET_WINDOWS
40 #include "storage/DetectDVDType.h"
41 #endif
42 #include "storage/MediaManager.h"
43 #include "utils/FileUtils.h"
44 #include "utils/StringUtils.h"
45 #include "utils/URIUtils.h"
46 #include "utils/Variant.h"
47 #include "utils/log.h"
48 #include "video/VideoDatabase.h"
50 #ifdef HAS_CDDA_RIPPER
51 #include "cdrip/CDDARipper.h"
52 #endif
54 using namespace XFILE;
55 using namespace MEDIA_DETECT;
56 using namespace KODI;
57 using namespace KODI::MESSAGING;
58 using namespace KODI::VIDEO;
59 using namespace std::chrono_literals;
61 using KODI::MESSAGING::HELPERS::DialogResponse;
63 CAutorun::CAutorun()
65 m_bEnable = true;
68 CAutorun::~CAutorun() = default;
70 bool CAutorun::ExecuteAutorun(const std::string& path)
72 if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_LOGIN_SCREEN)
73 return false;
75 CCdInfo* pInfo = CServiceBroker::GetMediaManager().GetCdInfo(path);
77 if ( pInfo == NULL )
78 return false;
80 auto& components = CServiceBroker::GetAppComponents();
81 const auto appPower = components.GetComponent<CApplicationPowerHandling>();
82 appPower->ResetScreenSaver();
83 appPower->WakeUpScreenSaverAndDPMS(); // turn off the screensaver if it's active
85 bool success = false;
87 #ifdef HAS_CDDA_RIPPER
88 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_AUDIOCDS_AUTOACTION) == AUTOCD_RIP &&
89 pInfo->IsAudio(1) && !CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetCurrentProfile().musicLocked())
91 success = KODI::CDRIP::CCDDARipper::GetInstance().RipCD();
93 else
94 #endif
96 success = PlayDisc(path, false, false);
97 return success;
100 bool CAutorun::PlayDisc(const std::string& path, bool bypassSettings, bool startFromBeginning)
102 if ( !bypassSettings && CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_AUDIOCDS_AUTOACTION) != AUTOCD_PLAY && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_DVDS_AUTORUN))
103 return false;
105 int nSize = CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::Id::TYPE_MUSIC).size();
106 int nAddedToPlaylist = 0;
108 std::string mediaPath;
110 CCdInfo* pInfo = CServiceBroker::GetMediaManager().GetCdInfo(path);
111 if (pInfo == NULL)
112 return false;
114 if (pInfo->IsAudio(1))
115 mediaPath = "cdda://local/";
117 if (mediaPath.empty() && (pInfo->IsISOUDF(1) || pInfo->IsISOHFS(1) || pInfo->IsIso9660(1) || pInfo->IsIso9660Interactive(1)))
118 mediaPath = "iso9660://";
120 if (mediaPath.empty())
121 mediaPath = path;
123 if (mediaPath.empty() || mediaPath == "iso9660://")
124 mediaPath = CServiceBroker::GetMediaManager().GetDiscPath();
126 const CURL pathToUrl(mediaPath);
127 std::unique_ptr<IDirectory> pDir ( CDirectoryFactory::Create( pathToUrl ));
128 bool bPlaying = RunDisc(pDir.get(), mediaPath, nAddedToPlaylist, true, bypassSettings, startFromBeginning);
130 if ( !bPlaying && nAddedToPlaylist > 0 )
132 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
133 CServiceBroker::GetGUI()->GetWindowManager().SendMessage( msg );
134 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::Id::TYPE_MUSIC);
135 // Start playing the items we inserted
136 return CServiceBroker::GetPlaylistPlayer().Play(nSize, "");
139 return bPlaying;
143 * This method tries to determine what type of disc is located in the given drive and starts to play the content appropriately.
145 bool CAutorun::RunDisc(IDirectory* pDir, const std::string& strDrive, int& nAddedToPlaylist, bool bRoot, bool bypassSettings /* = false */, bool startFromBeginning /* = false */)
147 if (!pDir)
149 CLog::Log(LOGDEBUG, "CAutorun::{}: cannot run disc. is it properly mounted?", __FUNCTION__);
150 return false;
153 bool bPlaying(false);
154 CFileItemList vecItems;
156 CURL pathToUrl{strDrive};
157 // if the url being requested is a generic "iso9660://" we need to enrich it with the actual drive.
158 // use the hostname section to prepend the drive path
159 if (pathToUrl.GetRedacted() == "iso9660://")
161 pathToUrl.Reset();
162 pathToUrl.SetProtocol("iso9660");
163 pathToUrl.SetHostName(CServiceBroker::GetMediaManager().TranslateDevicePath(""));
166 if ( !pDir->GetDirectory( pathToUrl, vecItems ) )
168 return false;
171 // Sorting necessary for easier HDDVD handling
172 vecItems.Sort(SortByLabel, SortOrderAscending);
174 bool bAllowVideo = true;
175 // bool bAllowPictures = true;
176 bool bAllowMusic = true;
177 if (!g_passwordManager.IsMasterLockUnlocked(false))
179 const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
181 bAllowVideo = !profileManager->GetCurrentProfile().videoLocked();
182 // bAllowPictures = !profileManager->GetCurrentProfile().picturesLocked();
183 bAllowMusic = !profileManager->GetCurrentProfile().musicLocked();
186 // is this a root folder we have to check the content to determine a disc type
187 if (bRoot)
189 std::string hddvdname = "";
190 CFileItemPtr phddvdItem;
191 bool bAutorunDVDs = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_DVDS_AUTORUN);
193 // check root folders next, for normal structured dvd's
194 for (const auto& pItem : vecItems)
196 // is the current item a (non system) folder?
197 if (pItem->m_bIsFolder && pItem->GetPath() != "." && pItem->GetPath() != "..")
199 std::string name = pItem->GetPath();
200 URIUtils::RemoveSlashAtEnd(name);
201 name = URIUtils::GetFileName(name);
203 // Check if the current foldername indicates a DVD structure (name is "VIDEO_TS")
204 if (StringUtils::EqualsNoCase(name, "VIDEO_TS") && bAllowVideo
205 && (bypassSettings || bAutorunDVDs))
207 std::string path = URIUtils::AddFileToFolder(pItem->GetPath(), "VIDEO_TS.IFO");
208 if (!CFileUtils::Exists(path))
209 path = URIUtils::AddFileToFolder(pItem->GetPath(), "video_ts.ifo");
210 CFileItemPtr item(new CFileItem(path, false));
211 item->SetLabel(CServiceBroker::GetMediaManager().GetDiskLabel(strDrive));
212 item->GetVideoInfoTag()->m_strFileNameAndPath =
213 CServiceBroker::GetMediaManager().GetDiskUniqueId(strDrive);
215 if (!startFromBeginning && !item->GetVideoInfoTag()->m_strFileNameAndPath.empty())
216 item->SetStartOffset(STARTOFFSET_RESUME);
218 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::Id::TYPE_VIDEO);
219 CServiceBroker::GetPlaylistPlayer().SetShuffle(PLAYLIST::Id::TYPE_VIDEO, false);
220 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::Id::TYPE_VIDEO, item);
221 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::Id::TYPE_VIDEO);
222 CServiceBroker::GetPlaylistPlayer().Play(0, "");
223 return true;
226 // Check if the current foldername indicates a Blu-Ray structure (default is "BDMV").
227 // A BR should also include an "AACS" folder for encryption, Sony-BRs can also include update folders for PS3 (PS3_UPDATE / PS3_VPRM).
228 //! @todo for the time being, the DVD autorun settings are used to determine if the BR should be started automatically.
229 if (StringUtils::EqualsNoCase(name, "BDMV") && bAllowVideo
230 && (bypassSettings || bAutorunDVDs))
232 CFileItemPtr item(new CFileItem(URIUtils::AddFileToFolder(pItem->GetPath(), "index.bdmv"), false));
233 item->SetLabel(CServiceBroker::GetMediaManager().GetDiskLabel(strDrive));
234 item->GetVideoInfoTag()->m_strFileNameAndPath =
235 CServiceBroker::GetMediaManager().GetDiskUniqueId(strDrive);
237 if (!startFromBeginning && !item->GetVideoInfoTag()->m_strFileNameAndPath.empty())
238 item->SetStartOffset(STARTOFFSET_RESUME);
240 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::Id::TYPE_VIDEO);
241 CServiceBroker::GetPlaylistPlayer().SetShuffle(PLAYLIST::Id::TYPE_VIDEO, false);
242 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::Id::TYPE_VIDEO, item);
243 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::Id::TYPE_VIDEO);
244 CServiceBroker::GetPlaylistPlayer().Play(0, "");
245 return true;
248 // Check if the current foldername indicates a HD DVD structure (default is "HVDVD_TS").
249 // Most HD DVD will also include an "ADV_OBJ" folder for advanced content. This folder should be handled first.
250 //! @todo for the time being, the DVD autorun settings are used to determine if the HD DVD should be started automatically.
251 CFileItemList items, sitems;
253 // Advanced Content HD DVD (most discs?)
254 if (StringUtils::EqualsNoCase(name, "ADV_OBJ"))
256 CLog::Log(LOGINFO,"HD DVD: Checking for playlist.");
257 // find playlist file
258 CDirectory::GetDirectory(pItem->GetPath(), items, "*.xpl", DIR_FLAG_DEFAULTS);
259 if (items.Size())
261 // HD DVD Standard says the highest numbered playlist has to be handled first.
262 CLog::Log(LOGINFO,"HD DVD: Playlist found. Set filetypes to *.xpl for external player.");
263 items.Sort(SortByLabel, SortOrderDescending);
264 phddvdItem = pItem;
265 hddvdname = URIUtils::GetFileName(items[0]->GetPath());
266 CLog::Log(LOGINFO, "HD DVD: {}", items[0]->GetPath());
270 // Standard Content HD DVD (few discs?)
271 if (StringUtils::EqualsNoCase(name, "HVDVD_TS") && bAllowVideo
272 && (bypassSettings || bAutorunDVDs))
274 if (hddvdname == "")
276 CLog::Log(LOGINFO,"HD DVD: Checking for ifo.");
277 // find Video Manager or Title Set Information
278 CDirectory::GetDirectory(pItem->GetPath(), items, "HV*.ifo", DIR_FLAG_DEFAULTS);
279 if (items.Size())
281 // HD DVD Standard says the lowest numbered ifo has to be handled first.
282 CLog::Log(LOGINFO,"HD DVD: IFO found. Set filename to HV* and filetypes to *.ifo for external player.");
283 items.Sort(SortByLabel, SortOrderAscending);
284 phddvdItem = pItem;
285 hddvdname = URIUtils::GetFileName(items[0]->GetPath());
286 CLog::Log(LOGINFO, "HD DVD: {}", items[0]->GetPath());
289 // Find and sort *.evo files for internal playback.
290 // While this algorithm works for all of my HD DVDs, it may fail on other discs. If there are very large extras which are
291 // alphabetically before the main movie they will be sorted to the top of the playlist and get played first.
292 CDirectory::GetDirectory(pItem->GetPath(), items, "*.evo", DIR_FLAG_DEFAULTS);
293 if (items.Size())
295 // Sort *.evo files in alphabetical order.
296 items.Sort(SortByLabel, SortOrderAscending);
297 int64_t asize = 0;
298 int ecount = 0;
299 // calculate average size of elements above 1gb
300 for (int j = 0; j < items.Size(); j++)
301 if (items[j]->m_dwSize > 1000000000)
303 ecount++;
304 asize = asize + items[j]->m_dwSize;
306 if (ecount > 0)
307 asize = asize / ecount;
308 // Put largest files in alphabetical order to top of new list.
309 for (int j = 0; j < items.Size(); j++)
310 if (items[j]->m_dwSize >= asize)
311 sitems.Add (items[j]);
312 // Sort *.evo files by size.
313 items.Sort(SortBySize, SortOrderDescending);
314 // Add other files with descending size to bottom of new list.
315 for (int j = 0; j < items.Size(); j++)
316 if (items[j]->m_dwSize < asize)
317 sitems.Add (items[j]);
318 // Replace list with optimized list.
319 items.Clear();
320 items.Copy (sitems);
321 sitems.Clear();
323 if (hddvdname != "")
325 CFileItem item(URIUtils::AddFileToFolder(phddvdItem->GetPath(), hddvdname), false);
326 item.SetLabel(CServiceBroker::GetMediaManager().GetDiskLabel(strDrive));
327 item.GetVideoInfoTag()->m_strFileNameAndPath =
328 CServiceBroker::GetMediaManager().GetDiskUniqueId(strDrive);
330 if (!startFromBeginning && !item.GetVideoInfoTag()->m_strFileNameAndPath.empty())
331 item.SetStartOffset(STARTOFFSET_RESUME);
333 // get playername
334 std::string hdVideoPlayer = CServiceBroker::GetPlayerCoreFactory().GetDefaultPlayer(item);
336 // Single *.xpl or *.ifo files require an external player to handle playback.
337 // If no matching rule was found, VideoPlayer will be default player.
338 if (hdVideoPlayer != "VideoPlayer")
340 CLog::Log(LOGINFO, "HD DVD: External singlefile playback initiated: {}", hddvdname);
341 g_application.PlayFile(item, hdVideoPlayer, false);
342 return true;
343 } else
344 CLog::Log(LOGINFO,"HD DVD: No external player found. Fallback to internal one.");
347 // internal *.evo playback.
348 CLog::Log(LOGINFO,"HD DVD: Internal multifile playback initiated.");
349 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::Id::TYPE_VIDEO);
350 CServiceBroker::GetPlaylistPlayer().SetShuffle(PLAYLIST::Id::TYPE_VIDEO, false);
351 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::Id::TYPE_VIDEO, items);
352 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::Id::TYPE_VIDEO);
353 CServiceBroker::GetPlaylistPlayer().Play(0, "");
354 return true;
357 // Video CDs can have multiple file formats. First we need to determine which one is used on the CD
358 std::string strExt;
359 if (StringUtils::EqualsNoCase(name, "MPEGAV"))
360 strExt = ".dat";
361 if (StringUtils::EqualsNoCase(name, "MPEG2"))
362 strExt = ".mpg";
364 // If a file format was extracted we are sure this is a VCD. Autoplay if settings indicate we should.
365 if (!strExt.empty() && bAllowVideo
366 && (bypassSettings || bAutorunDVDs))
368 CFileItemList items;
369 CDirectory::GetDirectory(pItem->GetPath(), items, strExt, DIR_FLAG_DEFAULTS);
370 if (items.Size())
372 items.Sort(SortByLabel, SortOrderAscending);
373 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::Id::TYPE_VIDEO);
374 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::Id::TYPE_VIDEO, items);
375 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::Id::TYPE_VIDEO);
376 CServiceBroker::GetPlaylistPlayer().Play(0, "");
377 return true;
380 /* Probably want this if/when we add some automedia action dialog...
381 else if (pItem->GetPath().Find("PICTURES") != -1 && bAllowPictures
382 && (bypassSettings))
384 bPlaying = true;
385 std::string strExec = StringUtils::Format("RecursiveSlideShow({})", pItem->GetPath());
386 CBuiltins::Execute(strExec);
387 return true;
394 // check video first
395 if (!nAddedToPlaylist && !bPlaying && (bypassSettings || CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_DVDS_AUTORUN)))
397 // stack video files
398 CFileItemList tempItems;
399 tempItems.Append(vecItems);
400 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MYVIDEOS_STACKVIDEOS))
401 tempItems.Stack();
402 CFileItemList itemlist;
404 for (int i = 0; i < tempItems.Size(); i++)
406 CFileItemPtr pItem = tempItems[i];
407 if (!pItem->m_bIsFolder && IsVideo(*pItem))
409 bPlaying = true;
410 if (pItem->IsStack())
412 //! @todo remove this once the app/player is capable of handling stacks immediately
413 CStackDirectory dir;
414 CFileItemList items;
415 dir.GetDirectory(pItem->GetURL(), items);
416 itemlist.Append(items);
418 else
419 itemlist.Add(pItem);
422 if (itemlist.Size())
424 if (!bAllowVideo)
426 if (!bypassSettings)
427 return false;
429 if (!g_passwordManager.IsMasterLockUnlocked(true))
430 return false;
432 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(PLAYLIST::Id::TYPE_VIDEO);
433 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::Id::TYPE_VIDEO, itemlist);
434 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(PLAYLIST::Id::TYPE_VIDEO);
435 CServiceBroker::GetPlaylistPlayer().Play(0, "");
438 // then music
439 if (!bPlaying && (bypassSettings || CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_AUDIOCDS_AUTOACTION) == AUTOCD_PLAY) && bAllowMusic)
441 for (int i = 0; i < vecItems.Size(); i++)
443 CFileItemPtr pItem = vecItems[i];
444 if (!pItem->m_bIsFolder && MUSIC::IsAudio(*pItem))
446 nAddedToPlaylist++;
447 CServiceBroker::GetPlaylistPlayer().Add(PLAYLIST::Id::TYPE_MUSIC, pItem);
451 /* Probably want this if/when we add some automedia action dialog...
452 // and finally pictures
453 if (!nAddedToPlaylist && !bPlaying && bypassSettings && bAllowPictures)
455 for (int i = 0; i < vecItems.Size(); i++)
457 CFileItemPtr pItem = vecItems[i];
458 if (!pItem->m_bIsFolder && pItem->IsPicture())
460 bPlaying = true;
461 std::string strExec = StringUtils::Format("RecursiveSlideShow({})", strDrive);
462 CBuiltins::Execute(strExec);
463 break;
469 // check subdirs if we are not playing yet
470 if (!bPlaying)
472 for (int i = 0; i < vecItems.Size(); i++)
474 CFileItemPtr pItem = vecItems[i];
475 if (pItem->m_bIsFolder)
477 if (pItem->GetPath() != "." && pItem->GetPath() != ".." )
479 if (RunDisc(pDir, pItem->GetPath(), nAddedToPlaylist, false, bypassSettings, startFromBeginning))
481 bPlaying = true;
482 break;
485 } // if (non system) folder
486 } // for all items in directory
487 } // if root folder
489 return bPlaying;
492 void CAutorun::HandleAutorun()
494 #if !defined(TARGET_WINDOWS) && defined(HAS_OPTICAL_DRIVE)
495 const CDetectDVDMedia& mediadetect = CServiceBroker::GetDetectDVDMedia();
497 if (!m_bEnable)
499 mediadetect.m_evAutorun.Reset();
500 return ;
503 if (mediadetect.m_evAutorun.Wait(0ms))
505 if (!ExecuteAutorun(""))
506 CLog::Log(LOGDEBUG, "{}: Could not execute autorun", __func__);
507 mediadetect.m_evAutorun.Reset();
509 #endif
512 void CAutorun::Enable()
514 m_bEnable = true;
517 void CAutorun::Disable()
519 m_bEnable = false;
522 bool CAutorun::IsEnabled() const
524 return m_bEnable;
527 bool CAutorun::PlayDiscAskResume(const std::string& path)
529 return PlayDisc(path, true,
530 !CanResumePlayDVD(path) ||
531 HELPERS::ShowYesNoDialogText(CVariant{341}, CVariant{""}, CVariant{13404},
532 CVariant{12021}) == DialogResponse::CHOICE_YES);
535 bool CAutorun::CanResumePlayDVD(const std::string& path)
537 std::string strUniqueId = CServiceBroker::GetMediaManager().GetDiskUniqueId(path);
538 if (!strUniqueId.empty())
540 CVideoDatabase dbs;
541 dbs.Open();
542 CBookmark bookmark;
543 if (dbs.GetResumeBookMark(strUniqueId, bookmark))
544 return true;
546 return false;
549 void CAutorun::SettingOptionAudioCdActionsFiller(const SettingConstPtr& setting,
550 std::vector<IntegerSettingOption>& list,
551 int& current,
552 void* data)
554 list.emplace_back(g_localizeStrings.Get(16018), AUTOCD_NONE);
555 list.emplace_back(g_localizeStrings.Get(14098), AUTOCD_PLAY);
556 #ifdef HAS_CDDA_RIPPER
557 list.emplace_back(g_localizeStrings.Get(14096), AUTOCD_RIP);
558 #endif