diff options
Diffstat (limited to 'xbmc/storage/cdioSupport.h')
-rw-r--r-- | xbmc/storage/cdioSupport.h | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/xbmc/storage/cdioSupport.h b/xbmc/storage/cdioSupport.h new file mode 100644 index 0000000..b786ff2 --- /dev/null +++ b/xbmc/storage/cdioSupport.h @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +// CCdInfo - Information about media type of an inserted cd +// CCdIoSupport - Wrapper class for libcdio with the interface of CIoSupport +// and detecting the filesystem on the Disc. +// +// by Bobbin007 in 2003 +// CD-Text support by Mog - Oct 2004 + +#include "threads/CriticalSection.h" + +#include <map> +#include <memory> +#include <string> +#include <utility> + +#include "PlatformDefs.h" // for ssize_t typedef, used by cdio + +#include <cdio/cdio.h> + +namespace MEDIA_DETECT +{ + +#define STRONG "__________________________________\n" +//#define NORMAL "" + +#define FS_NO_DATA 0 /* audio only */ +#define FS_HIGH_SIERRA 1 +#define FS_ISO_9660 2 +#define FS_INTERACTIVE 3 +#define FS_HFS 4 +#define FS_UFS 5 +#define FS_EXT2 6 +#define FS_ISO_HFS 7 /* both hfs & isofs filesystem */ +#define FS_ISO_9660_INTERACTIVE 8 /* both CD-RTOS and isofs filesystem */ +#define FS_3DO 9 +#define FS_UDF 11 +#define FS_ISO_UDF 12 +#define FS_UNKNOWN 15 +#define FS_MASK 15 + +#define XA 16 +#define MULTISESSION 32 +#define PHOTO_CD 64 +#define HIDDEN_TRACK 128 +#define CDTV 256 +#define BOOTABLE 512 +#define VIDEOCDI 1024 +#define ROCKRIDGE 2048 +#define JOLIET 4096 +#define CVD 8192 /* Choiji Video CD */ + +#define IS_ISOFS 0 +#define IS_CD_I 1 +#define IS_CDTV 2 +#define IS_CD_RTOS 3 +#define IS_HS 4 +#define IS_BRIDGE 5 +#define IS_XA 6 +#define IS_PHOTO_CD 7 +#define IS_EXT2 8 +#define IS_UFS 9 +#define IS_BOOTABLE 10 +#define IS_VIDEO_CD 11 /* Video CD */ +#define IS_CVD 12 /* Chinese Video CD - slightly incompatible with SVCD */ +#define IS_UDF 14 + +typedef struct signature +{ + unsigned int buf_num; + unsigned int offset; + const char *sig_str; + const char *description; +} +signature_t; + +typedef std::map<cdtext_field_t, std::string> xbmc_cdtext_t; + +typedef struct TRACKINFO +{ + int nfsInfo; // Information of the Tracks Filesystem + int nJolietLevel; // Jouliet Level + int ms_offset; // Multisession Offset + int isofs_size; // Size of the ISO9660 Filesystem + int nFrames; // Can be used for cddb query + int nMins; // minutes playtime part of Track + int nSecs; // seconds playtime part of Track + xbmc_cdtext_t cdtext; // CD-Text for this track +} +trackinfo; + +/*! \brief Helper enum class for the MMC tray state +*/ +enum class CdioTrayStatus +{ + /* The MMC tray state is reported closed */ + CLOSED, + /* The MMC tray state is reported open */ + OPEN, + /* The MMC tray status operation is not supported */ + UNKNOWN, + /* Generic driver error */ + DRIVER_ERROR +}; + +class CCdInfo +{ +public: + CCdInfo() + { + m_bHasCDDBInfo = true; + m_nLength = m_nFirstTrack = m_nNumTrack = m_nNumAudio = m_nFirstAudio = m_nNumData = m_nFirstData = 0; + } + + trackinfo GetTrackInformation( int nTrack ) { return m_ti[nTrack -1]; } + xbmc_cdtext_t GetDiscCDTextInformation() { return m_cdtext; } + + bool HasDataTracks() { return (m_nNumData > 0); } + bool HasAudioTracks() { return (m_nNumAudio > 0); } + int GetFirstTrack() { return m_nFirstTrack; } + int GetTrackCount() { return m_nNumTrack; } + int GetFirstAudioTrack() { return m_nFirstAudio; } + int GetFirstDataTrack() { return m_nFirstData; } + int GetDataTrackCount() { return m_nNumData; } + int GetAudioTrackCount() { return m_nNumAudio; } + uint32_t GetCddbDiscId() { return m_ulCddbDiscId; } + int GetDiscLength() { return m_nLength; } + std::string GetDiscLabel(){ return m_strDiscLabel; } + + // CD-ROM with ISO 9660 filesystem + bool IsIso9660( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_9660); } + // CD-ROM with joliet extension + bool IsJoliet( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & JOLIET) ? false : true; } + // Joliet extension level + int GetJolietLevel( int nTrack ) { return m_ti[nTrack - 1].nJolietLevel; } + // ISO filesystem size + int GetIsoSize( int nTrack ) { return m_ti[nTrack - 1].isofs_size; } + // CD-ROM with rockridge extensions + bool IsRockridge( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & ROCKRIDGE) ? false : true; } + + // CD-ROM with CD-RTOS and ISO 9660 filesystem + bool IsIso9660Interactive( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_9660_INTERACTIVE); } + + // CD-ROM with High Sierra filesystem + bool IsHighSierra( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_HIGH_SIERRA); } + + // CD-Interactive, with audiotracks > 0 CD-Interactive/Ready + bool IsCDInteractive( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_INTERACTIVE); } + + // CD-ROM with Macintosh HFS + bool IsHFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_HFS); } + + // CD-ROM with both Macintosh HFS and ISO 9660 filesystem + bool IsISOHFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_HFS); } + + // CD-ROM with both UDF and ISO 9660 filesystem + bool IsISOUDF( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_UDF); } + + // CD-ROM with Unix UFS + bool IsUFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_UFS); } + + // CD-ROM with Linux second extended filesystem + bool IsEXT2( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_EXT2); } + + // CD-ROM with Panasonic 3DO filesystem + bool Is3DO( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_3DO); } + + // Mixed Mode CD-ROM + bool IsMixedMode( int nTrack ) { return (m_nFirstData == 1 && m_nNumAudio > 0); } + + // CD-ROM with XA sectors + bool IsXA( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & XA) ? false : true; } + + // Multisession CD-ROM + bool IsMultiSession( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & MULTISESSION) ? false : true; } + // Gets multisession offset + int GetMultisessionOffset( int nTrack ) { return m_ti[nTrack - 1].ms_offset; } + + // Hidden Track on Audio CD + bool IsHiddenTrack( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & HIDDEN_TRACK) ? false : true; } + + // Photo CD, with audiotracks > 0 Portfolio Photo CD + bool IsPhotoCd( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & PHOTO_CD) ? false : true; } + + // CD-ROM with Commodore CDTV + bool IsCdTv( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & CDTV) ? false : true; } + + // CD-Plus/Extra + bool IsCDExtra( int nTrack ) { return (m_nFirstData > 1); } + + // Bootable CD + bool IsBootable( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & BOOTABLE) ? false : true; } + + // Video CD + bool IsVideoCd( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & VIDEOCDI && m_nNumAudio == 0); } + + // Chaoji Video CD + bool IsChaojiVideoCD( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & CVD) ? false : true; } + + // Audio Track + bool IsAudio( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_NO_DATA); } + + // UDF filesystem + bool IsUDF( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_UDF); } + + // Has the cd a filesystem that is readable by the xbox + bool IsValidFs() { return (IsISOHFS(1) || IsIso9660(1) || IsIso9660Interactive(1) || IsISOUDF(1) || IsUDF(1) || IsAudio(1)); } + + void SetFirstTrack( int nTrack ) { m_nFirstTrack = nTrack; } + void SetTrackCount( int nCount ) { m_nNumTrack = nCount; } + void SetFirstAudioTrack( int nTrack ) { m_nFirstAudio = nTrack; } + void SetFirstDataTrack( int nTrack ) { m_nFirstData = nTrack; } + void SetDataTrackCount( int nCount ) { m_nNumData = nCount; } + void SetAudioTrackCount( int nCount ) { m_nNumAudio = nCount; } + void SetTrackInformation(int nTrack, trackinfo nInfo) + { + if (nTrack > 0 && nTrack <= 99) + m_ti[nTrack - 1] = std::move(nInfo); + } + void SetDiscCDTextInformation(xbmc_cdtext_t cdtext) { m_cdtext = std::move(cdtext); } + + void SetCddbDiscId( uint32_t ulCddbDiscId ) { m_ulCddbDiscId = ulCddbDiscId; } + void SetDiscLength( int nLength ) { m_nLength = nLength; } + bool HasCDDBInfo() { return m_bHasCDDBInfo; } + void SetNoCDDBInfo() { m_bHasCDDBInfo = false; } + + void SetDiscLabel(const std::string& strDiscLabel){ m_strDiscLabel = strDiscLabel; } + +private: + int m_nFirstData; /* # of first data track */ + int m_nNumData; /* # of data tracks */ + int m_nFirstAudio; /* # of first audio track */ + int m_nNumAudio; /* # of audio tracks */ + int m_nNumTrack; + int m_nFirstTrack; + trackinfo m_ti[100]; + uint32_t m_ulCddbDiscId; + int m_nLength; // Disclength can be used for cddb query, also see trackinfo.nFrames + bool m_bHasCDDBInfo; + std::string m_strDiscLabel; + xbmc_cdtext_t m_cdtext; // CD-Text for this disc +}; + +class CLibcdio : public CCriticalSection +{ +private: + CLibcdio(); +public: + virtual ~CLibcdio(); + + static void ReleaseInstance(); + static std::shared_ptr<CLibcdio> GetInstance(); + + // libcdio is not thread safe so these are wrappers to libcdio routines + CdIo_t* cdio_open(const char *psz_source, driver_id_t driver_id); + CdIo_t* cdio_open_win32(const char *psz_source); + void cdio_destroy(CdIo_t *p_cdio); + discmode_t cdio_get_discmode(CdIo_t *p_cdio); + CdioTrayStatus mmc_get_tray_status(const CdIo_t* p_cdio); + driver_return_code_t cdio_eject_media(CdIo_t** p_cdio); + track_t cdio_get_last_track_num(const CdIo_t *p_cdio); + lsn_t cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track); + lsn_t cdio_get_track_last_lsn(const CdIo_t *p_cdio, track_t i_track); + driver_return_code_t cdio_read_audio_sectors(const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, uint32_t i_blocks); + driver_return_code_t cdio_close_tray(const char* psz_source, driver_id_t* driver_id); + const char* cdio_driver_errmsg(driver_return_code_t drc); + + char* GetDeviceFileName(); + +private: + char* s_defaultDevice; + CCriticalSection m_critSection; + static std::shared_ptr<CLibcdio> m_pInstance; +}; + +class CCdIoSupport +{ +public: + CCdIoSupport(); + virtual ~CCdIoSupport(); + + bool EjectTray(); + bool CloseTray(); + + HANDLE OpenCDROM(); + HANDLE OpenIMAGE( std::string& strFilename ); + int ReadSector(HANDLE hDevice, DWORD dwSector, char* lpczBuffer); + int ReadSectorMode2(HANDLE hDevice, DWORD dwSector, char* lpczBuffer); + int ReadSectorCDDA(HANDLE hDevice, DWORD dwSector, char* lpczBuffer); + void CloseCDROM(HANDLE hDevice); + + void PrintAnalysis(int fs, int num_audio); + + CCdInfo* GetCdInfo(char* cDeviceFileName=NULL); + void GetCdTextInfo(xbmc_cdtext_t &xcdt, int trackNum); + +protected: + int ReadBlock(int superblock, uint32_t offset, uint8_t bufnum, track_t track_num); + bool IsIt(int num); + int IsHFS(void); + int Is3DO(void); + int IsJoliet(void); + int IsUDF(void); + int GetSize(void); + int GetJolietLevel( void ); + int GuessFilesystem(int start_session, track_t track_num); + + uint32_t CddbDiscId(); + int CddbDecDigitSum(int n); + unsigned int MsfSeconds(msf_t *msf); + +private: + char buffer[7][CDIO_CD_FRAMESIZE_RAW]; /* for CD-Data */ + static signature_t sigs[17]; + int i = 0, j = 0; /* index */ + int m_nStartTrack; /* first sector of track */ + int m_nIsofsSize; /* size of session */ + int m_nJolietLevel; + int m_nMsOffset; /* multisession offset found by track-walking */ + int m_nDataStart; /* start of data area */ + int m_nFs; + int m_nUDFVerMinor; + int m_nUDFVerMajor; + + CdIo* cdio; + track_t m_nNumTracks = CDIO_INVALID_TRACK; + track_t m_nFirstTrackNum = CDIO_INVALID_TRACK; + + std::string m_strDiscLabel; + + int m_nFirstData; /* # of first data track */ + int m_nNumData; /* # of data tracks */ + int m_nFirstAudio; /* # of first audio track */ + int m_nNumAudio; /* # of audio tracks */ + + std::shared_ptr<CLibcdio> m_cdio; +}; + +} |