kodi
cdioSupport.h
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 }
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 
102 enum class CdioTrayStatus
103 {
104  /* The MMC tray state is reported closed */
105  CLOSED,
106  /* The MMC tray state is reported open */
107  OPEN,
108  /* The MMC tray status operation is not supported */
109  UNKNOWN,
110  /* Generic driver error */
111  DRIVER_ERROR
112 };
113 
114 class CCdInfo
115 {
116 public:
117  CCdInfo()
118  {
119  m_bHasCDDBInfo = true;
120  m_nLength = m_nFirstTrack = m_nNumTrack = m_nNumAudio = m_nFirstAudio = m_nNumData = m_nFirstData = 0;
121  }
122 
123  trackinfo GetTrackInformation( int nTrack ) { return m_ti[nTrack -1]; }
124  xbmc_cdtext_t GetDiscCDTextInformation() { return m_cdtext; }
125 
126  bool HasDataTracks() { return (m_nNumData > 0); }
127  bool HasAudioTracks() { return (m_nNumAudio > 0); }
128  int GetFirstTrack() { return m_nFirstTrack; }
129  int GetTrackCount() { return m_nNumTrack; }
130  int GetFirstAudioTrack() { return m_nFirstAudio; }
131  int GetFirstDataTrack() { return m_nFirstData; }
132  int GetDataTrackCount() { return m_nNumData; }
133  int GetAudioTrackCount() { return m_nNumAudio; }
134  uint32_t GetCddbDiscId() { return m_ulCddbDiscId; }
135  int GetDiscLength() { return m_nLength; }
136  std::string GetDiscLabel(){ return m_strDiscLabel; }
137 
138  // CD-ROM with ISO 9660 filesystem
139  bool IsIso9660( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_9660); }
140  // CD-ROM with joliet extension
141  bool IsJoliet( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & JOLIET) ? false : true; }
142  // Joliet extension level
143  int GetJolietLevel( int nTrack ) { return m_ti[nTrack - 1].nJolietLevel; }
144  // ISO filesystem size
145  int GetIsoSize( int nTrack ) { return m_ti[nTrack - 1].isofs_size; }
146  // CD-ROM with rockridge extensions
147  bool IsRockridge( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & ROCKRIDGE) ? false : true; }
148 
149  // CD-ROM with CD-RTOS and ISO 9660 filesystem
150  bool IsIso9660Interactive( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_9660_INTERACTIVE); }
151 
152  // CD-ROM with High Sierra filesystem
153  bool IsHighSierra( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_HIGH_SIERRA); }
154 
155  // CD-Interactive, with audiotracks > 0 CD-Interactive/Ready
156  bool IsCDInteractive( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_INTERACTIVE); }
157 
158  // CD-ROM with Macintosh HFS
159  bool IsHFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_HFS); }
160 
161  // CD-ROM with both Macintosh HFS and ISO 9660 filesystem
162  bool IsISOHFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_HFS); }
163 
164  // CD-ROM with both UDF and ISO 9660 filesystem
165  bool IsISOUDF( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_ISO_UDF); }
166 
167  // CD-ROM with Unix UFS
168  bool IsUFS( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_UFS); }
169 
170  // CD-ROM with Linux second extended filesystem
171  bool IsEXT2( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_EXT2); }
172 
173  // CD-ROM with Panasonic 3DO filesystem
174  bool Is3DO( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_3DO); }
175 
176  // Mixed Mode CD-ROM
177  bool IsMixedMode( int nTrack ) { return (m_nFirstData == 1 && m_nNumAudio > 0); }
178 
179  // CD-ROM with XA sectors
180  bool IsXA( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & XA) ? false : true; }
181 
182  // Multisession CD-ROM
183  bool IsMultiSession( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & MULTISESSION) ? false : true; }
184  // Gets multisession offset
185  int GetMultisessionOffset( int nTrack ) { return m_ti[nTrack - 1].ms_offset; }
186 
187  // Hidden Track on Audio CD
188  bool IsHiddenTrack( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & HIDDEN_TRACK) ? false : true; }
189 
190  // Photo CD, with audiotracks > 0 Portfolio Photo CD
191  bool IsPhotoCd( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & PHOTO_CD) ? false : true; }
192 
193  // CD-ROM with Commodore CDTV
194  bool IsCdTv( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & CDTV) ? false : true; }
195 
196  // CD-Plus/Extra
197  bool IsCDExtra( int nTrack ) { return (m_nFirstData > 1); }
198 
199  // Bootable CD
200  bool IsBootable( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & BOOTABLE) ? false : true; }
201 
202  // Video CD
203  bool IsVideoCd( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & VIDEOCDI && m_nNumAudio == 0); }
204 
205  // Chaoji Video CD
206  bool IsChaojiVideoCD( int nTrack ) { return (m_ti[nTrack - 1].nfsInfo & CVD) ? false : true; }
207 
208  // Audio Track
209  bool IsAudio( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_NO_DATA); }
210 
211  // UDF filesystem
212  bool IsUDF( int nTrack ) { return ((m_ti[nTrack - 1].nfsInfo & FS_MASK) == FS_UDF); }
213 
214  // Has the cd a filesystem that is readable by the xbox
215  bool IsValidFs() { return (IsISOHFS(1) || IsIso9660(1) || IsIso9660Interactive(1) || IsISOUDF(1) || IsUDF(1) || IsAudio(1)); }
216 
217  void SetFirstTrack( int nTrack ) { m_nFirstTrack = nTrack; }
218  void SetTrackCount( int nCount ) { m_nNumTrack = nCount; }
219  void SetFirstAudioTrack( int nTrack ) { m_nFirstAudio = nTrack; }
220  void SetFirstDataTrack( int nTrack ) { m_nFirstData = nTrack; }
221  void SetDataTrackCount( int nCount ) { m_nNumData = nCount; }
222  void SetAudioTrackCount( int nCount ) { m_nNumAudio = nCount; }
223  void SetTrackInformation(int nTrack, trackinfo nInfo)
224  {
225  if (nTrack > 0 && nTrack <= 99)
226  m_ti[nTrack - 1] = std::move(nInfo);
227  }
228  void SetDiscCDTextInformation(xbmc_cdtext_t cdtext) { m_cdtext = std::move(cdtext); }
229 
230  void SetCddbDiscId( uint32_t ulCddbDiscId ) { m_ulCddbDiscId = ulCddbDiscId; }
231  void SetDiscLength( int nLength ) { m_nLength = nLength; }
232  bool HasCDDBInfo() { return m_bHasCDDBInfo; }
233  void SetNoCDDBInfo() { m_bHasCDDBInfo = false; }
234 
235  void SetDiscLabel(const std::string& strDiscLabel){ m_strDiscLabel = strDiscLabel; }
236 
237 private:
238  int m_nFirstData; /* # of first data track */
239  int m_nNumData; /* # of data tracks */
240  int m_nFirstAudio; /* # of first audio track */
241  int m_nNumAudio; /* # of audio tracks */
242  int m_nNumTrack;
243  int m_nFirstTrack;
244  trackinfo m_ti[100];
245  uint32_t m_ulCddbDiscId;
246  int m_nLength; // Disclength can be used for cddb query, also see trackinfo.nFrames
247  bool m_bHasCDDBInfo;
248  std::string m_strDiscLabel;
249  xbmc_cdtext_t m_cdtext; // CD-Text for this disc
250 };
251 
252 class CLibcdio : public CCriticalSection
253 {
254 private:
255  CLibcdio();
256 public:
257  virtual ~CLibcdio();
258 
259  static void ReleaseInstance();
260  static std::shared_ptr<CLibcdio> GetInstance();
261 
262  // libcdio is not thread safe so these are wrappers to libcdio routines
263  CdIo_t* cdio_open(const char *psz_source, driver_id_t driver_id);
264  CdIo_t* cdio_open_win32(const char *psz_source);
265  void cdio_destroy(CdIo_t *p_cdio);
266  discmode_t cdio_get_discmode(CdIo_t *p_cdio);
267  CdioTrayStatus mmc_get_tray_status(const CdIo_t* p_cdio);
268  driver_return_code_t cdio_eject_media(CdIo_t** p_cdio);
269  track_t cdio_get_last_track_num(const CdIo_t *p_cdio);
270  lsn_t cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track);
271  lsn_t cdio_get_track_last_lsn(const CdIo_t *p_cdio, track_t i_track);
272  driver_return_code_t cdio_read_audio_sectors(const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, uint32_t i_blocks);
273  driver_return_code_t cdio_close_tray(const char* psz_source, driver_id_t* driver_id);
274  const char* cdio_driver_errmsg(driver_return_code_t drc);
275 
276  char* GetDeviceFileName();
277 
278 private:
279  char* s_defaultDevice;
280  CCriticalSection m_critSection;
281  static std::shared_ptr<CLibcdio> m_pInstance;
282 };
283 
285 {
286 public:
287  CCdIoSupport();
288  virtual ~CCdIoSupport();
289 
290  bool EjectTray();
291  bool CloseTray();
292 
293  HANDLE OpenCDROM();
294  HANDLE OpenIMAGE( std::string& strFilename );
295  int ReadSector(HANDLE hDevice, DWORD dwSector, char* lpczBuffer);
296  int ReadSectorMode2(HANDLE hDevice, DWORD dwSector, char* lpczBuffer);
297  int ReadSectorCDDA(HANDLE hDevice, DWORD dwSector, char* lpczBuffer);
298  void CloseCDROM(HANDLE hDevice);
299 
300  void PrintAnalysis(int fs, int num_audio);
301 
302  CCdInfo* GetCdInfo(char* cDeviceFileName=NULL);
303  void GetCdTextInfo(xbmc_cdtext_t &xcdt, int trackNum);
304 
305 protected:
306  int ReadBlock(int superblock, uint32_t offset, uint8_t bufnum, track_t track_num);
307  bool IsIt(int num);
308  int IsHFS(void);
309  int Is3DO(void);
310  int IsJoliet(void);
311  int IsUDF(void);
312  int GetSize(void);
313  int GetJolietLevel( void );
314  int GuessFilesystem(int start_session, track_t track_num);
315 
316  uint32_t CddbDiscId();
317  int CddbDecDigitSum(int n);
318  unsigned int MsfSeconds(msf_t *msf);
319 
320 private:
321  char buffer[7][CDIO_CD_FRAMESIZE_RAW]; /* for CD-Data */
322  static signature_t sigs[17];
323  int i = 0, j = 0; /* index */
324  int m_nStartTrack; /* first sector of track */
325  int m_nIsofsSize; /* size of session */
326  int m_nJolietLevel;
327  int m_nMsOffset; /* multisession offset found by track-walking */
328  int m_nDataStart; /* start of data area */
329  int m_nFs;
330  int m_nUDFVerMinor;
331  int m_nUDFVerMajor;
332 
333  CdIo* cdio;
334  track_t m_nNumTracks = CDIO_INVALID_TRACK;
335  track_t m_nFirstTrackNum = CDIO_INVALID_TRACK;
336 
337  std::string m_strDiscLabel;
338 
339  int m_nFirstData; /* # of first data track */
340  int m_nNumData; /* # of data tracks */
341  int m_nFirstAudio; /* # of first audio track */
342  int m_nNumAudio; /* # of audio tracks */
343 
344  std::shared_ptr<CLibcdio> m_cdio;
345 };
346 
347 }
Definition: XHandle.h:21
Definition: cdioSupport.h:76
Definition: cdioSupport.h:114
Definition: cdioSupport.h:252
Definition: Application.h:57
Definition: Filesystem.h:18
Definition: cdioSupport.h:284
Definition: cdioSupport.h:87