示例#1
0
static int
CDDA_init(cdio_CDDAObject *self, PyObject *args, PyObject *kwds)
{
    const char *drive = NULL;
    self->pcm_module = NULL;

    if (!PyArg_ParseTuple(args, "s", &drive))
        return -1;

    if ((self->pcm_module = PyImport_ImportModule("audiotools.pcm")) == NULL)
        return -1;

    self->cdrom_drive = cdio_cddap_identify(drive, 0, NULL);
    if (self->cdrom_drive == NULL) {
        PyErr_SetString(PyExc_IOError,
                        "error opening CD-ROM");
        return -1;
    }

    if (0 != cdio_cddap_open(self->cdrom_drive)) {
        PyErr_SetString(PyExc_IOError,
                        "error opening CD-ROM");
        return -1;
    }

    self->paranoia = cdio_paranoia_init(self->cdrom_drive);
    paranoia_modeset(self->paranoia,
                     PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP);

    return 0;
}
示例#2
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);
}
示例#3
0
bool CdParanoia::init()
{
    free();
    #ifdef CDIOPARANOIA_FOUND
    drive = cdda_identify(dev.toLatin1().data(), 0, 0);
    #else
    drive = cdda_identify(dev.toLatin1().data(), 0, 0);
    #endif
    if (!drive) {
        return false;
    }

    #ifdef CDIOPARANOIA_FOUND
    cdio_cddap_open(drive);
    paranoia = cdio_paranoia_init(drive);
    #else
    cdda_open(drive);
    paranoia = paranoia_init(drive);
    #endif
    if (paranoia == 0) {
        free();
        return false;
    }

    return true;
}
static av_cold int read_header(AVFormatContext *ctx)
{
    CDIOContext *s = ctx->priv_data;
    AVStream *st;
    int ret, i;
    char *err = NULL;

    if (!(st = avformat_new_stream(ctx, NULL)))
        return AVERROR(ENOMEM);
    s->drive = cdio_cddap_identify(ctx->filename, CDDA_MESSAGE_LOGIT, &err);
    if (!s->drive) {
        av_log(ctx, AV_LOG_ERROR, "Could not open drive %s.\n", ctx->filename);
        return AVERROR(EINVAL);
    }
    if (err) {
        av_log(ctx, AV_LOG_VERBOSE, "%s\n", err);
        free(err);
    }
    if ((ret = cdio_cddap_open(s->drive)) < 0 || !s->drive->opened) {
        av_log(ctx, AV_LOG_ERROR, "Could not open disk in drive %s.\n", ctx->filename);
        return AVERROR(EINVAL);
    }

    cdio_cddap_verbose_set(s->drive, CDDA_MESSAGE_LOGIT, CDDA_MESSAGE_LOGIT);
    if (s->speed)
        cdio_cddap_speed_set(s->drive, s->speed);

    s->paranoia = cdio_paranoia_init(s->drive);
    if (!s->paranoia) {
        av_log(ctx, AV_LOG_ERROR, "Could not init paranoia.\n");
        return AVERROR(EINVAL);
    }
    cdio_paranoia_modeset(s->paranoia, s->paranoia_mode);

    st->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
    if (s->drive->bigendianp)
        st->codec->codec_id    = AV_CODEC_ID_PCM_S16BE;
    else
        st->codec->codec_id    = AV_CODEC_ID_PCM_S16LE;
    st->codec->sample_rate     = 44100;
    st->codec->channels        = 2;
    if (s->drive->audio_last_sector != CDIO_INVALID_LSN &&
        s->drive->audio_first_sector != CDIO_INVALID_LSN)
        st->duration           = s->drive->audio_last_sector - s->drive->audio_first_sector;
    else if (s->drive->tracks)
        st->duration = s->drive->disc_toc[s->drive->tracks].dwStartSector;
    avpriv_set_pts_info(st, 64, CDIO_CD_FRAMESIZE_RAW, 2*st->codec->channels*st->codec->sample_rate);

    for (i = 0; i < s->drive->tracks; i++) {
        char title[16];
        snprintf(title, sizeof(title), "track %02d", s->drive->disc_toc[i].bTrack);
        avpriv_new_chapter(ctx, i, st->time_base, s->drive->disc_toc[i].dwStartSector,
                       s->drive->disc_toc[i+1].dwStartSector, title);
    }

    s->last_sector = cdio_cddap_disc_lastsector(s->drive);

    return 0;
}
示例#5
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;
}
示例#6
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();
}
static int
CDDAReader_init_device(cdio_CDDAReader *self, const char *device)
{
    self->_.drive.drive = NULL;
    self->_.drive.paranoia = NULL;
    self->_.drive.current_sector = 0;
    self->_.drive.final_sector = 0;

    if ((self->_.drive.drive = cdio_cddap_identify(device, 0, NULL)) == NULL) {
        PyErr_SetString(PyExc_IOError, "error opening CD-ROM");
        return -1;
    }
    if (cdio_cddap_open(self->_.drive.drive) != 0) {
        PyErr_SetString(PyExc_IOError, "error opening CD-ROM");
        return -1;
    }
    self->_.drive.paranoia = cdio_paranoia_init(self->_.drive.drive);
    paranoia_modeset(self->_.drive.paranoia,
                     PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP);

    self->first_track_num  = CDDAReader_first_track_num_device;
    self->last_track_num = CDDAReader_last_track_num_device;
    self->track_lsn = CDDAReader_track_lsn_device;
    self->track_last_lsn = CDDAReader_track_last_lsn_device;
    self->first_sector = CDDAReader_first_sector_device;
    self->last_sector = CDDAReader_last_sector_device;
    self->read = CDDAReader_read_device;
    self->seek = CDDAReader_seek_device;
    self->set_speed = CDDAReader_set_speed_device;
    self->dealloc = CDDAReader_dealloc_device;

    self->_.drive.final_sector = self->last_sector(self);

    if ((self->_.drive.final_sector == -1) ||
            (self->first_sector(self) == -1)) {
        PyErr_SetString(PyExc_IOError, "no disc in CD-ROM drive");
        return -1;
    }

    return 0;
}
		cdio() {
			/* See if we can find a device with a loaded CD-DA in it. */
			ppsz_cd_drives = cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);

			if (ppsz_cd_drives) {
				/* Found such a CD-ROM with a CD-DA loaded. Use the first drive in the list. */
				d = cdio_cddap_identify(*ppsz_cd_drives, 1, NULL);
			} else {
				printf("Unable find or access a CD-ROM drive with an audio CD in it.\n");
			}

			/* Don't need a list of CD's with CD-DA's any more. */
			if (ppsz_cd_drives) cdio_free_device_list(ppsz_cd_drives);

			/* We'll set for verbose paranoia messages. */
			if (d) cdio_cddap_verbose_set(d, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_PRINTIT);

			if ( d && cdio_cddap_open(d) != 0 ) {
				printf("Unable to open disc.\n");
			}
		}
