1 /* 2 * Copyright (C) 2005-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #pragma once 10 11 // CCdInfo - Information about media type of an inserted cd 12 // CCdIoSupport - Wrapper class for libcdio with the interface of CIoSupport 13 // and detecting the filesystem on the Disc. 14 // 15 // by Bobbin007 in 2003 16 // CD-Text support by Mog - Oct 2004 17 18 #include "threads/CriticalSection.h" 19 20 #include <map> 21 #include <memory> 22 #include <string> 23 #include <utility> 24 25 #include "PlatformDefs.h" // for ssize_t typedef, used by cdio 26 27 #include <cdio/cdio.h> 28 29 namespace MEDIA_DETECT 30 { 31 32 #define STRONG "__________________________________\n" 33 //#define NORMAL "" 34 35 #define FS_NO_DATA 0 /* audio only */ 36 #define FS_HIGH_SIERRA 1 37 #define FS_ISO_9660 2 38 #define FS_INTERACTIVE 3 39 #define FS_HFS 4 40 #define FS_UFS 5 41 #define FS_EXT2 6 42 #define FS_ISO_HFS 7 /* both hfs & isofs filesystem */ 43 #define FS_ISO_9660_INTERACTIVE 8 /* both CD-RTOS and isofs filesystem */ 44 #define FS_3DO 9 45 #define FS_UDF 11 46 #define FS_ISO_UDF 12 47 #define FS_UNKNOWN 15 48 #define FS_MASK 15 49 50 #define XA 16 51 #define MULTISESSION 32 52 #define PHOTO_CD 64 53 #define HIDDEN_TRACK 128 54 #define CDTV 256 55 #define BOOTABLE 512 56 #define VIDEOCDI 1024 57 #define ROCKRIDGE 2048 58 #define JOLIET 4096 59 #define CVD 8192 /* Choiji Video CD */ 60 61 #define IS_ISOFS 0 62 #define IS_CD_I 1 63 #define IS_CDTV 2 64 #define IS_CD_RTOS 3 65 #define IS_HS 4 66 #define IS_BRIDGE 5 67 #define IS_XA 6 68 #define IS_PHOTO_CD 7 69 #define IS_EXT2 8 70 #define IS_UFS 9 71 #define IS_BOOTABLE 10 72 #define IS_VIDEO_CD 11 /* Video CD */ 73 #define IS_CVD 12 /* Chinese Video CD - slightly incompatible with SVCD */ 74 #define IS_UDF 14 75 76 typedef struct signature 77 { 78 unsigned int buf_num; 79 unsigned int offset; 80 const char *sig_str; 81 const char *description; 82 } 83 signature_t; 84 85 typedef std::map<cdtext_field_t, std::string> xbmc_cdtext_t; 86 87 typedef struct TRACKINFO 88 { 89 int nfsInfo; // Information of the Tracks Filesystem 90 int nJolietLevel; // Jouliet Level 91 int ms_offset; // Multisession Offset 92 int isofs_size; // Size of the ISO9660 Filesystem 93 int nFrames; // Can be used for cddb query 94 int nMins; // minutes playtime part of Track 95 int nSecs; // seconds playtime part of Track 96 xbmc_cdtext_t cdtext; // CD-Text for this track 97 } 98 trackinfo; 99 100 101 class CCdInfo 102 { 103 public: CCdInfo()104 CCdInfo() 105 { 106 m_bHasCDDBInfo = true; 107 m_nLength = m_nFirstTrack = m_nNumTrack = m_nNumAudio = m_nFirstAudio = m_nNumData = m_nFirstData = 0; 108 } 109 GetTrackInformation(int nTrack)110 trackinfo GetTrackInformation( int nTrack ) { return m_ti[nTrack -1]; } GetDiscCDTextInformation()111 xbmc_cdtext_t GetDiscCDTextInformation() { return m_cdtext; } 112 HasDataTracks()113 bool HasDataTracks() { return (m_nNumData > 0); } HasAudioTracks()114 bool HasAudioTracks() { return (m_nNumAudio > 0); } GetFirstTrack()115 int GetFirstTrack() { return m_nFirstTrack; } GetTrackCount()116 int GetTrackCount() { return m_nNumTrack; } GetFirstAudioTrack()117 int GetFirstAudioTrack() { return m_nFirstAudio; } GetFirstDataTrack()118 int GetFirstDataTrack() { return m_nFirstData; } GetDataTrackCount()119 int GetDataTrackCount() { return m_nNumData; } GetAudioTrackCount()120 int GetAudioTrackCount() { return m_nNumAudio; } GetCddbDiscId()121 uint32_t GetCddbDiscId() { return m_ulCddbDiscId; } GetDiscLength()122 int GetDiscLength() { return m_nLength; } GetDiscLabel()123 std::string GetDiscLabel(){ return m_strDiscLabel; } 124 125 // CD-ROM with ISO 9660 filesystem IsIso9660(int nTrack)126 bool IsIso9660( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_9660); } 127 // CD-ROM with joliet extension IsJoliet(int nTrack)128 bool IsJoliet( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & JOLIET) ? false : true; } 129 // Joliet extension level GetJolietLevel(int nTrack)130 int GetJolietLevel( int nTrack ) { return m_ti[nTrack - 1].nJolietLevel; } 131 // ISO filesystem size GetIsoSize(int nTrack)132 int GetIsoSize( int nTrack ) { return m_ti[nTrack - 1].isofs_size; } 133 // CD-ROM with rockridge extensions IsRockridge(int nTrack)134 bool IsRockridge( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & ROCKRIDGE) ? false : true; } 135 136 // CD-ROM with CD-RTOS and ISO 9660 filesystem IsIso9660Interactive(int nTrack)137 bool IsIso9660Interactive( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_9660_INTERACTIVE); } 138 139 // CD-ROM with High Sierra filesystem IsHighSierra(int nTrack)140 bool IsHighSierra( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_HIGH_SIERRA); } 141 142 // CD-Interactive, with audiotracks > 0 CD-Interactive/Ready IsCDInteractive(int nTrack)143 bool IsCDInteractive( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_INTERACTIVE); } 144 145 // CD-ROM with Macintosh HFS IsHFS(int nTrack)146 bool IsHFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_HFS); } 147 148 // CD-ROM with both Macintosh HFS and ISO 9660 filesystem IsISOHFS(int nTrack)149 bool IsISOHFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_HFS); } 150 151 // CD-ROM with both UDF and ISO 9660 filesystem IsISOUDF(int nTrack)152 bool IsISOUDF( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_UDF); } 153 154 // CD-ROM with Unix UFS IsUFS(int nTrack)155 bool IsUFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_UFS); } 156 157 // CD-ROM with Linux second extended filesystem IsEXT2(int nTrack)158 bool IsEXT2( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_EXT2); } 159 160 // CD-ROM with Panasonic 3DO filesystem Is3DO(int nTrack)161 bool Is3DO( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_3DO); } 162 163 // Mixed Mode CD-ROM IsMixedMode(int nTrack)164 bool IsMixedMode( int nTrack ) { return (m_nFirstData == 1 && m_nNumAudio > 0); } 165 166 // CD-ROM with XA sectors IsXA(int nTrack)167 bool IsXA( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & XA) ? false : true; } 168 169 // Multisession CD-ROM IsMultiSession(int nTrack)170 bool IsMultiSession( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & MULTISESSION) ? false : true; } 171 // Gets multisession offset GetMultisessionOffset(int nTrack)172 int GetMultisessionOffset( int nTrack ) { return m_ti[nTrack - 1].ms_offset; } 173 174 // Hidden Track on Audio CD IsHiddenTrack(int nTrack)175 bool IsHiddenTrack( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & HIDDEN_TRACK) ? false : true; } 176 177 // Photo CD, with audiotracks > 0 Portfolio Photo CD IsPhotoCd(int nTrack)178 bool IsPhotoCd( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & PHOTO_CD) ? false : true; } 179 180 // CD-ROM with Commodore CDTV IsCdTv(int nTrack)181 bool IsCdTv( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & CDTV) ? false : true; } 182 183 // CD-Plus/Extra IsCDExtra(int nTrack)184 bool IsCDExtra( int nTrack ) { return (m_nFirstData > 1); } 185 186 // Bootable CD IsBootable(int nTrack)187 bool IsBootable( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & BOOTABLE) ? false : true; } 188 189 // Video CD IsVideoCd(int nTrack)190 bool IsVideoCd( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & VIDEOCDI && m_nNumAudio == 0); } 191 192 // Chaoji Video CD IsChaojiVideoCD(int nTrack)193 bool IsChaojiVideoCD( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & CVD) ? false : true; } 194 195 // Audio Track IsAudio(int nTrack)196 bool IsAudio( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_NO_DATA); } 197 198 // UDF filesystem IsUDF(int nTrack)199 bool IsUDF( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_UDF); } 200 201 // Has the cd a filesystem that is readable by the xbox IsValidFs()202 bool IsValidFs() { return (IsISOHFS(1) || IsIso9660(1) || IsIso9660Interactive(1) || IsISOUDF(1) || IsUDF(1) || IsAudio(1)); } 203 SetFirstTrack(int nTrack)204 void SetFirstTrack( int nTrack ) { m_nFirstTrack = nTrack; } SetTrackCount(int nCount)205 void SetTrackCount( int nCount ) { m_nNumTrack = nCount; } SetFirstAudioTrack(int nTrack)206 void SetFirstAudioTrack( int nTrack ) { m_nFirstAudio = nTrack; } SetFirstDataTrack(int nTrack)207 void SetFirstDataTrack( int nTrack ) { m_nFirstData = nTrack; } SetDataTrackCount(int nCount)208 void SetDataTrackCount( int nCount ) { m_nNumData = nCount; } SetAudioTrackCount(int nCount)209 void SetAudioTrackCount( int nCount ) { m_nNumAudio = nCount; } SetTrackInformation(int nTrack,trackinfo nInfo)210 void SetTrackInformation(int nTrack, trackinfo nInfo) 211 { 212 if (nTrack > 0 && nTrack <= 99) 213 m_ti[nTrack - 1] = std::move(nInfo); 214 } SetDiscCDTextInformation(xbmc_cdtext_t cdtext)215 void SetDiscCDTextInformation(xbmc_cdtext_t cdtext) { m_cdtext = std::move(cdtext); } 216 SetCddbDiscId(uint32_t ulCddbDiscId)217 void SetCddbDiscId( uint32_t ulCddbDiscId ) { m_ulCddbDiscId = ulCddbDiscId; } SetDiscLength(int nLength)218 void SetDiscLength( int nLength ) { m_nLength = nLength; } HasCDDBInfo()219 bool HasCDDBInfo() { return m_bHasCDDBInfo; } SetNoCDDBInfo()220 void SetNoCDDBInfo() { m_bHasCDDBInfo = false; } 221 SetDiscLabel(const std::string & strDiscLabel)222 void SetDiscLabel(const std::string& strDiscLabel){ m_strDiscLabel = strDiscLabel; } 223 224 private: 225 int m_nFirstData; /* # of first data track */ 226 int m_nNumData; /* # of data tracks */ 227 int m_nFirstAudio; /* # of first audio track */ 228 int m_nNumAudio; /* # of audio tracks */ 229 int m_nNumTrack; 230 int m_nFirstTrack; 231 trackinfo m_ti[100]; 232 uint32_t m_ulCddbDiscId; 233 int m_nLength; // Disclength can be used for cddb query, also see trackinfo.nFrames 234 bool m_bHasCDDBInfo; 235 std::string m_strDiscLabel; 236 xbmc_cdtext_t m_cdtext; // CD-Text for this disc 237 }; 238 239 class CLibcdio : public CCriticalSection 240 { 241 private: 242 CLibcdio(); 243 public: 244 virtual ~CLibcdio(); 245 246 static void ReleaseInstance(); 247 static std::shared_ptr<CLibcdio> GetInstance(); 248 249 // libcdio is not thread safe so these are wrappers to libcdio routines 250 CdIo_t* cdio_open(const char *psz_source, driver_id_t driver_id); 251 CdIo_t* cdio_open_win32(const char *psz_source); 252 void cdio_destroy(CdIo_t *p_cdio); 253 discmode_t cdio_get_discmode(CdIo_t *p_cdio); 254 int mmc_get_tray_status(const CdIo_t *p_cdio); 255 int cdio_eject_media(CdIo_t **p_cdio); 256 track_t cdio_get_last_track_num(const CdIo_t *p_cdio); 257 lsn_t cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track); 258 lsn_t cdio_get_track_last_lsn(const CdIo_t *p_cdio, track_t i_track); 259 driver_return_code_t cdio_read_audio_sectors(const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, uint32_t i_blocks); 260 261 char* GetDeviceFileName(); 262 263 private: 264 char* s_defaultDevice; 265 CCriticalSection m_critSection; 266 static std::shared_ptr<CLibcdio> m_pInstance; 267 }; 268 269 class CCdIoSupport 270 { 271 public: 272 CCdIoSupport(); 273 virtual ~CCdIoSupport(); 274 275 bool EjectTray(); 276 bool CloseTray(); 277 278 HANDLE OpenCDROM(); 279 HANDLE OpenIMAGE( std::string& strFilename ); 280 int ReadSector(HANDLE hDevice, DWORD dwSector, char* lpczBuffer); 281 int ReadSectorMode2(HANDLE hDevice, DWORD dwSector, char* lpczBuffer); 282 int ReadSectorCDDA(HANDLE hDevice, DWORD dwSector, char* lpczBuffer); 283 void CloseCDROM(HANDLE hDevice); 284 285 void PrintAnalysis(int fs, int num_audio); 286 287 CCdInfo* GetCdInfo(char* cDeviceFileName=NULL); 288 void GetCdTextInfo(xbmc_cdtext_t &xcdt, int trackNum); 289 290 protected: 291 int ReadBlock(int superblock, uint32_t offset, uint8_t bufnum, track_t track_num); 292 bool IsIt(int num); 293 int IsHFS(void); 294 int Is3DO(void); 295 int IsJoliet(void); 296 int IsUDF(void); 297 int GetSize(void); 298 int GetJolietLevel( void ); 299 int GuessFilesystem(int start_session, track_t track_num); 300 301 uint32_t CddbDiscId(); 302 int CddbDecDigitSum(int n); 303 unsigned int MsfSeconds(msf_t *msf); 304 305 private: 306 char buffer[7][CDIO_CD_FRAMESIZE_RAW]; /* for CD-Data */ 307 static signature_t sigs[17]; 308 int i = 0, j = 0; /* index */ 309 int m_nStartTrack; /* first sector of track */ 310 int m_nIsofsSize; /* size of session */ 311 int m_nJolietLevel; 312 int m_nMsOffset; /* multisession offset found by track-walking */ 313 int m_nDataStart; /* start of data area */ 314 int m_nFs; 315 int m_nUDFVerMinor; 316 int m_nUDFVerMajor; 317 318 CdIo* cdio; 319 track_t m_nNumTracks = CDIO_INVALID_TRACK; 320 track_t m_nFirstTrackNum = CDIO_INVALID_TRACK; 321 322 std::string m_strDiscLabel; 323 324 int m_nFirstData; /* # of first data track */ 325 int m_nNumData; /* # of data tracks */ 326 int m_nFirstAudio; /* # of first audio track */ 327 int m_nNumAudio; /* # of audio tracks */ 328 329 std::shared_ptr<CLibcdio> m_cdio; 330 }; 331 332 } 333