Ejemplo n.º 1
0
static void device_open(ripncode_t *r)
{
    char *msg = NULL;

    r->cdio = cdio_open(r->device, driver_id(r));

    if (r->cdio == NULL)
        ripncode_fatal(r, "failed to open CdIo device '%s' with driver '%s'",
                       r->device, r->driver);

    r->cdda = cdio_cddap_identify_cdio(r->cdio, CDDA_MESSAGE_LOGIT, &msg);

    if (r->cdda == NULL)
        ripncode_fatal(r, "failed to identify CDDA device '%s' (%s)", r->device,
                       msg ? msg : "unknown error");

    cdio_cddap_free_messages(msg);

    if (cdio_cddap_open(r->cdda) < 0)
        ripncode_fatal(r, "failed to open CDDA device '%s' (%d: %s)", r->device,
                       errno, strerror(errno));

    r->cdpa = cdio_paranoia_init(r->cdda);

    if (r->cdpa == NULL)
        ripncode_fatal(r, "failed to open CD-Paranoia device '%s'", r->device);

    r->endian = data_bigendianp(r->cdda);

    ripncode_info(r, "Drive endianness: %d\n", r->endian);
}
Ejemplo n.º 2
0
static int cdpa_open(rnc_dev_t *dev, const char *device)
{
    cdpa_t *cdpa;
    char   *msg;

    mrp_debug("opening device '%s' with cdparanoia", device);

    msg  = NULL;
    cdpa = dev->data = mrp_allocz(sizeof(*cdpa));

    if (cdpa == NULL)
        goto fail;

    cdpa->cdio = cdio_open(device, DRIVER_LINUX);

    if (cdpa->cdio == NULL) {
        msg = "failed open device";
        goto fail;
    }

    cdpa->cdda = cdio_cddap_identify_cdio(cdpa->cdio, CDDA_MESSAGE_LOGIT, &msg);

    if (cdpa->cdda == NULL)
        goto fail;

    cdio_cddap_free_messages(msg);
    msg = NULL;

    if (cdio_cddap_open(cdpa->cdda) < 0) {
        msg = "failed to CDDAP-open device";
        goto fail;
    }

    cdpa->cdpa = cdio_paranoia_init(cdpa->cdda);

    if (cdpa->cdpa == NULL) {
        msg = "failed to initialize cd-paranoia";
        goto fail;
    }

    cdpa->ctrack = -1;

    return 0;

 fail:
    if (cdpa != NULL && msg != NULL)
        cdpa->errmsg = mrp_strdup(msg);

    return -1;
}
Ejemplo n.º 3
0
void CddaImpl::open()
{
   driver_id_t driver_id = DRIVER_UNKNOWN;

   if (_device.empty())
   {
   char **ppsz_cd_drives = cdio_get_devices_with_cap_ret(NULL,  
                                                         CDIO_FS_AUDIO, 
                                                         false,
                                                         &driver_id);
   if (ppsz_cd_drives && *ppsz_cd_drives)
      _device = ppsz_cd_drives[0];

   cdio_free_device_list(ppsz_cd_drives);
   }

   _cdio = cdio_open(_device.c_str(), driver_id);

   if (_cdio == NULL) 
   {
      THROW_EXCEPTION(CddaException, "Could not open device.");
   }

   // Detect empty drive   
   if (cdio_get_first_track_num(_cdio) == CDIO_INVALID_TRACK) 
   {
      close();
      return;
   }

   _cdrom = cdio_cddap_identify_cdio(_cdio, CDDA_MESSAGE_LOGIT, NULL);

   if (_cdrom == NULL) 
   {
      THROW_EXCEPTION(CddaException, "Could not read cdrom structure.");
   }

   cdio_cddap_verbose_set(_cdrom, CDDA_MESSAGE_LOGIT, CDDA_MESSAGE_LOGIT);

   int ret = cdio_cddap_open(_cdrom);
   if (ret != 0) 
   {
      THROW_EXCEPTION(CddaException, cdda_error_message(ret));
   }

   _is_open = true;

   read_toc();
   //read_cddb();
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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);
    }
}
Ejemplo n.º 6
0
/* 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 struct input_stream *
input_cdio_open(const char *uri,
		GMutex *mutex, GCond *cond,
		GError **error_r)
{
	struct input_cdio_paranoia *i;

	struct cdio_uri parsed_uri;
	if (!parse_cdio_uri(&parsed_uri, uri, error_r))
		return NULL;

	i = g_new(struct input_cdio_paranoia, 1);
	input_stream_init(&i->base, &input_plugin_cdio_paranoia, uri,
			  mutex, cond);

	/* initialize everything (should be already) */
	i->drv = NULL;
	i->cdio = NULL;
	i->para = NULL;
	i->trackno = parsed_uri.track;
	pcm_buffer_init(&i->conv_buffer);

	/* get list of CD's supporting CD-DA */
	char *device = parsed_uri.device[0] != 0
		? g_strdup(parsed_uri.device)
		: cdio_detect_device();
	if (device == NULL) {
		g_set_error(error_r, cdio_quark(), 0,
			    "Unable find or access a CD-ROM drive with an audio CD in it.");
		input_cdio_close(&i->base);
		return NULL;
	}

	/* Found such a CD-ROM with a CD-DA loaded. Use the first drive in the list. */
	i->cdio = cdio_open(device, DRIVER_UNKNOWN);
	g_free(device);

	i->drv = cdio_cddap_identify_cdio(i->cdio, 1, NULL);

	if ( !i->drv ) {
		g_set_error(error_r, cdio_quark(), 0,
			    "Unable to identify audio CD disc.");
		input_cdio_close(&i->base);
		return NULL;
	}

	cdda_verbose_set(i->drv, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);

	if ( 0 != cdio_cddap_open(i->drv) ) {
		g_set_error(error_r, cdio_quark(), 0, "Unable to open disc.");
		input_cdio_close(&i->base);
		return NULL;
	}

	i->endian = data_bigendianp(i->drv);
	switch (i->endian) {
	case -1:
		g_debug("cdda: drive returns unknown audio data, assuming Little Endian");
		i->endian = 0;
		break;
	case 0:
		g_debug("cdda: drive returns audio data Little Endian.");
		break;
	case 1:
		g_debug("cdda: drive returns audio data Big Endian.");
		break;
	default:
		g_set_error(error_r, cdio_quark(), 0,
			    "Drive returns unknown data type %d", i->endian);
		input_cdio_close(&i->base);
		return NULL;
	}

	i->lsn_relofs = 0;

	if (i->trackno >= 0) {
		i->lsn_from = cdio_get_track_lsn(i->cdio, i->trackno);
		i->lsn_to = cdio_get_track_last_lsn(i->cdio, i->trackno);
	} else {
		i->lsn_from = 0;
		i->lsn_to = cdio_get_disc_last_lsn(i->cdio);
	}

	i->para = cdio_paranoia_init(i->drv);

	/* Set reading mode for full paranoia, but allow skipping sectors. */
	paranoia_modeset(i->para, PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP);

	/* seek to beginning of the track */
	cdio_paranoia_seek(i->para, i->lsn_from, SEEK_SET);

	i->base.ready = true;
	i->base.seekable = true;
	i->base.size = (i->lsn_to - i->lsn_from + 1) * CDIO_CD_FRAMESIZE_RAW;

	/* hack to make MPD select the "pcm" decoder plugin */
	i->base.mime = g_strdup("audio/x-mpd-cdda-pcm");

	return &i->base;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
