[PVR][Estuary] Timer settings dialog: Show client name in timer type selection dialog...
[xbmc.git] / xbmc / storage / DetectDVDType.cpp
blob2392901217ee746001839da3a0f8e6ae56163a27
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 "DetectDVDType.h"
11 #include "GUIUserMessages.h"
12 #include "ServiceBroker.h"
13 #include "application/ApplicationComponents.h"
14 #include "application/ApplicationPlayer.h"
15 #include "cdioSupport.h"
16 #include "guilib/GUIComponent.h"
17 #include "guilib/GUIWindowManager.h"
18 #include "guilib/LocalizeStrings.h"
19 #include "settings/AdvancedSettings.h"
20 #include "settings/SettingsComponent.h"
21 #include "storage/MediaManager.h"
22 #include "utils/StringUtils.h"
23 #include "utils/log.h"
25 #include <mutex>
27 using namespace MEDIA_DETECT;
28 using namespace std::chrono_literals;
30 CCriticalSection CDetectDVDMedia::m_muReadingMedia;
31 CEvent CDetectDVDMedia::m_evAutorun;
32 DriveState CDetectDVDMedia::m_DriveState{DriveState::CLOSED_NO_MEDIA};
33 CCdInfo* CDetectDVDMedia::m_pCdInfo = NULL;
34 time_t CDetectDVDMedia::m_LastPoll = 0;
35 CDetectDVDMedia* CDetectDVDMedia::m_pInstance = NULL;
36 std::string CDetectDVDMedia::m_diskLabel = "";
37 std::string CDetectDVDMedia::m_diskPath = "";
38 UTILS::DISCS::DiscInfo CDetectDVDMedia::m_discInfo;
40 CDetectDVDMedia::CDetectDVDMedia() : CThread("DetectDVDMedia"),
41 m_cdio(CLibcdio::GetInstance())
43 m_bStop = false;
44 m_pInstance = this;
47 CDetectDVDMedia::~CDetectDVDMedia() = default;
49 void CDetectDVDMedia::OnStartup()
51 // SetPriority( ThreadPriority::LOWEST );
52 CLog::Log(LOGDEBUG, "Compiled with libcdio Version 0.{}", LIBCDIO_VERSION_NUM);
55 void CDetectDVDMedia::Process()
57 // for apple - currently disable this check since cdio will return null if no media is loaded
58 #if !defined(TARGET_DARWIN)
59 //Before entering loop make sure we actually have a CDrom drive
60 CdIo_t *p_cdio = m_cdio->cdio_open(NULL, DRIVER_DEVICE);
61 if (p_cdio == NULL)
62 return;
63 else
64 m_cdio->cdio_destroy(p_cdio);
65 #endif
67 const auto& components = CServiceBroker::GetAppComponents();
68 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
70 while (!m_bStop)
72 if (appPlayer->IsPlayingVideo())
74 CThread::Sleep(10000ms);
76 else
78 UpdateDvdrom();
79 m_bStartup = false;
80 CThread::Sleep(2000ms);
81 if (m_bAutorun)
83 // Media in drive, wait 1.5s more to be sure the device is ready for playback
84 CThread::Sleep(1500ms);
85 m_evAutorun.Set();
86 m_bAutorun = false;
92 void CDetectDVDMedia::OnExit()
96 // Gets state of the DVD drive
97 void CDetectDVDMedia::UpdateDvdrom()
99 // Signal for WaitMediaReady()
100 // that we are busy detecting the
101 // newly inserted media.
103 std::unique_lock<CCriticalSection> waitLock(m_muReadingMedia);
104 switch (PollDriveState())
106 case DriveState::NONE:
107 //! @todo reduce / stop polling for drive updates
108 break;
110 case DriveState::OPEN:
112 // Send Message to GUI that disc been ejected
113 SetNewDVDShareUrl(CServiceBroker::GetMediaManager().TranslateDevicePath(m_diskPath), false,
114 g_localizeStrings.Get(502));
115 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REMOVED_MEDIA);
116 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
117 // Clear all stored info
118 Clear();
119 // Update drive state
120 waitLock.unlock();
121 m_DriveState = DriveState::OPEN;
122 return;
124 break;
125 case DriveState::NOT_READY:
127 // Drive is not ready (closing, opening)
128 SetNewDVDShareUrl(CServiceBroker::GetMediaManager().TranslateDevicePath(m_diskPath), false,
129 g_localizeStrings.Get(503));
130 m_DriveState = DriveState::NOT_READY;
131 // DVD-ROM in undefined state
132 // Better delete old CD Information
133 if (m_pCdInfo != nullptr)
135 delete m_pCdInfo;
136 m_pCdInfo = nullptr;
138 waitLock.unlock();
139 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_SOURCES);
140 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
141 // Do we really need sleep here? This will fix: [ 1530771 ] "Open tray" problem
142 // CThread::Sleep(6000ms);
143 return;
145 break;
147 case DriveState::CLOSED_NO_MEDIA:
149 // Nothing in there...
150 SetNewDVDShareUrl(CServiceBroker::GetMediaManager().TranslateDevicePath(m_diskPath), false,
151 g_localizeStrings.Get(504));
152 m_DriveState = DriveState::CLOSED_NO_MEDIA;
153 // Send Message to GUI that disc has changed
154 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_SOURCES);
155 waitLock.unlock();
156 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
157 return;
159 break;
160 case DriveState::READY:
161 #if !defined(TARGET_DARWIN)
162 return ;
163 #endif
164 break;
165 case DriveState::CLOSED_MEDIA_PRESENT:
167 if (m_DriveState != DriveState::CLOSED_MEDIA_PRESENT)
169 m_DriveState = DriveState::CLOSED_MEDIA_PRESENT;
170 // Detect ISO9660(mode1/mode2) or CDDA filesystem
171 DetectMediaType();
172 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_SOURCES);
173 waitLock.unlock();
174 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
175 // Tell the application object that a new Cd is inserted
176 // So autorun can be started.
177 if (!m_bStartup)
178 m_bAutorun = true;
180 return;
182 default:
183 break;
186 // We have finished media detection
187 // Signal for WaitMediaReady()
193 // Generates the drive url, (like iso9660://)
194 // from the CCdInfo class
195 void CDetectDVDMedia::DetectMediaType()
197 bool bCDDA(false);
198 CLog::Log(LOGINFO, "Detecting DVD-ROM media filesystem...");
200 // Probe and store DiscInfo result
201 // even if no valid tracks are detected we might still be able to play the disc via libdvdnav or libbluray
202 // as long as they can correctly detect the disc
203 UTILS::DISCS::DiscInfo discInfo;
204 if (UTILS::DISCS::GetDiscInfo(discInfo,
205 CServiceBroker::GetMediaManager().TranslateDevicePath(m_diskPath)))
207 m_discInfo = discInfo;
210 std::string strNewUrl;
211 CCdIoSupport cdio;
213 // Delete old CD-Information
214 if ( m_pCdInfo != NULL )
216 delete m_pCdInfo;
217 m_pCdInfo = NULL;
220 // Detect new CD-Information
221 m_pCdInfo = cdio.GetCdInfo();
222 if (m_pCdInfo == NULL)
224 CLog::Log(LOGERROR, "Detection of DVD-ROM media failed.");
225 return ;
227 CLog::Log(LOGINFO, "Tracks overall:{}; Audio tracks:{}; Data tracks:{}",
228 m_pCdInfo->GetTrackCount(), m_pCdInfo->GetAudioTrackCount(),
229 m_pCdInfo->GetDataTrackCount());
231 // Detect ISO9660(mode1/mode2), CDDA filesystem or UDF
232 if (m_pCdInfo->IsISOHFS(1) || m_pCdInfo->IsIso9660(1) || m_pCdInfo->IsIso9660Interactive(1))
234 strNewUrl = "iso9660://";
236 else
238 if (m_pCdInfo->IsUDF(1))
239 strNewUrl = CServiceBroker::GetMediaManager().TranslateDevicePath(m_diskPath);
240 else if (m_pCdInfo->IsAudio(1))
242 strNewUrl = "cdda://local/";
243 bCDDA = true;
245 else
246 strNewUrl = CServiceBroker::GetMediaManager().TranslateDevicePath(m_diskPath);
249 if (m_pCdInfo->IsISOUDF(1))
251 if (!CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_detectAsUdf)
253 strNewUrl = "iso9660://";
255 else
257 strNewUrl = CServiceBroker::GetMediaManager().TranslateDevicePath(m_diskPath);
261 CLog::Log(LOGINFO, "Using protocol {}", strNewUrl);
263 if (m_pCdInfo->IsValidFs())
265 if (!m_pCdInfo->IsAudio(1))
266 CLog::Log(LOGINFO, "Disc label: {}", m_pCdInfo->GetDiscLabel());
268 else
270 CLog::Log(LOGWARNING, "Filesystem is not supported");
273 std::string strLabel;
274 if (bCDDA)
276 strLabel = "Audio-CD";
278 else
280 strLabel = m_pCdInfo->GetDiscLabel();
281 StringUtils::TrimRight(strLabel);
284 SetNewDVDShareUrl( strNewUrl , bCDDA, strLabel);
287 void CDetectDVDMedia::SetNewDVDShareUrl( const std::string& strNewUrl, bool bCDDA, const std::string& strDiscLabel )
289 std::string strDescription = "DVD";
290 if (bCDDA) strDescription = "CD";
292 if (strDiscLabel != "") strDescription = strDiscLabel;
294 // Store it in case others want it
295 m_diskLabel = strDescription;
296 m_diskPath = strNewUrl;
299 DriveState CDetectDVDMedia::PollDriveState()
301 const std::shared_ptr<IDiscDriveHandler> platformDiscDriveHandler =
302 CServiceBroker::GetMediaManager().GetDiscDriveHandler();
303 if (!platformDiscDriveHandler)
305 return DriveState::NONE;
308 const std::string discPath = CServiceBroker::GetMediaManager().TranslateDevicePath("");
309 const DriveState driveState = platformDiscDriveHandler->GetDriveState(discPath);
310 switch (driveState)
312 case DriveState::CLOSED_MEDIA_UNDEFINED:
313 // We only poll for new traystatus when driveState has changed or if the last recorded
314 // tray state is undefined
315 if (driveState == DriveState::CLOSED_MEDIA_UNDEFINED &&
316 (m_LastTrayState == TrayState::UNDEFINED || driveState != m_LastDriveState))
318 m_TrayState = platformDiscDriveHandler->GetTrayState(discPath);
320 break;
321 case DriveState::OPEN:
322 m_TrayState = TrayState::OPEN;
323 break;
324 default:
325 m_TrayState = TrayState::UNDEFINED;
326 break;
328 m_LastDriveState = driveState;
330 if (m_TrayState == TrayState::CLOSED_MEDIA_PRESENT)
332 if (m_LastTrayState != TrayState::CLOSED_MEDIA_PRESENT)
334 m_LastTrayState = m_TrayState;
335 return DriveState::CLOSED_MEDIA_PRESENT;
337 else
339 return DriveState::READY;
342 else if (m_TrayState == TrayState::CLOSED_NO_MEDIA)
344 if ((m_LastTrayState != TrayState::CLOSED_NO_MEDIA) &&
345 (m_LastTrayState != TrayState::CLOSED_MEDIA_PRESENT))
347 m_LastTrayState = m_TrayState;
348 return DriveState::CLOSED_NO_MEDIA;
350 else
352 return DriveState::READY;
355 else if (m_TrayState == TrayState::OPEN)
357 if (m_LastTrayState != TrayState::OPEN)
359 m_LastTrayState = m_TrayState;
360 return DriveState::OPEN;
362 else
364 return DriveState::READY;
367 else
369 m_LastTrayState = m_TrayState;
372 #ifdef HAS_DVD_DRIVE
373 return DriveState::NOT_READY;
374 #else
375 return DriveState::READY;
376 #endif
379 void CDetectDVDMedia::UpdateState()
381 std::unique_lock<CCriticalSection> waitLock(m_muReadingMedia);
382 m_pInstance->DetectMediaType();
385 // Static function
386 // Wait for drive, to finish media detection.
387 void CDetectDVDMedia::WaitMediaReady()
389 std::unique_lock<CCriticalSection> waitLock(m_muReadingMedia);
392 // Static function
393 // Returns status of the DVD Drive
394 bool CDetectDVDMedia::DriveReady()
396 return m_DriveState == DriveState::READY;
399 DriveState CDetectDVDMedia::GetDriveState()
401 return m_DriveState;
404 // Static function
405 // Whether a disc is in drive
406 bool CDetectDVDMedia::IsDiscInDrive()
408 return m_DriveState == DriveState::CLOSED_MEDIA_PRESENT;
411 // Static function
412 // Returns a CCdInfo class, which contains
413 // Media information of the current inserted CD.
414 // Can be NULL
415 CCdInfo* CDetectDVDMedia::GetCdInfo()
417 std::unique_lock<CCriticalSection> waitLock(m_muReadingMedia);
418 CCdInfo* pCdInfo = m_pCdInfo;
419 return pCdInfo;
422 const std::string &CDetectDVDMedia::GetDVDLabel()
424 if (!m_discInfo.empty())
426 return m_discInfo.name;
429 return m_diskLabel;
432 const std::string &CDetectDVDMedia::GetDVDPath()
434 return m_diskPath;
438 void CDetectDVDMedia::Clear()
440 if (!m_discInfo.empty())
442 m_discInfo.clear();
444 m_diskLabel.clear();
445 m_diskPath.clear();