/*! Read a data sector @param p_cdio object to read from @param p_buf place to read data into. The caller should make sure this location can store at least ISO_BLOCKSIZE, M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE depending on the kind of sector getting read. If you don't know whether you have a Mode 1/2, Form 1/ Form 2/Formless sector best to reserve space for the maximum, M2RAW_SECTOR_SIZE. @param i_lsn sector to read @param i_blocksize size of block. Should be either ISO_BLOCKSIZE M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE. See comment above under p_buf. */ driver_return_code_t read_data_sectors_image ( void *p_user_data, void *p_buf, lsn_t i_lsn, uint16_t i_blocksize, uint32_t i_blocks ) { const _img_private_t *p_env = p_user_data; if (!p_env || !p_env->gen.cdio) return DRIVER_OP_UNINIT; { CdIo_t *p_cdio = p_env->gen.cdio; track_t i_track = cdio_get_track(p_cdio, i_lsn); track_format_t e_track_format = cdio_get_track_format(p_cdio, i_track); switch(e_track_format) { case TRACK_FORMAT_PSX: case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_ERROR: return DRIVER_OP_ERROR; case TRACK_FORMAT_DATA: return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, false, i_blocks); case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, false, i_blocks); } } return DRIVER_OP_ERROR; }
static DB_playItem_t * insert_single_track (CdIo_t* cdio, ddb_playlist_t *plt, DB_playItem_t *after, const char* file, int track_nr, int discid) { char tmp[file ? strlen (file) + 20 : 20]; if (file) snprintf (tmp, sizeof (tmp), "%s#%d.cda", file, track_nr); else snprintf (tmp, sizeof (tmp), "#%d.cda", track_nr); if (TRACK_FORMAT_AUDIO != cdio_get_track_format (cdio, track_nr)) { trace ("Not an audio track (%d)\n", track_nr); return NULL; } int sector_count = cdio_get_track_sec_count (cdio, track_nr); DB_playItem_t *it = deadbeef->pl_item_alloc_init (tmp, plugin.plugin.id); deadbeef->pl_add_meta (it, ":FILETYPE", "cdda"); deadbeef->plt_set_item_duration (plt, it, (float)sector_count / 75.0); snprintf (tmp, sizeof (tmp), "CD Track %02d", track_nr); deadbeef->pl_add_meta (it, "title", tmp); snprintf (tmp, sizeof (tmp), "%02d", track_nr); deadbeef->pl_add_meta (it, "track", tmp); deadbeef->pl_set_meta_int (it, ":CDIO_DISCID", discid); after = deadbeef->plt_insert_item (plt, after, it); return after; }
static PyObject* CDImage_track_type(cdio_CDImage* self, PyObject *args) { int tracknum; if (!PyArg_ParseTuple(args, "i", &tracknum)) return NULL; return Py_BuildValue("i", cdio_get_track_format(self->image, (track_t)tracknum)); }
static DB_playItem_t * insert_disc (ddb_playlist_t *plt, DB_playItem_t *after, const char *path, const track_t single_track, CdIo_t* cdio) { struct cddb_thread_params *p = calloc(1, sizeof(struct cddb_thread_params)); if (!p) { return NULL; } p->disc = create_disc(cdio); if (!p->disc) { cleanup_thread_params(p); return NULL; } const track_t tracks = single_track ? 1 : cddb_disc_get_track_count(p->disc); p->items = calloc(tracks+1, sizeof(*p->items)); if (!p->items) { cleanup_thread_params(p); return NULL; } const unsigned long discid = cddb_disc_get_discid(p->disc); DB_playItem_t *inserted = NULL; const track_t first_track = single_track ? single_track : cdio_get_first_track_num(cdio); track_t item_count = 0; for (track_t i = 0; i < tracks; i++) { if (cdio_get_track_format(cdio, first_track+i) == TRACK_FORMAT_AUDIO) { trace("inserting track %d from %s\n", first_track+i, path); inserted = insert_track(plt, after, path, first_track+i, cdio, discid); p->items[item_count++] = inserted; after = inserted; } } intptr_t tid = 0; if (item_count) { const int got_cdtext = read_disc_cdtext(cdio, p->items, tracks); const int prefer_cdtext = deadbeef->conf_get_int("cdda.prefer_cdtext", DEFAULT_PREFER_CDTEXT); const int enable_cddb = deadbeef->conf_get_int("cdda.freedb.enable", DEFAULT_USE_CDDB); if (!(got_cdtext && prefer_cdtext) && enable_cddb) { trace("cdda: querying freedb...\n"); tid = deadbeef->thread_start(cddb_thread, p); if (tid) { deadbeef->thread_detach(tid); } } } if (!tid) { cleanup_thread_params(p); } return inserted; }
static PyObject* CDDA_track_type(cdio_CDDAObject* self, PyObject *args) { int tracknum; if (!PyArg_ParseTuple(args, "i", &tracknum)) return NULL; return Py_BuildValue("i", cdio_get_track_format(self->cdrom_drive->p_cdio, (track_t)tracknum)); }
/*! Read CD TOC and set CD information. */ static void read_toc(CdIo_t *p_cdio) { track_t i; i_first_track = cdio_get_first_track_num(p_cdio); i_last_track = cdio_get_last_track_num(p_cdio); i_tracks = cdio_get_num_tracks(p_cdio); i_first_audio_track = i_first_track; i_last_audio_track = i_last_track; if ( CDIO_INVALID_TRACK == i_first_track || CDIO_INVALID_TRACK == i_last_track ) { xperror("read toc header"); b_cd = false; b_record = false; } else { b_cd = true; i_data = 0; for (i = i_first_track; i <= i_last_track+1; i++) { if ( !cdio_get_track_msf(p_cdio, i, &(toc[i])) ) { xperror("read toc entry"); b_cd = false; return; } if ( TRACK_FORMAT_AUDIO != cdio_get_track_format(p_cdio, i) ) { if ((i != i_last_track+1) ) { i_data++; if (i == i_first_track) { if (i == i_last_track) i_first_audio_track = CDIO_CDROM_LEADOUT_TRACK; else i_first_audio_track++; } } } } b_record = true; read_subchannel(p_cdio); if (auto_mode && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY) play_track(1, CDIO_CDROM_LEADOUT_TRACK); } }
/*! Read the Primary Volume Descriptor for of CD. */ bool iso9660_fs_read_pvd(const CdIo_t *p_cdio, /*out*/ iso9660_pvd_t *p_pvd) { /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ bool b_mode2; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; int i_rc; switch(cdio_get_track_format(p_cdio, 1)) { case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: b_mode2 = true; break; case TRACK_FORMAT_DATA: b_mode2 = false; break; case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_PSX: case TRACK_FORMAT_ERROR: default: return false; } i_rc = b_mode2 ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR, false) : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR, false); if (i_rc) { cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR); return false; } /* The size of a PVD or SVD is smaller than a sector. So we allocated a bigger block above (buf) and now we'll copy just the part we need to save. */ cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t)); memcpy(p_pvd, buf, sizeof(iso9660_pvd_t)); return check_pvd(p_pvd); }
//public int CdDecoder::getNumCDAudioTracks() { QMutexLocker lock(&getCdioMutex()); StCdioDevice cdio(m_devicename); if (!cdio) return 0; int nAudio = 0; const track_t last = cdio_get_last_track_num(cdio); if (CDIO_INVALID_TRACK != last) { for (track_t t = cdio_get_first_track_num(cdio) ; t <= last; ++t) { if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio, t)) ++nAudio; } LOG(VB_MEDIA, LOG_DEBUG, QString("getNumCDAudioTracks = %1").arg(nAudio)); } return nAudio; }
QList< Playlist::Entry > AudioCDDemux::getTracks( const QString &_device ) { QList< Playlist::Entry > tracks; Playlist::Entry entry; device = _device; cdio_close_tray( device.toLocal8Bit(), NULL ); if ( ( cdio = cdio_open( device.toLocal8Bit(), DRIVER_UNKNOWN ) ) ) { numTracks = cdio_get_num_tracks( cdio ); if ( cdio_get_discmode( cdio ) != CDIO_DISC_MODE_ERROR && numTracks > 0 && numTracks != CDIO_INVALID_TRACK ) { cddb_disc_t *cddb_disc = NULL; bool cddb_ok = useCDDB; for ( trackNo = 1 ; trackNo <= numTracks ; ++trackNo ) { chn = cdio_get_track_channels( cdio, trackNo ); if ( chn != 2 && chn != 4 ) continue; if ( useCDTEXT ) readCDText( trackNo ); isData = cdio_get_track_format( cdio, trackNo ) != TRACK_FORMAT_AUDIO; duration = CD_BLOCKSIZE / chn / ( double )srate; numSectors = cdio_get_track_last_lsn( cdio, trackNo ) - cdio_get_track_lsn( cdio, trackNo ); if ( cddb_ok && ( cddb_disc || ( Title.isEmpty() && ( cddb_ok = freedb_query( cddb_disc ) ) ) ) ) freedb_get_track_info( cddb_disc ); entry.name = title(); entry.url = AudioCDName"://" + QString::number( trackNo ) + "?device=" + device; entry.length = length(); tracks += entry; } cddb_disc_destroy( cddb_disc ); } } return tracks; }
static Cddb::Toc& GetToc(CdIo_t *cdio, Cddb::Toc& toc) { // Get lead-in const track_t firstTrack = cdio_get_first_track_num(cdio); lsn_t lsn0 = 0; msf_t msf; if (cdio_get_track_msf(cdio, firstTrack, &msf)) lsn0 = (msf.m * 60 + msf.s) * CDIO_CD_FRAMES_PER_SEC + msf.f; const track_t lastTrack = cdio_get_last_track_num(cdio); for (track_t t = firstTrack; t <= lastTrack + 1; ++t) { #if 0 // This would be better but the msf's returned are way off in libcdio 0.81 if (!cdio_get_track_msf(cdio, t, &msf)) break; #else lsn_t lsn = cdio_get_track_lsn(cdio, t); if (s_lastAudioLsn && lsn > s_lastAudioLsn) lsn = s_lastAudioLsn; lsn += lsn0; // lead-in std::div_t d = std::div(lsn, CDIO_CD_FRAMES_PER_SEC); msf.f = d.rem; d = std::div(d.quot, 60); msf.s = d.rem; msf.m = d.quot; #endif //LOG(VB_MEDIA, LOG_INFO, QString("Track %1 msf: %2:%3:%4"). // arg(t,2).arg(msf.m,2).arg(msf.s,2).arg(msf.f,2) ); toc.push_back(Cddb::Msf(msf.m, msf.s, msf.f)); if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, t)) break; } return toc; }
bool AudioCDDemux::open( const QString &_url ) { #ifdef Q_OS_WIN if ( _url.toLower().contains( QRegExp( "file://\\D:/track\\d\\d.cda" ) ) ) { QString url = _url; url.remove( "file://" ); device = url.mid( 0, url.indexOf( '/' ) ); trackNo = url.mid( url.toLower().indexOf( "track" ) + 5, 2 ).toUInt(); } else #endif { if ( _url.left( 10 ) != "AudioCD://" ) return false; QUrl url( _url.mid( 10 ) ); device = QUrlQuery( url ).queryItemValue( "device" ); trackNo = url.path().toUInt(); } if ( trackNo > 0 && trackNo < CDIO_INVALID_TRACK ) { cdio = destroyTimer.getInstance( device, discID ); if ( cdio || ( cdio = cdio_open( device.toLocal8Bit(), DRIVER_UNKNOWN ) ) ) { cdio_set_speed( cdio, 1 ); numTracks = cdio_get_num_tracks( cdio ); if ( cdio_get_discmode( cdio ) != CDIO_DISC_MODE_ERROR && numTracks > 0 && numTracks != CDIO_INVALID_TRACK ) { chn = cdio_get_track_channels( cdio, trackNo ); if ( numTracks >= trackNo && ( chn == 2 || chn == 4 ) ) { if ( useCDTEXT ) { readCDText( 0 ); readCDText( trackNo ); } isData = cdio_get_track_format( cdio, trackNo ) != TRACK_FORMAT_AUDIO; duration = CD_BLOCKSIZE / chn / ( double )srate; startSector = cdio_get_track_lsn( cdio, trackNo ); numSectors = cdio_get_track_last_lsn( cdio, trackNo ) - startSector; if ( useCDDB && Title.isEmpty() ) { cddb_disc_t *cddb_disc; if ( freedb_query( cddb_disc ) ) { if ( cdTitle.isEmpty() && cdArtist.isEmpty() ) freedb_get_disc_info( cddb_disc ); freedb_get_track_info( cddb_disc ); cddb_disc_destroy( cddb_disc ); } } StreamInfo *streamInfo = new StreamInfo; streamInfo->type = QMPLAY2_TYPE_AUDIO; streamInfo->is_default = true; streamInfo->sample_rate = srate; streamInfo->channels = chn; streams_info += streamInfo; return true; } else QMPlay2Core.log( tr( "Błąd odczytu ścieżki" ) ); } else QMPlay2Core.log( tr( "Brak płyty w napędzie" ) ); } else QMPlay2Core.log( tr( "Nieprawidłowa ścieżka do napędu CD" ) ); } else //dodawanie do listy ścieżek AudioCD { #ifndef Q_OS_WIN device = QUrl( _url ).path(); #else device = _url.mid( strlen( AudioCDName"://" ), 2 ); #endif #ifndef Q_OS_WIN if ( !QFileInfo( device ).isDir() ) #endif if ( !device.isEmpty() ) { emit QMPlay2Core.processParam( "DelPlaylistEntries", _url ); QList< Playlist::Entry > entries = getTracks( device ); if ( !entries.isEmpty() && Playlist::write( entries, "file://" + AudioCDPlaylist ) ) { emit QMPlay2Core.processParam( "open", AudioCDPlaylist ); return true; } } } return false; }
/* Try to determine what kind of CD-image and/or filesystem we have at track i_track. Return information about the CD image is returned in cdio_analysis and the return value. */ cdio_fs_anal_t cdio_guess_cd_type(const CdIo_t *p_cdio, int start_session, track_t i_track, /*out*/ cdio_iso_analysis_t *iso_analysis) { int ret = CDIO_FS_UNKNOWN; bool sector0_read_ok; if (TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i_track)) return CDIO_FS_AUDIO; if ( DRIVER_OP_SUCCESS != _cdio_read_block(p_cdio, ISO_PVD_SECTOR, start_session, 0, i_track) ) return CDIO_FS_UNKNOWN; if ( _cdio_is_it(INDEX_XISO) ) return CDIO_FS_ANAL_XISO; if ( DRIVER_OP_SUCCESS != _cdio_read_block(p_cdio, ISO_SUPERBLOCK_SECTOR, start_session, 0, i_track) ) return ret; if ( _cdio_is_it(INDEX_UDF) ) { /* Detect UDF version Test if we have a valid version of UDF the xbox can read natively */ if (_cdio_read_block(p_cdio, 35, start_session, 5, i_track) < 0) return CDIO_FS_UNKNOWN; iso_analysis->UDFVerMinor=(unsigned int)buffer[5][240]; iso_analysis->UDFVerMajor=(unsigned int)buffer[5][241]; /* Read disc label */ if (_cdio_read_block(p_cdio, 32, start_session, 5, i_track) < 0) return CDIO_FS_UDF; strncpy(iso_analysis->iso_label, buffer[5]+25, 33); iso_analysis->iso_label[32] = '\0'; return CDIO_FS_UDF; } /* We have something that smells of a filesystem. */ if (_cdio_is_it(INDEX_CD_I) && _cdio_is_it(INDEX_CD_RTOS) && !_cdio_is_it(INDEX_BRIDGE) && !_cdio_is_it(INDEX_XA)) { return (CDIO_FS_INTERACTIVE | CDIO_FS_ANAL_ISO9660_ANY); } else { /* read sector 0 ONLY, when NO greenbook CD-I !!!! */ sector0_read_ok = _cdio_read_block(p_cdio, 0, start_session, 1, i_track) == 0; if (_cdio_is_it(INDEX_HS)) ret |= CDIO_FS_HIGH_SIERRA; else if (_cdio_is_it(INDEX_ISOFS)) { if (_cdio_is_it(INDEX_CD_RTOS) && _cdio_is_it(INDEX_BRIDGE)) ret = (CDIO_FS_ISO_9660_INTERACTIVE | CDIO_FS_ANAL_ISO9660_ANY); else if (_cdio_is_hfs()) ret = CDIO_FS_ISO_HFS; else ret = (CDIO_FS_ISO_9660 | CDIO_FS_ANAL_ISO9660_ANY); iso_analysis->isofs_size = _cdio_get_iso9660_fs_sec_count(); strncpy(iso_analysis->iso_label, buffer[0]+40,33); iso_analysis->iso_label[32] = '\0'; if ( _cdio_read_block(p_cdio, UDF_ANCHOR_SECTOR, start_session, 5, i_track) < 0) return ret; /* Maybe there is an UDF anchor in IOS session so its ISO/UDF session and we prefere UDF */ if ( _cdio_is_UDF() ) { /* Detect UDF version. Test if we have a valid version of UDF the xbox can read natively */ if ( _cdio_read_block(p_cdio, 35, start_session, 5, i_track) < 0) return ret; iso_analysis->UDFVerMinor=(unsigned int)buffer[5][240]; iso_analysis->UDFVerMajor=(unsigned int)buffer[5][241]; #if 0 /* We are using ISO/UDF cd's as iso, no need to get UDF disc label */ if (_cdio_read_block(p_cdio, 32, start_session, 5, i_track) < 0) return ret; stnrcpy(iso_analysis->iso_label, buffer[5]+25, 33); iso_analysis->iso_label[32] = '\0'; #endif ret=CDIO_FS_ISO_UDF; } #if 0 if (_cdio_is_rockridge()) ret |= CDIO_FS_ANAL_ROCKRIDGE; #endif if (_cdio_read_block(p_cdio, BOOT_SECTOR, start_session, 3, i_track) < 0) return ret; if (_cdio_is_joliet()) { iso_analysis->joliet_level = _cdio_get_joliet_level(); ret |= (CDIO_FS_ANAL_JOLIET | CDIO_FS_ANAL_ISO9660_ANY); } if (_cdio_is_it(INDEX_BOOTABLE)) ret |= CDIO_FS_ANAL_BOOTABLE; if ( _cdio_is_it(INDEX_XA) && _cdio_is_it(INDEX_ISOFS) && !(sector0_read_ok && _cdio_is_it(INDEX_PHOTO_CD)) ) { if ( _cdio_read_block(p_cdio, VCD_INFO_SECTOR, start_session, 4, i_track) < 0 ) return ret; if (_cdio_is_it(INDEX_BRIDGE) && _cdio_is_it(INDEX_CD_RTOS)) { ret |= CDIO_FS_ANAL_ISO9660_ANY; if (_cdio_is_it(INDEX_VIDEO_CD)) ret |= CDIO_FS_ANAL_VIDEOCD; else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_SVCD; } else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_CVD; } } else if (_cdio_is_hfs()) ret |= CDIO_FS_HFS; else if (sector0_read_ok && _cdio_is_it(INDEX_EXT2)) ret |= (CDIO_FS_EXT2 | CDIO_FS_ANAL_ISO9660_ANY); else if (_cdio_is_3do()) ret |= CDIO_FS_3DO; else { if ( _cdio_read_block(p_cdio, UFS_SUPERBLOCK_SECTOR, start_session, 2, i_track) < 0 ) return ret; if (sector0_read_ok && _cdio_is_it(INDEX_UFS)) ret |= CDIO_FS_UFS; else ret |= CDIO_FS_UNKNOWN; } } /* other checks */ if (_cdio_is_it(INDEX_XA)) ret |= (CDIO_FS_ANAL_XA | CDIO_FS_ANAL_ISO9660_ANY); if (_cdio_is_it(INDEX_PHOTO_CD)) ret |= (CDIO_FS_ANAL_PHOTO_CD | CDIO_FS_ANAL_ISO9660_ANY); if (_cdio_is_it(INDEX_CDTV)) ret |= CDIO_FS_ANAL_CDTV; return ret; }
/*! Here we fix up a couple of things that will never happen. yeah, right. The multisession stuff is from Hannu code; it assumes it knows the leadout/leadin size. [I think Hannu refers to Hannu Savolainen from GNU/Linux Kernel code.] @return -1 if we can't get multisession info, 0 if there is one session only or the last session LBA is the same as the first audio track and 1 if the multi-session lba is higher than first audio track */ int FixupTOC(cdrom_drive_t *d, track_t i_tracks) { int j; /* First off, make sure the 'starting sector' is >=0 */ for( j=0; j<i_tracks; j++){ if (d->disc_toc[j].dwStartSector<0 ) { cdmessage(d,"\n\tTOC entry claims a negative start offset: massaging" ".\n"); d->disc_toc[j].dwStartSector=0; } if( j<i_tracks-1 && d->disc_toc[j].dwStartSector> d->disc_toc[j+1].dwStartSector ) { cdmessage(d,"\n\tTOC entry claims an overly large start offset: massaging" ".\n"); d->disc_toc[j].dwStartSector=0; } } /* Make sure the listed 'starting sectors' are actually increasing. Flag things that are blatant/stupid/wrong */ { lsn_t last=d->disc_toc[0].dwStartSector; for ( j=1; j<i_tracks; j++){ if ( d->disc_toc[j].dwStartSector<last ) { cdmessage(d,"\n\tTOC entries claim non-increasing offsets: massaging" ".\n"); d->disc_toc[j].dwStartSector=last; } last=d->disc_toc[j].dwStartSector; } } d->audio_last_sector = CDIO_INVALID_LSN; { lsn_t last_ses_lsn; if (cdio_get_last_session (d->p_cdio, &last_ses_lsn) < 0) return -1; /* A Red Book Disc must have only one session, otherwise this is a * CD Extra */ if (last_ses_lsn > d->disc_toc[0].dwStartSector) { /* CD Extra discs have two session, the first one ending after * the last audio track * Thus the need to fix the length of the the audio data portion to * not cross the lead-out of this session */ for (j = i_tracks-1; j > 1; j--) { if (cdio_get_track_format(d->p_cdio, j+1) != TRACK_FORMAT_AUDIO && cdio_get_track_format(d->p_cdio, j) == TRACK_FORMAT_AUDIO) { /* First session lead-out is 1:30 * Lead-ins are 1:00 * Every session's first track have a 0:02 pregap * * That makes a control data section of (90+60+2)*75 sectors in the * last audio track */ const int gap = ((90+60+2) * CDIO_CD_FRAMES_PER_SEC); if ((last_ses_lsn - gap >= d->disc_toc[j-1].dwStartSector) && (last_ses_lsn - gap < d->disc_toc[j].dwStartSector)) { d->audio_last_sector = last_ses_lsn - gap - 1; break; } } } return 1; } } return 0; }
/* Try to determine what kind of CD-image and/or filesystem we have at track track_num. Return information about the CD image is returned in cdio_analysis and the return value. */ cdio_fs_anal_t cdio_guess_cd_type(const CdIo *cdio, int start_session, track_t track_num, /*out*/ cdio_analysis_t *cdio_analysis) { int ret = 0; bool sector0_read_ok; if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio, track_num)) return CDIO_FS_AUDIO; if ( _cdio_read_block(cdio, ISO_PVD_SECTOR, start_session, 0, track_num) < 0 ) return CDIO_FS_UNKNOWN; /* We have something that smells of a filesystem. */ if (_cdio_is_it(INDEX_CD_I) && _cdio_is_it(INDEX_CD_RTOS) && !_cdio_is_it(INDEX_BRIDGE) && !_cdio_is_it(INDEX_XA)) { return CDIO_FS_INTERACTIVE; } else { /* read sector 0 ONLY, when NO greenbook CD-I !!!! */ sector0_read_ok = _cdio_read_block(cdio, 0, start_session, 1, track_num) == 0; if (_cdio_is_it(INDEX_HS)) ret |= CDIO_FS_HIGH_SIERRA; else if (_cdio_is_it(INDEX_ISOFS)) { if (_cdio_is_it(INDEX_CD_RTOS) && _cdio_is_it(INDEX_BRIDGE)) ret = CDIO_FS_ISO_9660_INTERACTIVE; else if (_cdio_is_hfs()) ret = CDIO_FS_ISO_HFS; else ret = CDIO_FS_ISO_9660; cdio_analysis->isofs_size = _cdio_get_iso9660_fs_sec_count(); sprintf(cdio_analysis->iso_label, buffer[0]+40); #if 0 if (_cdio_is_rockridge()) ret |= CDIO_FS_ANAL_ROCKRIDGE; #endif if (_cdio_read_block(cdio, BOOT_SECTOR, start_session, 3, track_num) < 0) return ret; if (_cdio_is_joliet()) { cdio_analysis->joliet_level = _cdio_get_joliet_level(); ret |= CDIO_FS_ANAL_JOLIET; } if (_cdio_is_it(INDEX_BOOTABLE)) ret |= CDIO_FS_ANAL_BOOTABLE; if ( _cdio_is_it(INDEX_XA) && _cdio_is_it(INDEX_ISOFS) && !(sector0_read_ok && _cdio_is_it(INDEX_PHOTO_CD)) ) { if ( _cdio_read_block(cdio, VCD_INFO_SECTOR, start_session, 4, track_num) < 0 ) return ret; if (_cdio_is_it(INDEX_BRIDGE) && _cdio_is_it(INDEX_CD_RTOS)) { if (_cdio_is_it(INDEX_VIDEO_CD)) ret |= CDIO_FS_ANAL_VIDEOCD; else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_SVCD; } else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_CVD; } } else if (_cdio_is_hfs()) ret |= CDIO_FS_HFS; else if (sector0_read_ok && _cdio_is_it(INDEX_EXT2)) ret |= CDIO_FS_EXT2; else if (_cdio_is_3do()) ret |= CDIO_FS_3DO; else { if ( _cdio_read_block(cdio, UFS_SUPERBLOCK_SECTOR, start_session, 2, track_num) < 0 ) return ret; if (sector0_read_ok && _cdio_is_it(INDEX_UFS)) ret |= CDIO_FS_UFS; else ret |= CDIO_FS_UNKNOWN; } } /* other checks */ if (_cdio_is_it(INDEX_XA)) ret |= CDIO_FS_ANAL_XA; if (_cdio_is_it(INDEX_PHOTO_CD)) ret |= CDIO_FS_ANAL_PHOTO_CD; if (_cdio_is_it(INDEX_CDTV)) ret |= CDIO_FS_ANAL_CDTV; return ret; }
/** Read CD TOC and set CD information. */ static void read_toc(CdIo_t *p_cdio) { track_t i; action("read toc..."); memset(cd_info, 0, sizeof(cd_info)); title[0] = artist[0] = genre[0] = category[0] = year[0] = '\0'; i_first_track = cdio_get_first_track_num(p_cdio); i_last_track = cdio_get_last_track_num(p_cdio); i_tracks = cdio_get_num_tracks(p_cdio); i_first_audio_track = i_first_track; i_last_audio_track = i_last_track; cdio_audio_get_volume(p_cdio, &audio_volume); for (i_vol_port=0; i_vol_port<4; i_vol_port++) { if (audio_volume.level[i_vol_port] > 0) break; } if ( CDIO_INVALID_TRACK == i_first_track || CDIO_INVALID_TRACK == i_last_track ) { xperror("read toc header"); b_cd = false; b_record = false; i_last_display_track = CDIO_INVALID_TRACK; } else { b_cd = true; i_data = 0; get_disc_info(p_cdio); for (i = i_first_track; i <= i_last_track+1; i++) { int s; if ( !cdio_get_track_msf(p_cdio, i, &(toc[i])) ) { xperror("read toc entry"); b_cd = false; return; } if ( TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i) ) { if (i != i_first_track) { s = cdio_audio_get_msf_seconds(&toc[i]) - cdio_audio_get_msf_seconds(&toc[i-1]); snprintf(cd_info[i-1].length, sizeof(cd_info[0].length), "%02d:%02d", s / CDIO_CD_SECS_PER_MIN, s % CDIO_CD_SECS_PER_MIN); } } else { if ((i != i_last_track+1) ) { i_data++; if (i == i_first_track) { if (i == i_last_track) i_first_audio_track = CDIO_CDROM_LEADOUT_TRACK; else i_first_audio_track++; } } } get_track_info(i); } b_record = true; read_subchannel(p_cdio); if (auto_mode && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY) play_track(1, CDIO_CDROM_LEADOUT_TRACK); } action(""); if (!b_all_tracks) display_cdinfo(p_cdio, i_tracks, i_first_track); }
static int cda_init (DB_fileinfo_t *_info, DB_playItem_t *it) { deadbeef->pl_lock(); const char *uri = deadbeef->pl_find_meta(it, ":URI"); const char *nr = uri ? strchr(uri, '#') : NULL; if (!nr || nr == uri) { deadbeef->pl_unlock(); trace ("cdda: bad name: %s\n", uri); return -1; } trace ("cdda: init %s\n", uri); const int track_nr = atoi(nr+1); const size_t device_length = nr - uri; char device[device_length+1]; strncpy(device, uri, device_length); device[device_length] = '\0'; deadbeef->pl_unlock(); cdda_info_t *info = (cdda_info_t *)_info; info->cdio = cdio_open(device, DRIVER_UNKNOWN); if (!info->cdio) { trace ("cdda: Could not open CD device\n"); return -1; } const int need_bitrate = info->hints & DDB_DECODER_HINT_NEED_BITRATE; const int drive_speed = deadbeef->conf_get_int("cdda.drive_speed", 2); cdio_set_speed(info->cdio, need_bitrate && drive_speed < 5 ? 1<<drive_speed : -1); cddb_disc_t *disc = create_disc(info->cdio); if (!disc) { return -1; } const unsigned long discid = cddb_disc_get_discid(disc); cddb_disc_destroy(disc); deadbeef->pl_lock(); const char *discid_hex = deadbeef->pl_find_meta(it, CDDB_DISCID_TAG); const unsigned long trk_discid = discid_hex ? strtoul(discid_hex, NULL, 16) : 0; deadbeef->pl_unlock(); if (trk_discid != discid) { trace ("cdda: the track belongs to another disc (%x vs %x), skipped\n", trk_discid, discid); return -1; } if (cdio_get_track_format(info->cdio, track_nr) != TRACK_FORMAT_AUDIO) { trace ("cdda: Not an audio track (%d)\n", track_nr); return -1; } info->first_sector = cdio_get_track_lsn(info->cdio, track_nr); info->current_sector = info->first_sector; info->last_sector = info->first_sector + cdio_get_track_sec_count(info->cdio, track_nr) - 1; trace("cdio nchannels (should always be 2 for an audio track): %d\n", cdio_get_track_channels (info->cdio, track_nr)); if (info->first_sector == CDIO_INVALID_LSN || info->last_sector <= info->first_sector) { trace ("cdda: invalid track\n"); return -1; } #if USE_PARANOIA if (cdio_get_driver_id(info->cdio) != DRIVER_NRG) { info->cdrom = cdda_identify(device, CDDA_MESSAGE_FORGETIT, NULL); if (info->cdrom) { cdda_open(info->cdrom); info->paranoia = paranoia_init(info->cdrom); } if (!info->paranoia) { trace ("cdda: cannot re-open %s for paranoia\n", device); return -1; } const int no_paranoia = need_bitrate || !deadbeef->conf_get_int("cdda.paranoia", 0); if (no_paranoia) { paranoia_cachemodel_size(info->paranoia, 100); } paranoia_modeset(info->paranoia, no_paranoia ? PARANOIA_MODE_DISABLE : PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP); paranoia_seek(info->paranoia, info->first_sector, SEEK_SET); } #endif return 0; }
/*! Read the Super block of an ISO 9660 image. This is the Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume Descriptor if (Joliet) extensions are acceptable. */ bool iso9660_fs_read_superblock (CdIo_t *p_cdio, iso_extension_mask_t iso_extension_mask) { if (!p_cdio) return false; { generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; iso9660_pvd_t *p_pvd = &(p_env->pvd); iso9660_svd_t *p_svd = &(p_env->svd); char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; bool b_mode2; int i_rc; /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ switch(cdio_get_track_format(p_cdio, 1)) { case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: b_mode2 = true; break; case TRACK_FORMAT_DATA: b_mode2 = false; break; case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_PSX: case TRACK_FORMAT_ERROR: default: return false; } if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) ) return false; p_env->i_joliet_level = 0; i_rc = (b_mode2) ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false) : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false); if (0 == i_rc) { /* The size of a PVD or SVD is smaller than a sector. So we allocated a bigger block above (buf) and now we'll copy just the part we need to save. */ cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t)); memcpy(p_svd, buf, sizeof(iso9660_svd_t)); if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) { if (p_svd->escape_sequences[0] == 0x25 && p_svd->escape_sequences[1] == 0x2f) { switch (p_svd->escape_sequences[2]) { case 0x40: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) p_env->i_joliet_level = 1; break; case 0x43: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) p_env->i_joliet_level = 2; break; case 0x45: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) p_env->i_joliet_level = 3; break; default: cdio_info("Supplementary Volume Descriptor found, but not Joliet"); } if (p_env->i_joliet_level > 0) { cdio_info("Found Extension: Joliet Level %d", p_env->i_joliet_level); } } } } } return true; }
//virtual Metadata *CdDecoder::getMetadata() { QString artist, album, compilation_artist, title, genre; int year = 0; unsigned long length = 0; track_t tracknum = 0; if (-1 == m_settracknum) tracknum = getFilename().toUInt(); else { tracknum = m_settracknum; setFilename(QString("%1" CDEXT).arg(tracknum)); } QMutexLocker lock(&getCdioMutex()); StCdioDevice cdio(m_devicename); if (!cdio) return NULL; const track_t lastTrack = cdio_get_last_track_num(cdio); if (CDIO_INVALID_TRACK == lastTrack) return NULL; if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, tracknum)) return NULL; // Assume disc changed if max LSN different bool isDiscChanged = false; static lsn_t s_totalSectors; lsn_t totalSectors = cdio_get_track_lsn(cdio, CDIO_CDROM_LEADOUT_TRACK); if (s_totalSectors != totalSectors) { s_totalSectors = totalSectors; isDiscChanged = true; } // NB cdio_get_track_last_lsn is unreliable for the last audio track // of discs with data tracks beyond lsn_t end = cdio_get_track_last_lsn(cdio, tracknum); if (isDiscChanged) { const track_t audioTracks = getNumCDAudioTracks(); s_lastAudioLsn = cdio_get_track_last_lsn(cdio, audioTracks); if (audioTracks < lastTrack) { cdrom_drive_t *dev = cdio_cddap_identify_cdio(cdio, 0, NULL); if (NULL != dev) { if (DRIVER_OP_SUCCESS == cdio_cddap_open(dev)) { // NB this can be S L O W but is reliable lsn_t end2 = cdio_cddap_track_lastsector(dev, getNumCDAudioTracks()); if (CDIO_INVALID_LSN != end2) s_lastAudioLsn = end2; } cdio_cddap_close_no_free_cdio(dev); } } } if (s_lastAudioLsn && s_lastAudioLsn < end) end = s_lastAudioLsn; const lsn_t start = cdio_get_track_lsn(cdio, tracknum); if (CDIO_INVALID_LSN != start && CDIO_INVALID_LSN != end) { length = ((end - start + 1) * 1000 + CDIO_CD_FRAMES_PER_SEC/2) / CDIO_CD_FRAMES_PER_SEC; } bool isCompilation = false; #define CDTEXT 0 // Disabled - cd-text access on discs without it is S L O W #if CDTEXT static int s_iCdtext; if (isDiscChanged) s_iCdtext = -1; if (s_iCdtext) { // cdio_get_cdtext can't take >5 seconds on some CD's without cdtext if (s_iCdtext < 0) LOG(VB_MEDIA, LOG_INFO, QString("Getting cdtext for track %1...").arg(tracknum)); cdtext_t * cdtext = cdio_get_cdtext(m_cdio, tracknum); if (NULL != cdtext) { genre = cdtext_get_const(CDTEXT_GENRE, cdtext); artist = cdtext_get_const(CDTEXT_PERFORMER, cdtext); title = cdtext_get_const(CDTEXT_TITLE, cdtext); const char* isrc = cdtext_get_const(CDTEXT_ISRC, cdtext); /* ISRC codes are 12 characters long, in the form CCXXXYYNNNNN * CC = country code * XXX = registrant e.g. BMG * CC = year withou century * NNNNN = unique ID */ if (isrc && strlen(isrc) >= 7) { year = (isrc[5] - '0') * 10 + (isrc[6] - '0'); year += (year <= 30) ? 2000 : 1900; } cdtext_destroy(cdtext); if (!title.isNull()) { if (s_iCdtext < 0) LOG(VB_MEDIA, LOG_INFO, "Found cdtext track title"); s_iCdtext = 1; // Get disc info cdtext = cdio_get_cdtext(cdio, 0); if (NULL != cdtext) { compilation_artist = cdtext_get_const( CDTEXT_PERFORMER, cdtext); if (!compilation_artist.isEmpty() && artist != compilation_artist) isCompilation = true; album = cdtext_get_const(CDTEXT_TITLE, cdtext); if (genre.isNull()) genre = cdtext_get_const(CDTEXT_GENRE, cdtext); cdtext_destroy(cdtext); } } else { if (s_iCdtext < 0) LOG(VB_MEDIA, LOG_INFO, "No cdtext title for track"); s_iCdtext = 0; } } else { if (s_iCdtext < 0) LOG(VB_MEDIA, LOG_INFO, "No cdtext"); s_iCdtext = 0; } } if (title.isEmpty() || artist.isEmpty() || album.isEmpty()) #endif // CDTEXT { // CDDB lookup Cddb::Toc toc; Cddb::Matches r; if (Cddb::Query(r, GetToc(cdio, toc))) { Cddb::Matches::match_t::const_iterator select = r.matches.begin(); if (r.matches.size() > 1) { // TODO prompt user to select one // In the meantime, select the first non-generic genre for (Cddb::Matches::match_t::const_iterator it = select; it != r.matches.end(); ++it) { QString g = it->genre.toLower(); if (g != "misc" && g != "data") { select = it; break; } } } Cddb::Album info; if (Cddb::Read(info, select->genre, select->discID)) { isCompilation = info.isCompilation; if (info.genre.toLower() != "misc") genre = info.genre; album = info.title; compilation_artist = info.artist; year = info.year; if (info.tracks.size() >= tracknum) { const Cddb::Track& track = info.tracks[tracknum - 1]; title = track.title; artist = track.artist; } // Create a temporary local alias for future lookups if (r.discID != info.discID) Cddb::Alias(info, r.discID); } } } if (compilation_artist.toLower().left(7) == "various") compilation_artist = QObject::tr("Various Artists"); if (artist.isEmpty()) { artist = compilation_artist; compilation_artist.clear(); } if (title.isEmpty()) title = QObject::tr("Track %1").arg(tracknum); Metadata *m = new Metadata(getFilename(), artist, compilation_artist, album, title, genre, year, tracknum, length); if (m) m->setCompilation(isCompilation); return m; }
int main(int argc, const char *argv[]) { CdIo_t *p_cdio; cdio_fs_anal_t fs=0; track_t num_tracks; track_t first_track_num; lsn_t start_track; /* first sector of track */ lsn_t data_start =0; /* start of data area */ int first_data = -1; /* # of first data track */ int first_audio = -1; /* # of first audio track */ unsigned int num_data = 0; /* # of data tracks */ unsigned int num_audio = 0; /* # of audio tracks */ unsigned int i; char *cd_image_name = NULL; if (argc > 1) cd_image_name = strdup(argv[1]); cdio_log_set_handler (log_handler); p_cdio = cdio_open (cd_image_name, DRIVER_UNKNOWN); if (NULL == p_cdio) { printf("-- Problem in trying to find a driver.\n\n"); free(cd_image_name); return 77; } first_track_num = cdio_get_first_track_num(p_cdio); num_tracks = cdio_get_num_tracks(p_cdio); /* Count the number of data and audio tracks. */ for (i = first_track_num; i <= num_tracks; i++) { if (TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i)) { num_audio++; if (-1 == first_audio) first_audio = i; } else { num_data++; if (-1 == first_data) first_data = i; } } /* try to find out what sort of CD we have */ if (0 == num_data) { printf("-- Audio CD\n"); } else { /* we have data track(s) */ cdio_iso_analysis_t cdio_iso_analysis; memset(&cdio_iso_analysis, 0, sizeof(cdio_iso_analysis)); for (i = first_data; i <= num_tracks; i++) { lsn_t lsn; track_format_t track_format = cdio_get_track_format(p_cdio, i); lsn = cdio_get_track_lsn(p_cdio, i); switch ( track_format ) { case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_ERROR: break; case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: case TRACK_FORMAT_DATA: case TRACK_FORMAT_PSX: ; } start_track = (i == 1) ? 0 : lsn; /* save the start of the data area */ if (i == first_data) data_start = start_track; /* skip tracks which belong to the current walked session */ if (start_track < data_start + cdio_iso_analysis.isofs_size) continue; fs = cdio_guess_cd_type(p_cdio, start_track, i, &cdio_iso_analysis); print_analysis(cdio_iso_analysis, fs, first_data, num_audio); if ( !(CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660 || CDIO_FSTYPE(fs) == CDIO_FS_ISO_HFS || CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660_INTERACTIVE) ) /* no method for non-ISO9660 multisessions */ break; } } free(cd_image_name); cdio_destroy(p_cdio); return 0; }
CDRFile *cdrfile_open(const char *path) { CDRFile *ret = (CDRFile *)calloc(1, sizeof(CDRFile)); struct stat stat_buf; if(path == NULL || stat(path, &stat_buf) || !S_ISREG(stat_buf.st_mode)) { CdIo *p_cdio; char **devices; char **parseit; cdio_init(); GetFileBase("cdrom"); devices = cdio_get_devices(DRIVER_DEVICE); parseit = devices; if(parseit) { MDFN_printf(_("Connected physical devices:\n")); MDFN_indent(1); while(*parseit) { MDFN_printf("%s\n", *parseit); parseit++; } MDFN_indent(-1); } if(!parseit || parseit == devices) { MDFN_PrintError(_("No CDROM drives detected(or no disc present).")); if(devices) cdio_free_device_list(devices); free(ret); return(NULL); } if(devices) cdio_free_device_list(devices); p_cdio = cdio_open_cd(path); //, DRIVER_UNKNOWN); //NULL, DRIVER_UNKNOWN); if(!p_cdio) { free(ret); return(NULL); } ret->p_cdio = p_cdio; ret->FirstTrack = cdio_get_first_track_num(ret->p_cdio); ret->NumTracks = cdio_get_num_tracks(ret->p_cdio); ret->total_sectors = cdio_stat_size(ret->p_cdio); if(ret->FirstTrack > 99) { MDFN_PrintError(_("Invalid first track: %d\n"), ret->FirstTrack); free(ret); cdio_destroy(p_cdio); return(NULL); } if(ret->NumTracks > 100) { MDFN_PrintError(_("Invalid track count: %d\n"), ret->NumTracks); free(ret); cdio_destroy(p_cdio); return(NULL); } for(track_t track = ret->FirstTrack; track < (ret->FirstTrack + ret->NumTracks); track++) { memset(&ret->Tracks[track], 0, sizeof(CDRFILE_TRACK_INFO)); ret->Tracks[track].sectors = cdio_get_track_sec_count(ret->p_cdio, track); ret->Tracks[track].LSN = cdio_get_track_lsn(ret->p_cdio, track); ret->Tracks[track].Format = cdio_get_track_format(ret->p_cdio, track); } return(ret); } FILE *fp = fopen(path, "rb"); bool IsTOC = FALSE; // Assign opposite maximum values so our tests will work! int FirstTrack = 99; int LastTrack = 0; if(!fp) { MDFN_PrintError(_("Error opening CUE sheet/TOC \"%s\": %m\n"), path, errno); free(ret); return(NULL); } GetFileBase(path); char linebuf[512]; int32 active_track = -1; int32 AutoTrackInc = 1; // For TOC CDRFILE_TRACK_INFO TmpTrack; memset(&TmpTrack, 0, sizeof(TmpTrack)); while(fgets(linebuf, 512, fp) > 0) { char cmdbuf[512], raw_args[512], args[4][512]; int argcount = 0; raw_args[0] = 0; cmdbuf[0] = 0; args[0][0] = args[1][0] = args[2][0] = args[3][0] = 0; if(!strncasecmp(linebuf, "CD_ROM", 6) || !strncasecmp(linebuf, "CD_DA", 5) || !strncasecmp(linebuf, "CD_ROM_XA", 9)) { IsTOC = TRUE; puts("TOC file detected."); } if(IsTOC) { char *ss_loc = strstr(linebuf, "//"); if(ss_loc) { ss_loc[0] = '\n'; // For consistency! ss_loc[1] = 0; } } trio_sscanf(linebuf, "%s %[^\r\n]", cmdbuf, raw_args); if(!strcasecmp(cmdbuf, "CD_ROM") || !strcasecmp(cmdbuf, "CD_DA")) IsTOC = TRUE; UnQuotify(UnQuotify(UnQuotify(UnQuotify(raw_args, args[0]), args[1]), args[2]), args[3]); if(args[0][0]) { argcount++; if(args[1][0]) { argcount++; if(args[2][0]) { argcount++; if(args[3][0]) { argcount++; } } } } if(IsTOC) { if(!strcasecmp(cmdbuf, "TRACK")) { if(active_track >= 0) { memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); memset(&TmpTrack, 0, sizeof(TmpTrack)); active_track = -1; } if(AutoTrackInc > 99) { MDFN_printf(_("Invalid track number: %d\n"), AutoTrackInc); free(ret); return(NULL); } active_track = AutoTrackInc++; if(active_track < FirstTrack) FirstTrack = active_track; if(active_track > LastTrack) LastTrack = active_track; if(!strcasecmp(args[0], "AUDIO")) { TmpTrack.Format = TRACK_FORMAT_AUDIO; TmpTrack.RawAudioMSBFirst = TRUE; // Silly cdrdao... } else if(!strcasecmp(args[0], "MODE1")) { TmpTrack.Format = TRACK_FORMAT_DATA; TmpTrack.IsData2352 = 0; } else if(!strcasecmp(args[0], "MODE1_RAW")) { TmpTrack.Format = TRACK_FORMAT_DATA; TmpTrack.IsData2352 = 1; } if(!strcasecmp(args[1], "RW")) { TmpTrack.SubchannelMode = CDRF_SUBM_RW; MDFN_printf(_("\"RW\" format subchannel data not supported, only \"RW_RAW\" is!\n")); free(ret); return(0); } else if(!strcasecmp(args[1], "RW_RAW")) TmpTrack.SubchannelMode = CDRF_SUBM_RW_RAW; } // end to TRACK else if(!strcasecmp(cmdbuf, "SILENCE")) { } else if(!strcasecmp(cmdbuf, "ZERO")) { } else if(!strcasecmp(cmdbuf, "FILE") || !strcasecmp(cmdbuf, "AUDIOFILE")) { const char *binoffset = NULL; const char *msfoffset = NULL; const char *length = NULL; if(args[1][0] == '#') { binoffset = args[1] + 1; msfoffset = args[2]; length = args[3]; } else { msfoffset = args[1]; length = args[2]; } //printf("%s, %s, %s, %s\n", args[0], binoffset, msfoffset, length); if(!ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, msfoffset, length)) { free(ret); return(0); } } else if(!strcasecmp(cmdbuf, "DATAFILE")) { const char *binoffset = NULL; const char *length = NULL; if(args[1][0] == '#') { binoffset = args[1] + 1; length = args[2]; } else length = args[1]; if(!ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, NULL, length)) { free(ret); return(0); } } else if(!strcasecmp(cmdbuf, "INDEX")) { } else if(!strcasecmp(cmdbuf, "PREGAP")) { if(active_track < 0) { MDFN_printf(_("Command %s is outside of a TRACK definition!\n"), cmdbuf); free(ret); return(NULL); } int m,s,f; trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f); TmpTrack.pregap = (m * 60 + s) * 75 + f; } // end to PREGAP else if(!strcasecmp(cmdbuf, "START")) { if(active_track < 0) { MDFN_printf(_("Command %s is outside of a TRACK definition!\n"), cmdbuf); free(ret); return(NULL); } int m,s,f; trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f); TmpTrack.pregap = (m * 60 + s) * 75 + f; } } /*********** END TOC HANDLING ************/ else // now for CUE sheet handling { if(!strcasecmp(cmdbuf, "FILE")) { if(active_track >= 0) { memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); memset(&TmpTrack, 0, sizeof(TmpTrack)); active_track = -1; } std::string efn = MDFN_MakeFName(MDFNMKF_AUX, 0, args[0]); if(NULL == (TmpTrack.fp = fopen(efn.c_str(), "rb"))) { MDFN_printf(_("Could not open referenced file \"%s\": %m\n"), efn.c_str(), errno); free(ret); return(0); } TmpTrack.FirstFileInstance = 1; if(!strcasecmp(args[1], "BINARY")) { //TmpTrack.Format = TRACK_FORMAT_DATA; //struct stat stat_buf; //fstat(fileno(TmpTrack.fp), &stat_buf); //TmpTrack.sectors = stat_buf.st_size; // / 2048; } else if(!strcasecmp(args[1], "OGG") || !strcasecmp(args[1], "VORBIS") || !strcasecmp(args[1], "WAVE") || !strcasecmp(args[1], "WAV") || !strcasecmp(args[1], "PCM") || !strcasecmp(args[1], "MPC") || !strcasecmp(args[1], "MP+")) { TmpTrack.ovfile = (OggVorbis_File *) calloc(1, sizeof(OggVorbis_File)); if((TmpTrack.sf = sf_open_fd(fileno(TmpTrack.fp), SFM_READ, &TmpTrack.sfinfo, 0))) { free(TmpTrack.ovfile); TmpTrack.ovfile = NULL; } else if(!lseek(fileno(TmpTrack.fp), 0, SEEK_SET) && !ov_open(TmpTrack.fp, TmpTrack.ovfile, NULL, 0)) { //TmpTrack.Format = TRACK_FORMAT_AUDIO; //TmpTrack.sectors = ov_pcm_total(&TmpTrack.ovfile, -1) / 588; } else { free(TmpTrack.ovfile); TmpTrack.ovfile = NULL; fseek(TmpTrack.fp, 0, SEEK_SET); TmpTrack.MPCReaderFile = (mpc_reader_file *)calloc(1, sizeof(mpc_reader_file)); TmpTrack.MPCStreamInfo = (mpc_streaminfo *)calloc(1, sizeof(mpc_streaminfo)); TmpTrack.MPCDecoder = (mpc_decoder *)calloc(1, sizeof(mpc_decoder)); TmpTrack.MPCBuffer = (MPC_SAMPLE_FORMAT *)calloc(MPC_DECODER_BUFFER_LENGTH, sizeof(MPC_SAMPLE_FORMAT)); mpc_streaminfo_init(TmpTrack.MPCStreamInfo); mpc_reader_setup_file_reader(TmpTrack.MPCReaderFile, TmpTrack.fp); if(mpc_streaminfo_read(TmpTrack.MPCStreamInfo, &TmpTrack.MPCReaderFile->reader) != ERROR_CODE_OK) { MDFN_printf(_("Unsupported audio track file format: %s\n"), args[0]); free(TmpTrack.MPCReaderFile); free(TmpTrack.MPCStreamInfo); free(TmpTrack.MPCDecoder); free(TmpTrack.MPCBuffer); free(ret); return(0); } mpc_decoder_setup(TmpTrack.MPCDecoder, &TmpTrack.MPCReaderFile->reader); if(!mpc_decoder_initialize(TmpTrack.MPCDecoder, TmpTrack.MPCStreamInfo)) { MDFN_printf(_("Error initializing MusePack decoder: %s!\n"), args[0]); free(TmpTrack.MPCReaderFile); free(TmpTrack.MPCStreamInfo); free(TmpTrack.MPCDecoder); free(TmpTrack.MPCBuffer); free(ret); return(0); } } } else { MDFN_printf(_("Unsupported track format: %s\n"), args[1]); free(ret); return(0); } } else if(!strcasecmp(cmdbuf, "TRACK")) { if(active_track >= 0) { memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); TmpTrack.FirstFileInstance = 0; TmpTrack.pregap = 0; } active_track = atoi(args[0]); if(active_track < FirstTrack) FirstTrack = active_track; if(active_track > LastTrack) LastTrack = active_track; if(!strcasecmp(args[1], "AUDIO")) TmpTrack.Format = TRACK_FORMAT_AUDIO; else if(!strcasecmp(args[1], "MODE1/2048")) { TmpTrack.Format = TRACK_FORMAT_DATA; TmpTrack.IsData2352 = 0; } else if(!strcasecmp(args[1], "MODE1/2352")) { TmpTrack.Format = TRACK_FORMAT_DATA; TmpTrack.IsData2352 = 1; } TmpTrack.sectors = GetSectorCount(&TmpTrack); if(active_track < 0 || active_track > 99) { MDFN_printf(_("Invalid track number: %d\n"), active_track); return(0); } } else if(!strcasecmp(cmdbuf, "INDEX")) { if(active_track >= 0 && (!strcasecmp(args[0], "01") || !strcasecmp(args[0], "1"))) { int m,s,f; trio_sscanf(args[1], "%d:%d:%d", &m, &s, &f); TmpTrack.index = (m * 60 + s) * 75 + f; } } else if(!strcasecmp(cmdbuf, "PREGAP")) { if(active_track >= 0) { int m,s,f; trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f); TmpTrack.pregap = (m * 60 + s) * 75 + f; } } } // end of CUE sheet handling } // end of fgets() loop if(ferror(fp)) { if(IsTOC) MDFN_printf(_("Error reading TOC file: %m\n"), errno); else MDFN_printf(_("Error reading CUE sheet: %m\n"), errno); return(0); } if(active_track >= 0) memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); if(FirstTrack > LastTrack) { MDFN_printf(_("No tracks found!\n")); return(0); } ret->FirstTrack = FirstTrack; ret->NumTracks = 1 + LastTrack - FirstTrack; lsn_t RunningLSN = 0; lsn_t LastIndex = 0; long FileOffset = 0; for(int x = ret->FirstTrack; x < (ret->FirstTrack + ret->NumTracks); x++) { if(IsTOC) { RunningLSN += ret->Tracks[x].pregap; ret->Tracks[x].LSN = RunningLSN; RunningLSN += ret->Tracks[x].sectors; } else // else handle CUE sheet... { if(ret->Tracks[x].FirstFileInstance) { LastIndex = 0; FileOffset = 0; } RunningLSN += ret->Tracks[x].pregap; ret->Tracks[x].LSN = RunningLSN; // Make sure this is set before the call to GetSectorCount() for the last track sector count fix. ret->Tracks[x].FileOffset = FileOffset; if((x + 1) >= (ret->FirstTrack + ret->NumTracks)) { if(!(ret->Tracks[x].FirstFileInstance)) { // This will fix the last sector count for CUE+BIN ret->Tracks[x].sectors = GetSectorCount(&ret->Tracks[x]); } } else if(ret->Tracks[x+1].FirstFileInstance) { //RunningLSN += ret->Tracks[x].sectors; } else { // Fix the sector count if we're CUE+BIN ret->Tracks[x].sectors = ret->Tracks[x + 1].index - ret->Tracks[x].index; } //printf("Poo: %d %d\n", x, ret->Tracks[x].sectors); RunningLSN += ret->Tracks[x].sectors; //printf("%d, %ld %d %d %d %d\n", x, FileOffset, ret->Tracks[x].index, ret->Tracks[x].pregap, ret->Tracks[x].sectors, ret->Tracks[x].LSN); if(ret->Tracks[x].Format == TRACK_FORMAT_AUDIO || TmpTrack.IsData2352) FileOffset += ret->Tracks[x].sectors * 2352; else FileOffset += ret->Tracks[x].sectors * 2048; } // end to cue sheet handling } // end to track loop LEC_Eval = MDFN_GetSettingB("cdrom.lec_eval"); if(LEC_Eval) { Init_LEC_Correct(); } MDFN_printf(_("Raw rip data correction using L-EC: %s\n\n"), LEC_Eval ? _("Enabled") : _("Disabled")); ret->total_sectors = RunningLSN; // Running LBA? Running LSN? arghafsdf...LSNBAN!#!$ -_- return(ret); }
static int cdpa_get_tracks(rnc_dev_t *dev, rnc_track_t *buf, size_t size) { cdpa_t *cdpa = dev->data; cdpa_track_t *tracks, *trk; int ntrack, base, naudio; rnc_track_t *t; int id, i; mrp_debug("getting tracks"); base = cdio_get_first_track_num(cdpa->cdio); if (cdpa->ntrack == 0) { ntrack = cdio_get_num_tracks(cdpa->cdio); if (ntrack == 0) return 0; tracks = mrp_allocz_array(typeof(*tracks), ntrack); if (tracks == NULL) return -1; naudio = 0; trk = tracks; for (i = 0; i < ntrack; i++) { id = base + i; if (cdio_get_track_format(cdpa->cdio, id) != TRACK_FORMAT_AUDIO) continue; trk->id = id; trk->idx = i; trk->fblk = cdio_get_track_lsn(cdpa->cdio, id); trk->lblk = cdio_get_track_last_lsn(cdpa->cdio, id); naudio++; trk++; } cdpa->tracks = tracks; cdpa->ntrack = naudio; } else ntrack = cdpa->ntrack; if ((int)size > cdpa->ntrack) size = cdpa->ntrack; for (i = 0, t = buf, trk = cdpa->tracks; i < (int)size; i++, t++, trk++) { t->idx = trk - cdpa->tracks; t->id = base + i; t->fblk = trk->fblk; t->nblk = trk->lblk - trk->fblk + 1; t->length = 1.0 * t->nblk / 75.0; } if (cdpa->ctrack < 0) { cdio_paranoia_modeset(cdpa->cdpa, PARANOIA_MODE_FULL); cdpa->ctrack = 0; seek_track(cdpa, 0, 0); } return ntrack; }
void cued_rip_disc(rip_context_t *rip) { cued_rip_prologue(rip); if (ripToOneFile) { // TODO: broken for cd-extra; stop at first data track? in cued.c? if (TRACK_FORMAT_AUDIO != cdio_get_track_format(rip->cdObj, rip->firstTrack)) { cdio2_abort("track %02d is not an audio track", rip->firstTrack); } if (rip->firstTrack > 1) { rip->firstSector = cdio_get_track_lsn(rip->cdObj, rip->firstTrack); if (CDIO_INVALID_LSN == rip->firstSector) { cdio2_abort("failed to get first sector number for track %02d", rip->firstTrack); } } else { rip->firstSector = 0; } rip->lastSector = cdio_get_track_last_lsn(rip->cdObj, rip->lastTrack); // , rip->discLastTrack); if (CDIO_INVALID_LSN == rip->lastSector) { cdio2_abort("failed to get last sector number for track %02d", rip->lastTrack); } rip->channels = cdio2_get_track_channels(rip->cdObj, rip->firstTrack); if (ripVerbose) { printf("progress: reading sectors from %d to %d\n", rip->firstSector, rip->lastSector); } rip->currentTrack = 0; cued_rip_to_file(rip); } else { rip_fn_t ripfn; track_format_t format; track_t track; for (track = rip->firstTrack; track <= rip->lastTrack; ++track) { rip->firstSector = cdio_get_track_lsn(rip->cdObj, track); if (CDIO_INVALID_LSN == rip->firstSector) { cdio2_abort("failed to get first sector number for track %02d", track); } format = cdio_get_track_format(rip->cdObj, track); switch (format) { case TRACK_FORMAT_AUDIO: rip->channels = cdio2_get_track_channels(rip->cdObj, track); // rip first track pregap to track 00 file if (1 == track && rip->firstSector > 0) { lsn_t saveFirstSector = rip->firstSector; if (ripVerbose) { printf("progress: reading track %02d\n", 0); } rip->lastSector = rip->firstSector - 1; rip->firstSector = 0; rip->currentTrack = 0; cued_rip_to_file(rip); if (ripSilentPregap && ripExtract) { if (unlink(rip->fileNameBuffer)) { cdio2_unix_error("unlink", rip->fileNameBuffer, 1); } } rip->firstSector = saveFirstSector; } ripfn = cued_rip_to_file; break; case TRACK_FORMAT_DATA: //ripfn = cued_rip_data_track; //break; default: cdio_warn("track %02d is not an audio track; skipping track", track); continue; } rip->lastSector = cdio_get_track_last_lsn(rip->cdObj, track); // , rip->discLastTrack); if (CDIO_INVALID_LSN == rip->lastSector) { cdio2_abort("failed to get last sector number for track %02d", track); } else { //cdio_debug("track %02d last sector is %d", track, rip->lastSector); } if (ripVerbose) { printf("progress: reading track %02d\n", track); } rip->currentTrack = track; ripfn(rip); } } cued_rip_epilogue(rip); }
/*! Get the format (audio, mode2, mode1) of track. */ track_format_t getFormat() { return cdio_get_track_format(p_cdio, i_track); }
static int cda_init (DB_fileinfo_t *_info, DB_playItem_t *it) { cdda_info_t *info = (cdda_info_t *)_info; trace ("cdda: init %s\n", deadbeef->pl_find_meta (it, ":URI")); size_t l = strlen (deadbeef->pl_find_meta (it, ":URI")); char location[l+1]; memcpy (location, deadbeef->pl_find_meta (it, ":URI"), l+1); char *nr = strchr (location, '#'); if (nr) { *nr = 0; nr++; } else { trace ("cdda: bad name: %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } int track_nr = atoi (nr); char *fname = (*location) ? location : NULL; //NULL if empty string; means pysical CD drive info->cdio = cdio_open (fname, DRIVER_UNKNOWN); if (!info->cdio) { trace ("cdda: Could not open CD\n"); return -1; } track_t first_track = cdio_get_first_track_num (info->cdio); if (first_track == 0xff) { trace ("cdda: no medium found\n"); return -1; } track_t tracks = cdio_get_num_tracks (info->cdio); track_t i; cddb_track_t *track; cddb_disc_t *disc = cddb_disc_new(); cddb_disc_set_length (disc, cdio_get_track_lba (info->cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC); for (i = 0; i < tracks; i++) { lsn_t offset = cdio_get_track_lba (info->cdio, i+first_track); track = cddb_track_new(); cddb_track_set_frame_offset (track, offset); cddb_disc_add_track (disc, track); } cddb_disc_calc_discid (disc); int discid = cddb_disc_get_discid (disc); int trk_discid = deadbeef->pl_find_meta_int (it, ":CDIO_DISCID", 0); if (trk_discid != discid) { cddb_disc_destroy (disc); trace ("cdda: the track belongs to another disc, skipped\n"); return -1; } cddb_disc_destroy (disc); if (TRACK_FORMAT_AUDIO != cdio_get_track_format (info->cdio, track_nr)) { trace ("cdda: Not an audio track (%d)\n", track_nr); return -1; } int channels = cdio_get_track_channels (info->cdio, track_nr); trace ("cdio nchannels: %d\n", channels); _info->plugin = &plugin; _info->fmt.bps = 16; _info->fmt.channels = 2; _info->fmt.samplerate = 44100; _info->fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT; _info->readpos = 0; info->first_sector = cdio_get_track_lsn (info->cdio, track_nr); info->sector_count = cdio_get_track_sec_count (info->cdio, track_nr); info->current_sector = info->first_sector; info->tail_len = 0; info->current_sample = 0; return 0; }
static void get_track_info(ripncode_t *r) { rip_track_t *t; int i, base; char file[1024], *msg; int16_t *samples; int fd, n, l, total; base = cdio_get_first_track_num(r->cdio); r->ntrack = cdio_get_num_tracks(r->cdio); r->tracks = mrp_allocz_array(rip_track_t, r->ntrack); if (r->tracks == NULL && r->ntrack > 0) ripncode_fatal(r, "failed to allocate track info"); cdio_paranoia_modeset(r->cdpa, PARANOIA_MODE_FULL); for (i = 0, t = r->tracks; i < r->ntrack; i++, t++) { if (i >= r->last) break; t->id = base + i; t->format = cdio_get_track_format(r->cdio, base + i); t->lsn_beg = cdio_get_track_lsn(r->cdio, base + i); t->lsn_end = cdio_get_track_last_lsn(r->cdio, base + i); t->lba = cdio_get_track_lba(r->cdio, base + i); printf("track #%d (id %d): lsn: %u - %u (lba %u), format: %s\n", i, base + i, t->lsn_beg, t->lsn_end, t->lba, track_format_name(t->format)); if (r->dryrun) continue; snprintf(file, sizeof(file), "track-%d.raw", i); if ((fd = open(file, O_WRONLY|O_CREAT, 0644)) < 0) ripncode_fatal(r, "failed to open '%s' (%d: %s)", file, errno, strerror(errno)); cdio_paranoia_seek(r->cdpa, t->lsn_beg * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); total = t->lsn_end - t->lsn_beg + 1; for (l = 0; l <= total; l++) { printf("\rreading track sector %d/%d (#%d)...", l, total, t->lsn_beg + l); fflush(stdout); samples = cdio_paranoia_read(r->cdpa, read_status); if (samples == NULL) { msg = cdio_cddap_errors(r->cdda); ripncode_fatal(r, "failed to seek to LSN %d (%s)", t->lsn_beg, msg ? msg : "unknown error"); } n = write(fd, samples, CDIO_CD_FRAMESIZE_RAW); if (n < 0) ripncode_fatal(r, "failed to write sector data (%d: %s)", errno, strerror(errno)); } close(fd); } }