// pure virtual
bool CdDecoder::initialize()
{
    if (m_inited)
        return true;

    m_inited = m_user_stop = m_finish = false;
    m_freq = m_bitrate = 0L;
    m_stat = DecoderEvent::Error;
    m_chan = 0;
    m_seekTime = -1.;

    if (output())
        output()->PauseUntilBuffered();

    QFile* file = dynamic_cast< QFile* >(input()); // From QIODevice*
    if (file)
    {
        setFilename(file->fileName());
        m_tracknum = getFilename().section('.', 0, 0).toUInt();
    }

    QMutexLocker lock(&getCdioMutex());

    m_cdio = openCdio(m_devicename);
    if (!m_cdio)
        return false;

    m_start = cdio_get_track_lsn(m_cdio, m_tracknum);
    m_end = cdio_get_track_last_lsn(m_cdio, m_tracknum);
    if (CDIO_INVALID_LSN  == m_start ||
        CDIO_INVALID_LSN  == m_end)
    {
        LOG(VB_MEDIA, LOG_INFO, "CdDecoder: No tracks on " + m_devicename);
        cdio_destroy(m_cdio), m_cdio = 0;
        return false;
    }

    LOG(VB_MEDIA, LOG_DEBUG, QString("CdDecoder track=%1 lsn start=%2 end=%3")
            .arg(m_tracknum).arg(m_start).arg(m_end));
    m_curpos = m_start;

    m_device = cdio_cddap_identify_cdio(m_cdio, 0, NULL);
    if (NULL == m_device)
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("Error: CdDecoder: cdio_cddap_identify(%1) failed")
                .arg(m_devicename));
        cdio_destroy(m_cdio), m_cdio = 0;
        return false;
    }

    cdio_cddap_verbose_set(m_device,
        VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_ANY) ? CDDA_MESSAGE_PRINTIT :
            CDDA_MESSAGE_FORGETIT,
        VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_DEBUG) ? CDDA_MESSAGE_PRINTIT :
            CDDA_MESSAGE_FORGETIT);

    if (DRIVER_OP_SUCCESS == cdio_cddap_open(m_device))
    {
        // cdio_get_track_last_lsn is unreliable on discs with data at end
        lsn_t end2 = cdio_cddap_track_lastsector(m_device, m_tracknum);
        if (end2 < m_end)
        {
            LOG(VB_MEDIA, LOG_INFO, QString("CdDecoder: trim last lsn from %1 to %2")
                .arg(m_end).arg(end2));
            m_end = end2;
        }

        m_paranoia = cdio_paranoia_init(m_device);
        if (NULL != m_paranoia)
        {
            cdio_paranoia_modeset(m_paranoia, PARANOIA_MODE_DISABLE);
            (void)cdio_paranoia_seek(m_paranoia, m_start, SEEK_SET);
        }
        else
        {
            LOG(VB_GENERAL, LOG_ERR, "Warn: CD reading with paranoia is disabled");
        }
    }
    else
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("Warn: drive '%1' is not cdda capable").
            arg(m_devicename));
    }

    int chnls = cdio_get_track_channels(m_cdio, m_tracknum);
    m_chan = chnls > 0 ? chnls : 2;
    m_freq = kSamplesPerSec;

    if (output())
    {
        const AudioSettings settings(FORMAT_S16, m_chan,
            CODEC_ID_PCM_S16LE, m_freq, false /* AC3/DTS passthru */);
        output()->Reconfigure(settings);
        output()->SetSourceBitrate(m_freq * m_chan * 16);
    }

    // 20ms worth
    m_bks = (m_freq * m_chan * 2) / 50;
    m_bksFrames = m_freq / 50;
    // decode 8 bks worth of samples each time we need more
    m_decodeBytes = m_bks << 3;

    m_output_buf = reinterpret_cast< char* >(
        ::av_malloc(m_decodeBytes + CDIO_CD_FRAMESIZE_RAW * 2));
    m_output_at = 0;

    setCDSpeed(2);
    m_inited = true;

    return m_inited;
}