summaryrefslogtreecommitdiffstats
path: root/xbmc/storage/cdioSupport.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/storage/cdioSupport.h')
-rw-r--r--xbmc/storage/cdioSupport.h347
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;
+};
+
+}