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", §ors_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; } }
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; }
/*! 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; }
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); }
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", §ors_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; }
/* 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; }
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; }