示例#9
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;
}
示例#10
0
文件: rip.c 项目: RomanHargrave/cued
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);
    }
}
示例#11
0
int
main(int argc, const char *argv[])
{
  cdrom_drive_t *d = NULL; /* Place to store handle given by cd-parapnioa. */
  driver_id_t driver_id;
  char **ppsz_cd_drives;  /* List of all drives with a loaded CDDA in it. */
  int i_rc=0;

  /* See if we can find a device with a loaded CD-DA in it. If successful
     drive_id will be set.  */
  ppsz_cd_drives = cdio_get_devices_with_cap_ret(NULL, CDIO_FS_AUDIO, false,
						 &driver_id);

  if (ppsz_cd_drives && *ppsz_cd_drives) {
    /* Found such a CD-ROM with a CD-DA loaded. Use the first drive in
       the list. */
    d=cdda_identify(*ppsz_cd_drives, 1, NULL);
  } else {
    printf("Unable find or access a CD-ROM drive with an audio CD in it.\n");
    exit(SKIP_TEST_RC);
  }

  /** We had a bug in is_device when driver_id == DRIVER_UNKNOWN or
     DRIVER_DEVICE. Let's make sure we've fixed that problem. **/
  if (!cdio_is_device(*ppsz_cd_drives, DRIVER_UNKNOWN) || 
      !cdio_is_device(*ppsz_cd_drives, DRIVER_DEVICE))
    exit(99);
  
  /* Don't need a list of CD's with CD-DA's any more. */
  cdio_free_device_list(ppsz_cd_drives);

  /* We'll set for verbose paranoia messages. */
  cdda_verbose_set(d, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_PRINTIT);

  if ( 0 != cdio_cddap_open(d) ) {
    printf("Unable to open disc.\n");
    exit(SKIP_TEST_RC);
  }

  /* Okay now set up to read up to the first 300 frames of the first
     audio track of the Audio CD. */
  { 
    cdrom_paranoia_t *p = paranoia_init(d);
    lsn_t i_first_lsn = cdda_disc_firstsector(d);

    if ( -1 == i_first_lsn ) {
      printf("Trouble getting starting LSN\n");
    } else {
      lsn_t   i_lsn; /* Current LSN to read */
      lsn_t   i_last_lsn = cdda_disc_lastsector(d);
      unsigned int i_sectors = i_last_lsn - i_first_lsn + 1;
      unsigned int j;
      unsigned int i_good = 0;
      unsigned int i_bad  = 0;
      
      /* Set reading mode for full paranoia, but allow skipping sectors. */
      paranoia_modeset(p, PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP);

      for ( j=0; j<10; j++ ) {
	
	/* Pick a place to start reading. */
	i_lsn = i_first_lsn + (rand() % i_sectors);
	paranoia_seek(p, i_lsn, SEEK_SET);

	printf("Testing %d sectors starting at %ld\n",
	       MAX_SECTORS, (long int) i_lsn);
	for ( i = 0; 
	      i < MAX_SECTORS && i_lsn <= i_last_lsn; 
	      i++, i_lsn++ ) {
	  /* read a sector */
	  int16_t *p_readbuf = paranoia_read(p, callback);
	  char *psz_err=cdio_cddap_errors(d);
	  char *psz_mes=cdio_cddap_messages(d);

	  memcpy(audio_buf[i], p_readbuf, CDIO_CD_FRAMESIZE_RAW);
	  
	  if (psz_mes || psz_err)
	    printf("%s%s\n", psz_mes ? psz_mes: "", psz_err ? psz_err: "");
	  
	  if (psz_err) free(psz_err);
	  if (psz_mes) free(psz_mes);
	  if( !p_readbuf ) {
	    printf("paranoia read error. Stopping.\n");
	    goto out;
	  }
	}

	/* Compare with the sectors from paranoia. */
	i_lsn -= MAX_SECTORS;
	for ( i = 0; i < MAX_SECTORS; i++, i_lsn++ ) {
	  uint8_t readbuf[CDIO_CD_FRAMESIZE_RAW] = {0,};
	  if ( PARANOIA_CB_READ == audio_status[i] || 
	       PARANOIA_CB_VERIFY == audio_status[i] ) {
	    /* We read the block via paranoia without an error. */

	    if ( 0 == cdio_read_audio_sector(d->p_cdio, readbuf, i_lsn) ) {
	      if ( BIGENDIAN != d->bigendianp ) {
		/* We will compare in the slow, pedantic way*/
		int j;
		for (j=0; j < CDIO_CD_FRAMESIZE_RAW ; j +=2) {
		  if (audio_buf[i][j]   != readbuf[j+1] && 
		      audio_buf[i][j+1] != readbuf[j] ) {
		    printf("LSN %ld doesn't match\n", (long int) i_lsn);
		    i_bad++;
		  } else {
		    i_good++;
		  }
		}
	      } else {
		if ( 0 != memcmp(audio_buf[i], readbuf, 
				 CDIO_CD_FRAMESIZE_RAW) ) {
		  printf("LSN %ld doesn't match\n", (long int) i_lsn);
		  i_bad++;
		} else {
		  i_good++;
		}
	      }
	    }
	  } else {
	    printf("Skipping LSN %ld because of status: %s\n", 
		   (long int) i_lsn, paranoia_cb_mode2str[audio_status[i]]);
	  }
	}
      }
      printf("%u sectors compared okay %u sectors were different\n",
	     i_good, i_bad);
      if (i_bad > i_good) i_rc = 1;
    }
  out: paranoia_free(p);
  }
  
  cdio_cddap_close(d);

  exit(i_rc);
}
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;
}
示例#13
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;
}
示例#14
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;
}