CCdInfo* CCdIoSupport::GetCdInfo(char* cDeviceFileName) { CSingleLock lock(*m_cdio); char* source_name; if(cDeviceFileName == NULL) source_name = m_cdio->GetDeviceFileName(); else source_name = cDeviceFileName; cdio = ::cdio_open(source_name, DRIVER_UNKNOWN); if (cdio == NULL) { CLog::Log(LOGERROR, "%s: Error in automatically selecting driver with input", __FUNCTION__); return NULL; } bool bIsCDRom = true; m_nFirstTrackNum = ::cdio_get_first_track_num(cdio); if (m_nFirstTrackNum == CDIO_INVALID_TRACK) { #if !defined(TARGET_DARWIN) ::cdio_destroy(cdio); return NULL; #else m_nFirstTrackNum = 1; bIsCDRom = false; #endif } m_nNumTracks = ::cdio_get_num_tracks(cdio); if (m_nNumTracks == CDIO_INVALID_TRACK) { #if !defined(TARGET_DARWIN) ::cdio_destroy(cdio); return NULL; #else m_nNumTracks = 1; bIsCDRom = false; #endif } CCdInfo* info = new CCdInfo; info->SetFirstTrack( m_nFirstTrackNum ); info->SetTrackCount( m_nNumTracks ); for (i = m_nFirstTrackNum; i <= CDIO_CDROM_LEADOUT_TRACK; i++) { msf_t msf; if (bIsCDRom && !::cdio_get_track_msf(cdio, i, &msf)) { trackinfo ti; ti.nfsInfo = FS_UNKNOWN; ti.ms_offset = 0; ti.isofs_size = 0; ti.nJolietLevel = 0; ti.nFrames = 0; ti.nMins = 0; ti.nSecs = 0; info->SetTrackInformation( i, ti ); CLog::Log(LOGDEBUG, "cdio_track_msf for track %i failed, I give up.", i); delete info; ::cdio_destroy(cdio); return NULL; } trackinfo ti; if (bIsCDRom && TRACK_FORMAT_AUDIO == ::cdio_get_track_format(cdio, i)) { m_nNumAudio++; ti.nfsInfo = FS_NO_DATA; m_nFs = FS_NO_DATA; int temp1 = ::cdio_get_track_lba(cdio, i) - CDIO_PREGAP_SECTORS; int temp2 = ::cdio_get_track_lba(cdio, i + 1) - CDIO_PREGAP_SECTORS; // The length is the address of the second track minus the address of the first track temp2 -= temp1; // temp2 now has length of track1 in frames ti.nMins = temp2 / (60 * 75); // calculate the number of minutes temp2 %= 60 * 75; // calculate the left-over frames ti.nSecs = temp2 / 75; // calculate the number of seconds if ( -1 == m_nFirstAudio) m_nFirstAudio = i; // Make sure that we have the Disc related info available if (i == 1) { xbmc_cdtext_t xcdt; GetCdTextInfo(xcdt, 0); info->SetDiscCDTextInformation( xcdt ); } // Get this tracks info GetCdTextInfo(ti.cdtext, i); } else { m_nNumData++; if ( -1 == m_nFirstData) m_nFirstData = i; } ti.nfsInfo = FS_NO_DATA; ti.ms_offset = 0; ti.isofs_size = 0; ti.nJolietLevel = 0; ti.nFrames = ::cdio_get_track_lba(cdio, i); ti.nMins = 0; ti.nSecs = 0; info->SetTrackInformation( i, ti ); /* skip to leadout? */ if (i == m_nNumTracks) i = CDIO_CDROM_LEADOUT_TRACK; } info->SetCddbDiscId( CddbDiscId() ); info->SetDiscLength( ::cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC ); info->SetAudioTrackCount( m_nNumAudio ); info->SetDataTrackCount( m_nNumData ); info->SetFirstAudioTrack( m_nFirstAudio ); info->SetFirstDataTrack( m_nFirstData ); CLog::Log(LOGINFO, "CD Analysis Report"); CLog::Log(LOGINFO, STRONG); /* Try to find out what sort of CD we have */ if (0 == m_nNumData) { /* no data track, may be a "real" audio CD or hidden track CD */ msf_t msf; ::cdio_get_track_msf(cdio, 1, &msf); m_nStartTrack = ::cdio_msf_to_lsn(&msf); /* CD-I/Ready says start_track <= 30*75 then CDDA */ if (m_nStartTrack > 100 /* 100 is just a guess */) { m_nFs = GuessFilesystem(0, 1); if ((m_nFs & FS_MASK) != FS_UNKNOWN) m_nFs |= HIDDEN_TRACK; else { m_nFs &= ~FS_MASK; /* del filesystem info */ CLog::Log(LOGDEBUG, "Oops: %i unused sectors at start, but hidden track check failed.", m_nStartTrack); } } PrintAnalysis(m_nFs, m_nNumAudio); } else { /* We have data track(s) */ for (j = 2, i = m_nFirstData; i <= m_nNumTracks; i++) { msf_t msf; track_format_t track_format = ::cdio_get_track_format(cdio, i); ::cdio_get_track_msf(cdio, i, &msf); switch ( track_format ) { case TRACK_FORMAT_AUDIO: { trackinfo ti; ti.nfsInfo = FS_NO_DATA; m_nFs = FS_NO_DATA; ti.ms_offset = 0; ti.isofs_size = 0; ti.nJolietLevel = 0; ti.nFrames = ::cdio_get_track_lba(cdio, i); ti.nMins = 0; ti.nSecs = 0; info->SetTrackInformation( i + 1, ti ); } case TRACK_FORMAT_ERROR: break; case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: case TRACK_FORMAT_DATA: case TRACK_FORMAT_PSX: break; } m_nStartTrack = (i == 1) ? 0 : ::cdio_msf_to_lsn(&msf); /* Save the start of the data area */ if (i == m_nFirstData) m_nDataStart = m_nStartTrack; /* Skip tracks which belong to the current walked session */ if (m_nStartTrack < m_nDataStart + m_nIsofsSize) continue; m_nFs = GuessFilesystem(m_nStartTrack, i); trackinfo ti; ti.nfsInfo = m_nFs; ti.ms_offset = m_nMsOffset; ti.isofs_size = m_nIsofsSize; ti.nJolietLevel = m_nJolietLevel; ti.nFrames = ::cdio_get_track_lba(cdio, i); ti.nMins = 0; ti.nSecs = 0; info->SetDiscLabel(m_strDiscLabel); if (i > 1) { /* Track is beyond last session -> new session found */ m_nMsOffset = m_nStartTrack; CLog::Log(LOGINFO, "Session #%d starts at track %2i, LSN: %6i," " ISO 9660 blocks: %6i", j++, i, m_nStartTrack, m_nIsofsSize); CLog::Log(LOGINFO, "ISO 9660: %i blocks, label %s", m_nIsofsSize, m_strDiscLabel.c_str()); m_nFs |= MULTISESSION; ti.nfsInfo = m_nFs; } else { PrintAnalysis(m_nFs, m_nNumAudio); } info->SetTrackInformation( i, ti ); } } ::cdio_destroy( cdio ); return info; }
CCdInfo* CCdIoSupport::GetCdInfo(char* cDeviceFileName) { CSingleLock lock(*m_cdio); char* source_name; if(cDeviceFileName == NULL) source_name = m_cdio->GetDeviceFileName(); else source_name = cDeviceFileName; cdio = ::cdio_open(source_name, DRIVER_UNKNOWN); if (cdio == NULL) { char buf[1024]; sprintf(buf, "%s: Error in automatically selecting driver with input\n", __FUNCTION__); OutputDebugString( buf ); return NULL; } bool bIsCDRom = true; m_nFirstTrackNum = ::cdio_get_first_track_num(cdio); if (m_nFirstTrackNum == CDIO_INVALID_TRACK) { #ifndef __APPLE__ ::cdio_destroy(cdio); return NULL; #else m_nFirstTrackNum = 1; bIsCDRom = false; #endif } m_nNumTracks = ::cdio_get_num_tracks(cdio); if (m_nNumTracks == CDIO_INVALID_TRACK) { #ifndef __APPLE__ ::cdio_destroy(cdio); return NULL; #else m_nNumTracks = 1; bIsCDRom = false; #endif } CCdInfo* info = new CCdInfo; info->SetFirstTrack( m_nFirstTrackNum ); info->SetTrackCount( m_nNumTracks ); for (i = m_nFirstTrackNum; i <= CDIO_CDROM_LEADOUT_TRACK; i++) { msf_t msf; if (bIsCDRom && !::cdio_get_track_msf(cdio, i, &msf)) { char buf[1024]; trackinfo ti; ti.nfsInfo = FS_UNKNOWN; ti.ms_offset = 0; ti.isofs_size = 0; ti.nJolietLevel = 0; ti.nFrames = 0; cdtext_init(&ti.cdtext); info->SetTrackInformation( i, ti ); sprintf( buf, "cdio_track_msf for track %i failed, I give up.\n", i); OutputDebugString( buf ); delete info; ::cdio_destroy(cdio); return NULL; } trackinfo ti_0, ti; cdtext_init(&ti_0.cdtext); cdtext_init(&ti.cdtext); if (bIsCDRom && TRACK_FORMAT_AUDIO == ::cdio_get_track_format(cdio, i)) { m_nNumAudio++; ti.nfsInfo = FS_NO_DATA; m_nFs = FS_NO_DATA; int temp1 = ::cdio_get_track_lba(cdio, i) - CDIO_PREGAP_SECTORS; int temp2 = ::cdio_get_track_lba(cdio, i + 1) - CDIO_PREGAP_SECTORS; // the length is the address of the second track minus the address of the first track temp2 -= temp1; // temp2 now has length of track1 in frames ti.nMins = temp2 / (60 * 75); // calculate the number of minutes temp2 %= 60 * 75; // calculate the left-over frames ti.nSecs = temp2 / 75; // calculate the number of seconds if ( -1 == m_nFirstAudio) m_nFirstAudio = i; // Make sure that we have the Disc related info available if (i == 1) { GetCdTextInfo(&ti_0, 0); info->SetDiscCDTextInformation( ti_0.cdtext ); } // Get this tracks info GetCdTextInfo(&ti, i); } else { m_nNumData++; if ( -1 == m_nFirstData) m_nFirstData = i; } ti.ms_offset = 0; ti.isofs_size = 0; ti.nJolietLevel = 0; ti.nFrames = ::cdio_get_track_lba(cdio, i); info->SetTrackInformation( i, ti ); /* skip to leadout? */ if (i == m_nNumTracks) i = CDIO_CDROM_LEADOUT_TRACK; } info->SetCddbDiscId( CddbDiscId() ); info->SetDiscLength( ::cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC ); info->SetAudioTrackCount( m_nNumAudio ); info->SetDataTrackCount( m_nNumData ); info->SetFirstAudioTrack( m_nFirstAudio ); info->SetFirstDataTrack( m_nFirstData ); char buf[1024]; CLog::Log(LOGINFO, "CD Analysis Report"); CLog::Log(LOGINFO, STRONG); /* try to find out what sort of CD we have */ if (0 == m_nNumData) { /* no data track, may be a "real" audio CD or hidden track CD */ msf_t msf; ::cdio_get_track_msf(cdio, 1, &msf); m_nStartTrack = ::cdio_msf_to_lsn(&msf); /* CD-I/Ready says start_track <= 30*75 then CDDA */ if (m_nStartTrack > 100 /* 100 is just a guess */) { m_nFs = GuessFilesystem(0, 1); if ((m_nFs & FS_MASK) != FS_UNKNOWN) m_nFs |= HIDDEN_TRACK; else { m_nFs &= ~FS_MASK; /* del filesystem info */ sprintf(buf, "Oops: %i unused sectors at start, " "but hidden track check failed.\n", m_nStartTrack); OutputDebugString( buf ); } } PrintAnalysis(m_nFs, m_nNumAudio); } else { /* we have data track(s) */ for (j = 2, i = m_nFirstData; i <= m_nNumTracks; i++) { msf_t msf; track_format_t track_format = ::cdio_get_track_format(cdio, i); ::cdio_get_track_msf(cdio, i, &msf); switch ( track_format ) { case TRACK_FORMAT_AUDIO: trackinfo ti; ti.nfsInfo = FS_NO_DATA; m_nFs = FS_NO_DATA; ti.ms_offset = 0; ti.isofs_size = 0; ti.nJolietLevel = 0; ti.nFrames = ::cdio_get_track_lba(cdio, i); cdtext_init(&ti.cdtext); info->SetTrackInformation( i + 1, ti ); case TRACK_FORMAT_ERROR: break; case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: case TRACK_FORMAT_DATA: case TRACK_FORMAT_PSX: break; } m_nStartTrack = (i == 1) ? 0 : ::cdio_msf_to_lsn(&msf); /* save the start of the data area */ if (i == m_nFirstData) m_nDataStart = m_nStartTrack; /* skip tracks which belong to the current walked session */ if (m_nStartTrack < m_nDataStart + m_nIsofsSize) continue; m_nFs = GuessFilesystem(m_nStartTrack, i); trackinfo ti; cdtext_init(&ti.cdtext); ti.nfsInfo = m_nFs; // valid UDF version for xbox if ((m_nFs & FS_MASK) == FS_UDF) { // Is UDF 1.02 if (m_nUDFVerMajor > 0x1) { ti.nfsInfo = FS_UNKNOWN; m_strDiscLabel.Empty(); } else if (m_nUDFVerMinor > 0x2) { ti.nfsInfo = FS_UNKNOWN; m_strDiscLabel.Empty(); } } if ((m_nFs & FS_MASK) == FS_ISO_UDF) { // fallback to iso9660 if not udf 1.02 if (m_nUDFVerMajor > 0x1) ti.nfsInfo = FS_ISO_9660; else if (m_nUDFVerMinor > 0x2) ti.nfsInfo = FS_ISO_9660; } ti.ms_offset = m_nMsOffset; ti.isofs_size = m_nIsofsSize; ti.nJolietLevel = m_nJolietLevel; ti.nFrames = ::cdio_get_track_lba(cdio, i); info->SetDiscLabel(m_strDiscLabel); if (i > 1) { /* track is beyond last session -> new session found */ m_nMsOffset = m_nStartTrack; CLog::Log(LOGINFO, "Session #%d starts at track %2i, LSN: %6i," " ISO 9660 blocks: %6i", j++, i, m_nStartTrack, m_nIsofsSize); CLog::Log(LOGINFO, "ISO 9660: %i blocks, label '%.32s'\n", m_nIsofsSize, buffer[0] + 40); m_nFs |= MULTISESSION; ti.nfsInfo = m_nFs; } else { PrintAnalysis(m_nFs, m_nNumAudio); } info->SetTrackInformation( i, ti ); // xbox does not support multisession cd's if (!(((m_nFs & FS_MASK) == FS_ISO_9660 || (m_nFs & FS_MASK) == FS_ISO_HFS || /* (fs & FS_MASK) == FS_ISO_9660_INTERACTIVE) && (fs & XA))) */ (m_nFs & FS_MASK) == FS_ISO_9660_INTERACTIVE))) break; /* no method for non-iso9660 multisessions */ } } ::cdio_destroy( cdio ); return info; }