Audio-FLAC-Decoder
    
    
  
  
  
view release on metacpan or search on metacpan
	union {
		double seconds;
		FLAC__int64 samples;
	} value;
} SkipUntilSpecification;
/* Allow multiple instances of the decoder object. Stuff each filehandle into (void*)stream */
typedef struct {
	int abort_flag;
	int bytes_streamed;
	int is_streaming;
	FLAC__uint64 stream_length;
	void *buffer;
	PerlIO *stream;
	decoder_t *decoder;
	FLAC__bool has_replaygain;
	/* (24/8) for max bytes per sample */
	FLAC__byte sample_buffer[SAMPLES_PER_WRITE * FLAC__MAX_SUPPORTED_CHANNELS * (24/8)];
	FLAC__int32 reservoir[FLAC__MAX_BLOCK_SIZE * 2 * FLAC__MAX_SUPPORTED_CHANNELS];
	FLAC__uint64 decode_position_last;
	warn("FLAC decoder error_callback: %s\n", status);
}
static FLAC__StreamDecoderSeekStatus seek_callback(
	const decoder_t *decoder,
	FLAC__uint64 absolute_byte_offset, void *client_data) {
	flac_datasource *datasource = (flac_datasource *)client_data;
	/* can't seek on a socket */
	if (datasource->is_streaming) {
		return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
	}
	if (PerlIO_seek(datasource->stream, absolute_byte_offset, SEEK_SET) >= 0) {
		return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
	}
	return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
}
static FLAC__StreamDecoderTellStatus tell_callback(
	const decoder_t *decoder,
	FLAC__uint64 *absolute_byte_offset, void *client_data) {
	flac_datasource *datasource = (flac_datasource *)client_data;
	FLAC__uint64 pos = -1;
	
	/* can't tell on a socket */
	if (datasource->is_streaming) {
		return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
	}
	pos = PerlIO_tell(datasource->stream);
	if (pos < 0) {
		return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
	}
	*absolute_byte_offset = pos;
	return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
static FLAC__StreamDecoderLengthStatus length_callback(
	const decoder_t *decoder,
	FLAC__uint64 *stream_length, void *client_data) {
	flac_datasource *datasource = (flac_datasource *)client_data;
	/* can't find the total length of a socket */
	if (datasource->is_streaming) {
		return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
	}
	*stream_length = datasource->stream_length;
	return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
static FLAC__bool eof_callback(
	const decoder_t *decoder, void *client_data) {
	flac_datasource *datasource = (flac_datasource *)client_data;
	FLAC__uint64 pos = 0;
	if (datasource->is_streaming) {
		return false;
	}
	pos = PerlIO_tell(datasource->stream);
	if (pos >= 0 && pos >= datasource->stream_length) {
		/* printf("stream length: %d pos: %d\n", datasource->stream_length, pos); */
		return true;
	}
			FLACdecoder_finish(datasource->decoder);
			FLACdecoder_delete(datasource->decoder);
			safefree(datasource);
			warn("failed on open: [%d] - [%s]\n", errno, strerror(errno));
			XSRETURN_UNDEF;
		}
		datasource->is_streaming = 0;
	} else if (SvOK(path)) {
		/* Did we get a Glob, or a IO::Socket subclass?
		 *
		 * XXX This should really be a class method so the caller
		 * can tell us if it's streaming or not. But how to do this on
		 * a per object basis without changing open()s arugments. That
		 * may be the easiest/only way. XXX
		 *
		 */
		if (sv_isobject(path) && sv_derived_from(path, "IO::Socket")) {
			datasource->is_streaming = 1;
		} else {
			datasource->is_streaming = 0;
		}
		/* dereference and get the SV* that contains the Magic & FH,
		 * then pull the fd from the PerlIO object */
		datasource->stream = IoIFP(GvIOp(SvRV(path)));
	} else {
		XSRETURN_UNDEF;
	}
	if (!datasource->is_streaming) {
		pos = PerlIO_tell(datasource->stream);
		if (PerlIO_seek(datasource->stream, 0, SEEK_END) != -1) {
		
			datasource->stream_length = PerlIO_tell(datasource->stream);
			if (PerlIO_seek(datasource->stream, pos, SEEK_SET) == -1) {
				FLACdecoder_finish(datasource->decoder);
	long pos;
	int whence;
	CODE:
	{
	HV *self = (HV *) SvRV(obj);
	flac_datasource *datasource = (flac_datasource *) SvIV(*(my_hv_fetch(self, "DATASOURCE")));
	/* can't seek on a socket. */
	if (datasource->is_streaming) {
		XSRETURN_UNDEF;
	}
	if (!FLAC__stream_decoder_reset(datasource->decoder)) {
		XSRETURN_UNDEF;
	}
	RETVAL = PerlIO_seek(datasource->stream, pos, whence);
	}
( run in 0.267 second using v1.01-cache-2.11-cpan-5dc5da66d9d )