/*! Find the track which contans lsn. CDIO_INVALID_TRACK is returned if the lsn outside of the CD or if there was some error. If the lsn is before the pregap of the first track 0 is returned. Otherwise we return the track that spans the lsn. */ track_t cdio_get_track(const CdIo_t *p_cdio, lsn_t lsn) { if (!p_cdio) return CDIO_INVALID_TRACK; { track_t i_low_track = cdio_get_first_track_num(p_cdio); track_t i_high_track = cdio_get_last_track_num(p_cdio)+1; /* LEADOUT */ if (CDIO_INVALID_TRACK == i_low_track || CDIO_INVALID_TRACK == i_high_track ) return CDIO_INVALID_TRACK; if (lsn < cdio_get_track_lsn(p_cdio, i_low_track)) return 0; /* We're in the pre-gap of first track */ if (lsn > cdio_get_track_lsn(p_cdio, i_high_track)) return CDIO_INVALID_TRACK; /* We're beyond the end. */ do { const track_t i_mid = (i_low_track + i_high_track) / 2; const lsn_t i_mid_lsn = cdio_get_track_lsn(p_cdio, i_mid); if (lsn <= i_mid_lsn) i_high_track = i_mid - 1; if (lsn >= i_mid_lsn) i_low_track = i_mid + 1; } while ( i_low_track <= i_high_track ); return (i_low_track > i_high_track + 1) ? i_high_track + 1 : i_high_track; } }
/*! 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); } }
static void display_toc(cdrom_drive_t *d) { long audiolen=0; track_t i; report("\nTable of contents (audio tracks only):\n" "track length begin copy pre ch\n" "==========================================================="); for( i=cdio_get_first_track_num(d->p_cdio); i<=cdio_get_last_track_num(d->p_cdio); i++) if ( cdda_track_audiop(d,i) > 0 ) { lsn_t sec=cdda_track_firstsector(d,i); lsn_t off=cdda_track_lastsector(d,i)-sec+1; report("%3d. %7ld [%02d:%02d.%02d] %7ld [%02d:%02d.%02d] %s %s %s", i, (long int) off, (int) (off/(CDIO_CD_FRAMES_PER_MIN)), (int) ((off/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN), (int) (off % CDIO_CD_FRAMES_PER_SEC), (long int) sec, (int) (sec/(CDIO_CD_FRAMES_PER_MIN)), (int) ((sec/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN), (int) (sec % CDIO_CD_FRAMES_PER_SEC), cdda_track_copyp(d,i)?" OK":" no", cdda_track_preemp(d,i)?" yes":" no", cdda_track_channels(d,i)==2?" 2":" 4"); audiolen+=off; } report("TOTAL %7ld [%02d:%02d.%02d] (audio only)", audiolen, (int) (audiolen/(CDIO_CD_FRAMES_PER_MIN)), (int) ((audiolen/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN), (int) (audiolen % CDIO_CD_FRAMES_PER_SEC)); report(" "); }
//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; }
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; }
static int read_toc(vcd_priv * priv, char ** iso_label) { int i, j; cdio_iso_analysis_t iso; cdio_fs_anal_t fs; int first_track; priv->num_tracks = cdio_get_last_track_num(priv->cdio); if(priv->num_tracks == CDIO_INVALID_TRACK) { return 0; } /* VCD needs at least 2 tracks */ if(priv->num_tracks < 2) return 0; priv->tracks = calloc(priv->num_tracks, sizeof(*(priv->tracks))); priv->num_video_tracks = 0; first_track = cdio_get_first_track_num(priv->cdio); if(iso_label) { fs = cdio_guess_cd_type(priv->cdio, 0, first_track, &iso); /* Remove trailing spaces */ j = strlen(iso.iso_label)-1; while(j) { if(!isspace(iso.iso_label[j])) break; j--; } if(!j && isspace(iso.iso_label[j])) iso.iso_label[j] = '\0'; else iso.iso_label[j+1] = '\0'; *iso_label = gavl_strdup(iso.iso_label); priv->tracks[first_track - 1].mode = TRACK_OTHER; } /* Actually it's (first_track - 1) + 1 */ for(i = first_track; i < priv->num_tracks; i++) { priv->tracks[i].start_sector = cdio_get_track_lsn(priv->cdio, i+1); priv->tracks[i].end_sector = cdio_get_track_last_lsn(priv->cdio, i+1); fs = cdio_guess_cd_type(priv->cdio, 0, i+1, &iso); if(fs & CDIO_FS_ANAL_VIDEOCD) { priv->num_video_tracks++; priv->tracks[i].mode = TRACK_VCD; } else if(fs & CDIO_FS_ANAL_SVCD) { priv->num_video_tracks++; priv->tracks[i].mode = TRACK_SVCD; } else if(fs & CDIO_FS_ANAL_CVD) { priv->tracks[i].mode = TRACK_CVD; priv->num_video_tracks++; } else if(fs & CDIO_FS_ANAL_ISO9660_ANY) { priv->tracks[i].mode = TRACK_VCD; priv->num_video_tracks++; } } if(!priv->num_video_tracks) { free(priv->tracks); priv->tracks = NULL; return 0; } return 1; }
/** 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); }
/* mutex must be locked */ static void scan_cd (void) { AUDDBG ("Scanning CD drive.\n"); g_return_if_fail (pcdrom_drive != NULL); g_return_if_fail (trackinfo == NULL); gint trackno; /* general track initialization */ /* skip endianness detection (because it only affects cdda_read, and we use * cdio_read_audio_sectors instead) */ pcdrom_drive->bigendianp = 0; /* finish initialization of drive/disc (performs disc TOC sanitization) */ if (cdda_open (pcdrom_drive) != 0) { cdaudio_error ("Failed to finish initializing opened CD drive."); goto ERR; } if (cdda_speed_set (pcdrom_drive, cdng_cfg.disc_speed) != DRIVER_OP_SUCCESS) warn ("Cannot set drive speed.\n"); firsttrackno = cdio_get_first_track_num (pcdrom_drive->p_cdio); lasttrackno = cdio_get_last_track_num (pcdrom_drive->p_cdio); if (firsttrackno == CDIO_INVALID_TRACK || lasttrackno == CDIO_INVALID_TRACK) { cdaudio_error ("Failed to retrieve first/last track number."); goto ERR; } AUDDBG ("first track is %d and last track is %d\n", firsttrackno, lasttrackno); trackinfo = (trackinfo_t *) g_new (trackinfo_t, (lasttrackno + 1)); cdaudio_set_fullinfo (&trackinfo[0], cdda_track_firstsector (pcdrom_drive, 0), cdda_track_lastsector (pcdrom_drive, lasttrackno), "", "", ""); n_audio_tracks = 0; for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { cdaudio_set_fullinfo (&trackinfo[trackno], cdda_track_firstsector (pcdrom_drive, trackno), cdda_track_lastsector (pcdrom_drive, trackno), "", "", ""); if (trackinfo[trackno].startlsn == CDIO_INVALID_LSN || trackinfo[trackno].endlsn == CDIO_INVALID_LSN) { cdaudio_error ("Cannot read start/end LSN for track %d.", trackno); goto ERR; } /* count how many tracks are audio tracks */ if (cdda_track_audiop (pcdrom_drive, trackno)) n_audio_tracks++; } /* get trackinfo[0] cdtext information (the disc) */ if (cdng_cfg.use_cdtext) { AUDDBG ("getting cd-text information for disc\n"); cdtext_t *pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio, 0); if (pcdtext == NULL || pcdtext->field[CDTEXT_TITLE] == NULL) { AUDDBG ("no cd-text available for disc\n"); } else { cdaudio_set_strinfo (&trackinfo[0], pcdtext->field[CDTEXT_PERFORMER] ? pcdtext-> field[CDTEXT_PERFORMER] : "", pcdtext->field[CDTEXT_TITLE] ? pcdtext-> field[CDTEXT_TITLE] : "", pcdtext->field[CDTEXT_GENRE] ? pcdtext-> field[CDTEXT_GENRE] : ""); } } /* get track information from cdtext */ gboolean cdtext_was_available = FALSE; for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { cdtext_t *pcdtext = NULL; if (cdng_cfg.use_cdtext) { AUDDBG ("getting cd-text information for track %d\n", trackno); pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio, trackno); if (pcdtext == NULL || pcdtext->field[CDTEXT_PERFORMER] == NULL) { AUDDBG ("no cd-text available for track %d\n", trackno); pcdtext = NULL; } } if (pcdtext != NULL) { cdaudio_set_strinfo (&trackinfo[trackno], pcdtext->field[CDTEXT_PERFORMER] ? pcdtext-> field[CDTEXT_PERFORMER] : "", pcdtext->field[CDTEXT_TITLE] ? pcdtext-> field[CDTEXT_TITLE] : "", pcdtext->field[CDTEXT_GENRE] ? pcdtext-> field[CDTEXT_GENRE] : ""); cdtext_was_available = TRUE; } else { cdaudio_set_strinfo (&trackinfo[trackno], "", "", ""); snprintf (trackinfo[trackno].name, DEF_STRING_LEN, "Track %d", trackno); } } if (!cdtext_was_available) { /* initialize de cddb subsystem */ cddb_conn_t *pcddb_conn = NULL; cddb_disc_t *pcddb_disc = NULL; cddb_track_t *pcddb_track = NULL; lba_t lba; /* Logical Block Address */ if (cdng_cfg.use_cddb) { pcddb_conn = cddb_new (); if (pcddb_conn == NULL) cdaudio_error ("Failed to create the cddb connection."); else { AUDDBG ("getting CDDB info\n"); cddb_cache_enable (pcddb_conn); // cddb_cache_set_dir(pcddb_conn, "~/.cddbslave"); if (cdng_cfg.use_proxy) { cddb_http_proxy_enable (pcddb_conn); cddb_set_http_proxy_server_name (pcddb_conn, cdng_cfg.proxy_host); cddb_set_http_proxy_server_port (pcddb_conn, cdng_cfg.proxy_port); cddb_set_http_proxy_username (pcddb_conn, cdng_cfg.proxy_username); cddb_set_http_proxy_password (pcddb_conn, cdng_cfg.proxy_password); cddb_set_server_name (pcddb_conn, cdng_cfg.cddb_server); cddb_set_server_port (pcddb_conn, cdng_cfg.cddb_port); } else if (cdng_cfg.cddb_http) { cddb_http_enable (pcddb_conn); cddb_set_server_name (pcddb_conn, cdng_cfg.cddb_server); cddb_set_server_port (pcddb_conn, cdng_cfg.cddb_port); cddb_set_http_path_query (pcddb_conn, cdng_cfg.cddb_path); } else { cddb_set_server_name (pcddb_conn, cdng_cfg.cddb_server); cddb_set_server_port (pcddb_conn, cdng_cfg.cddb_port); } pcddb_disc = cddb_disc_new (); lba = cdio_get_track_lba (pcdrom_drive->p_cdio, CDIO_CDROM_LEADOUT_TRACK); cddb_disc_set_length (pcddb_disc, FRAMES_TO_SECONDS (lba)); for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { pcddb_track = cddb_track_new (); cddb_track_set_frame_offset (pcddb_track, cdio_get_track_lba ( pcdrom_drive->p_cdio, trackno)); cddb_disc_add_track (pcddb_disc, pcddb_track); } cddb_disc_calc_discid (pcddb_disc); #if DEBUG guint discid = cddb_disc_get_discid (pcddb_disc); AUDDBG ("CDDB disc id = %x\n", discid); #endif gint matches; if ((matches = cddb_query (pcddb_conn, pcddb_disc)) == -1) { if (cddb_errno (pcddb_conn) == CDDB_ERR_OK) cdaudio_error ("Failed to query the CDDB server"); else cdaudio_error ("Failed to query the CDDB server: %s", cddb_error_str (cddb_errno (pcddb_conn))); cddb_disc_destroy (pcddb_disc); pcddb_disc = NULL; } else { if (matches == 0) { AUDDBG ("no cddb info available for this disc\n"); cddb_disc_destroy (pcddb_disc); pcddb_disc = NULL; } else { AUDDBG ("CDDB disc category = \"%s\"\n", cddb_disc_get_category_str (pcddb_disc)); cddb_read (pcddb_conn, pcddb_disc); if (cddb_errno (pcddb_conn) != CDDB_ERR_OK) { cdaudio_error ("failed to read the cddb info: %s", cddb_error_str (cddb_errno (pcddb_conn))); cddb_disc_destroy (pcddb_disc); pcddb_disc = NULL; } else { cdaudio_set_strinfo (&trackinfo[0], cddb_disc_get_artist (pcddb_disc), cddb_disc_get_title (pcddb_disc), cddb_disc_get_genre (pcddb_disc)); gint trackno; for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { cddb_track_t *pcddb_track = cddb_disc_get_track (pcddb_disc, trackno - 1); cdaudio_set_strinfo (&trackinfo[trackno], cddb_track_get_artist (pcddb_track), cddb_track_get_title (pcddb_track), cddb_disc_get_genre (pcddb_disc)); } } } } } } if (pcddb_disc != NULL) cddb_disc_destroy (pcddb_disc); if (pcddb_conn != NULL) cddb_destroy (pcddb_conn); } return; ERR: g_free (trackinfo); trackinfo = NULL; }
static PyObject* CDImage_last_sector(cdio_CDImage* self, PyObject *args) { return Py_BuildValue("i", cdio_get_track_last_lsn(self->image, cdio_get_last_track_num(self->image))); }
static PyObject* CDImage_total_tracks(cdio_CDImage* self) { track_t last_track = cdio_get_last_track_num(self->image); return Py_BuildValue("i", (int)last_track); }
/* 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; }
static int CDDAReader_last_track_num_image(cdio_CDDAReader *self) { return cdio_get_last_track_num(self->_.image.image); }
//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; }