Merge pull request #25922 from sarbes/shader-cleanup
[xbmc.git] / xbmc / storage / cdioSupport.cpp
blobcd90504564446581fca1cbb6116c463f84c0d857
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 "cdioSupport.h"
11 #include "platform/Environment.h"
12 #include "utils/log.h"
14 #include <mutex>
16 #include <cdio/cd_types.h>
17 #include <cdio/cdio.h>
18 #include <cdio/logging.h>
19 #include <cdio/mmc.h>
20 #include <cdio/util.h>
22 namespace
24 /* Helper constexpr to hide the 0 return code for tray closed. */
25 constexpr int CDIO_TRAY_STATUS_CLOSED = 0;
26 /* Helper constexpr to hide the 1 return code for tray open */
27 constexpr int CDIO_TRAY_STATUS_OPEN = 1;
28 /* Helper constexpr to hide the -2 driver code for unsupported tray status get operation */
29 constexpr int CDIO_TRAY_STATUS_OP_UNSUPPORTED = -2;
30 } // namespace
32 using namespace MEDIA_DETECT;
34 std::shared_ptr<CLibcdio> CLibcdio::m_pInstance;
36 /* Some interesting sector numbers stored in the above buffer. */
37 #define ISO_SUPERBLOCK_SECTOR 16 /* buffer[0] */
38 #define UFS_SUPERBLOCK_SECTOR 4 /* buffer[2] */
39 #define BOOT_SECTOR 17 /* buffer[3] */
40 #define VCD_INFO_SECTOR 150 /* buffer[4] */
41 #define UDF_ANCHOR_SECTOR 256 /* buffer[5] */
44 signature_t CCdIoSupport::sigs[] = {
45 /*buffer[x] off look for description */
46 {0, 1, "CD001\0", "ISO 9660\0"},
47 {0, 1, "CD-I", "CD-I"},
48 {0, 8, "CDTV", "CDTV"},
49 {0, 8, "CD-RTOS", "CD-RTOS"},
50 {0, 9, "CDROM", "HIGH SIERRA"},
51 {0, 16, "CD-BRIDGE", "BRIDGE"},
52 {0, 1024, "CD-XA001", "XA"},
53 {1, 64, "PPPPHHHHOOOOTTTTOOOO____CCCCDDDD", "PHOTO CD"},
54 {1, 0x438, "\x53\xef", "EXT2 FS"},
55 {2, 1372, "\x54\x19\x01\x0", "UFS"},
56 {3, 7, "EL TORITO", "BOOTABLE"},
57 {4, 0, "VIDEO_CD", "VIDEO CD"},
58 {4, 0, "SUPERVCD", "Chaoji VCD"},
59 {0, 1, "BEA01", "UDF"},
60 {}};
62 #undef DEBUG_CDIO
64 static void
65 cdio_log_handler (cdio_log_level_t level, const char message[])
67 #ifdef DEBUG_CDIO
68 switch (level)
70 case CDIO_LOG_ERROR:
71 CLog::Log(LOGDEBUG, "**ERROR: {}", message);
72 break;
73 case CDIO_LOG_DEBUG:
74 CLog::Log(LOGDEBUG, "--DEBUG: {}", message);
75 break;
76 case CDIO_LOG_WARN:
77 CLog::Log(LOGDEBUG, "++ WARN: {}", message);
78 break;
79 case CDIO_LOG_INFO:
80 CLog::Log(LOGDEBUG, " INFO: {}", message);
81 break;
82 case CDIO_LOG_ASSERT:
83 CLog::Log(LOGDEBUG, "!ASSERT: {}", message);
84 break;
85 default:
86 //cdio_assert_not_reached ();
87 break;
89 #endif
92 //////////////////////////////////////////////////////////////////////
93 // Construction/Destruction
94 //////////////////////////////////////////////////////////////////////
95 CLibcdio::CLibcdio(): s_defaultDevice(NULL)
97 cdio_log_set_handler( cdio_log_handler );
100 CLibcdio::~CLibcdio()
102 free(s_defaultDevice);
103 s_defaultDevice = NULL;
106 void CLibcdio::ReleaseInstance()
108 m_pInstance.reset();
111 std::shared_ptr<CLibcdio> CLibcdio::GetInstance()
113 if (!m_pInstance)
115 m_pInstance = std::shared_ptr<CLibcdio>(new CLibcdio());
117 return m_pInstance;
120 CdIo_t* CLibcdio::cdio_open(const char *psz_source, driver_id_t driver_id)
122 std::unique_lock<CCriticalSection> lock(*this);
124 return( ::cdio_open(psz_source, driver_id) );
127 CdIo_t* CLibcdio::cdio_open_win32(const char *psz_source)
129 std::unique_lock<CCriticalSection> lock(*this);
131 return( ::cdio_open_win32(psz_source) );
134 void CLibcdio::cdio_destroy(CdIo_t *p_cdio)
136 std::unique_lock<CCriticalSection> lock(*this);
138 ::cdio_destroy(p_cdio);
141 discmode_t CLibcdio::cdio_get_discmode(CdIo_t *p_cdio)
143 std::unique_lock<CCriticalSection> lock(*this);
145 return( ::cdio_get_discmode(p_cdio) );
148 CdioTrayStatus CLibcdio::mmc_get_tray_status(const CdIo_t* p_cdio)
150 std::unique_lock<CCriticalSection> lock(*this);
152 int status = ::mmc_get_tray_status(p_cdio);
153 switch (status)
155 case CDIO_TRAY_STATUS_CLOSED:
156 return CdioTrayStatus::CLOSED;
157 case CDIO_TRAY_STATUS_OPEN:
158 return CdioTrayStatus::OPEN;
159 case CDIO_TRAY_STATUS_OP_UNSUPPORTED:
160 return CdioTrayStatus::UNKNOWN;
161 default:
162 break;
164 return CdioTrayStatus::DRIVER_ERROR;
167 driver_return_code_t CLibcdio::cdio_eject_media(CdIo_t** p_cdio)
169 std::unique_lock<CCriticalSection> lock(*this);
171 return( ::cdio_eject_media(p_cdio) );
174 track_t CLibcdio::cdio_get_last_track_num(const CdIo_t *p_cdio)
176 std::unique_lock<CCriticalSection> lock(*this);
178 return( ::cdio_get_last_track_num(p_cdio) );
181 lsn_t CLibcdio::cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track)
183 std::unique_lock<CCriticalSection> lock(*this);
185 return( ::cdio_get_track_lsn(p_cdio, i_track) );
188 lsn_t CLibcdio::cdio_get_track_last_lsn(const CdIo_t *p_cdio, track_t i_track)
190 std::unique_lock<CCriticalSection> lock(*this);
192 return( ::cdio_get_track_last_lsn(p_cdio, i_track) );
195 driver_return_code_t CLibcdio::cdio_read_audio_sectors(
196 const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, uint32_t i_blocks)
198 std::unique_lock<CCriticalSection> lock(*this);
200 return( ::cdio_read_audio_sectors(p_cdio, p_buf, i_lsn, i_blocks) );
203 driver_return_code_t CLibcdio::cdio_close_tray(const char* psz_source, driver_id_t* driver_id)
205 std::unique_lock<CCriticalSection> lock(*this);
206 return (::cdio_close_tray(psz_source, driver_id));
209 const char* CLibcdio::cdio_driver_errmsg(driver_return_code_t drc)
211 return (::cdio_driver_errmsg(drc));
214 char* CLibcdio::GetDeviceFileName()
216 std::unique_lock<CCriticalSection> lock(*this);
218 // If We don't have a DVD device initially present (Darwin or a USB DVD drive),
219 // We have to keep checking in case one appears.
220 if (s_defaultDevice && strlen(s_defaultDevice) == 0)
222 free(s_defaultDevice);
223 s_defaultDevice = NULL;
226 if (s_defaultDevice == NULL)
228 std::string strEnvDvd = CEnvironment::getenv("KODI_DVD_DEVICE");
229 if (!strEnvDvd.empty())
230 s_defaultDevice = strdup(strEnvDvd.c_str());
231 else
233 CdIo_t *p_cdio = ::cdio_open(NULL, DRIVER_UNKNOWN);
234 if (p_cdio != NULL)
236 s_defaultDevice = strdup(::cdio_get_arg(p_cdio, "source"));
237 ::cdio_destroy(p_cdio);
239 else
240 s_defaultDevice = strdup("");
243 return s_defaultDevice;
247 //////////////////////////////////////////////////////////////////////
248 // Construction/Destruction
249 //////////////////////////////////////////////////////////////////////
250 CCdIoSupport::CCdIoSupport() : cdio(nullptr), m_cdio(CLibcdio::GetInstance())
252 m_nFirstData = -1; /* # of first data track */
253 m_nNumData = 0; /* # of data tracks */
254 m_nFirstAudio = -1; /* # of first audio track */
255 m_nNumAudio = 0; /* # of audio tracks */
256 m_nIsofsSize = 0; /* size of session */
257 m_nJolietLevel = 0;
258 m_nFs = 0;
259 m_nUDFVerMinor = 0;
260 m_nUDFVerMajor = 0;
261 m_nDataStart = 0;
262 m_nMsOffset = 0;
263 m_nStartTrack = 0;
266 CCdIoSupport::~CCdIoSupport() = default;
268 bool CCdIoSupport::EjectTray()
270 return false;
273 bool CCdIoSupport::CloseTray()
275 return false;
278 HANDLE CCdIoSupport::OpenCDROM()
280 std::unique_lock<CCriticalSection> lock(*m_cdio);
282 char* source_name = m_cdio->GetDeviceFileName();
283 CdIo* cdio = ::cdio_open(source_name, DRIVER_UNKNOWN);
285 return reinterpret_cast<HANDLE>(cdio);
288 HANDLE CCdIoSupport::OpenIMAGE( std::string& strFilename )
290 std::unique_lock<CCriticalSection> lock(*m_cdio);
292 CdIo* cdio = ::cdio_open(strFilename.c_str(), DRIVER_UNKNOWN);
294 return reinterpret_cast<HANDLE>(cdio);
297 int CCdIoSupport::ReadSector(HANDLE hDevice, DWORD dwSector, char* lpczBuffer)
299 std::unique_lock<CCriticalSection> lock(*m_cdio);
301 CdIo* cdio = (CdIo*) hDevice;
302 if ( cdio == NULL )
303 return -1;
305 if ( ::cdio_read_mode1_sector( cdio, lpczBuffer, dwSector, false ) == 0 )
306 return dwSector;
308 return -1;
311 int CCdIoSupport::ReadSectorMode2(HANDLE hDevice, DWORD dwSector, char* lpczBuffer)
313 std::unique_lock<CCriticalSection> lock(*m_cdio);
315 CdIo* cdio = (CdIo*) hDevice;
316 if ( cdio == NULL )
317 return -1;
319 if ( ::cdio_read_mode2_sector( cdio, lpczBuffer, dwSector, false ) == 0 )
320 return dwSector;
322 return -1;
325 int CCdIoSupport::ReadSectorCDDA(HANDLE hDevice, DWORD dwSector, char* lpczBuffer)
327 std::unique_lock<CCriticalSection> lock(*m_cdio);
329 CdIo* cdio = (CdIo*) hDevice;
330 if ( cdio == NULL )
331 return -1;
333 if ( ::cdio_read_audio_sector( cdio, lpczBuffer, dwSector ) == 0 )
334 return dwSector;
336 return -1;
339 void CCdIoSupport::CloseCDROM(HANDLE hDevice)
341 std::unique_lock<CCriticalSection> lock(*m_cdio);
343 CdIo* cdio = (CdIo*) hDevice;
345 if ( cdio == NULL )
346 return ;
348 ::cdio_destroy( cdio );
351 void CCdIoSupport::PrintAnalysis(int fs, int num_audio)
353 switch (fs & FS_MASK)
355 case FS_UDF:
356 CLog::Log(LOGINFO, "CD-ROM with UDF filesystem");
357 break;
358 case FS_NO_DATA:
359 CLog::Log(LOGINFO, "CD-ROM with audio tracks");
360 break;
361 case FS_ISO_9660:
362 CLog::Log(LOGINFO, "CD-ROM with ISO 9660 filesystem");
363 if (fs & JOLIET)
365 CLog::Log(LOGINFO, " with joliet extension level {}", m_nJolietLevel);
367 if (fs & ROCKRIDGE)
369 CLog::Log(LOGINFO, " and rockridge extensions");
371 break;
372 case FS_ISO_9660_INTERACTIVE:
373 CLog::Log(LOGINFO, "CD-ROM with CD-RTOS and ISO 9660 filesystem");
374 break;
375 case FS_HIGH_SIERRA:
376 CLog::Log(LOGINFO, "CD-ROM with High Sierra filesystem");
377 break;
378 case FS_INTERACTIVE:
379 CLog::Log(LOGINFO, "CD-Interactive{}", num_audio > 0 ? "/Ready" : "");
380 break;
381 case FS_HFS:
382 CLog::Log(LOGINFO, "CD-ROM with Macintosh HFS");
383 break;
384 case FS_ISO_HFS:
385 CLog::Log(LOGINFO, "CD-ROM with both Macintosh HFS and ISO 9660 filesystem");
386 break;
387 case FS_ISO_UDF:
388 CLog::Log(LOGINFO, "CD-ROM with both UDF and ISO 9660 filesystem");
389 break;
390 case FS_UFS:
391 CLog::Log(LOGINFO, "CD-ROM with Unix UFS");
392 break;
393 case FS_EXT2:
394 CLog::Log(LOGINFO, "CD-ROM with Linux second extended filesystem");
395 break;
396 case FS_3DO:
397 CLog::Log(LOGINFO, "CD-ROM with Panasonic 3DO filesystem");
398 break;
399 case FS_UNKNOWN:
400 CLog::Log(LOGINFO, "CD-ROM with unknown filesystem");
401 break;
404 switch (fs & FS_MASK)
406 case FS_ISO_9660:
407 case FS_ISO_9660_INTERACTIVE:
408 case FS_ISO_HFS:
409 case FS_ISO_UDF:
410 CLog::Log(LOGINFO, "ISO 9660: {} blocks, label {}", m_nIsofsSize, m_strDiscLabel);
411 break;
414 switch (fs & FS_MASK)
416 case FS_UDF:
417 case FS_ISO_UDF:
418 CLog::Log(LOGINFO, "UDF: version {:x}.{:02x}", m_nUDFVerMajor, m_nUDFVerMinor);
419 break;
422 if (m_nFirstData == 1 && num_audio > 0)
424 CLog::Log(LOGINFO, "mixed mode CD ");
426 if (fs & XA)
428 CLog::Log(LOGINFO, "XA sectors ");
430 if (fs & MULTISESSION)
432 CLog::Log(LOGINFO, "Multisession, offset = {} ", m_nMsOffset);
434 if (fs & HIDDEN_TRACK)
436 CLog::Log(LOGINFO, "Hidden Track ");
438 if (fs & PHOTO_CD)
440 CLog::Log(LOGINFO, "{}Photo CD ", num_audio > 0 ? " Portfolio " : "");
442 if (fs & CDTV)
444 CLog::Log(LOGINFO, "Commodore CDTV ");
446 if (m_nFirstData > 1)
448 CLog::Log(LOGINFO, "CD-Plus/Extra ");
450 if (fs & BOOTABLE)
452 CLog::Log(LOGINFO, "bootable CD ");
454 if (fs & VIDEOCDI && num_audio == 0)
456 CLog::Log(LOGINFO, "Video CD ");
457 #if defined(HAVE_VCDINFO) && defined(DEBUG)
458 if (!opts.no_vcd)
460 printf("\n");
461 print_vcd_info();
463 #endif
466 if (fs & CVD)
468 CLog::Log(LOGINFO, "Chaoji Video CD");
472 int CCdIoSupport::ReadBlock(int superblock, uint32_t offset, uint8_t bufnum, track_t track_num)
474 std::unique_lock<CCriticalSection> lock(*m_cdio);
476 unsigned int track_sec_count = ::cdio_get_track_sec_count(cdio, track_num);
477 memset(buffer[bufnum], 0, CDIO_CD_FRAMESIZE);
479 if ( track_sec_count < static_cast<unsigned int>(superblock))
481 ::cdio_debug("reading block %u skipped track %d has only %u sectors\n",
482 superblock, track_num, track_sec_count);
483 return -1;
486 ::cdio_debug("about to read sector %lu\n",
487 (long unsigned int) offset + superblock);
489 if (::cdio_get_track_green(cdio, track_num))
491 if (0 < ::cdio_read_mode2_sector(cdio, buffer[bufnum],
492 offset + superblock, false))
493 return -1;
495 else
497 if (0 < ::cdio_read_mode1_sector(cdio, buffer[bufnum],
498 offset + superblock, false))
499 return -1;
502 return 0;
505 bool CCdIoSupport::IsIt(int num)
507 signature_t *sigp = &sigs[num];
508 int len = strlen(sigp->sig_str);
510 //! @todo check that num < largest sig.
511 return 0 == memcmp(&buffer[sigp->buf_num][sigp->offset], sigp->sig_str, len);
514 int CCdIoSupport::IsHFS(void)
516 return (0 == memcmp(&buffer[1][512], "PM", 2)) ||
517 (0 == memcmp(&buffer[1][512], "TS", 2)) ||
518 (0 == memcmp(&buffer[1][1024], "BD", 2));
521 int CCdIoSupport::Is3DO(void)
523 return (0 == memcmp(&buffer[1][0], "\x01\x5a\x5a\x5a\x5a\x5a\x01", 7)) &&
524 (0 == memcmp(&buffer[1][40], "CD-ROM", 6));
527 int CCdIoSupport::IsJoliet(void)
529 return 2 == buffer[3][0] && buffer[3][88] == 0x25 && buffer[3][89] == 0x2f;
532 int CCdIoSupport::IsUDF(void)
534 return 2 == ((uint16_t)buffer[5][0] | ((uint16_t)buffer[5][1] << 8));
537 /* ISO 9660 volume space in M2F1_SECTOR_SIZE byte units */
538 int CCdIoSupport::GetSize(void)
540 return ((buffer[0][80] & 0xff) |
541 ((buffer[0][81] & 0xff) << 8) |
542 ((buffer[0][82] & 0xff) << 16) |
543 ((buffer[0][83] & 0xff) << 24));
546 int CCdIoSupport::GetJolietLevel( void )
548 switch (buffer[3][90])
550 case 0x40:
551 return 1;
552 case 0x43:
553 return 2;
554 case 0x45:
555 return 3;
557 return 0;
560 #define is_it_dbg(sig) /*\
561 if (is_it(sig)) printf("%s, ", sigs[sig].description)*/
563 int CCdIoSupport::GuessFilesystem(int start_session, track_t track_num)
565 std::unique_lock<CCriticalSection> lock(*m_cdio);
567 int ret = FS_UNKNOWN;
568 cdio_iso_analysis_t anal;
569 cdio_fs_anal_t fs;
570 bool udf = false;
572 memset(&anal, 0, sizeof(anal));
573 discmode_t mode = ::cdio_get_discmode(cdio);
574 if (::cdio_is_discmode_dvd(mode))
576 m_strDiscLabel = "";
577 m_nIsofsSize = ::cdio_get_disc_last_lsn(cdio);
578 m_nJolietLevel = ::cdio_get_joliet_level(cdio);
580 return FS_ISO_9660;
583 fs = ::cdio_guess_cd_type(cdio, start_session, track_num, &anal);
585 switch(CDIO_FSTYPE(fs))
587 case CDIO_FS_AUDIO:
588 ret = FS_NO_DATA;
589 break;
591 case CDIO_FS_HIGH_SIERRA:
592 ret = FS_HIGH_SIERRA;
593 break;
595 case CDIO_FS_ISO_9660:
596 ret = FS_ISO_9660;
597 break;
599 case CDIO_FS_INTERACTIVE:
600 ret = FS_ISO_9660_INTERACTIVE;
601 break;
603 case CDIO_FS_HFS:
604 ret = FS_HFS;
605 break;
607 case CDIO_FS_UFS:
608 ret = FS_UFS;
609 break;
611 case CDIO_FS_EXT2:
612 ret = FS_EXT2;
613 break;
615 case CDIO_FS_UDF:
616 ret = FS_UDF;
617 udf = true;
618 break;
620 case CDIO_FS_ISO_UDF:
621 ret = FS_ISO_UDF;
622 udf = true;
623 break;
625 default:
626 break;
629 if (udf)
631 m_nUDFVerMinor = anal.UDFVerMinor;
632 m_nUDFVerMajor = anal.UDFVerMajor;
635 m_strDiscLabel = anal.iso_label;
636 m_nIsofsSize = anal.isofs_size;
637 m_nJolietLevel = anal.joliet_level;
639 return ret;
642 void CCdIoSupport::GetCdTextInfo(xbmc_cdtext_t &xcdt, int trackNum)
644 // cdtext disabled for windows as some setup doesn't like mmc commands
645 // and stall for over a minute in cdio_get_cdtext 83
646 #if !defined(TARGET_WINDOWS)
647 std::unique_lock<CCriticalSection> lock(*m_cdio);
649 // Get the CD-Text , if any
650 #if defined(LIBCDIO_VERSION_NUM) && (LIBCDIO_VERSION_NUM >= 84)
651 cdtext_t *pcdtext = static_cast<cdtext_t*>( cdio_get_cdtext(cdio) );
652 #else
653 //! @todo - remove after Ubuntu 16.04 (Xenial) is EOL
654 cdtext_t *pcdtext = (cdtext_t *)::cdio_get_cdtext(cdio, trackNum);
655 #endif
657 if (pcdtext == NULL)
658 return ;
660 #if defined(LIBCDIO_VERSION_NUM) && (LIBCDIO_VERSION_NUM >= 84)
661 for (int i=0; i < MAX_CDTEXT_FIELDS; i++)
662 if (cdtext_get_const(pcdtext, (cdtext_field_t)i, trackNum))
663 xcdt[(cdtext_field_t)i] = cdtext_field2str((cdtext_field_t)i);
664 #else
665 //! @todo - remove after Ubuntu 16.04 (Xenial) is EOL
666 // Same ids used in libcdio and for our structure + the ids are consecutive make this copy loop safe.
667 for (int i = 0; i < MAX_CDTEXT_FIELDS; i++)
668 if (pcdtext->field[i])
669 xcdt[(cdtext_field_t)i] = pcdtext->field[(cdtext_field_t)i];
670 #endif
671 #endif // TARGET_WINDOWS
674 CCdInfo* CCdIoSupport::GetCdInfo(char* cDeviceFileName)
676 std::unique_lock<CCriticalSection> lock(*m_cdio);
678 char* source_name;
679 if(cDeviceFileName == NULL)
680 source_name = m_cdio->GetDeviceFileName();
681 else
682 source_name = cDeviceFileName;
684 cdio = ::cdio_open(source_name, DRIVER_UNKNOWN);
685 if (cdio == NULL)
687 CLog::Log(LOGERROR, "{}: Error in automatically selecting driver with input", __FUNCTION__);
688 return NULL;
691 bool bIsCDRom = true;
693 m_nFirstTrackNum = ::cdio_get_first_track_num(cdio);
694 if (m_nFirstTrackNum == CDIO_INVALID_TRACK)
696 #if !defined(TARGET_DARWIN)
697 ::cdio_destroy(cdio);
698 return NULL;
699 #else
700 m_nFirstTrackNum = 1;
701 bIsCDRom = false;
702 #endif
705 m_nNumTracks = ::cdio_get_num_tracks(cdio);
706 if (m_nNumTracks == CDIO_INVALID_TRACK)
708 #if !defined(TARGET_DARWIN)
709 ::cdio_destroy(cdio);
710 return NULL;
711 #else
712 m_nNumTracks = 1;
713 bIsCDRom = false;
714 #endif
717 CCdInfo* info = new CCdInfo;
718 info->SetFirstTrack( m_nFirstTrackNum );
719 info->SetTrackCount( m_nNumTracks );
721 for (i = m_nFirstTrackNum; i <= CDIO_CDROM_LEADOUT_TRACK; i++)
723 msf_t msf;
724 if (bIsCDRom && !::cdio_get_track_msf(cdio, i, &msf))
726 trackinfo ti;
727 ti.nfsInfo = FS_UNKNOWN;
728 ti.ms_offset = 0;
729 ti.isofs_size = 0;
730 ti.nJolietLevel = 0;
731 ti.nFrames = 0;
732 ti.nMins = 0;
733 ti.nSecs = 0;
734 info->SetTrackInformation( i, ti );
735 CLog::Log(LOGDEBUG, "cdio_track_msf for track {} failed, I give up.", i);
736 delete info;
737 ::cdio_destroy(cdio);
738 return NULL;
741 trackinfo ti;
742 if (bIsCDRom && TRACK_FORMAT_AUDIO == ::cdio_get_track_format(cdio, i))
744 m_nNumAudio++;
745 ti.nfsInfo = FS_NO_DATA;
746 m_nFs = FS_NO_DATA;
747 int temp1 = ::cdio_get_track_lba(cdio, i) - CDIO_PREGAP_SECTORS;
748 int temp2 = ::cdio_get_track_lba(cdio, i + 1) - CDIO_PREGAP_SECTORS;
749 // The length is the address of the second track minus the address of the first track
750 temp2 -= temp1; // temp2 now has length of track1 in frames
751 ti.nMins = temp2 / (60 * 75); // calculate the number of minutes
752 temp2 %= 60 * 75; // calculate the left-over frames
753 ti.nSecs = temp2 / 75; // calculate the number of seconds
754 if ( -1 == m_nFirstAudio)
755 m_nFirstAudio = i;
757 // Make sure that we have the Disc related info available
758 if (i == 1)
760 xbmc_cdtext_t xcdt;
761 GetCdTextInfo(xcdt, 0);
762 info->SetDiscCDTextInformation( xcdt );
765 // Get this tracks info
766 GetCdTextInfo(ti.cdtext, i);
768 else
770 m_nNumData++;
771 if ( -1 == m_nFirstData)
772 m_nFirstData = i;
774 ti.nfsInfo = FS_NO_DATA;
775 ti.ms_offset = 0;
776 ti.isofs_size = 0;
777 ti.nJolietLevel = 0;
778 ti.nFrames = ::cdio_get_track_lba(cdio, i);
779 ti.nMins = 0;
780 ti.nSecs = 0;
782 info->SetTrackInformation( i, ti );
783 /* skip to leadout? */
784 if (i == m_nNumTracks)
785 i = CDIO_CDROM_LEADOUT_TRACK;
788 info->SetCddbDiscId( CddbDiscId() );
789 info->SetDiscLength( ::cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC );
791 info->SetAudioTrackCount( m_nNumAudio );
792 info->SetDataTrackCount( m_nNumData );
793 info->SetFirstAudioTrack( m_nFirstAudio );
794 info->SetFirstDataTrack( m_nFirstData );
796 CLog::Log(LOGINFO, "CD Analysis Report");
797 CLog::Log(LOGINFO, STRONG);
799 /* Try to find out what sort of CD we have */
800 if (0 == m_nNumData)
802 /* no data track, may be a "real" audio CD or hidden track CD */
804 msf_t msf;
805 ::cdio_get_track_msf(cdio, 1, &msf);
806 m_nStartTrack = ::cdio_msf_to_lsn(&msf);
808 /* CD-I/Ready says start_track <= 30*75 then CDDA */
809 if (m_nStartTrack > 100 /* 100 is just a guess */)
811 m_nFs = GuessFilesystem(0, 1);
812 if ((m_nFs & FS_MASK) != FS_UNKNOWN)
813 m_nFs |= HIDDEN_TRACK;
814 else
816 m_nFs &= ~FS_MASK; /* del filesystem info */
817 CLog::Log(LOGDEBUG, "Oops: {} unused sectors at start, but hidden track check failed.",
818 m_nStartTrack);
821 PrintAnalysis(m_nFs, m_nNumAudio);
823 else
825 /* We have data track(s) */
826 for (j = 2, i = m_nFirstData; i <= m_nNumTracks; i++)
828 msf_t msf;
829 track_format_t track_format = ::cdio_get_track_format(cdio, i);
831 ::cdio_get_track_msf(cdio, i, &msf);
833 switch ( track_format )
835 case TRACK_FORMAT_AUDIO:
837 trackinfo ti;
838 ti.nfsInfo = FS_NO_DATA;
839 m_nFs = FS_NO_DATA;
840 ti.ms_offset = 0;
841 ti.isofs_size = 0;
842 ti.nJolietLevel = 0;
843 ti.nFrames = ::cdio_get_track_lba(cdio, i);
844 ti.nMins = 0;
845 ti.nSecs = 0;
846 info->SetTrackInformation( i + 1, ti );
848 case TRACK_FORMAT_ERROR:
849 break;
850 case TRACK_FORMAT_CDI:
851 case TRACK_FORMAT_XA:
852 case TRACK_FORMAT_DATA:
853 case TRACK_FORMAT_PSX:
854 break;
857 m_nStartTrack = (i == 1) ? 0 : ::cdio_msf_to_lsn(&msf);
859 /* Save the start of the data area */
860 if (i == m_nFirstData)
861 m_nDataStart = m_nStartTrack;
863 /* Skip tracks which belong to the current walked session */
864 if (m_nStartTrack < m_nDataStart + m_nIsofsSize)
865 continue;
867 m_nFs = GuessFilesystem(m_nStartTrack, i);
868 trackinfo ti;
869 ti.nfsInfo = m_nFs;
870 ti.ms_offset = m_nMsOffset;
871 ti.isofs_size = m_nIsofsSize;
872 ti.nJolietLevel = m_nJolietLevel;
873 ti.nFrames = ::cdio_get_track_lba(cdio, i);
874 ti.nMins = 0;
875 ti.nSecs = 0;
876 info->SetDiscLabel(m_strDiscLabel);
879 if (i > 1)
881 /* Track is beyond last session -> new session found */
882 m_nMsOffset = m_nStartTrack;
884 CLog::Log(LOGINFO,
885 "Session #{} starts at track {:2}, LSN: {:6},"
886 " ISO 9660 blocks: {:6}",
887 j++, i, m_nStartTrack, m_nIsofsSize);
889 CLog::Log(LOGINFO, "ISO 9660: {} blocks, label {}", m_nIsofsSize, m_strDiscLabel);
890 m_nFs |= MULTISESSION;
891 ti.nfsInfo = m_nFs;
893 else
895 PrintAnalysis(m_nFs, m_nNumAudio);
898 info->SetTrackInformation( i, ti );
902 ::cdio_destroy( cdio );
903 return info;
907 // Returns the sum of the decimal digits in a number. Eg. 1955 = 20
908 int CCdIoSupport::CddbDecDigitSum(int n)
910 int ret = 0;
912 for (;;)
914 ret += n % 10;
915 n = n / 10;
916 if (!n)
917 return ret;
921 // Return the number of seconds (discarding frame portion) of an MSF
922 unsigned int CCdIoSupport::MsfSeconds(msf_t *msf)
924 std::unique_lock<CCriticalSection> lock(*m_cdio);
926 return ::cdio_from_bcd8(msf->m)*60 + ::cdio_from_bcd8(msf->s);
930 // Compute the CDDB disk ID for an Audio disk.
931 // This is a funny checksum consisting of the concatenation of 3 things:
932 // The sum of the decimal digits of sizes of all tracks,
933 // The total length of the disk, and
934 // The number of tracks.
936 uint32_t CCdIoSupport::CddbDiscId()
938 std::unique_lock<CCriticalSection> lock(*m_cdio);
940 int i, t, n = 0;
941 msf_t start_msf;
942 msf_t msf;
944 for (i = 1; i <= m_nNumTracks; i++)
946 ::cdio_get_track_msf(cdio, i, &msf);
947 n += CddbDecDigitSum(MsfSeconds(&msf));
950 ::cdio_get_track_msf(cdio, 1, &start_msf);
951 ::cdio_get_track_msf(cdio, CDIO_CDROM_LEADOUT_TRACK, &msf);
953 t = MsfSeconds(&msf) - MsfSeconds(&start_msf);
955 return ((n % 0xff) << 24 | t << 8 | m_nNumTracks);