static void cued_rip_epilogue(rip_context_t *rip) { free(rip->mmcBuf); #ifdef CUED_HAVE_PARANOIA if (ripUseParanoia) { rip->paranoiaCtlObj->read_audio = rip->save_read_paranoid; cdio_paranoia_free(rip->paranoiaRipObj); cdio_cddap_close_no_free_cdio(rip->paranoiaCtlObj); } #endif // CUED_HAVE_PARANOIA if (rip->qSubChannelFileName && rip->qSubChannelFile != stdout) { fclose(rip->qSubChannelFile); } if (rip->crcFailure || rip->crcSuccess) { int totalCrcs = rip->crcSuccess + rip->crcFailure; if (rip->crcFailure * 100 / totalCrcs > 5) { cdio_warn("greater than 5 percent of Q sub-channel records failed CRC check (try --qsc-fq?)"); } if (ripVerbose) { printf("progress: correctly read %d of %d Q sub-channel records\n", rip->crcSuccess, totalCrcs); } } }
/*! Closes d and releases all storage associated with it. Doubles as "cdrom_drive_free()". @param d cdrom_drive_t object to be closed. @return 0 if passed a null pointer and 1 if not in which case some work was probably done. @see cdio_cddap_close_no_free_cdio */ int cdio_cddap_close(cdrom_drive_t *d) { if (d) { CdIo_t *p_cdio = d->p_cdio; cdio_cddap_close_no_free_cdio(d); cdio_destroy (p_cdio); return 1; } return 0; }
static void input_cdio_close(struct input_stream *is) { struct input_cdio_paranoia *i = (struct input_cdio_paranoia *)is; pcm_buffer_deinit(&i->conv_buffer); if (i->para) cdio_paranoia_free(i->para); if (i->drv) cdio_cddap_close_no_free_cdio( i->drv); if (i->cdio) cdio_destroy( i->cdio ); input_stream_deinit(&i->base); g_free(i); }
static void xmms_cdda_destroy (xmms_xform_t *xform) { xmms_cdda_data_t *data; g_return_if_fail (xform); data = xmms_xform_private_data_get (xform); if (data) { if (data->drive) { cdio_cddap_close_no_free_cdio (data->drive); } if (data->cdio) { cdio_destroy (data->cdio); } g_free (data); } }
static gboolean xmms_cdda_init (xmms_xform_t *xform) { CdIo_t *cdio = NULL; cdrom_drive_t *drive = NULL; const gchar *url; gchar **url_data = NULL; gchar *url_end; xmms_cdda_data_t *data; guint playtime; lsn_t first_lsn; track_t track; gchar *disc_id = NULL; gchar *cddb_id = NULL; xmms_config_property_t *val; const gchar *device; const gchar *metakey; gboolean ret = TRUE; g_return_val_if_fail (xform, FALSE); url = xmms_xform_indata_get_str (xform, XMMS_STREAM_TYPE_URL); if (g_ascii_strcasecmp (url, "cdda://") == 0) { xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "application/x-xmms2-playlist-entries", XMMS_STREAM_TYPE_END); return TRUE; } val = xmms_xform_config_lookup (xform, "device"); device = xmms_config_property_get_string (val); if (!get_disc_ids (device, &disc_id, &cddb_id, 0)) { return FALSE; } url += 7; url_data = g_strsplit (url, "/", 2); if (g_ascii_strcasecmp (url_data[0], disc_id)) { xmms_log_error ("Wrong disc inserted."); ret = FALSE; goto end; } if (url_data[1] == NULL) { xmms_log_error ("Missing track number."); ret = FALSE; goto end; } track = strtol (url_data[1], &url_end, 10); if (url_data[1] == url_end) { xmms_log_error ("Invalid track, need a number."); ret = FALSE; goto end; } cdio = open_cd (xform); if (!cdio) { ret = FALSE; goto end; } drive = cdio_cddap_identify_cdio (cdio, 1, NULL); if (!drive) { xmms_log_error ("Failed to identify drive."); ret = FALSE; goto end; } if (cdio_cddap_open (drive)) { xmms_log_error ("Unable to open disc."); ret = FALSE; goto end; } first_lsn = cdio_cddap_track_firstsector (drive, track); if (first_lsn == -1) { xmms_log_error ("No such track."); ret = FALSE; goto end; } data = g_new (xmms_cdda_data_t, 1); data->cdio = cdio; data->drive = drive; data->track = track; data->first_lsn = first_lsn; data->last_lsn = cdio_cddap_track_lastsector (drive, data->track); data->current_lsn = first_lsn; data->buf_used = CDIO_CD_FRAMESIZE_RAW; playtime = (data->last_lsn - data->first_lsn) * 1000.0 / CDIO_CD_FRAMES_PER_SEC; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, playtime); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, 141120); xmms_xform_metadata_set_str (xform, "disc_id", url_data[0]); xmms_xform_metadata_set_str (xform, "cddb_id", cddb_id); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR; xmms_xform_metadata_set_int (xform, metakey, track); xmms_xform_private_data_set (xform, data); xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, XMMS_STREAM_TYPE_FMT_CHANNELS, 2, XMMS_STREAM_TYPE_FMT_SAMPLERATE, 44100, XMMS_STREAM_TYPE_END); end: /* These are to be destroyed in every cases... */ g_free (cddb_id); g_free (disc_id); g_strfreev (url_data); /* destroy cdio/drive in case of failure */ if (!ret) { if (drive) { cdio_cddap_close_no_free_cdio (drive); } if (cdio) { cdio_destroy (cdio); } } return ret; }
static void cued_rip_prologue(rip_context_t *rip) { rip->mmcBuf = NULL; rip->allocatedSectors = 0; #ifdef CUED_HAVE_PARANOIA if (ripUseParanoia) { char *msg = 0; int rc; // N.B. this behavior does not match documentation: // the 0 here appears to prevent the message "Checking <filename> for cdrom..." rip->paranoiaCtlObj = cdio_cddap_identify_cdio(rip->cdObj, 0, &msg); if (rip->paranoiaCtlObj) { if (msg) { cdio_warn("identify returned paranoia message(s) \"%s\"", msg); } cdio_cddap_verbose_set(rip->paranoiaCtlObj, CDDA_MESSAGE_LOGIT, CDDA_MESSAGE_LOGIT); rc = cdio_cddap_open(rip->paranoiaCtlObj); cdio2_paranoia_msg(rip->paranoiaCtlObj, "open of device"); if (!rc) { rip->paranoiaRipObj = cdio_paranoia_init(rip->paranoiaCtlObj); cdio2_paranoia_msg(rip->paranoiaCtlObj, "initialization of paranoia"); if (!rip->paranoiaRipObj) { cdio2_abort("out of memory initializing paranoia"); } cdio_paranoia_modeset(rip->paranoiaRipObj, PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP); // N.B. not needed at the moment cdio2_paranoia_msg(rip->paranoiaCtlObj, "setting of paranoia mode"); rip->save_read_paranoid = rip->paranoiaCtlObj->read_audio; rip->paranoiaCtlObj->read_audio = cued_read_paranoid; } else { cdio_cddap_close_no_free_cdio(rip->paranoiaCtlObj); cdio_error("disabling paranoia"); CLRF(RIP_F_USE_PARANOIA, rip->flags); } } else { cdio_error("disabling paranoia due to the following message(s):\n%s", msg); CLRF(RIP_F_USE_PARANOIA, rip->flags); } } #endif // CUED_HAVE_PARANOIA if (rip->qSubChannelFileName) { if (!strcmp("-", rip->qSubChannelFileName)) { rip->qSubChannelFile = stdout; } else { (void) format_get_file_path(rip->cdObj, rip->cddbObj, rip->qSubChannelFileName, "", 0, rip->fileNameBuffer, rip->bufferSize); // replaced O_EXCL with O_TRUNC to allow using /dev/null for testing rip->qSubChannelFile = fopen2(rip->fileNameBuffer, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0666); if (!rip->qSubChannelFile) { cdio2_unix_error("fopen2", rip->fileNameBuffer, 0); cdio_error("not creating sub-channel file \"%s\"", rip->fileNameBuffer); rip->qSubChannelFileName = 0; } } } rip->endOfDiscSector = cdio_get_disc_last_lsn(rip->cdObj); if (CDIO_INVALID_LSN == rip->endOfDiscSector) { cdio2_abort("failed to get last sector number"); } else { //cdio_debug("end of disc sector is %d", rip->endOfDiscSector); } }
/* return 0 if OK, -1 if drive is apparently not available */ int cdda_scan_drive(char * device_path, cdda_drive_t * cdda_drive) { track_t tracks; track_t first_track; track_t last_track; track_t skipped = 0; int i, n = 0; cdrom_drive_t * d; if (cdda_drive->cdio == NULL) { cdda_drive->cdio = cdio_open(device_path, DRIVER_DEVICE); if (!cdda_drive->cdio) { return -1; } strncpy(cdda_drive->device_path, device_path, CDDA_MAXLEN-1); } cdda_drive->disc.n_tracks = 0; tracks = cdio_get_num_tracks(cdda_drive->cdio); if (tracks < 1 || tracks >= 100) { cdda_drive->disc.hash_prev = cdda_drive->disc.hash; cdda_drive->disc.hash = 0L; return 0; } d = cdio_cddap_identify_cdio(cdda_drive->cdio, 0, NULL); if (d == NULL) { return -1; } first_track = cdio_get_first_track_num(cdda_drive->cdio); last_track = cdio_get_last_track_num(cdda_drive->cdio); for (i = first_track; i <= last_track; i++) { if (!cdio_cddap_track_audiop(d, i)) { skipped = i; last_track = i-1; break; } } cdio_cddap_close_no_free_cdio(d); if (last_track < first_track) { return 0; } cdda_drive->disc.n_tracks = last_track - first_track + 1; for (i = first_track; i <= last_track; i++) { lsn_t lsn = cdio_get_track_lsn(cdda_drive->cdio, i); if (lsn != CDIO_INVALID_LSN) { cdda_drive->disc.toc[n++] = lsn; } } if (skipped == 0) { cdda_drive->disc.toc[n] = cdio_get_track_lsn(cdda_drive->cdio, CDIO_CDROM_LEADOUT_TRACK); } else { cdda_drive->disc.toc[n] = cdio_get_track_lsn(cdda_drive->cdio, skipped); if ((cdda_drive->disc.toc[n] - cdda_drive->disc.toc[n-1]) >= 11400) { /* compensate end of track with multisession offset */ cdda_drive->disc.toc[n] -= 11400; } } cdda_drive->disc.hash_prev = cdda_drive->disc.hash; cdda_drive->disc.hash = calc_cdda_hash(&cdda_drive->disc); if (cdda_drive->disc.hash != cdda_drive->disc.hash_prev) { strncpy(cdda_drive->disc.artist_name, _("Unknown Artist"), MAXLEN-1); strncpy(cdda_drive->disc.record_name, _("Unknown Record"), MAXLEN-1); cdda_drive->swap_bytes = -1; /* unknown */ } return 0; }
//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; }