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; }
int main(int argc, char *argv[]) { uint8_t buffer[CDIO_CD_FRAMESIZE_RAW] = { 0, }; unsigned int blocklen=CDIO_CD_FRAMESIZE_RAW; CdIo *p_cdio=NULL; int output_fd=-1; FILE *output_stream; init(); /* Parse our arguments; every option seen by `parse_opt' will be reflected in `arguments'. */ parse_options(argc, argv); print_version(program_name, VERSION, opts.no_header, opts.version_only); p_cdio = open_input(source_name, opts.source_image, opts.access_mode); if (opts.output_file!=NULL) { /* If hexdump not explicitly set, then don't produce hexdump when writing to a file. */ if (opts.hexdump == 2) opts.hexdump = 0; output_fd = open(opts.output_file, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (-1 == output_fd) { err_exit("Error opening output file %s: %s\n", opts.output_file, strerror(errno)); } } else /* If we are writing to stdout, then the default is to produce a hexdump. */ if (opts.hexdump == 2) opts.hexdump = 1; for ( ; opts.start_lsn <= opts.end_lsn; opts.start_lsn++ ) { switch (opts.read_mode) { case READ_AUDIO: case READ_M1F1: case READ_M1F2: case READ_M2F1: case READ_M2F2: if (DRIVER_OP_SUCCESS != cdio_read_sector(p_cdio, &buffer, opts.start_lsn, (cdio_read_mode_t) opts.read_mode)) { report( stderr, "error reading block %u\n", (unsigned int) opts.start_lsn ); blocklen = 0; } else { switch (opts.read_mode) { case READ_M1F1: blocklen=CDIO_CD_FRAMESIZE; break; case READ_M1F2: blocklen=M2RAW_SECTOR_SIZE; case READ_M2F1: blocklen=CDIO_CD_FRAMESIZE; case READ_M2F2: blocklen=M2F2_SECTOR_SIZE; default: ; } } break; case READ_ANY: { driver_id_t driver_id = cdio_get_driver_id(p_cdio); if (cdio_is_device(source_name, driver_id)) { if (DRIVER_OP_SUCCESS != mmc_read_sectors(p_cdio, &buffer, opts.start_lsn, CDIO_MMC_READ_TYPE_ANY, 1)) { report( stderr, "error reading block %u\n", (unsigned int) opts.start_lsn ); blocklen = 0; } } else { err_exit( "%s: mode 'any' must be used with a real CD-ROM, not an image file.\n", program_name); } } break; case READ_MODE_UNINIT: err_exit("%s: Reading mode not set\n", program_name); break; } if (!opts.output_file) { output_stream = stdout; } else { output_stream = fdopen(output_fd, "w"); } if (opts.hexdump) hexdump(output_stream, buffer, blocklen, opts.just_hex); else if (opts.output_file) write(output_fd, buffer, blocklen); else { unsigned int i; for (i=0; i<blocklen; i++) printf("%c", buffer[i]); } } if (opts.output_file) close(output_fd); myexit(p_cdio, EXIT_SUCCESS); /* Not reached:*/ return(EXIT_SUCCESS); }