Пример #1
0
static PyObject*
CDImage_read_sectors(cdio_CDImage* self, PyObject *args) {
    uint32_t sectors_to_read;
    uint8_t* data;
    PyObject* to_return;

    if (!PyArg_ParseTuple(args, "I", &sectors_to_read))
        return NULL;

    data = malloc(CDIO_CD_FRAMESIZE_RAW * sectors_to_read);
    switch (cdio_read_audio_sectors(self->image,
                                    data,
                                    self->current_sector,
                                    sectors_to_read)) {
    case DRIVER_OP_SUCCESS:
        to_return = PyObject_CallMethod(self->pcm_module,
                                        "FrameList",
                                        "s#iiii",
                                        (char *)data,
                                        (int)(CDIO_CD_FRAMESIZE_RAW *
                                              sectors_to_read),
                                        2, 16, 0, 1);
        free(data);
        self->current_sector += sectors_to_read;
        return to_return;
    default:
        free(data);
        PyErr_SetString(PyExc_IOError, "error reading sectors");
        return NULL;
    }
}
Пример #2
0
int
cda_read (DB_fileinfo_t *_info, char *bytes, int size) {
    cdda_info_t *info = (cdda_info_t *)_info;
    int extrasize = 0;
    
    if (info->tail_len > 0)
    {
        if (info->tail_len >= size)
        {
//            trace ("Easy case\n");
            memcpy (bytes, info->tail, size);
            info->tail_len -= size;
            memmove (info->tail, info->tail+size, info->tail_len);
            return size;
        }
//        trace ("Prepending with tail of %d bytes\n", tail_len);
        extrasize = info->tail_len;
        memcpy (bytes, info->tail, info->tail_len);
        bytes += info->tail_len;
        size -= info->tail_len;
        info->tail_len = 0;
    }

    int sectors_to_read = size / SECTORSIZE + 1;
    int end = 0;
    
    if (info->current_sector + sectors_to_read > info->first_sector + info->sector_count) // reached end of track
    {
        end = 1;
        sectors_to_read = info->first_sector + info->sector_count - info->current_sector;
//        trace ("cdda: reached end of track\n");
    }

    int bufsize = sectors_to_read * SECTORSIZE;

    info->tail_len = end ? 0 : bufsize - size;

    char *buf = alloca (bufsize);

    driver_return_code_t ret = cdio_read_audio_sectors (info->cdio, buf, info->current_sector, sectors_to_read);
    if (ret != DRIVER_OP_SUCCESS)
        return 0;
    info->current_sector += sectors_to_read;

    int retsize = end ? bufsize : size;

    memcpy (bytes, buf, retsize);
    if (!end)
        memcpy (info->tail, buf+retsize, info->tail_len);

    retsize += extrasize;
//    trace ("requested: %d; tail_len: %d; size: %d; sectors_to_read: %d; return: %d\n", initsize, tail_len, size, sectors_to_read, retsize);
    info->current_sample += retsize / SAMPLESIZE;
    _info->readpos = (float)info->current_sample / _info->fmt.samplerate;
    return retsize;
}
Пример #3
0
/*!
  Reads a number of sectors (AKA blocks).

  @param p_buf place to read data into. The caller should make sure
  this location is large enough. See below for size information.
  @param read_mode the kind of "mode" to use in reading.
  @param i_lsn sector to read
  @param i_blocks number of sectors to read
  @return DRIVER_OP_SUCCESS (0) if no error, other (negative) enumerations
  are returned on error.

  If read_mode is CDIO_MODE_AUDIO,
    *p_buf should hold at least CDIO_FRAMESIZE_RAW * i_blocks bytes.

  If read_mode is CDIO_MODE_DATA,
    *p_buf should hold at least i_blocks times either ISO_BLOCKSIZE,
    M1RAW_SECTOR_SIZE or M2F2_SECTOR_SIZE depending on the kind of
    sector getting read. If you don't know whether you have a Mode 1/2,
    Form 1/ Form 2/Formless sector best to reserve space for the maximum
    which is M2RAW_SECTOR_SIZE.

  If read_mode is CDIO_MODE_M2F1,
    *p_buf should hold at least M2RAW_SECTOR_SIZE * i_blocks bytes.

  If read_mode is CDIO_MODE_M2F2,
    *p_buf should hold at least CDIO_CD_FRAMESIZE * i_blocks bytes.


*/
driver_return_code_t
cdio_read_sectors(const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn,
                  cdio_read_mode_t read_mode, uint32_t i_blocks)
{
    switch(read_mode) {
    case CDIO_READ_MODE_AUDIO:
        return cdio_read_audio_sectors (p_cdio, p_buf, i_lsn, i_blocks);
    case CDIO_READ_MODE_M1F1:
        return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, false, i_blocks);
    case CDIO_READ_MODE_M1F2:
        return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, true,  i_blocks);
    case CDIO_READ_MODE_M2F1:
        return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, false, i_blocks);
    case CDIO_READ_MODE_M2F2:
        return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, true,  i_blocks);
    }
    /* Can't happen. Just to shut up gcc. */
    return DRIVER_OP_ERROR;
}
Пример #4
0
static long int
read_blocks (cdrom_drive_t *d, void *p, lsn_t begin, long i_sectors)
{
  int retry_count = 0;
  int err;
  char *buffer=(char *)p;

  do {
    err = cdio_read_audio_sectors( d->p_cdio, buffer, begin, i_sectors);
    
    if ( 0 != err ) {
      if (!d->error_retry) return -7;
      
      if (i_sectors==1) {
	/* *Could* be I/O or media error.  I think.  If we're at
	   30 retries, we better skip this unhappy little
	   sector. */
	if (retry_count>MAX_RETRIES-1) {
	  char b[256];
	  snprintf(b, sizeof(b), 
		   "010: Unable to access sector %ld: skipping...\n",
		   (long int) begin);
	  cderror(d, b);
	  return -10;
	}
	break;
      }

      if(retry_count>4)
	if(i_sectors>1)
	  i_sectors=i_sectors*3/4;
      retry_count++;
      if (retry_count>MAX_RETRIES) {
	cderror(d,"007: Unknown, unrecoverable error reading data\n");
	return(-7);
      }
    } else
      break;
  } while (err);
  
  return(i_sectors);
}
Пример #5
0
static PyObject*
CDImage_read_sectors(cdio_CDImage* self, PyObject *args) {
    int sectors_to_read;
    uint8_t* data;
    PyObject* to_return;
    int result;

    if (!PyArg_ParseTuple(args, "i", &sectors_to_read)) {
        return NULL;
    } else if (sectors_to_read < 0) {
        PyErr_SetString(PyExc_ValueError, "sectors to read must be >= 0");
        return NULL;
    }

    data = malloc(CDIO_CD_FRAMESIZE_RAW * sectors_to_read);

    Py_BEGIN_ALLOW_THREADS
    result = cdio_read_audio_sectors(self->image,
                                     data,
                                     self->current_sector,
                                     sectors_to_read);
    Py_END_ALLOW_THREADS

    if (result == DRIVER_OP_SUCCESS) {
        to_return = PyObject_CallMethod(self->pcm_module,
                                        "FrameList",
                                        "s#iiii",
                                        (char *)data,
                                        (int)(CDIO_CD_FRAMESIZE_RAW *
                                              sectors_to_read),
                                        2, 16, 0, 1);
        free(data);
        self->current_sector += sectors_to_read;
        return to_return;
    } else {
        free(data);
        PyErr_SetString(PyExc_IOError, "error reading sectors");
        return NULL;
    }
}
static long int
read_blocks (cdrom_drive_t *d, void *p, lsn_t begin, long i_sectors)
{
  int retry_count = 0;
  int err;
  int ret = 0;
  char *buffer=(char *)p;

  if(p==NULL)buffer = malloc(i_sectors*CD_FRAMESIZE_RAW);

  do {
    struct timespec tv1;
    struct timespec tv2;
    int ret1,ret2;

    ret1 = gettime(&tv1);
    err  = cdio_read_audio_sectors( d->p_cdio, buffer, begin, i_sectors);
    ret2 = gettime(&tv2);

    if(ret1<0 || ret2<0) {
      d->last_milliseconds=-1;
    } else {
      d->last_milliseconds = (tv2.tv_sec-tv1.tv_sec)*1000. + (tv2.tv_nsec-tv1.tv_nsec)/1000000.;
    }

    if ( DRIVER_OP_SUCCESS != err ) {
      if (!d->error_retry) {
	ret=-7;
	goto done;
      }

      if (i_sectors==1) {
	/* *Could* be I/O or media error.  I think.  If we're at
	   30 retries, we better skip this unhappy little
	   sector. */
	if (retry_count>MAX_RETRIES-1) {
	  char b[256];
	  snprintf(b, sizeof(b),
		   "010: Unable to access sector %ld: skipping...\n",
		   (long int) begin);
	  cderror(d, b);
	  ret=-10;
	  goto done;
	}
      }

      if(retry_count>4)
	if(i_sectors>1)
	  i_sectors=i_sectors*3/4;
      retry_count++;
      if (retry_count>MAX_RETRIES) {
	cderror(d,"007: Unknown, unrecoverable error reading data\n");
	ret=-7;
	goto done;
      }
    } else
      break;
  } while (err);

  ret=i_sectors;

 done:
  if(p==NULL && buffer)free(buffer);
  return ret;
}
Пример #7
0
/* play thread only */
static gboolean cdaudio_play (InputPlayback * p, const gchar * name, VFSFile *
 file, gint start, gint stop, gboolean pause)
{
    g_mutex_lock (mutex);

    if (trackinfo == NULL)
    {
        refresh_trackinfo (TRUE);

        if (trackinfo == NULL)
        {
ERR:
            g_mutex_unlock (mutex);
            return FALSE;
        }
    }

    gint trackno = find_trackno_from_filename (name);

    if (trackno < 0)
    {
        cdaudio_error ("Invalid URI %s.", name);
        goto ERR;
    }

    if (trackno < firsttrackno || trackno > lasttrackno)
    {
        cdaudio_error ("Track %d not found.", trackno);
        goto ERR;
    }

    /* don't play any data tracks */
    if (!cdda_track_audiop (pcdrom_drive, trackno))
    {
        cdaudio_error ("Track %d is a data track.\n", trackno);
        goto ERR;
    }

    gint startlsn = trackinfo[trackno].startlsn;
    gint endlsn = trackinfo[trackno].endlsn;

    if (! p->output->open_audio (FMT_S16_LE, 44100, 2))
    {
        cdaudio_error ("Failed to open audio output.");
        goto ERR;
    }

    seek_time = (start > 0) ? start : -1;
    stop_flag = FALSE;

    if (stop >= 0)
        endlsn = MIN (endlsn, startlsn + stop * 75 / 1000);

    if (pause)
        p->output->pause (TRUE);

    p->set_params (p, 1411200, 44100, 2);
    p->set_pb_ready (p);

    g_mutex_unlock (mutex);

    gint buffer_size = mlp_get_int (NULL, "output_buffer_size");
    gint sectors = CLAMP (buffer_size / 2, 50, 250) * cdng_cfg.disc_speed * 75 / 1000;
    guchar buffer[2352 * sectors];
    gint currlsn = startlsn;
    gint retry_count = 0, skip_count = 0;

    while (1)
    {
        g_mutex_lock (mutex);

        if (stop_flag)
        {
            g_mutex_unlock (mutex);
            goto CLOSE;
        }

        if (seek_time >= 0)
        {
            p->output->flush (seek_time);
            currlsn = startlsn + (seek_time * 75 / 1000);
            seek_time = -1;
        }

        g_mutex_unlock (mutex);

        sectors = MIN (sectors, endlsn + 1 - currlsn);
        if (sectors < 1)
            break;

        if (cdio_read_audio_sectors (pcdrom_drive->p_cdio, buffer, currlsn, sectors) ==
         DRIVER_OP_SUCCESS)
        {
            retry_count = 0;
            skip_count = 0;
        }
        else if (sectors > 16)
        {
            warn ("Read failed; reducing read size.\n");
            sectors /= 2;
            continue;
        }
        else if (retry_count < MAX_RETRIES)
        {
            warn ("Read failed; retrying.\n");
            retry_count ++;
            continue;
        }
        else if (skip_count < MAX_SKIPS)
        {
            warn ("Read failed; skipping.\n");
            currlsn = MIN (currlsn + 75, endlsn + 1);
            skip_count ++;
            continue;
        }
        else
        {
            cdaudio_error ("Too many read errors; giving up.");
            break;
        }

        p->output->write_audio (buffer, 2352 * sectors);
        currlsn += sectors;
    }

    while (p->output->buffer_playing ())
        g_usleep (20000);

    g_mutex_lock (mutex);
    stop_flag = FALSE;
    g_mutex_unlock (mutex);

CLOSE:
    p->output->close_audio ();
    return TRUE;
}
Пример #8
0
static driver_return_code_t cued_read_audio(rip_context_t *rip, lsn_t firstSector, long sectors, audio_buffer_t *pbuf, int retry)
{
    mmc_read_cd_fn readfn;
    uint8_t *mbuf, *dbuf;
    int blockSize, subchannel, i;
    driver_return_code_t drc;
    qsc_file_buffer_t qsc;

    blockSize = sizeof(audio_buffer_t);

    if (ripGetIndices || rip->qSubChannelFileName) {
        if (ripUseFormattedQsc) {
            subchannel = 2;
            blockSize += sizeof(qsc_buffer_t);
        } else {
            blockSize += sizeof(mmc_raw_pwsc_t);
            if (ripUseEccQsc) {
                subchannel = 4;
            } else {
                subchannel = 1;
            }
        }
    } else {
        subchannel = 0;
    }

    // TODO:  should check for ripRead* be both here and in cued_rip_to_file?
    // does paranoia present a problem?
    //

    if (ripReadPregap && firstSector < 0) {
        readfn = mmc_read_cd_msf;
    } else if (ripReadLeadout && firstSector + sectors > rip->endOfDiscSector) {
        if (firstSector >= rip->endOfDiscSector) {
            readfn = mmc_read_cd_leadout;
        } else {
            readfn = mmc_read_cd;
            cdio_warn("reading lead-out");
        }
    } else if (subchannel || ripDapFixup) {
        readfn = mmc_read_cd;
    } else {
        readfn = NULL;
    }

    if (sectors > rip->allocatedSectors) {
        free(rip->mmcBuf);
        rip->mmcBuf = (uint8_t *) malloc(sectors * blockSize);
        if (rip->mmcBuf) {
            rip->allocatedSectors = sectors;
        } else {
            rip->allocatedSectors = 0;
            cdio2_abort("out of memory reading %ld sectors", sectors);
        }
    }

    do {

        if (readfn) {

            drc = readfn(
                rip->cdObj,
                (pbuf && !subchannel) ? (void *) pbuf : rip->mmcBuf,
                firstSector,

                // expected read_sector_type;  could be CDIO_MMC_READ_TYPE_CDDA
                CDIO_MMC_READ_TYPE_ANY,

                // DAP (Digital Audio Play)
                ripDapFixup ? true : false,

                // return SYNC header
                false,

                // header codes
                0,

                // must return user data according to mmc5 spec
                true,

                // no EDC or ECC is included with audio data
                false,

                // C2 error information is synthetic;  it is not needed to get Q sub-channel,
                // even though it is an adjacent field according to the standard
                //
                false,

                subchannel,
                blockSize,
                sectors);

            if (DRIVER_OP_SUCCESS == drc) {

                if (subchannel) {

                    mbuf = dbuf = rip->mmcBuf;
                    for (i = 0;  i < sectors;  ++i) {

                        if (pbuf) {
                            memcpy(pbuf[i].buf, mbuf, sizeof(audio_buffer_t));
                        } else {
                            //dbuf = rip->mmcBuf + i * sizeof(audio_buffer_t);
                            if (dbuf != mbuf) {
                                memmove(dbuf, mbuf, sizeof(audio_buffer_t));
                            }
                            dbuf += sizeof(audio_buffer_t);
                        }
                        mbuf += sizeof(audio_buffer_t);

                        // if (subchannel) {

                        if (ripUseFormattedQsc) {
                            memcpy(&qsc.buf, mbuf, sizeof(qsc_buffer_t));
                            mbuf += sizeof(qsc_buffer_t);
                        } else {
                            pwsc_get_qsc((mmc_raw_pwsc_t *) mbuf, &qsc.buf);
                            mbuf += sizeof(mmc_raw_pwsc_t);
                        }

                        if (ripGetIndices) {
                            cued_parse_qsc(&qsc.buf, rip);
                        }

                        if (!ripUseParanoia && rip->qSubChannelFileName) {
                            qsc.requested = firstSector + i;
                            if (1 != fwrite(&qsc, sizeof(qsc), 1, rip->qSubChannelFile)) {
                                // probably out of disk space, which is bad, because most things rely on it
                                cdio2_unix_error("fwrite", rip->qSubChannelFileName, 0);
                                cdio2_abort("failed to write to file \"%s\"", rip->qSubChannelFileName);
                            }
                        }
                    }
                }

                return drc;
            }

        } else {

            drc = cdio_read_audio_sectors(rip->cdObj, pbuf ? (void *) pbuf : rip->mmcBuf, firstSector, sectors);
            if (DRIVER_OP_SUCCESS == drc) {
                return drc;
            }
        }

        cdio2_driver_error(drc, "read of audio sector");

    } while (retry--);

    cdio_error("skipping extraction of audio sectors %d through %ld in track %02d", firstSector, firstSector + sectors - 1, rip->currentTrack);

    return drc;
}