Add mpd-indent.sh
Indent the entire tree, hopefully we can keep it indented. git-svn-id: https://svn.musicpd.org/mpd/trunk@4410 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
@@ -38,8 +38,8 @@
|
||||
#include <FLAC/format.h>
|
||||
#include <FLAC/metadata.h>
|
||||
|
||||
void init_FlacData (FlacData * data, OutputBuffer * cb,
|
||||
DecoderControl * dc, InputStream * inStream)
|
||||
void init_FlacData(FlacData * data, OutputBuffer * cb,
|
||||
DecoderControl * dc, InputStream * inStream)
|
||||
{
|
||||
data->chunk_length = 0;
|
||||
data->time = 0;
|
||||
@@ -53,24 +53,24 @@ void init_FlacData (FlacData * data, OutputBuffer * cb,
|
||||
}
|
||||
|
||||
static int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block,
|
||||
char * cmnt, float * fl)
|
||||
char *cmnt, float *fl)
|
||||
{
|
||||
int offset = FLAC__metadata_object_vorbiscomment_find_entry_from(
|
||||
block,0,cmnt);
|
||||
int offset =
|
||||
FLAC__metadata_object_vorbiscomment_find_entry_from(block, 0, cmnt);
|
||||
|
||||
if(offset >= 0) {
|
||||
size_t pos = strlen(cmnt)+1; /* 1 is for '=' */
|
||||
if (offset >= 0) {
|
||||
size_t pos = strlen(cmnt) + 1; /* 1 is for '=' */
|
||||
int len = block->data.vorbis_comment.comments[offset].length
|
||||
-pos;
|
||||
if(len > 0) {
|
||||
- pos;
|
||||
if (len > 0) {
|
||||
unsigned char tmp;
|
||||
unsigned char * dup = &(block->data.vorbis_comment.
|
||||
comments[offset].entry[pos]);
|
||||
unsigned char *dup = &(block->data.vorbis_comment.
|
||||
comments[offset].entry[pos]);
|
||||
tmp = dup[len];
|
||||
dup[len] = '\0';
|
||||
*fl = atof((char *)dup);
|
||||
dup[len] = tmp;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -79,8 +79,9 @@ static int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block,
|
||||
}
|
||||
|
||||
/* replaygain stuff by AliasMrJones */
|
||||
static void flacParseReplayGain(const FLAC__StreamMetadata *block,
|
||||
FlacData * data) {
|
||||
static void flacParseReplayGain(const FLAC__StreamMetadata * block,
|
||||
FlacData * data)
|
||||
{
|
||||
unsigned int found = 0;
|
||||
|
||||
if (data->replayGainInfo)
|
||||
@@ -88,14 +89,14 @@ static void flacParseReplayGain(const FLAC__StreamMetadata *block,
|
||||
|
||||
data->replayGainInfo = newReplayGainInfo();
|
||||
|
||||
found &= flacFindVorbisCommentFloat(block,"replaygain_album_gain",
|
||||
&data->replayGainInfo->albumGain);
|
||||
found &= flacFindVorbisCommentFloat(block,"replaygain_album_peak",
|
||||
&data->replayGainInfo->albumPeak);
|
||||
found &= flacFindVorbisCommentFloat(block,"replaygain_track_gain",
|
||||
&data->replayGainInfo->trackGain);
|
||||
found &= flacFindVorbisCommentFloat(block,"replaygain_track_peak",
|
||||
&data->replayGainInfo->trackPeak);
|
||||
found &= flacFindVorbisCommentFloat(block, "replaygain_album_gain",
|
||||
&data->replayGainInfo->albumGain);
|
||||
found &= flacFindVorbisCommentFloat(block, "replaygain_album_peak",
|
||||
&data->replayGainInfo->albumPeak);
|
||||
found &= flacFindVorbisCommentFloat(block, "replaygain_track_gain",
|
||||
&data->replayGainInfo->trackGain);
|
||||
found &= flacFindVorbisCommentFloat(block, "replaygain_track_peak",
|
||||
&data->replayGainInfo->trackPeak);
|
||||
|
||||
if (!found) {
|
||||
freeReplayGainInfo(data->replayGainInfo);
|
||||
@@ -105,50 +106,55 @@ static void flacParseReplayGain(const FLAC__StreamMetadata *block,
|
||||
|
||||
/* tracknumber is used in VCs, MPD uses "track" ..., all the other
|
||||
* tag names match */
|
||||
static const char * VORBIS_COMMENT_TRACK_KEY = "tracknumber";
|
||||
static const char * VORBIS_COMMENT_DISC_KEY = "discnumber";
|
||||
static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber";
|
||||
static const char *VORBIS_COMMENT_DISC_KEY = "discnumber";
|
||||
|
||||
static unsigned int commentMatchesAddToTag(
|
||||
const FLAC__StreamMetadata_VorbisComment_Entry * entry,
|
||||
unsigned int itemType,
|
||||
MpdTag ** tag)
|
||||
static unsigned int commentMatchesAddToTag(const
|
||||
FLAC__StreamMetadata_VorbisComment_Entry
|
||||
* entry, unsigned int itemType,
|
||||
MpdTag ** tag)
|
||||
{
|
||||
const char * str;
|
||||
const char *str;
|
||||
size_t slen;
|
||||
int vlen;
|
||||
|
||||
switch (itemType) {
|
||||
case TAG_ITEM_TRACK: str = VORBIS_COMMENT_TRACK_KEY; break;
|
||||
case TAG_ITEM_DISC: str = VORBIS_COMMENT_DISC_KEY; break;
|
||||
default: str = mpdTagItemKeys[itemType];
|
||||
case TAG_ITEM_TRACK:
|
||||
str = VORBIS_COMMENT_TRACK_KEY;
|
||||
break;
|
||||
case TAG_ITEM_DISC:
|
||||
str = VORBIS_COMMENT_DISC_KEY;
|
||||
break;
|
||||
default:
|
||||
str = mpdTagItemKeys[itemType];
|
||||
}
|
||||
slen = strlen(str);
|
||||
vlen = entry->length - slen - 1;
|
||||
|
||||
if ((vlen > 0) && (0 == strncasecmp(str,(char *)entry->entry, slen))
|
||||
&& (*(entry->entry + slen) == '=')) {
|
||||
if ((vlen > 0) && (0 == strncasecmp(str, (char *)entry->entry, slen))
|
||||
&& (*(entry->entry + slen) == '=')) {
|
||||
if (!*tag)
|
||||
*tag = newMpdTag();
|
||||
|
||||
addItemToMpdTagWithLen(*tag, itemType,
|
||||
(char *)(entry->entry+slen + 1), vlen);
|
||||
|
||||
|
||||
addItemToMpdTagWithLen(*tag, itemType,
|
||||
(char *)(entry->entry + slen + 1), vlen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
|
||||
MpdTag * tag)
|
||||
|
||||
MpdTag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
|
||||
MpdTag * tag)
|
||||
{
|
||||
unsigned int i, j;
|
||||
FLAC__StreamMetadata_VorbisComment_Entry *comments;
|
||||
|
||||
|
||||
comments = block->data.vorbis_comment.comments;
|
||||
|
||||
|
||||
for (i = block->data.vorbis_comment.num_comments; i != 0; --i) {
|
||||
for (j = TAG_NUM_OF_ITEM_TYPES; j--; ) {
|
||||
for (j = TAG_NUM_OF_ITEM_TYPES; j--;) {
|
||||
if (commentMatchesAddToTag(comments, j, &tag))
|
||||
break;
|
||||
}
|
||||
@@ -158,34 +164,36 @@ MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
|
||||
return tag;
|
||||
}
|
||||
|
||||
void flac_metadata_common_cb(const FLAC__StreamMetadata *block, FlacData *data)
|
||||
void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
|
||||
FlacData * data)
|
||||
{
|
||||
DecoderControl *dc = data->dc;
|
||||
const FLAC__StreamMetadata_StreamInfo *si = &(block->data.stream_info);
|
||||
|
||||
switch(block->type) {
|
||||
switch (block->type) {
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
dc->audioFormat.bits = si->bits_per_sample;
|
||||
dc->audioFormat.sampleRate = si->sample_rate;
|
||||
dc->audioFormat.channels = si->channels;
|
||||
dc->totalTime = ((float)si->total_samples) / (si->sample_rate);
|
||||
getOutputAudioFormat(&(dc->audioFormat),
|
||||
&(data->cb->audioFormat));
|
||||
&(data->cb->audioFormat));
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
|
||||
flacParseReplayGain(block,data);
|
||||
default:
|
||||
break;
|
||||
flacParseReplayGain(block, data);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void flac_error_common_cb( const char * plugin,
|
||||
const FLAC__StreamDecoderErrorStatus status,
|
||||
FlacData *data)
|
||||
void flac_error_common_cb(const char *plugin,
|
||||
const FLAC__StreamDecoderErrorStatus status,
|
||||
FlacData * data)
|
||||
{
|
||||
if(data->dc->stop) return;
|
||||
if (data->dc->stop)
|
||||
return;
|
||||
|
||||
switch(status) {
|
||||
switch (status) {
|
||||
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
|
||||
ERROR("%s lost sync\n", plugin);
|
||||
break;
|
||||
@@ -196,8 +204,8 @@ void flac_error_common_cb( const char * plugin,
|
||||
ERROR("%s crc mismatch\n", plugin);
|
||||
break;
|
||||
default:
|
||||
ERROR("unknown %s error\n",plugin);
|
||||
ERROR("unknown %s error\n", plugin);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_FLAC || HAVE_OGGFLAC */
|
||||
#endif /* HAVE_FLAC || HAVE_OGGFLAC */
|
||||
|
@@ -41,38 +41,38 @@ typedef struct {
|
||||
float time;
|
||||
int bitRate;
|
||||
FLAC__uint64 position;
|
||||
OutputBuffer * cb;
|
||||
DecoderControl * dc;
|
||||
InputStream * inStream;
|
||||
ReplayGainInfo * replayGainInfo;
|
||||
MpdTag * tag;
|
||||
OutputBuffer *cb;
|
||||
DecoderControl *dc;
|
||||
InputStream *inStream;
|
||||
ReplayGainInfo *replayGainInfo;
|
||||
MpdTag *tag;
|
||||
} FlacData;
|
||||
|
||||
/* initializes a given FlacData struct */
|
||||
void init_FlacData (FlacData * data, OutputBuffer * cb,
|
||||
DecoderControl * dc, InputStream * inStream);
|
||||
void flac_metadata_common_cb( const FLAC__StreamMetadata *block,
|
||||
FlacData *data);
|
||||
void flac_error_common_cb( const char * plugin,
|
||||
FLAC__StreamDecoderErrorStatus status,
|
||||
FlacData *data);
|
||||
void init_FlacData(FlacData * data, OutputBuffer * cb,
|
||||
DecoderControl * dc, InputStream * inStream);
|
||||
void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
|
||||
FlacData * data);
|
||||
void flac_error_common_cb(const char *plugin,
|
||||
FLAC__StreamDecoderErrorStatus status,
|
||||
FlacData * data);
|
||||
|
||||
MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
|
||||
MpdTag * tag);
|
||||
MpdTag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
|
||||
MpdTag * tag);
|
||||
|
||||
/* keep this inlined, this is just macro but prettier :) */
|
||||
static inline int flacSendChunk(FlacData * data)
|
||||
{
|
||||
if (sendDataToOutputBuffer(data->cb, NULL, data->dc, 1, data->chunk,
|
||||
data->chunk_length, data->time, data->bitRate,
|
||||
data->replayGainInfo) == OUTPUT_BUFFER_DC_STOP)
|
||||
data->chunk_length, data->time,
|
||||
data->bitRate,
|
||||
data->replayGainInfo) ==
|
||||
OUTPUT_BUFFER_DC_STOP)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_FLAC || HAVE_OGGFLAC */
|
||||
|
||||
#endif /* HAVE_FLAC || HAVE_OGGFLAC */
|
||||
|
||||
#endif /* _FLAC_COMMON_H */
|
||||
|
||||
#endif /* _FLAC_COMMON_H */
|
||||
|
@@ -37,29 +37,37 @@ ogg_stream_type ogg_stream_type_detect(InputStream * inStream)
|
||||
size_t r, to_read = 41;
|
||||
|
||||
seekInputStream(inStream, 0, SEEK_SET);
|
||||
|
||||
|
||||
while (to_read) {
|
||||
r = readFromInputStream(inStream, buf, 1, to_read);
|
||||
if (r < 0)
|
||||
break;
|
||||
to_read -= r;
|
||||
if (!r && !inputStreamAtEOF(inStream))
|
||||
if (!r && !inputStreamAtEOF(inStream))
|
||||
my_usleep(10000);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
seekInputStream(inStream, 0, SEEK_SET);
|
||||
|
||||
if (r >= 32 && memcmp(buf, "OggS", 4) == 0 && (
|
||||
(memcmp(buf+29, "FLAC", 4) == 0
|
||||
&& memcmp(buf+37, "fLaC", 4) == 0)
|
||||
|| (memcmp(buf+28, "FLAC", 4) == 0)
|
||||
|| (memcmp(buf+28, "fLaC", 4) == 0))) {
|
||||
|
||||
if (r >= 32 && memcmp(buf, "OggS", 4) == 0 && ((memcmp
|
||||
(buf + 29, "FLAC",
|
||||
4) == 0
|
||||
&& memcmp(buf + 37,
|
||||
"fLaC",
|
||||
4) == 0)
|
||||
||
|
||||
(memcmp
|
||||
(buf + 28, "FLAC",
|
||||
4) == 0)
|
||||
||
|
||||
(memcmp
|
||||
(buf + 28, "fLaC",
|
||||
4) == 0))) {
|
||||
return FLAC;
|
||||
}
|
||||
return VORBIS;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */
|
||||
|
||||
#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */
|
||||
|
@@ -30,6 +30,6 @@ typedef enum _ogg_stream_type { VORBIS, FLAC } ogg_stream_type;
|
||||
|
||||
ogg_stream_type ogg_stream_type_detect(InputStream * inStream);
|
||||
|
||||
#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */
|
||||
#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */
|
||||
|
||||
#endif /* _OGG_COMMON_H */
|
||||
#endif /* _OGG_COMMON_H */
|
||||
|
@@ -36,7 +36,7 @@
|
||||
|
||||
/* all code here is either based on or copied from FAAD2's frontend code */
|
||||
typedef struct {
|
||||
InputStream * inStream;
|
||||
InputStream *inStream;
|
||||
long bytesIntoBuffer;
|
||||
long bytesConsumed;
|
||||
long fileOffset;
|
||||
@@ -44,163 +44,193 @@ typedef struct {
|
||||
int atEof;
|
||||
} AacBuffer;
|
||||
|
||||
static void fillAacBuffer(AacBuffer *b) {
|
||||
if(b->bytesConsumed > 0) {
|
||||
static void fillAacBuffer(AacBuffer * b)
|
||||
{
|
||||
if (b->bytesConsumed > 0) {
|
||||
int bread;
|
||||
|
||||
if(b->bytesIntoBuffer) {
|
||||
memmove((void *)b->buffer,(void*)(b->buffer+
|
||||
b->bytesConsumed),b->bytesIntoBuffer);
|
||||
if (b->bytesIntoBuffer) {
|
||||
memmove((void *)b->buffer, (void *)(b->buffer +
|
||||
b->bytesConsumed),
|
||||
b->bytesIntoBuffer);
|
||||
}
|
||||
|
||||
if(!b->atEof) {
|
||||
if (!b->atEof) {
|
||||
bread = readFromInputStream(b->inStream,
|
||||
(void *)(b->buffer+b->bytesIntoBuffer),
|
||||
1,b->bytesConsumed);
|
||||
if(bread!=b->bytesConsumed) b->atEof = 1;
|
||||
b->bytesIntoBuffer+=bread;
|
||||
(void *)(b->buffer +
|
||||
b->
|
||||
bytesIntoBuffer),
|
||||
1, b->bytesConsumed);
|
||||
if (bread != b->bytesConsumed)
|
||||
b->atEof = 1;
|
||||
b->bytesIntoBuffer += bread;
|
||||
}
|
||||
|
||||
b->bytesConsumed = 0;
|
||||
|
||||
if(b->bytesIntoBuffer > 3) {
|
||||
if(memcmp(b->buffer,"TAG",3)==0) b->bytesIntoBuffer = 0;
|
||||
if (b->bytesIntoBuffer > 3) {
|
||||
if (memcmp(b->buffer, "TAG", 3) == 0)
|
||||
b->bytesIntoBuffer = 0;
|
||||
}
|
||||
if(b->bytesIntoBuffer > 11) {
|
||||
if(memcmp(b->buffer,"LYRICSBEGIN",11)==0) {
|
||||
if (b->bytesIntoBuffer > 11) {
|
||||
if (memcmp(b->buffer, "LYRICSBEGIN", 11) == 0) {
|
||||
b->bytesIntoBuffer = 0;
|
||||
}
|
||||
}
|
||||
if(b->bytesIntoBuffer > 8) {
|
||||
if(memcmp(b->buffer,"APETAGEX",8)==0) {
|
||||
if (b->bytesIntoBuffer > 8) {
|
||||
if (memcmp(b->buffer, "APETAGEX", 8) == 0) {
|
||||
b->bytesIntoBuffer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void advanceAacBuffer(AacBuffer * b, int bytes) {
|
||||
b->fileOffset+=bytes;
|
||||
static void advanceAacBuffer(AacBuffer * b, int bytes)
|
||||
{
|
||||
b->fileOffset += bytes;
|
||||
b->bytesConsumed = bytes;
|
||||
b->bytesIntoBuffer-=bytes;
|
||||
b->bytesIntoBuffer -= bytes;
|
||||
}
|
||||
|
||||
static int adtsSampleRates[] = {96000,88200,64000,48000,44100,32000,24000,22050,
|
||||
16000,12000,11025,8000,7350,0,0,0};
|
||||
static int adtsSampleRates[] =
|
||||
{ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
|
||||
16000, 12000, 11025, 8000, 7350, 0, 0, 0
|
||||
};
|
||||
|
||||
static int adtsParse(AacBuffer * b, float * length) {
|
||||
static int adtsParse(AacBuffer * b, float *length)
|
||||
{
|
||||
int frames, frameLength;
|
||||
int tFrameLength = 0;
|
||||
int sampleRate = 0;
|
||||
float framesPerSec, bytesPerFrame;
|
||||
|
||||
/* Read all frames to ensure correct time and bitrate */
|
||||
for(frames = 0; ;frames++) {
|
||||
for (frames = 0;; frames++) {
|
||||
fillAacBuffer(b);
|
||||
|
||||
if(b->bytesIntoBuffer > 7) {
|
||||
if (b->bytesIntoBuffer > 7) {
|
||||
/* check syncword */
|
||||
if (!((b->buffer[0] == 0xFF) &&
|
||||
((b->buffer[1] & 0xF6) == 0xF0)))
|
||||
{
|
||||
if (!((b->buffer[0] == 0xFF) &&
|
||||
((b->buffer[1] & 0xF6) == 0xF0))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(frames==0) {
|
||||
sampleRate = adtsSampleRates[
|
||||
(b->buffer[2]&0x3c)>>2];
|
||||
if (frames == 0) {
|
||||
sampleRate = adtsSampleRates[(b->
|
||||
buffer[2] & 0x3c)
|
||||
>> 2];
|
||||
}
|
||||
|
||||
frameLength = ((((unsigned int)b->buffer[3] & 0x3))
|
||||
<< 11) | (((unsigned int)b->buffer[4])
|
||||
<< 3) | (b->buffer[5] >> 5);
|
||||
frameLength = ((((unsigned int)b->buffer[3] & 0x3))
|
||||
<< 11) | (((unsigned int)b->buffer[4])
|
||||
<< 3) | (b->buffer[5] >> 5);
|
||||
|
||||
tFrameLength+=frameLength;
|
||||
tFrameLength += frameLength;
|
||||
|
||||
if(frameLength > b->bytesIntoBuffer) break;
|
||||
if (frameLength > b->bytesIntoBuffer)
|
||||
break;
|
||||
|
||||
advanceAacBuffer(b,frameLength);
|
||||
}
|
||||
else break;
|
||||
advanceAacBuffer(b, frameLength);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
framesPerSec = (float)sampleRate/1024.0;
|
||||
if(frames!=0) {
|
||||
bytesPerFrame = (float)tFrameLength/(float)(frames*1000);
|
||||
}
|
||||
else bytesPerFrame = 0;
|
||||
if(framesPerSec!=0) *length = (float)frames/framesPerSec;
|
||||
framesPerSec = (float)sampleRate / 1024.0;
|
||||
if (frames != 0) {
|
||||
bytesPerFrame = (float)tFrameLength / (float)(frames * 1000);
|
||||
} else
|
||||
bytesPerFrame = 0;
|
||||
if (framesPerSec != 0)
|
||||
*length = (float)frames / framesPerSec;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void initAacBuffer(InputStream * inStream, AacBuffer * b, float * length,
|
||||
size_t * retFileread, size_t * retTagsize)
|
||||
static void initAacBuffer(InputStream * inStream, AacBuffer * b, float *length,
|
||||
size_t * retFileread, size_t * retTagsize)
|
||||
{
|
||||
size_t fileread;
|
||||
size_t bread;
|
||||
size_t tagsize;
|
||||
|
||||
if(length) *length = -1;
|
||||
if (length)
|
||||
*length = -1;
|
||||
|
||||
memset(b,0,sizeof(AacBuffer));
|
||||
memset(b, 0, sizeof(AacBuffer));
|
||||
|
||||
b->inStream = inStream;
|
||||
|
||||
fileread = inStream->size;
|
||||
|
||||
b->buffer = malloc(FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS);
|
||||
memset(b->buffer,0,FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS);
|
||||
b->buffer = malloc(FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
|
||||
memset(b->buffer, 0, FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
|
||||
|
||||
bread = readFromInputStream(inStream,b->buffer,1,
|
||||
FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS);
|
||||
bread = readFromInputStream(inStream, b->buffer, 1,
|
||||
FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
|
||||
b->bytesIntoBuffer = bread;
|
||||
b->bytesConsumed = 0;
|
||||
b->fileOffset = 0;
|
||||
|
||||
if(bread!=FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b->atEof = 1;
|
||||
if (bread != FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS)
|
||||
b->atEof = 1;
|
||||
|
||||
tagsize = 0;
|
||||
if(!memcmp(b->buffer,"ID3",3)) {
|
||||
if (!memcmp(b->buffer, "ID3", 3)) {
|
||||
tagsize = (b->buffer[6] << 21) | (b->buffer[7] << 14) |
|
||||
(b->buffer[8] << 7) | (b->buffer[9] << 0);
|
||||
(b->buffer[8] << 7) | (b->buffer[9] << 0);
|
||||
|
||||
tagsize+=10;
|
||||
advanceAacBuffer(b,tagsize);
|
||||
tagsize += 10;
|
||||
advanceAacBuffer(b, tagsize);
|
||||
fillAacBuffer(b);
|
||||
}
|
||||
|
||||
if(retFileread) *retFileread = fileread;
|
||||
if(retTagsize) *retTagsize = tagsize;
|
||||
if (retFileread)
|
||||
*retFileread = fileread;
|
||||
if (retTagsize)
|
||||
*retTagsize = tagsize;
|
||||
|
||||
if(length==NULL) return;
|
||||
if (length == NULL)
|
||||
return;
|
||||
|
||||
if((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) {
|
||||
if ((b->buffer[0] == 0xFF) && ((b->buffer[1] & 0xF6) == 0xF0)) {
|
||||
adtsParse(b, length);
|
||||
seekInputStream(b->inStream, tagsize, SEEK_SET);
|
||||
|
||||
bread = readFromInputStream(b->inStream, b->buffer, 1,
|
||||
FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS);
|
||||
if(bread != FAAD_MIN_STREAMSIZE*AAC_MAX_CHANNELS) b->atEof = 1;
|
||||
else b->atEof = 0;
|
||||
bread = readFromInputStream(b->inStream, b->buffer, 1,
|
||||
FAAD_MIN_STREAMSIZE *
|
||||
AAC_MAX_CHANNELS);
|
||||
if (bread != FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS)
|
||||
b->atEof = 1;
|
||||
else
|
||||
b->atEof = 0;
|
||||
b->bytesIntoBuffer = bread;
|
||||
b->bytesConsumed = 0;
|
||||
b->fileOffset = tagsize;
|
||||
}
|
||||
else if(memcmp(b->buffer,"ADIF",4) == 0) {
|
||||
} else if (memcmp(b->buffer, "ADIF", 4) == 0) {
|
||||
int bitRate;
|
||||
int skipSize = (b->buffer[4] & 0x80) ? 9 : 0;
|
||||
bitRate = ((unsigned int)(b->buffer[4 + skipSize] & 0x0F)<<19) |
|
||||
((unsigned int)b->buffer[5 + skipSize]<<11) |
|
||||
((unsigned int)b->buffer[6 + skipSize]<<3) |
|
||||
((unsigned int)b->buffer[7 + skipSize] & 0xE0);
|
||||
bitRate =
|
||||
((unsigned int)(b->
|
||||
buffer[4 +
|
||||
skipSize] & 0x0F) << 19) | ((unsigned
|
||||
int)b->
|
||||
buffer[5
|
||||
+
|
||||
skipSize]
|
||||
<< 11) |
|
||||
((unsigned int)b->
|
||||
buffer[6 + skipSize] << 3) | ((unsigned int)b->buffer[7 +
|
||||
skipSize]
|
||||
& 0xE0);
|
||||
|
||||
*length = fileread;
|
||||
if(*length!=0 && bitRate!=0) *length = *length*8.0/bitRate;
|
||||
if (*length != 0 && bitRate != 0)
|
||||
*length = *length * 8.0 / bitRate;
|
||||
}
|
||||
}
|
||||
|
||||
static float getAacFloatTotalTime(char * file) {
|
||||
static float getAacFloatTotalTime(char *file)
|
||||
{
|
||||
AacBuffer b;
|
||||
float length;
|
||||
size_t fileread, tagsize;
|
||||
@@ -211,46 +241,51 @@ static float getAacFloatTotalTime(char * file) {
|
||||
InputStream inStream;
|
||||
size_t bread;
|
||||
|
||||
if(openInputStream(&inStream,file) < 0) return -1;
|
||||
if (openInputStream(&inStream, file) < 0)
|
||||
return -1;
|
||||
|
||||
initAacBuffer(&inStream,&b,&length,&fileread,&tagsize);
|
||||
initAacBuffer(&inStream, &b, &length, &fileread, &tagsize);
|
||||
|
||||
if(length < 0) {
|
||||
if (length < 0) {
|
||||
decoder = faacDecOpen();
|
||||
|
||||
config = faacDecGetCurrentConfiguration(decoder);
|
||||
config->outputFormat = FAAD_FMT_16BIT;
|
||||
faacDecSetConfiguration(decoder,config);
|
||||
faacDecSetConfiguration(decoder, config);
|
||||
|
||||
fillAacBuffer(&b);
|
||||
#ifdef HAVE_FAAD_BUFLEN_FUNCS
|
||||
bread = faacDecInit(decoder,b.buffer,b.bytesIntoBuffer,
|
||||
&sampleRate,&channels);
|
||||
bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
|
||||
&sampleRate, &channels);
|
||||
#else
|
||||
bread = faacDecInit(decoder,b.buffer,&sampleRate,&channels);
|
||||
bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels);
|
||||
#endif
|
||||
if(bread >= 0 && sampleRate > 0 && channels > 0) length = 0;
|
||||
if (bread >= 0 && sampleRate > 0 && channels > 0)
|
||||
length = 0;
|
||||
|
||||
faacDecClose(decoder);
|
||||
}
|
||||
|
||||
if(b.buffer) free(b.buffer);
|
||||
if (b.buffer)
|
||||
free(b.buffer);
|
||||
closeInputStream(&inStream);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static int getAacTotalTime(char * file) {
|
||||
static int getAacTotalTime(char *file)
|
||||
{
|
||||
int time = -1;
|
||||
float length;
|
||||
|
||||
if((length = getAacFloatTotalTime(file))>=0) time = length+0.5;
|
||||
if ((length = getAacFloatTotalTime(file)) >= 0)
|
||||
time = length + 0.5;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
|
||||
{
|
||||
float time;
|
||||
float totalTime;
|
||||
faacDecHandle decoder;
|
||||
@@ -261,20 +296,22 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
unsigned char channels;
|
||||
int eof = 0;
|
||||
unsigned int sampleCount;
|
||||
char * sampleBuffer;
|
||||
char *sampleBuffer;
|
||||
size_t sampleBufferLen;
|
||||
/*float * seekTable;
|
||||
long seekTableEnd = -1;
|
||||
int seekPositionFound = 0;*/
|
||||
long seekTableEnd = -1;
|
||||
int seekPositionFound = 0; */
|
||||
mpd_uint16 bitRate = 0;
|
||||
AacBuffer b;
|
||||
InputStream inStream;
|
||||
|
||||
if((totalTime = getAacFloatTotalTime(path)) < 0) return -1;
|
||||
if ((totalTime = getAacFloatTotalTime(path)) < 0)
|
||||
return -1;
|
||||
|
||||
if(openInputStream(&inStream, path) < 0) return -1;
|
||||
if (openInputStream(&inStream, path) < 0)
|
||||
return -1;
|
||||
|
||||
initAacBuffer(&inStream,&b,NULL,NULL,NULL);
|
||||
initAacBuffer(&inStream, &b, NULL, NULL, NULL);
|
||||
|
||||
decoder = faacDecOpen();
|
||||
|
||||
@@ -286,21 +323,22 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
|
||||
config->dontUpSampleImplicitSBR = 0;
|
||||
#endif
|
||||
faacDecSetConfiguration(decoder,config);
|
||||
faacDecSetConfiguration(decoder, config);
|
||||
|
||||
fillAacBuffer(&b);
|
||||
|
||||
#ifdef HAVE_FAAD_BUFLEN_FUNCS
|
||||
bread = faacDecInit(decoder,b.buffer,b.bytesIntoBuffer,
|
||||
&sampleRate,&channels);
|
||||
bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer,
|
||||
&sampleRate, &channels);
|
||||
#else
|
||||
bread = faacDecInit(decoder,b.buffer,&sampleRate,&channels);
|
||||
bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels);
|
||||
#endif
|
||||
if(bread < 0) {
|
||||
if (bread < 0) {
|
||||
ERROR("Error not a AAC stream.\n");
|
||||
faacDecClose(decoder);
|
||||
closeInputStream(b.inStream);
|
||||
if(b.buffer) free(b.buffer);
|
||||
if (b.buffer)
|
||||
free(b.buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -310,64 +348,62 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
|
||||
time = 0.0;
|
||||
|
||||
advanceAacBuffer(&b,bread);
|
||||
advanceAacBuffer(&b, bread);
|
||||
|
||||
while(!eof) {
|
||||
while (!eof) {
|
||||
fillAacBuffer(&b);
|
||||
|
||||
if(b.bytesIntoBuffer==0) {
|
||||
if (b.bytesIntoBuffer == 0) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FAAD_BUFLEN_FUNCS
|
||||
sampleBuffer = faacDecDecode(decoder,&frameInfo,b.buffer,
|
||||
b.bytesIntoBuffer);
|
||||
sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer,
|
||||
b.bytesIntoBuffer);
|
||||
#else
|
||||
sampleBuffer = faacDecDecode(decoder,&frameInfo,b.buffer);
|
||||
sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer);
|
||||
#endif
|
||||
|
||||
if(frameInfo.error > 0) {
|
||||
if (frameInfo.error > 0) {
|
||||
ERROR("error decoding AAC file: %s\n", path);
|
||||
ERROR("faad2 error: %s\n",
|
||||
faacDecGetErrorMessage(frameInfo.error));
|
||||
faacDecGetErrorMessage(frameInfo.error));
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
|
||||
sampleRate = frameInfo.samplerate;
|
||||
#endif
|
||||
|
||||
if(dc->state != DECODE_STATE_DECODE) {
|
||||
if (dc->state != DECODE_STATE_DECODE) {
|
||||
dc->audioFormat.channels = frameInfo.channels;
|
||||
dc->audioFormat.sampleRate = sampleRate;
|
||||
getOutputAudioFormat(&(dc->audioFormat),
|
||||
&(cb->audioFormat));
|
||||
getOutputAudioFormat(&(dc->audioFormat),
|
||||
&(cb->audioFormat));
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
}
|
||||
|
||||
advanceAacBuffer(&b,frameInfo.bytesconsumed);
|
||||
advanceAacBuffer(&b, frameInfo.bytesconsumed);
|
||||
|
||||
sampleCount = (unsigned long)(frameInfo.samples);
|
||||
|
||||
if(sampleCount>0) {
|
||||
bitRate = frameInfo.bytesconsumed*8.0*
|
||||
frameInfo.channels*sampleRate/
|
||||
frameInfo.samples/1000+0.5;
|
||||
time+= (float)(frameInfo.samples)/frameInfo.channels/
|
||||
sampleRate;
|
||||
if (sampleCount > 0) {
|
||||
bitRate = frameInfo.bytesconsumed * 8.0 *
|
||||
frameInfo.channels * sampleRate /
|
||||
frameInfo.samples / 1000 + 0.5;
|
||||
time +=
|
||||
(float)(frameInfo.samples) / frameInfo.channels /
|
||||
sampleRate;
|
||||
}
|
||||
|
||||
sampleBufferLen = sampleCount*2;
|
||||
|
||||
sampleBufferLen = sampleCount * 2;
|
||||
|
||||
sendDataToOutputBuffer(cb, NULL, dc, 0, sampleBuffer,
|
||||
sampleBufferLen, time, bitRate, NULL);
|
||||
if(dc->seek) {
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}
|
||||
else if(dc->stop) {
|
||||
sampleBufferLen, time, bitRate, NULL);
|
||||
if (dc->seek) {
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
} else if (dc->stop) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
@@ -377,71 +413,73 @@ static int aac_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
|
||||
faacDecClose(decoder);
|
||||
closeInputStream(b.inStream);
|
||||
if(b.buffer) free(b.buffer);
|
||||
if (b.buffer)
|
||||
free(b.buffer);
|
||||
|
||||
if(dc->state != DECODE_STATE_DECODE) return -1;
|
||||
if (dc->state != DECODE_STATE_DECODE)
|
||||
return -1;
|
||||
|
||||
if(dc->seek) {
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}
|
||||
if (dc->seek) {
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}
|
||||
|
||||
if(dc->stop) {
|
||||
if (dc->stop) {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
else dc->state = DECODE_STATE_STOP;
|
||||
} else
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MpdTag * aacTagDup(char * file) {
|
||||
MpdTag * ret = NULL;
|
||||
static MpdTag *aacTagDup(char *file)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
int time;
|
||||
|
||||
time = getAacTotalTime(file);
|
||||
|
||||
if(time>=0) {
|
||||
if((ret = id3Dup(file))==NULL) ret = newMpdTag();
|
||||
if (time >= 0) {
|
||||
if ((ret = id3Dup(file)) == NULL)
|
||||
ret = newMpdTag();
|
||||
ret->time = time;
|
||||
}
|
||||
else {
|
||||
DEBUG("aacTagDup: Failed to get total song time from: %s\n", file);
|
||||
} else {
|
||||
DEBUG("aacTagDup: Failed to get total song time from: %s\n",
|
||||
file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * aacSuffixes[] = {"aac", NULL};
|
||||
static char *aacSuffixes[] = { "aac", NULL };
|
||||
|
||||
InputPlugin aacPlugin =
|
||||
{
|
||||
"aac",
|
||||
NULL,
|
||||
NULL,
|
||||
InputPlugin aacPlugin = {
|
||||
"aac",
|
||||
NULL,
|
||||
NULL,
|
||||
aac_decode,
|
||||
aacTagDup,
|
||||
INPUT_PLUGIN_STREAM_FILE,
|
||||
aacSuffixes,
|
||||
NULL
|
||||
NULL,
|
||||
NULL,
|
||||
aac_decode,
|
||||
aacTagDup,
|
||||
INPUT_PLUGIN_STREAM_FILE,
|
||||
aacSuffixes,
|
||||
NULL
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
InputPlugin aacPlugin =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
InputPlugin aacPlugin = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif /* HAVE_FAAD */
|
||||
#endif /* HAVE_FAAD */
|
||||
|
@@ -37,34 +37,35 @@
|
||||
#include <unistd.h>
|
||||
#include <audiofile.h>
|
||||
|
||||
static int getAudiofileTotalTime(char * file)
|
||||
static int getAudiofileTotalTime(char *file)
|
||||
{
|
||||
int time;
|
||||
AFfilehandle af_fp = afOpenFile(file, "r", NULL);
|
||||
if(af_fp == AF_NULL_FILEHANDLE) {
|
||||
if (af_fp == AF_NULL_FILEHANDLE) {
|
||||
return -1;
|
||||
}
|
||||
time = (int)
|
||||
((double)afGetFrameCount(af_fp,AF_DEFAULT_TRACK)
|
||||
/afGetRate(af_fp,AF_DEFAULT_TRACK));
|
||||
((double)afGetFrameCount(af_fp, AF_DEFAULT_TRACK)
|
||||
/ afGetRate(af_fp, AF_DEFAULT_TRACK));
|
||||
afCloseFile(af_fp);
|
||||
return time;
|
||||
}
|
||||
|
||||
static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
|
||||
{
|
||||
int fs, frame_count;
|
||||
AFfilehandle af_fp;
|
||||
int bits;
|
||||
mpd_uint16 bitRate;
|
||||
struct stat st;
|
||||
|
||||
if(stat(path, &st) < 0) {
|
||||
if (stat(path, &st) < 0) {
|
||||
ERROR("failed to stat: %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
af_fp = afOpenFile(path, "r", NULL);
|
||||
if(af_fp == AF_NULL_FILEHANDLE) {
|
||||
if (af_fp == AF_NULL_FILEHANDLE) {
|
||||
ERROR("failed to open: %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
@@ -72,119 +73,125 @@ static int audiofile_decode(OutputBuffer * cb, DecoderControl * dc, char * path)
|
||||
afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
|
||||
dc->audioFormat.bits = bits;
|
||||
dc->audioFormat.sampleRate = afGetRate(af_fp, AF_DEFAULT_TRACK);
|
||||
dc->audioFormat.channels = afGetChannels(af_fp,AF_DEFAULT_TRACK);
|
||||
getOutputAudioFormat(&(dc->audioFormat),&(cb->audioFormat));
|
||||
|
||||
frame_count = afGetFrameCount(af_fp,AF_DEFAULT_TRACK);
|
||||
|
||||
dc->totalTime = ((float)frame_count/(float)dc->audioFormat.sampleRate);
|
||||
dc->audioFormat.channels = afGetChannels(af_fp, AF_DEFAULT_TRACK);
|
||||
getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat));
|
||||
|
||||
frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);
|
||||
|
||||
dc->totalTime =
|
||||
((float)frame_count / (float)dc->audioFormat.sampleRate);
|
||||
|
||||
bitRate = st.st_size * 8.0 / dc->totalTime / 1000.0 + 0.5;
|
||||
|
||||
bitRate = st.st_size*8.0/dc->totalTime/1000.0+0.5;
|
||||
|
||||
if (dc->audioFormat.bits != 8 && dc->audioFormat.bits != 16) {
|
||||
ERROR("Only 8 and 16-bit files are supported. %s is %i-bit\n",
|
||||
path, dc->audioFormat.bits);
|
||||
path, dc->audioFormat.bits);
|
||||
afCloseFile(af_fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fs = (int)afGetFrameSize(af_fp, AF_DEFAULT_TRACK,1);
|
||||
|
||||
fs = (int)afGetFrameSize(af_fp, AF_DEFAULT_TRACK, 1);
|
||||
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
{
|
||||
int ret, eof = 0, current = 0;
|
||||
char chunk[CHUNK_SIZE];
|
||||
|
||||
while(!eof) {
|
||||
if(dc->seek) {
|
||||
clearOutputBuffer(cb);
|
||||
current = dc->seekWhere *
|
||||
dc->audioFormat.sampleRate;
|
||||
afSeekFrame(af_fp, AF_DEFAULT_TRACK,current);
|
||||
while (!eof) {
|
||||
if (dc->seek) {
|
||||
clearOutputBuffer(cb);
|
||||
current = dc->seekWhere *
|
||||
dc->audioFormat.sampleRate;
|
||||
afSeekFrame(af_fp, AF_DEFAULT_TRACK, current);
|
||||
dc->seek = 0;
|
||||
}
|
||||
|
||||
ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk, CHUNK_SIZE/fs);
|
||||
if(ret<=0) eof = 1;
|
||||
ret =
|
||||
afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,
|
||||
CHUNK_SIZE / fs);
|
||||
if (ret <= 0)
|
||||
eof = 1;
|
||||
else {
|
||||
current += ret;
|
||||
sendDataToOutputBuffer(cb,
|
||||
NULL,
|
||||
dc,
|
||||
1,
|
||||
chunk,
|
||||
ret*fs,
|
||||
(float)current /
|
||||
(float)dc->audioFormat.sampleRate,
|
||||
bitRate,
|
||||
NULL);
|
||||
if(dc->stop) break;
|
||||
sendDataToOutputBuffer(cb,
|
||||
NULL,
|
||||
dc,
|
||||
1,
|
||||
chunk,
|
||||
ret * fs,
|
||||
(float)current /
|
||||
(float)dc->audioFormat.
|
||||
sampleRate, bitRate,
|
||||
NULL);
|
||||
if (dc->stop)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flushOutputBuffer(cb);
|
||||
|
||||
/*if(dc->seek) {
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}*/
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
} */
|
||||
|
||||
if(dc->stop) {
|
||||
if (dc->stop) {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
else dc->state = DECODE_STATE_STOP;
|
||||
} else
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
}
|
||||
afCloseFile(af_fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MpdTag * audiofileTagDup(char * file) {
|
||||
MpdTag * ret = NULL;
|
||||
static MpdTag *audiofileTagDup(char *file)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
int time = getAudiofileTotalTime(file);
|
||||
|
||||
if (time>=0) {
|
||||
if(!ret) ret = newMpdTag();
|
||||
|
||||
if (time >= 0) {
|
||||
if (!ret)
|
||||
ret = newMpdTag();
|
||||
ret->time = time;
|
||||
}
|
||||
else {
|
||||
DEBUG("audiofileTagDup: Failed to get total song time from: %s\n", file);
|
||||
} else {
|
||||
DEBUG
|
||||
("audiofileTagDup: Failed to get total song time from: %s\n",
|
||||
file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * audiofileSuffixes[] = {"wav", "au", "aiff", "aif", NULL};
|
||||
static char *audiofileSuffixes[] = { "wav", "au", "aiff", "aif", NULL };
|
||||
|
||||
InputPlugin audiofilePlugin =
|
||||
{
|
||||
"audiofile",
|
||||
NULL,
|
||||
InputPlugin audiofilePlugin = {
|
||||
"audiofile",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
audiofile_decode,
|
||||
audiofileTagDup,
|
||||
INPUT_PLUGIN_STREAM_FILE,
|
||||
audiofileSuffixes,
|
||||
NULL
|
||||
NULL,
|
||||
audiofile_decode,
|
||||
audiofileTagDup,
|
||||
INPUT_PLUGIN_STREAM_FILE,
|
||||
audiofileSuffixes,
|
||||
NULL
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
InputPlugin audiofilePlugin =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
InputPlugin audiofilePlugin = {
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* HAVE_AUDIOFILE */
|
||||
#endif /* HAVE_AUDIOFILE */
|
||||
|
@@ -39,211 +39,240 @@
|
||||
/* this code is based on flac123, from flac-tools */
|
||||
|
||||
static void flacError(const FLAC__SeekableStreamDecoder *,
|
||||
FLAC__StreamDecoderErrorStatus, void *);
|
||||
FLAC__StreamDecoderErrorStatus, void *);
|
||||
static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state);
|
||||
static void flacMetadata(const FLAC__SeekableStreamDecoder *,
|
||||
const FLAC__StreamMetadata *, void *);
|
||||
static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *,
|
||||
const FLAC__Frame *, const FLAC__int32 * const buf[], void *);
|
||||
static FLAC__SeekableStreamDecoderReadStatus flacRead(
|
||||
const FLAC__SeekableStreamDecoder *, FLAC__byte buf[],
|
||||
unsigned *, void *);
|
||||
static FLAC__SeekableStreamDecoderSeekStatus flacSeek(
|
||||
const FLAC__SeekableStreamDecoder *, FLAC__uint64, void *);
|
||||
static FLAC__SeekableStreamDecoderTellStatus flacTell(
|
||||
const FLAC__SeekableStreamDecoder *, FLAC__uint64 *, void *);
|
||||
static FLAC__SeekableStreamDecoderLengthStatus flacLength(
|
||||
const FLAC__SeekableStreamDecoder *, FLAC__uint64 *, void *);
|
||||
const FLAC__StreamMetadata *, void *);
|
||||
static FLAC__StreamDecoderWriteStatus flacWrite(const
|
||||
FLAC__SeekableStreamDecoder *,
|
||||
const FLAC__Frame *,
|
||||
const FLAC__int32 * const buf[],
|
||||
void *);
|
||||
static FLAC__SeekableStreamDecoderReadStatus flacRead(const
|
||||
FLAC__SeekableStreamDecoder
|
||||
*, FLAC__byte buf[],
|
||||
unsigned *, void *);
|
||||
static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const
|
||||
FLAC__SeekableStreamDecoder
|
||||
*, FLAC__uint64, void *);
|
||||
static FLAC__SeekableStreamDecoderTellStatus flacTell(const
|
||||
FLAC__SeekableStreamDecoder
|
||||
*, FLAC__uint64 *,
|
||||
void *);
|
||||
static FLAC__SeekableStreamDecoderLengthStatus flacLength(const
|
||||
FLAC__SeekableStreamDecoder
|
||||
*, FLAC__uint64 *,
|
||||
void *);
|
||||
static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder *, void *);
|
||||
|
||||
static int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
|
||||
static int flac_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
InputStream * inStream)
|
||||
{
|
||||
FLAC__SeekableStreamDecoder * flacDec = NULL;
|
||||
FLAC__SeekableStreamDecoder *flacDec = NULL;
|
||||
FlacData data;
|
||||
int status = 1;
|
||||
int ret =0;
|
||||
int ret = 0;
|
||||
|
||||
init_FlacData(&data, cb, dc, inStream);
|
||||
|
||||
if(!(flacDec = FLAC__seekable_stream_decoder_new())) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
/*status&=FLAC__file_decoder_set_md5_checking(flacDec,1);*/
|
||||
status&=FLAC__seekable_stream_decoder_set_read_callback(flacDec,
|
||||
flacRead);
|
||||
status&=FLAC__seekable_stream_decoder_set_seek_callback(flacDec,
|
||||
flacSeek);
|
||||
status&=FLAC__seekable_stream_decoder_set_tell_callback(flacDec,
|
||||
flacTell);
|
||||
status&=FLAC__seekable_stream_decoder_set_length_callback(flacDec,
|
||||
flacLength);
|
||||
status&=FLAC__seekable_stream_decoder_set_eof_callback(flacDec,flacEOF);
|
||||
status&=FLAC__seekable_stream_decoder_set_write_callback(flacDec,
|
||||
flacWrite);
|
||||
status&=FLAC__seekable_stream_decoder_set_metadata_callback(flacDec,
|
||||
flacMetadata);
|
||||
status&=FLAC__seekable_stream_decoder_set_metadata_respond(flacDec,
|
||||
FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
status&=FLAC__seekable_stream_decoder_set_error_callback(flacDec,
|
||||
flacError);
|
||||
status&=FLAC__seekable_stream_decoder_set_client_data(flacDec,
|
||||
(void *)&data);
|
||||
if(!status) {
|
||||
if (!(flacDec = FLAC__seekable_stream_decoder_new())) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
/*status&=FLAC__file_decoder_set_md5_checking(flacDec,1); */
|
||||
status &= FLAC__seekable_stream_decoder_set_read_callback(flacDec,
|
||||
flacRead);
|
||||
status &= FLAC__seekable_stream_decoder_set_seek_callback(flacDec,
|
||||
flacSeek);
|
||||
status &= FLAC__seekable_stream_decoder_set_tell_callback(flacDec,
|
||||
flacTell);
|
||||
status &= FLAC__seekable_stream_decoder_set_length_callback(flacDec,
|
||||
flacLength);
|
||||
status &=
|
||||
FLAC__seekable_stream_decoder_set_eof_callback(flacDec, flacEOF);
|
||||
status &=
|
||||
FLAC__seekable_stream_decoder_set_write_callback(flacDec,
|
||||
flacWrite);
|
||||
status &=
|
||||
FLAC__seekable_stream_decoder_set_metadata_callback(flacDec,
|
||||
flacMetadata);
|
||||
status &=
|
||||
FLAC__seekable_stream_decoder_set_metadata_respond(flacDec,
|
||||
FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
status &=
|
||||
FLAC__seekable_stream_decoder_set_error_callback(flacDec,
|
||||
flacError);
|
||||
status &=
|
||||
FLAC__seekable_stream_decoder_set_client_data(flacDec,
|
||||
(void *)&data);
|
||||
if (!status) {
|
||||
ERROR("flac problem before init()\n");
|
||||
flacPrintErroredState(
|
||||
FLAC__seekable_stream_decoder_get_state(flacDec));
|
||||
flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
|
||||
(flacDec));
|
||||
ret = -1;
|
||||
goto fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(FLAC__seekable_stream_decoder_init(flacDec)!=
|
||||
FLAC__SEEKABLE_STREAM_DECODER_OK)
|
||||
{
|
||||
if (FLAC__seekable_stream_decoder_init(flacDec) !=
|
||||
FLAC__SEEKABLE_STREAM_DECODER_OK) {
|
||||
ERROR("flac problem doing init()\n");
|
||||
flacPrintErroredState(
|
||||
FLAC__seekable_stream_decoder_get_state(flacDec));
|
||||
ret = -1;
|
||||
goto fail;
|
||||
flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
|
||||
(flacDec));
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(!FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDec)) {
|
||||
if (!FLAC__seekable_stream_decoder_process_until_end_of_metadata
|
||||
(flacDec)) {
|
||||
ERROR("flac problem reading metadata\n");
|
||||
flacPrintErroredState(
|
||||
FLAC__seekable_stream_decoder_get_state(flacDec));
|
||||
flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
|
||||
(flacDec));
|
||||
ret = -1;
|
||||
goto fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
|
||||
while(1) {
|
||||
while (1) {
|
||||
FLAC__seekable_stream_decoder_process_single(flacDec);
|
||||
if(FLAC__seekable_stream_decoder_get_state(flacDec)!=
|
||||
FLAC__SEEKABLE_STREAM_DECODER_OK)
|
||||
{
|
||||
if (FLAC__seekable_stream_decoder_get_state(flacDec) !=
|
||||
FLAC__SEEKABLE_STREAM_DECODER_OK) {
|
||||
break;
|
||||
}
|
||||
if(dc->seek) {
|
||||
FLAC__uint64 sampleToSeek = dc->seekWhere*
|
||||
dc->audioFormat.sampleRate+0.5;
|
||||
if(FLAC__seekable_stream_decoder_seek_absolute(flacDec,
|
||||
sampleToSeek))
|
||||
if (dc->seek) {
|
||||
FLAC__uint64 sampleToSeek = dc->seekWhere *
|
||||
dc->audioFormat.sampleRate + 0.5;
|
||||
if (FLAC__seekable_stream_decoder_seek_absolute(flacDec,
|
||||
sampleToSeek))
|
||||
{
|
||||
clearOutputBuffer(cb);
|
||||
data.time = ((float)sampleToSeek)/
|
||||
dc->audioFormat.sampleRate;
|
||||
clearOutputBuffer(cb);
|
||||
data.time = ((float)sampleToSeek) /
|
||||
dc->audioFormat.sampleRate;
|
||||
data.position = 0;
|
||||
}
|
||||
else dc->seekError = 1;
|
||||
} else
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}
|
||||
}
|
||||
/* I don't think we need this bit here! -shank */
|
||||
/*FLAC__file_decoder_process_until_end_of_file(flacDec);*/
|
||||
if(!dc->stop) {
|
||||
flacPrintErroredState(
|
||||
FLAC__seekable_stream_decoder_get_state(flacDec));
|
||||
/*FLAC__file_decoder_process_until_end_of_file(flacDec); */
|
||||
if (!dc->stop) {
|
||||
flacPrintErroredState(FLAC__seekable_stream_decoder_get_state
|
||||
(flacDec));
|
||||
FLAC__seekable_stream_decoder_finish(flacDec);
|
||||
}
|
||||
/* send last little bit */
|
||||
if(data.chunk_length>0 && !dc->stop) {
|
||||
if (data.chunk_length > 0 && !dc->stop) {
|
||||
flacSendChunk(&data);
|
||||
flushOutputBuffer(data.cb);
|
||||
}
|
||||
|
||||
/*if(dc->seek) {
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
} */
|
||||
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
} */
|
||||
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
|
||||
fail:
|
||||
if(data.replayGainInfo) freeReplayGainInfo(data.replayGainInfo);
|
||||
fail:
|
||||
if (data.replayGainInfo)
|
||||
freeReplayGainInfo(data.replayGainInfo);
|
||||
|
||||
if(flacDec) FLAC__seekable_stream_decoder_delete(flacDec);
|
||||
if (flacDec)
|
||||
FLAC__seekable_stream_decoder_delete(flacDec);
|
||||
|
||||
closeInputStream(inStream);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static FLAC__SeekableStreamDecoderReadStatus flacRead(
|
||||
const FLAC__SeekableStreamDecoder * flacDec, FLAC__byte buf[],
|
||||
unsigned * bytes, void * fdata) {
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
static FLAC__SeekableStreamDecoderReadStatus flacRead(const
|
||||
FLAC__SeekableStreamDecoder
|
||||
* flacDec,
|
||||
FLAC__byte buf[],
|
||||
unsigned *bytes,
|
||||
void *fdata)
|
||||
{
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
size_t r;
|
||||
|
||||
while (1) {
|
||||
r = readFromInputStream(data->inStream,(void *)buf,1,*bytes);
|
||||
r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes);
|
||||
if (r == 0 && !inputStreamAtEOF(data->inStream) &&
|
||||
!data->dc->stop)
|
||||
!data->dc->stop)
|
||||
my_usleep(10000);
|
||||
else
|
||||
break;
|
||||
}
|
||||
*bytes = r;
|
||||
|
||||
if (*bytes==0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop)
|
||||
|
||||
if (*bytes == 0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop)
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__SeekableStreamDecoderSeekStatus flacSeek(
|
||||
const FLAC__SeekableStreamDecoder * flacDec,
|
||||
FLAC__uint64 offset, void * fdata)
|
||||
static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const
|
||||
FLAC__SeekableStreamDecoder
|
||||
* flacDec,
|
||||
FLAC__uint64 offset,
|
||||
void *fdata)
|
||||
{
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
|
||||
if(seekInputStream(data->inStream,offset,SEEK_SET)<0) {
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) {
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__SeekableStreamDecoderTellStatus flacTell(
|
||||
const FLAC__SeekableStreamDecoder * flacDec,
|
||||
FLAC__uint64 * offset, void * fdata)
|
||||
static FLAC__SeekableStreamDecoderTellStatus flacTell(const
|
||||
FLAC__SeekableStreamDecoder
|
||||
* flacDec,
|
||||
FLAC__uint64 * offset,
|
||||
void *fdata)
|
||||
{
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
|
||||
*offset = (long)(data->inStream->offset);
|
||||
*offset = (long)(data->inStream->offset);
|
||||
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__SeekableStreamDecoderLengthStatus flacLength(
|
||||
const FLAC__SeekableStreamDecoder * flacDec,
|
||||
FLAC__uint64 * length, void * fdata)
|
||||
static FLAC__SeekableStreamDecoderLengthStatus flacLength(const
|
||||
FLAC__SeekableStreamDecoder
|
||||
* flacDec,
|
||||
FLAC__uint64 * length,
|
||||
void *fdata)
|
||||
{
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
|
||||
*length = (size_t)(data->inStream->size);
|
||||
*length = (size_t) (data->inStream->size);
|
||||
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, void * fdata) {
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
|
||||
static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec,
|
||||
void *fdata)
|
||||
{
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
|
||||
if (inputStreamAtEOF(data->inStream) == 1)
|
||||
return true;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void flacError(const FLAC__SeekableStreamDecoder *dec,
|
||||
FLAC__StreamDecoderErrorStatus status, void *fdata)
|
||||
static void flacError(const FLAC__SeekableStreamDecoder * dec,
|
||||
FLAC__StreamDecoderErrorStatus status, void *fdata)
|
||||
{
|
||||
flac_error_common_cb("flac",status,(FlacData *) fdata);
|
||||
flac_error_common_cb("flac", status, (FlacData *) fdata);
|
||||
}
|
||||
|
||||
static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
|
||||
{
|
||||
switch(state) {
|
||||
switch (state) {
|
||||
case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
|
||||
ERROR("flac allocation error\n");
|
||||
break;
|
||||
@@ -272,48 +301,53 @@ static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
|
||||
}
|
||||
}
|
||||
|
||||
static void flacMetadata(const FLAC__SeekableStreamDecoder *dec,
|
||||
const FLAC__StreamMetadata *block, void *vdata)
|
||||
static void flacMetadata(const FLAC__SeekableStreamDecoder * dec,
|
||||
const FLAC__StreamMetadata * block, void *vdata)
|
||||
{
|
||||
flac_metadata_common_cb(block, (FlacData *)vdata);
|
||||
flac_metadata_common_cb(block, (FlacData *) vdata);
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec,
|
||||
const FLAC__Frame *frame, const FLAC__int32 * const buf[],
|
||||
void * vdata)
|
||||
static FLAC__StreamDecoderWriteStatus flacWrite(const
|
||||
FLAC__SeekableStreamDecoder *
|
||||
dec, const FLAC__Frame * frame,
|
||||
const FLAC__int32 * const buf[],
|
||||
void *vdata)
|
||||
{
|
||||
FlacData * data = (FlacData *)vdata;
|
||||
FlacData *data = (FlacData *) vdata;
|
||||
FLAC__uint32 samples = frame->header.blocksize;
|
||||
FLAC__uint16 u16;
|
||||
unsigned char * uc;
|
||||
unsigned char *uc;
|
||||
int c_samp, c_chan, d_samp;
|
||||
int i;
|
||||
float timeChange;
|
||||
FLAC__uint64 newPosition = 0;
|
||||
|
||||
timeChange = ((float)samples)/frame->header.sample_rate;
|
||||
data->time+= timeChange;
|
||||
|
||||
FLAC__seekable_stream_decoder_get_decode_position(dec,&newPosition);
|
||||
if(data->position) {
|
||||
data->bitRate = ((newPosition-data->position)*8.0/timeChange)
|
||||
/1000+0.5;
|
||||
timeChange = ((float)samples) / frame->header.sample_rate;
|
||||
data->time += timeChange;
|
||||
|
||||
FLAC__seekable_stream_decoder_get_decode_position(dec, &newPosition);
|
||||
if (data->position) {
|
||||
data->bitRate =
|
||||
((newPosition - data->position) * 8.0 / timeChange)
|
||||
/ 1000 + 0.5;
|
||||
}
|
||||
data->position = newPosition;
|
||||
|
||||
for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
|
||||
for(c_chan = 0; c_chan < frame->header.channels;
|
||||
c_chan++, d_samp++) {
|
||||
for (c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
|
||||
for (c_chan = 0; c_chan < frame->header.channels;
|
||||
c_chan++, d_samp++) {
|
||||
u16 = buf[c_chan][c_samp];
|
||||
uc = (unsigned char *)&u16;
|
||||
for(i=0;i<(data->dc->audioFormat.bits/8);i++) {
|
||||
if(data->chunk_length>=FLAC_CHUNK_SIZE) {
|
||||
if(flacSendChunk(data)<0) {
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) {
|
||||
if (data->chunk_length >= FLAC_CHUNK_SIZE) {
|
||||
if (flacSendChunk(data) < 0) {
|
||||
return
|
||||
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
data->chunk_length = 0;
|
||||
if(data->dc->seek) {
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
if (data->dc->seek) {
|
||||
return
|
||||
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
}
|
||||
data->chunk[data->chunk_length++] = *(uc++);
|
||||
@@ -324,66 +358,77 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecode
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) {
|
||||
MpdTag * ret = NULL;
|
||||
FLAC__Metadata_SimpleIterator * it;
|
||||
FLAC__StreamMetadata * block = NULL;
|
||||
static MpdTag *flacMetadataDup(char *file, int *vorbisCommentFound)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
FLAC__Metadata_SimpleIterator *it;
|
||||
FLAC__StreamMetadata *block = NULL;
|
||||
|
||||
*vorbisCommentFound = 0;
|
||||
|
||||
it = FLAC__metadata_simple_iterator_new();
|
||||
if(!FLAC__metadata_simple_iterator_init(it, file ,1,0)) {
|
||||
switch(FLAC__metadata_simple_iterator_status(it)) {
|
||||
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
|
||||
DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Illegal Input\n",file);
|
||||
break;
|
||||
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
|
||||
DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Error Opening File\n",file);
|
||||
break;
|
||||
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
|
||||
DEBUG("flacMetadataDup: Reading '%s' metadata gave the following error: Not A Flac File\n",file);
|
||||
break;
|
||||
default:
|
||||
DEBUG("flacMetadataDup: Reading '%s' metadata failed\n",file);
|
||||
if (!FLAC__metadata_simple_iterator_init(it, file, 1, 0)) {
|
||||
switch (FLAC__metadata_simple_iterator_status(it)) {
|
||||
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
|
||||
DEBUG
|
||||
("flacMetadataDup: Reading '%s' metadata gave the following error: Illegal Input\n",
|
||||
file);
|
||||
break;
|
||||
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
|
||||
DEBUG
|
||||
("flacMetadataDup: Reading '%s' metadata gave the following error: Error Opening File\n",
|
||||
file);
|
||||
break;
|
||||
case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
|
||||
DEBUG
|
||||
("flacMetadataDup: Reading '%s' metadata gave the following error: Not A Flac File\n",
|
||||
file);
|
||||
break;
|
||||
default:
|
||||
DEBUG("flacMetadataDup: Reading '%s' metadata failed\n",
|
||||
file);
|
||||
}
|
||||
FLAC__metadata_simple_iterator_delete(it);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
block = FLAC__metadata_simple_iterator_get_block(it);
|
||||
if(!block) break;
|
||||
if(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
|
||||
if (!block)
|
||||
break;
|
||||
if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
|
||||
ret = copyVorbisCommentBlockToMpdTag(block, ret);
|
||||
|
||||
if(ret) *vorbisCommentFound = 1;
|
||||
}
|
||||
else if(block->type == FLAC__METADATA_TYPE_STREAMINFO) {
|
||||
if(!ret) ret = newMpdTag();
|
||||
if (ret)
|
||||
*vorbisCommentFound = 1;
|
||||
} else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) {
|
||||
if (!ret)
|
||||
ret = newMpdTag();
|
||||
ret->time = ((float)block->data.stream_info.
|
||||
total_samples) /
|
||||
block->data.stream_info.sample_rate +
|
||||
0.5;
|
||||
total_samples) /
|
||||
block->data.stream_info.sample_rate + 0.5;
|
||||
}
|
||||
FLAC__metadata_object_delete(block);
|
||||
} while(FLAC__metadata_simple_iterator_next(it));
|
||||
} while (FLAC__metadata_simple_iterator_next(it));
|
||||
|
||||
FLAC__metadata_simple_iterator_delete(it);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MpdTag * flacTagDup(char * file) {
|
||||
MpdTag * ret = NULL;
|
||||
static MpdTag *flacTagDup(char *file)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
int foundVorbisComment = 0;
|
||||
|
||||
ret = flacMetadataDup(file, &foundVorbisComment);
|
||||
if(!ret) {
|
||||
DEBUG("flacTagDup: Failed to grab information from: %s\n", file);
|
||||
if (!ret) {
|
||||
DEBUG("flacTagDup: Failed to grab information from: %s\n",
|
||||
file);
|
||||
return NULL;
|
||||
}
|
||||
if(!foundVorbisComment) {
|
||||
MpdTag * temp = id3Dup(file);
|
||||
if(temp) {
|
||||
if (!foundVorbisComment) {
|
||||
MpdTag *temp = id3Dup(file);
|
||||
if (temp) {
|
||||
temp->time = ret->time;
|
||||
freeMpdTag(ret);
|
||||
ret = temp;
|
||||
@@ -393,11 +438,10 @@ static MpdTag * flacTagDup(char * file) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * flacSuffixes[] = {"flac", NULL};
|
||||
static char * flac_mime_types[] = {"application/x-flac", NULL};
|
||||
static char *flacSuffixes[] = { "flac", NULL };
|
||||
static char *flac_mime_types[] = { "application/x-flac", NULL };
|
||||
|
||||
InputPlugin flacPlugin =
|
||||
{
|
||||
InputPlugin flacPlugin = {
|
||||
"flac",
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -410,10 +454,9 @@ InputPlugin flacPlugin =
|
||||
flac_mime_types
|
||||
};
|
||||
|
||||
#else /* !HAVE_FLAC */
|
||||
#else /* !HAVE_FLAC */
|
||||
|
||||
InputPlugin flacPlugin =
|
||||
{
|
||||
InputPlugin flacPlugin = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -426,4 +469,4 @@ InputPlugin flacPlugin =
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif /* HAVE_FLAC */
|
||||
#endif /* HAVE_FLAC */
|
||||
|
@@ -39,23 +39,26 @@
|
||||
|
||||
#define MIKMOD_FRAME_SIZE 4096
|
||||
|
||||
static BOOL mod_mpd_Init(void) {
|
||||
static BOOL mod_mpd_Init(void)
|
||||
{
|
||||
return VC_Init();
|
||||
}
|
||||
|
||||
static void mod_mpd_Exit(void) {
|
||||
static void mod_mpd_Exit(void)
|
||||
{
|
||||
VC_Exit();
|
||||
}
|
||||
|
||||
static void mod_mpd_Update(void) {
|
||||
static void mod_mpd_Update(void)
|
||||
{
|
||||
}
|
||||
|
||||
static BOOL mod_mpd_IsThere(void) {
|
||||
static BOOL mod_mpd_IsThere(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static MDRIVER drv_mpd =
|
||||
{
|
||||
static MDRIVER drv_mpd = {
|
||||
NULL,
|
||||
"MPD",
|
||||
"MPD Output Driver v0.1",
|
||||
@@ -92,10 +95,12 @@ static MDRIVER drv_mpd =
|
||||
static int mod_mikModInitiated = 0;
|
||||
static int mod_mikModInitError = 0;
|
||||
|
||||
static int mod_initMikMod(void) {
|
||||
if(mod_mikModInitError) return -1;
|
||||
static int mod_initMikMod(void)
|
||||
{
|
||||
if (mod_mikModInitError)
|
||||
return -1;
|
||||
|
||||
if(!mod_mikModInitiated) {
|
||||
if (!mod_mikModInitiated) {
|
||||
mod_mikModInitiated = 1;
|
||||
|
||||
md_device = 0;
|
||||
@@ -108,11 +113,11 @@ static int mod_initMikMod(void) {
|
||||
md_pansep = 64;
|
||||
md_mixfreq = 44100;
|
||||
md_mode = (DMODE_SOFT_MUSIC | DMODE_INTERP | DMODE_STEREO |
|
||||
DMODE_16BITS);
|
||||
DMODE_16BITS);
|
||||
|
||||
if(MikMod_Init("")) {
|
||||
ERROR("Could not init MikMod: %s\n",
|
||||
MikMod_strerror(MikMod_errno));
|
||||
if (MikMod_Init("")) {
|
||||
ERROR("Could not init MikMod: %s\n",
|
||||
MikMod_strerror(MikMod_errno));
|
||||
mod_mikModInitError = 1;
|
||||
return -1;
|
||||
}
|
||||
@@ -120,20 +125,23 @@ static int mod_initMikMod(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mod_finishMikMod(void) {
|
||||
static void mod_finishMikMod(void)
|
||||
{
|
||||
MikMod_Exit();
|
||||
}
|
||||
|
||||
typedef struct _mod_Data {
|
||||
MODULE * moduleHandle;
|
||||
SBYTE * audio_buffer;
|
||||
} mod_Data;
|
||||
MODULE *moduleHandle;
|
||||
SBYTE *audio_buffer;
|
||||
} mod_Data;
|
||||
|
||||
static mod_Data * mod_open(char * path) {
|
||||
MODULE * moduleHandle;
|
||||
mod_Data * data;
|
||||
static mod_Data *mod_open(char *path)
|
||||
{
|
||||
MODULE *moduleHandle;
|
||||
mod_Data *data;
|
||||
|
||||
if(!(moduleHandle = Player_Load(path, 128, 0))) return NULL;
|
||||
if (!(moduleHandle = Player_Load(path, 128, 0)))
|
||||
return NULL;
|
||||
|
||||
data = malloc(sizeof(mod_Data));
|
||||
|
||||
@@ -145,51 +153,57 @@ static mod_Data * mod_open(char * path) {
|
||||
return data;
|
||||
}
|
||||
|
||||
static void mod_close(mod_Data * data) {
|
||||
static void mod_close(mod_Data * data)
|
||||
{
|
||||
Player_Stop();
|
||||
Player_Free(data->moduleHandle);
|
||||
free(data->audio_buffer);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
mod_Data * data;
|
||||
static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
|
||||
{
|
||||
mod_Data *data;
|
||||
float time = 0.0;
|
||||
int ret;
|
||||
float secPerByte;
|
||||
|
||||
if(mod_initMikMod() < 0) return -1;
|
||||
if (mod_initMikMod() < 0)
|
||||
return -1;
|
||||
|
||||
if(!(data = mod_open(path))) {
|
||||
if (!(data = mod_open(path))) {
|
||||
ERROR("failed to open mod: %s\n", path);
|
||||
MikMod_Exit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
dc->audioFormat.bits = 16;
|
||||
dc->audioFormat.sampleRate = 44100;
|
||||
dc->audioFormat.channels = 2;
|
||||
getOutputAudioFormat(&(dc->audioFormat),&(cb->audioFormat));
|
||||
getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat));
|
||||
|
||||
secPerByte =
|
||||
1.0 / ((dc->audioFormat.bits * dc->audioFormat.channels / 8.0) *
|
||||
(float)dc->audioFormat.sampleRate);
|
||||
|
||||
secPerByte = 1.0/((dc->audioFormat.bits*dc->audioFormat.channels/8.0)*
|
||||
(float)dc->audioFormat.sampleRate);
|
||||
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
while(1) {
|
||||
if(dc->seek) {
|
||||
while (1) {
|
||||
if (dc->seek) {
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}
|
||||
|
||||
if(dc->stop) break;
|
||||
if (dc->stop)
|
||||
break;
|
||||
|
||||
if(!Player_Active()) break;
|
||||
if (!Player_Active())
|
||||
break;
|
||||
|
||||
ret = VC_WriteBytes(data->audio_buffer, MIKMOD_FRAME_SIZE);
|
||||
time += ret*secPerByte;
|
||||
sendDataToOutputBuffer(cb, NULL, dc, 0,
|
||||
(char *)data->audio_buffer, ret, time,
|
||||
0, NULL);
|
||||
time += ret * secPerByte;
|
||||
sendDataToOutputBuffer(cb, NULL, dc, 0,
|
||||
(char *)data->audio_buffer, ret, time,
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
flushOutputBuffer(cb);
|
||||
@@ -198,27 +212,28 @@ static int mod_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
|
||||
MikMod_Exit();
|
||||
|
||||
if(dc->stop) {
|
||||
if (dc->stop) {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
else dc->state = DECODE_STATE_STOP;
|
||||
} else
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MpdTag * modTagDup(char * file) {
|
||||
MpdTag * ret = NULL;
|
||||
MODULE * moduleHandle;
|
||||
char * title;
|
||||
static MpdTag *modTagDup(char *file)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
MODULE *moduleHandle;
|
||||
char *title;
|
||||
|
||||
if(mod_initMikMod() < 0) {
|
||||
if (mod_initMikMod() < 0) {
|
||||
DEBUG("modTagDup: Failed to initialize MikMod\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!(moduleHandle = Player_Load(file, 128, 0))) {
|
||||
DEBUG("modTagDup: Failed to open file: %s\n",file);
|
||||
if (!(moduleHandle = Player_Load(file, 128, 0))) {
|
||||
DEBUG("modTagDup: Failed to open file: %s\n", file);
|
||||
MikMod_Exit();
|
||||
return NULL;
|
||||
|
||||
@@ -229,58 +244,58 @@ static MpdTag * modTagDup(char * file) {
|
||||
|
||||
ret->time = 0;
|
||||
title = strdup(Player_LoadTitle(file));
|
||||
if(title) addItemToMpdTag(ret, TAG_ITEM_TITLE, title);
|
||||
if (title)
|
||||
addItemToMpdTag(ret, TAG_ITEM_TITLE, title);
|
||||
|
||||
MikMod_Exit();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * modSuffixes[] = {"amf",
|
||||
"dsm",
|
||||
"far",
|
||||
"gdm",
|
||||
"imf",
|
||||
"it",
|
||||
"med",
|
||||
"mod",
|
||||
"mtm",
|
||||
"s3m",
|
||||
"stm",
|
||||
"stx",
|
||||
"ult",
|
||||
"uni",
|
||||
"xm",
|
||||
NULL};
|
||||
static char *modSuffixes[] = { "amf",
|
||||
"dsm",
|
||||
"far",
|
||||
"gdm",
|
||||
"imf",
|
||||
"it",
|
||||
"med",
|
||||
"mod",
|
||||
"mtm",
|
||||
"s3m",
|
||||
"stm",
|
||||
"stx",
|
||||
"ult",
|
||||
"uni",
|
||||
"xm",
|
||||
NULL
|
||||
};
|
||||
|
||||
InputPlugin modPlugin =
|
||||
{
|
||||
"mod",
|
||||
NULL,
|
||||
InputPlugin modPlugin = {
|
||||
"mod",
|
||||
NULL,
|
||||
mod_finishMikMod,
|
||||
NULL,
|
||||
NULL,
|
||||
mod_decode,
|
||||
modTagDup,
|
||||
INPUT_PLUGIN_STREAM_FILE,
|
||||
modSuffixes,
|
||||
NULL
|
||||
mod_decode,
|
||||
modTagDup,
|
||||
INPUT_PLUGIN_STREAM_FILE,
|
||||
modSuffixes,
|
||||
NULL
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
InputPlugin modPlugin =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
InputPlugin modPlugin = {
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* HAVE_AUDIOFILE */
|
||||
#endif /* HAVE_AUDIOFILE */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,8 @@
|
||||
|
||||
/* all code here is either based on or copied from FAAD2's frontend code */
|
||||
|
||||
static int mp4_getAACTrack(mp4ff_t *infile) {
|
||||
static int mp4_getAACTrack(mp4ff_t * infile)
|
||||
{
|
||||
/* find AAC track */
|
||||
int i, rc;
|
||||
int numTracks = mp4ff_total_tracks(infile);
|
||||
@@ -50,9 +51,9 @@ static int mp4_getAACTrack(mp4ff_t *infile) {
|
||||
#else
|
||||
unsigned long dummy1_32;
|
||||
unsigned char dummy2_8, dummy3_8, dummy4_8, dummy5_8, dummy6_8,
|
||||
dummy7_8, dummy8_8;
|
||||
dummy7_8, dummy8_8;
|
||||
#endif
|
||||
|
||||
|
||||
mp4ff_get_decoder_config(infile, i, &buff, buff_size);
|
||||
|
||||
if (buff) {
|
||||
@@ -60,11 +61,13 @@ static int mp4_getAACTrack(mp4ff_t *infile) {
|
||||
rc = AudioSpecificConfig(buff, *buff_size, &mp4ASC);
|
||||
#else
|
||||
rc = AudioSpecificConfig(buff, &dummy1_32, &dummy2_8,
|
||||
&dummy3_8, &dummy4_8, &dummy5_8,
|
||||
&dummy6_8, &dummy7_8, &dummy8_8);
|
||||
&dummy3_8, &dummy4_8,
|
||||
&dummy5_8, &dummy6_8,
|
||||
&dummy7_8, &dummy8_8);
|
||||
#endif
|
||||
free(buff);
|
||||
if (rc < 0) continue;
|
||||
if (rc < 0)
|
||||
continue;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -74,16 +77,18 @@ static int mp4_getAACTrack(mp4ff_t *infile) {
|
||||
}
|
||||
|
||||
static uint32_t mp4_inputStreamReadCallback(void *inStream, void *buffer,
|
||||
uint32_t length)
|
||||
uint32_t length)
|
||||
{
|
||||
return readFromInputStream((InputStream*) inStream, buffer, 1, length);
|
||||
return readFromInputStream((InputStream *) inStream, buffer, 1, length);
|
||||
}
|
||||
|
||||
static uint32_t mp4_inputStreamSeekCallback(void *inStream, uint64_t position) {
|
||||
static uint32_t mp4_inputStreamSeekCallback(void *inStream, uint64_t position)
|
||||
{
|
||||
return seekInputStream((InputStream *) inStream, position, SEEK_SET);
|
||||
}
|
||||
|
||||
static faacDecHandle * openConfigureFaad() {
|
||||
static faacDecHandle *openConfigureFaad()
|
||||
{
|
||||
faacDecConfigurationPtr config;
|
||||
faacDecHandle decoder = faacDecOpen();
|
||||
|
||||
@@ -95,20 +100,21 @@ static faacDecHandle * openConfigureFaad() {
|
||||
#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
|
||||
config->dontUpSampleImplicitSBR = 0;
|
||||
#endif
|
||||
faacDecSetConfiguration(decoder,config);
|
||||
faacDecSetConfiguration(decoder, config);
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
mp4ff_t * mp4fh;
|
||||
mp4ff_callback_t * mp4cb;
|
||||
static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char *path)
|
||||
{
|
||||
mp4ff_t *mp4fh;
|
||||
mp4ff_callback_t *mp4cb;
|
||||
int32_t track;
|
||||
float time;
|
||||
int32_t scale;
|
||||
faacDecHandle * decoder;
|
||||
faacDecHandle *decoder;
|
||||
faacDecFrameInfo frameInfo;
|
||||
unsigned char * mp4Buffer;
|
||||
unsigned char *mp4Buffer;
|
||||
unsigned int mp4BufferSize;
|
||||
uint32_t sampleRate;
|
||||
unsigned char channels;
|
||||
@@ -117,10 +123,10 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
int eof = 0;
|
||||
long dur;
|
||||
unsigned int sampleCount;
|
||||
char * sampleBuffer;
|
||||
char *sampleBuffer;
|
||||
size_t sampleBufferLen;
|
||||
unsigned int initial = 1;
|
||||
float * seekTable;
|
||||
float *seekTable;
|
||||
long seekTableEnd = -1;
|
||||
int seekPositionFound = 0;
|
||||
long offset;
|
||||
@@ -128,7 +134,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
InputStream inStream;
|
||||
int seeking = 0;
|
||||
|
||||
if(openInputStream(&inStream, path) < 0) {
|
||||
if (openInputStream(&inStream, path) < 0) {
|
||||
ERROR("failed to open %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
@@ -139,7 +145,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
mp4cb->user_data = &inStream;
|
||||
|
||||
mp4fh = mp4ff_open_read(mp4cb);
|
||||
if(!mp4fh) {
|
||||
if (!mp4fh) {
|
||||
ERROR("Input does not appear to be a mp4 stream.\n");
|
||||
free(mp4cb);
|
||||
closeInputStream(&inStream);
|
||||
@@ -147,7 +153,7 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
}
|
||||
|
||||
track = mp4_getAACTrack(mp4fh);
|
||||
if(track < 0) {
|
||||
if (track < 0) {
|
||||
ERROR("No AAC track found in mp4 stream.\n");
|
||||
mp4ff_close(mp4fh);
|
||||
closeInputStream(&inStream);
|
||||
@@ -161,11 +167,11 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
|
||||
mp4Buffer = NULL;
|
||||
mp4BufferSize = 0;
|
||||
mp4ff_get_decoder_config(mp4fh,track,&mp4Buffer,&mp4BufferSize);
|
||||
mp4ff_get_decoder_config(mp4fh, track, &mp4Buffer, &mp4BufferSize);
|
||||
|
||||
if(faacDecInit2(decoder,mp4Buffer,mp4BufferSize,&sampleRate,&channels)
|
||||
< 0)
|
||||
{
|
||||
if (faacDecInit2
|
||||
(decoder, mp4Buffer, mp4BufferSize, &sampleRate, &channels)
|
||||
< 0) {
|
||||
ERROR("Error not a AAC stream.\n");
|
||||
faacDecClose(decoder);
|
||||
mp4ff_close(mp4fh);
|
||||
@@ -176,12 +182,13 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
|
||||
dc->audioFormat.sampleRate = sampleRate;
|
||||
dc->audioFormat.channels = channels;
|
||||
time = mp4ff_get_track_duration_use_offsets(mp4fh,track);
|
||||
scale = mp4ff_time_scale(mp4fh,track);
|
||||
time = mp4ff_get_track_duration_use_offsets(mp4fh, track);
|
||||
scale = mp4ff_time_scale(mp4fh, track);
|
||||
|
||||
if(mp4Buffer) free(mp4Buffer);
|
||||
if (mp4Buffer)
|
||||
free(mp4Buffer);
|
||||
|
||||
if(scale < 0) {
|
||||
if (scale < 0) {
|
||||
ERROR("Error getting audio format of mp4 AAC track.\n");
|
||||
faacDecClose(decoder);
|
||||
mp4ff_close(mp4fh);
|
||||
@@ -189,107 +196,111 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
free(mp4cb);
|
||||
return -1;
|
||||
}
|
||||
dc->totalTime = ((float)time)/scale;
|
||||
dc->totalTime = ((float)time) / scale;
|
||||
|
||||
numSamples = mp4ff_num_samples(mp4fh,track);
|
||||
numSamples = mp4ff_num_samples(mp4fh, track);
|
||||
|
||||
time = 0.0;
|
||||
|
||||
seekTable = malloc(sizeof(float)*numSamples);
|
||||
seekTable = malloc(sizeof(float) * numSamples);
|
||||
|
||||
for(sampleId=0; sampleId<numSamples && !eof; sampleId++) {
|
||||
if(dc->seek) seeking = 1;
|
||||
for (sampleId = 0; sampleId < numSamples && !eof; sampleId++) {
|
||||
if (dc->seek)
|
||||
seeking = 1;
|
||||
|
||||
if(seeking && seekTableEnd>1 &&
|
||||
seekTable[seekTableEnd]>=dc->seekWhere)
|
||||
{
|
||||
if (seeking && seekTableEnd > 1 &&
|
||||
seekTable[seekTableEnd] >= dc->seekWhere) {
|
||||
int i = 2;
|
||||
while(seekTable[i]<dc->seekWhere) i++;
|
||||
sampleId = i-1;
|
||||
while (seekTable[i] < dc->seekWhere)
|
||||
i++;
|
||||
sampleId = i - 1;
|
||||
time = seekTable[sampleId];
|
||||
}
|
||||
|
||||
dur = mp4ff_get_sample_duration(mp4fh,track,sampleId);
|
||||
offset = mp4ff_get_sample_offset(mp4fh,track,sampleId);
|
||||
dur = mp4ff_get_sample_duration(mp4fh, track, sampleId);
|
||||
offset = mp4ff_get_sample_offset(mp4fh, track, sampleId);
|
||||
|
||||
if(sampleId>seekTableEnd) {
|
||||
if (sampleId > seekTableEnd) {
|
||||
seekTable[sampleId] = time;
|
||||
seekTableEnd = sampleId;
|
||||
}
|
||||
|
||||
if(sampleId==0) dur = 0;
|
||||
if(offset>dur) dur = 0;
|
||||
else dur-=offset;
|
||||
time+=((float)dur)/scale;
|
||||
if (sampleId == 0)
|
||||
dur = 0;
|
||||
if (offset > dur)
|
||||
dur = 0;
|
||||
else
|
||||
dur -= offset;
|
||||
time += ((float)dur) / scale;
|
||||
|
||||
if(seeking && time>dc->seekWhere) seekPositionFound = 1;
|
||||
if (seeking && time > dc->seekWhere)
|
||||
seekPositionFound = 1;
|
||||
|
||||
if(seeking && seekPositionFound) {
|
||||
if (seeking && seekPositionFound) {
|
||||
seekPositionFound = 0;
|
||||
clearOutputBuffer(cb);
|
||||
clearOutputBuffer(cb);
|
||||
seeking = 0;
|
||||
dc->seek = 0;
|
||||
}
|
||||
|
||||
if(seeking) continue;
|
||||
|
||||
if(mp4ff_read_sample(mp4fh,track,sampleId,&mp4Buffer,
|
||||
&mp4BufferSize) == 0)
|
||||
{
|
||||
if (seeking)
|
||||
continue;
|
||||
|
||||
if (mp4ff_read_sample(mp4fh, track, sampleId, &mp4Buffer,
|
||||
&mp4BufferSize) == 0) {
|
||||
eof = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FAAD_BUFLEN_FUNCS
|
||||
sampleBuffer = faacDecDecode(decoder,&frameInfo,mp4Buffer,
|
||||
mp4BufferSize);
|
||||
sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer,
|
||||
mp4BufferSize);
|
||||
#else
|
||||
sampleBuffer = faacDecDecode(decoder,&frameInfo,mp4Buffer);
|
||||
sampleBuffer = faacDecDecode(decoder, &frameInfo, mp4Buffer);
|
||||
#endif
|
||||
|
||||
if(mp4Buffer) free(mp4Buffer);
|
||||
if(frameInfo.error > 0) {
|
||||
if (mp4Buffer)
|
||||
free(mp4Buffer);
|
||||
if (frameInfo.error > 0) {
|
||||
ERROR("error decoding MP4 file: %s\n", path);
|
||||
ERROR("faad2 error: %s\n",
|
||||
faacDecGetErrorMessage(frameInfo.error));
|
||||
faacDecGetErrorMessage(frameInfo.error));
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(dc->state != DECODE_STATE_DECODE) {
|
||||
if (dc->state != DECODE_STATE_DECODE) {
|
||||
channels = frameInfo.channels;
|
||||
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
|
||||
scale = frameInfo.samplerate;
|
||||
#endif
|
||||
dc->audioFormat.sampleRate = scale;
|
||||
dc->audioFormat.channels = frameInfo.channels;
|
||||
getOutputAudioFormat(&(dc->audioFormat),
|
||||
&(cb->audioFormat));
|
||||
getOutputAudioFormat(&(dc->audioFormat),
|
||||
&(cb->audioFormat));
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
}
|
||||
|
||||
if(channels*(dur+offset) > frameInfo.samples) {
|
||||
dur = frameInfo.samples/channels;
|
||||
if (channels * (dur + offset) > frameInfo.samples) {
|
||||
dur = frameInfo.samples / channels;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
sampleCount = (unsigned long)(dur*channels);
|
||||
sampleCount = (unsigned long)(dur * channels);
|
||||
|
||||
if(sampleCount>0) {
|
||||
initial =0;
|
||||
bitRate = frameInfo.bytesconsumed*8.0*
|
||||
frameInfo.channels*scale/
|
||||
frameInfo.samples/1000+0.5;
|
||||
if (sampleCount > 0) {
|
||||
initial = 0;
|
||||
bitRate = frameInfo.bytesconsumed * 8.0 *
|
||||
frameInfo.channels * scale /
|
||||
frameInfo.samples / 1000 + 0.5;
|
||||
}
|
||||
|
||||
|
||||
sampleBufferLen = sampleCount*2;
|
||||
sampleBufferLen = sampleCount * 2;
|
||||
|
||||
sampleBuffer+=offset*channels*2;
|
||||
sampleBuffer += offset * channels * 2;
|
||||
|
||||
sendDataToOutputBuffer(cb, NULL, dc, 1, sampleBuffer,
|
||||
sampleBufferLen, time, bitRate, NULL);
|
||||
if(dc->stop) {
|
||||
sampleBufferLen, time, bitRate, NULL);
|
||||
if (dc->stop) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
@@ -301,33 +312,36 @@ static int mp4_decode(OutputBuffer * cb, DecoderControl * dc, char * path) {
|
||||
closeInputStream(&inStream);
|
||||
free(mp4cb);
|
||||
|
||||
if(dc->state != DECODE_STATE_DECODE) return -1;
|
||||
if (dc->state != DECODE_STATE_DECODE)
|
||||
return -1;
|
||||
|
||||
if(dc->seek && seeking) {
|
||||
clearOutputBuffer(cb);
|
||||
dc->seek = 0;
|
||||
}
|
||||
if (dc->seek && seeking) {
|
||||
clearOutputBuffer(cb);
|
||||
dc->seek = 0;
|
||||
}
|
||||
flushOutputBuffer(cb);
|
||||
|
||||
if(dc->stop) dc->stop = 0;
|
||||
if (dc->stop)
|
||||
dc->stop = 0;
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
|
||||
MpdTag * ret = NULL;
|
||||
static MpdTag *mp4DataDup(char *file, int *mp4MetadataFound)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
InputStream inStream;
|
||||
mp4ff_t * mp4fh;
|
||||
mp4ff_callback_t * cb;
|
||||
mp4ff_t *mp4fh;
|
||||
mp4ff_callback_t *cb;
|
||||
int32_t track;
|
||||
int32_t time;
|
||||
int32_t scale;
|
||||
int i;
|
||||
|
||||
*mp4MetadataFound = 0;
|
||||
|
||||
if(openInputStream(&inStream, file) < 0) {
|
||||
|
||||
if (openInputStream(&inStream, file) < 0) {
|
||||
DEBUG("mp4DataDup: Failed to open file: %s\n", file);
|
||||
return NULL;
|
||||
}
|
||||
@@ -338,14 +352,14 @@ static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
|
||||
cb->user_data = &inStream;
|
||||
|
||||
mp4fh = mp4ff_open_read(cb);
|
||||
if(!mp4fh) {
|
||||
if (!mp4fh) {
|
||||
free(cb);
|
||||
closeInputStream(&inStream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
track = mp4_getAACTrack(mp4fh);
|
||||
if(track < 0) {
|
||||
if (track < 0) {
|
||||
mp4ff_close(mp4fh);
|
||||
closeInputStream(&inStream);
|
||||
free(cb);
|
||||
@@ -353,48 +367,42 @@ static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
|
||||
}
|
||||
|
||||
ret = newMpdTag();
|
||||
time = mp4ff_get_track_duration_use_offsets(mp4fh,track);
|
||||
scale = mp4ff_time_scale(mp4fh,track);
|
||||
if(scale < 0) {
|
||||
time = mp4ff_get_track_duration_use_offsets(mp4fh, track);
|
||||
scale = mp4ff_time_scale(mp4fh, track);
|
||||
if (scale < 0) {
|
||||
mp4ff_close(mp4fh);
|
||||
closeInputStream(&inStream);
|
||||
free(cb);
|
||||
freeMpdTag(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret->time = ((float)time)/scale+0.5;
|
||||
ret->time = ((float)time) / scale + 0.5;
|
||||
|
||||
for(i = 0; i < mp4ff_meta_get_num_items(mp4fh); i++) {
|
||||
char * item;
|
||||
char * value;
|
||||
for (i = 0; i < mp4ff_meta_get_num_items(mp4fh); i++) {
|
||||
char *item;
|
||||
char *value;
|
||||
|
||||
mp4ff_meta_get_by_index(mp4fh, i, &item, &value);
|
||||
|
||||
if(0 == strcasecmp("artist", item)) {
|
||||
if (0 == strcasecmp("artist", item)) {
|
||||
addItemToMpdTag(ret, TAG_ITEM_ARTIST, value);
|
||||
*mp4MetadataFound = 1;
|
||||
}
|
||||
else if(0 == strcasecmp("title", item)) {
|
||||
} else if (0 == strcasecmp("title", item)) {
|
||||
addItemToMpdTag(ret, TAG_ITEM_TITLE, value);
|
||||
*mp4MetadataFound = 1;
|
||||
}
|
||||
else if(0 == strcasecmp("album", item)) {
|
||||
} else if (0 == strcasecmp("album", item)) {
|
||||
addItemToMpdTag(ret, TAG_ITEM_ALBUM, value);
|
||||
*mp4MetadataFound = 1;
|
||||
}
|
||||
else if(0 == strcasecmp("track", item)) {
|
||||
} else if (0 == strcasecmp("track", item)) {
|
||||
addItemToMpdTag(ret, TAG_ITEM_TRACK, value);
|
||||
*mp4MetadataFound = 1;
|
||||
}
|
||||
else if(0 == strcasecmp("disc", item)) { /* Is that the correct id? */
|
||||
} else if (0 == strcasecmp("disc", item)) { /* Is that the correct id? */
|
||||
addItemToMpdTag(ret, TAG_ITEM_DISC, value);
|
||||
*mp4MetadataFound = 1;
|
||||
}
|
||||
else if(0 == strcasecmp("genre", item)) {
|
||||
} else if (0 == strcasecmp("genre", item)) {
|
||||
addItemToMpdTag(ret, TAG_ITEM_GENRE, value);
|
||||
*mp4MetadataFound = 1;
|
||||
}
|
||||
else if(0 == strcasecmp("date", item)) {
|
||||
} else if (0 == strcasecmp("date", item)) {
|
||||
addItemToMpdTag(ret, TAG_ITEM_DATE, value);
|
||||
*mp4MetadataFound = 1;
|
||||
}
|
||||
@@ -410,15 +418,17 @@ static MpdTag * mp4DataDup(char * file, int * mp4MetadataFound) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MpdTag * mp4TagDup(char * file) {
|
||||
MpdTag * ret = NULL;
|
||||
static MpdTag *mp4TagDup(char *file)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
int mp4MetadataFound = 0;
|
||||
|
||||
ret = mp4DataDup(file, &mp4MetadataFound);
|
||||
if(!ret) return NULL;
|
||||
if(!mp4MetadataFound) {
|
||||
MpdTag * temp = id3Dup(file);
|
||||
if(temp) {
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!mp4MetadataFound) {
|
||||
MpdTag *temp = id3Dup(file);
|
||||
if (temp) {
|
||||
temp->time = ret->time;
|
||||
freeMpdTag(ret);
|
||||
ret = temp;
|
||||
@@ -428,10 +438,9 @@ static MpdTag * mp4TagDup(char * file) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * mp4Suffixes[] = {"m4a", "mp4", NULL};
|
||||
static char *mp4Suffixes[] = { "m4a", "mp4", NULL };
|
||||
|
||||
InputPlugin mp4Plugin =
|
||||
{
|
||||
InputPlugin mp4Plugin = {
|
||||
"mp4",
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -446,8 +455,7 @@ InputPlugin mp4Plugin =
|
||||
|
||||
#else
|
||||
|
||||
InputPlugin mp4Plugin =
|
||||
{
|
||||
InputPlugin mp4Plugin = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -460,4 +468,4 @@ InputPlugin mp4Plugin =
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* HAVE_FAAD */
|
||||
#endif /* HAVE_FAAD */
|
||||
|
@@ -37,66 +37,70 @@
|
||||
#include <math.h>
|
||||
|
||||
typedef struct _MpcCallbackData {
|
||||
InputStream * inStream;
|
||||
DecoderControl * dc;
|
||||
InputStream *inStream;
|
||||
DecoderControl *dc;
|
||||
} MpcCallbackData;
|
||||
|
||||
static mpc_int32_t mpc_read_cb(void * vdata, void * ptr, mpc_int32_t size) {
|
||||
static mpc_int32_t mpc_read_cb(void *vdata, void *ptr, mpc_int32_t size)
|
||||
{
|
||||
mpc_int32_t ret = 0;
|
||||
MpcCallbackData * data = (MpcCallbackData *)vdata;
|
||||
MpcCallbackData *data = (MpcCallbackData *) vdata;
|
||||
|
||||
while(1) {
|
||||
ret = readFromInputStream(data->inStream, ptr, 1, size);
|
||||
if(ret == 0 && !inputStreamAtEOF(data->inStream) &&
|
||||
(data->dc && !data->dc->stop))
|
||||
{
|
||||
my_usleep(10000);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
while (1) {
|
||||
ret = readFromInputStream(data->inStream, ptr, 1, size);
|
||||
if (ret == 0 && !inputStreamAtEOF(data->inStream) &&
|
||||
(data->dc && !data->dc->stop)) {
|
||||
my_usleep(10000);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mpc_bool_t mpc_seek_cb(void * vdata, mpc_int32_t offset) {
|
||||
MpcCallbackData * data = (MpcCallbackData *)vdata;
|
||||
static mpc_bool_t mpc_seek_cb(void *vdata, mpc_int32_t offset)
|
||||
{
|
||||
MpcCallbackData *data = (MpcCallbackData *) vdata;
|
||||
|
||||
return seekInputStream(data->inStream , offset, SEEK_SET) < 0 ? 0 : 1;
|
||||
return seekInputStream(data->inStream, offset, SEEK_SET) < 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
static mpc_int32_t mpc_tell_cb(void * vdata) {
|
||||
MpcCallbackData * data = (MpcCallbackData *)vdata;
|
||||
static mpc_int32_t mpc_tell_cb(void *vdata)
|
||||
{
|
||||
MpcCallbackData *data = (MpcCallbackData *) vdata;
|
||||
|
||||
return (long)(data->inStream->offset);
|
||||
}
|
||||
|
||||
static mpc_bool_t mpc_canseek_cb(void * vdata) {
|
||||
MpcCallbackData * data = (MpcCallbackData *)vdata;
|
||||
static mpc_bool_t mpc_canseek_cb(void *vdata)
|
||||
{
|
||||
MpcCallbackData *data = (MpcCallbackData *) vdata;
|
||||
|
||||
return data->inStream->seekable;
|
||||
}
|
||||
|
||||
static mpc_int32_t mpc_getsize_cb(void * vdata) {
|
||||
MpcCallbackData * data = (MpcCallbackData *)vdata;
|
||||
static mpc_int32_t mpc_getsize_cb(void *vdata)
|
||||
{
|
||||
MpcCallbackData *data = (MpcCallbackData *) vdata;
|
||||
|
||||
return data->inStream->size;
|
||||
}
|
||||
|
||||
/* this _looks_ performance-critical, don't de-inline -- eric */
|
||||
static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) {
|
||||
static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample)
|
||||
{
|
||||
/* only doing 16-bit audio for now */
|
||||
mpd_sint32 val;
|
||||
|
||||
const int clip_min = -1 << (16 - 1);
|
||||
const int clip_max = (1 << (16 - 1)) - 1;
|
||||
|
||||
const int clip_min = -1 << (16 - 1);
|
||||
const int clip_max = (1 << (16 - 1)) - 1;
|
||||
|
||||
#ifdef MPC_FIXED_POINT
|
||||
const int shift = 16 - MPC_FIXED_POINT_SCALE_SHIFT;
|
||||
|
||||
if( ssample > 0 ) {
|
||||
if (ssample > 0) {
|
||||
sample <<= shift;
|
||||
}
|
||||
else if ( shift < 0 ) {
|
||||
} else if (shift < 0) {
|
||||
sample >>= -shift;
|
||||
}
|
||||
val = sample;
|
||||
@@ -106,14 +110,16 @@ static inline mpd_sint16 convertSample(MPC_SAMPLE_FORMAT sample) {
|
||||
val = sample * float_scale;
|
||||
#endif
|
||||
|
||||
if( val < clip_min) val = clip_min;
|
||||
else if ( val > clip_max ) val = clip_max;
|
||||
if (val < clip_min)
|
||||
val = clip_min;
|
||||
else if (val > clip_max)
|
||||
val = clip_max;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
InputStream * inStream)
|
||||
static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
InputStream * inStream)
|
||||
{
|
||||
mpc_decoder decoder;
|
||||
mpc_reader reader;
|
||||
@@ -129,16 +135,16 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
char chunk[MPC_CHUNK_SIZE];
|
||||
int chunkpos = 0;
|
||||
long bitRate = 0;
|
||||
mpd_sint16 * s16 = (mpd_sint16 *) chunk;
|
||||
mpd_sint16 *s16 = (mpd_sint16 *) chunk;
|
||||
unsigned long samplePos = 0;
|
||||
mpc_uint32_t vbrUpdateAcc;
|
||||
mpc_uint32_t vbrUpdateBits;
|
||||
float time;
|
||||
int i;
|
||||
ReplayGainInfo * replayGainInfo = NULL;
|
||||
ReplayGainInfo *replayGainInfo = NULL;
|
||||
|
||||
data.inStream = inStream;
|
||||
data.dc = dc;
|
||||
data.inStream = inStream;
|
||||
data.dc = dc;
|
||||
|
||||
reader.read = mpc_read_cb;
|
||||
reader.seek = mpc_seek_cb;
|
||||
@@ -148,39 +154,37 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
reader.data = &data;
|
||||
|
||||
mpc_streaminfo_init(&info);
|
||||
|
||||
if((ret = mpc_streaminfo_read(&info, &reader)) != ERROR_CODE_OK) {
|
||||
|
||||
if ((ret = mpc_streaminfo_read(&info, &reader)) != ERROR_CODE_OK) {
|
||||
closeInputStream(inStream);
|
||||
if(!dc->stop) {
|
||||
ERROR("Not a valid musepack stream");
|
||||
if (!dc->stop) {
|
||||
ERROR("Not a valid musepack stream");
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpc_decoder_setup(&decoder, &reader);
|
||||
|
||||
if(!mpc_decoder_initialize(&decoder, &info)) {
|
||||
if (!mpc_decoder_initialize(&decoder, &info)) {
|
||||
closeInputStream(inStream);
|
||||
if(!dc->stop) {
|
||||
ERROR("Not a valid musepack stream");
|
||||
}
|
||||
else {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
if (!dc->stop) {
|
||||
ERROR("Not a valid musepack stream");
|
||||
} else {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dc->totalTime = mpc_streaminfo_get_length(&info);
|
||||
|
||||
dc->audioFormat.bits = 16;
|
||||
dc->audioFormat.channels = info.channels;
|
||||
dc->audioFormat.sampleRate = info.sample_freq;
|
||||
|
||||
|
||||
getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat));
|
||||
|
||||
replayGainInfo = newReplayGainInfo();
|
||||
@@ -191,23 +195,23 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
|
||||
while(!eof) {
|
||||
if(dc->seek) {
|
||||
while (!eof) {
|
||||
if (dc->seek) {
|
||||
samplePos = dc->seekWhere * dc->audioFormat.sampleRate;
|
||||
if(mpc_decoder_seek_sample(&decoder, samplePos)) {
|
||||
clearOutputBuffer(cb);
|
||||
chunkpos = 0;
|
||||
}
|
||||
else dc->seekError = 1;
|
||||
if (mpc_decoder_seek_sample(&decoder, samplePos)) {
|
||||
clearOutputBuffer(cb);
|
||||
chunkpos = 0;
|
||||
} else
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}
|
||||
|
||||
vbrUpdateAcc = 0;
|
||||
vbrUpdateBits = 0;
|
||||
ret = mpc_decoder_decode(&decoder, sample_buffer,
|
||||
&vbrUpdateAcc, &vbrUpdateBits);
|
||||
&vbrUpdateAcc, &vbrUpdateBits);
|
||||
|
||||
if(ret <= 0 || dc->stop ) {
|
||||
if (ret <= 0 || dc->stop) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
@@ -217,30 +221,28 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
/* ret is in samples, and we have stereo */
|
||||
ret *= 2;
|
||||
|
||||
for(i = 0; i < ret; i++) {
|
||||
for (i = 0; i < ret; i++) {
|
||||
/* 16 bit audio again */
|
||||
*s16 = convertSample(sample_buffer[i]);
|
||||
chunkpos += 2;
|
||||
s16++;
|
||||
|
||||
if(chunkpos >= MPC_CHUNK_SIZE) {
|
||||
time = ((float)samplePos) /
|
||||
dc->audioFormat.sampleRate;
|
||||
if (chunkpos >= MPC_CHUNK_SIZE) {
|
||||
time = ((float)samplePos) /
|
||||
dc->audioFormat.sampleRate;
|
||||
|
||||
bitRate = vbrUpdateBits *
|
||||
dc->audioFormat.sampleRate /
|
||||
1152 / 1000;
|
||||
|
||||
sendDataToOutputBuffer(cb, inStream, dc,
|
||||
inStream->seekable,
|
||||
chunk, chunkpos,
|
||||
time,
|
||||
bitRate,
|
||||
replayGainInfo);
|
||||
bitRate = vbrUpdateBits *
|
||||
dc->audioFormat.sampleRate / 1152 / 1000;
|
||||
|
||||
sendDataToOutputBuffer(cb, inStream, dc,
|
||||
inStream->seekable,
|
||||
chunk, chunkpos,
|
||||
time,
|
||||
bitRate, replayGainInfo);
|
||||
|
||||
chunkpos = 0;
|
||||
s16 = (mpd_sint16 *)chunk;
|
||||
if(dc->stop) {
|
||||
s16 = (mpd_sint16 *) chunk;
|
||||
if (dc->stop) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
@@ -248,13 +250,14 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
}
|
||||
}
|
||||
|
||||
if(!dc->stop && chunkpos > 0) {
|
||||
time = ((float)samplePos) / dc->audioFormat.sampleRate;
|
||||
if (!dc->stop && chunkpos > 0) {
|
||||
time = ((float)samplePos) / dc->audioFormat.sampleRate;
|
||||
|
||||
bitRate = vbrUpdateBits * dc->audioFormat.sampleRate / 1152 / 1000;
|
||||
bitRate =
|
||||
vbrUpdateBits * dc->audioFormat.sampleRate / 1152 / 1000;
|
||||
|
||||
sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable,
|
||||
chunk, chunkpos, time, bitRate,
|
||||
chunk, chunkpos, time, bitRate,
|
||||
replayGainInfo);
|
||||
}
|
||||
|
||||
@@ -264,27 +267,27 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
|
||||
freeReplayGainInfo(replayGainInfo);
|
||||
|
||||
if(dc->stop) {
|
||||
if (dc->stop) {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float mpcGetTime(char * file) {
|
||||
static float mpcGetTime(char *file)
|
||||
{
|
||||
InputStream inStream;
|
||||
float time = -1;
|
||||
|
||||
|
||||
mpc_reader reader;
|
||||
mpc_streaminfo info;
|
||||
MpcCallbackData data;
|
||||
|
||||
data.inStream = &inStream;
|
||||
data.dc = NULL;
|
||||
data.inStream = &inStream;
|
||||
data.dc = NULL;
|
||||
|
||||
reader.read = mpc_read_cb;
|
||||
reader.seek = mpc_seek_cb;
|
||||
@@ -295,12 +298,12 @@ static float mpcGetTime(char * file) {
|
||||
|
||||
mpc_streaminfo_init(&info);
|
||||
|
||||
if(openInputStream(&inStream, file) < 0) {
|
||||
if (openInputStream(&inStream, file) < 0) {
|
||||
DEBUG("mpcGetTime: Failed to open file: %s\n", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
|
||||
|
||||
if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
|
||||
closeInputStream(&inStream);
|
||||
return -1;
|
||||
}
|
||||
@@ -312,54 +315,56 @@ static float mpcGetTime(char * file) {
|
||||
return time;
|
||||
}
|
||||
|
||||
static MpdTag * mpcTagDup(char * file) {
|
||||
MpdTag * ret = NULL;
|
||||
static MpdTag *mpcTagDup(char *file)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
float time = mpcGetTime(file);
|
||||
|
||||
if(time < 0) {
|
||||
DEBUG("mpcTagDup: Failed to get Songlength of file: %s\n",file);
|
||||
return NULL;
|
||||
if (time < 0) {
|
||||
DEBUG("mpcTagDup: Failed to get Songlength of file: %s\n",
|
||||
file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = apeDup(file);
|
||||
if(!ret) ret = id3Dup(file);
|
||||
if(!ret) ret = newMpdTag();
|
||||
if (!ret)
|
||||
ret = id3Dup(file);
|
||||
if (!ret)
|
||||
ret = newMpdTag();
|
||||
ret->time = time;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * mpcSuffixes[] = {"mpc", NULL};
|
||||
static char * mpcMimeTypes[] = {NULL};
|
||||
static char *mpcSuffixes[] = { "mpc", NULL };
|
||||
static char *mpcMimeTypes[] = { NULL };
|
||||
|
||||
InputPlugin mpcPlugin =
|
||||
{
|
||||
"mpc",
|
||||
InputPlugin mpcPlugin = {
|
||||
"mpc",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
mpc_decode,
|
||||
NULL,
|
||||
mpcTagDup,
|
||||
INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
|
||||
mpcSuffixes,
|
||||
mpcMimeTypes
|
||||
mpc_decode,
|
||||
NULL,
|
||||
mpcTagDup,
|
||||
INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
|
||||
mpcSuffixes,
|
||||
mpcMimeTypes
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
InputPlugin mpcPlugin =
|
||||
{
|
||||
InputPlugin mpcPlugin = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -41,8 +41,8 @@
|
||||
#include <FLAC/metadata.h>
|
||||
|
||||
static void oggflac_cleanup(InputStream * inStream,
|
||||
FlacData * data,
|
||||
OggFLAC__SeekableStreamDecoder * decoder)
|
||||
FlacData * data,
|
||||
OggFLAC__SeekableStreamDecoder * decoder)
|
||||
{
|
||||
if (data->replayGainInfo)
|
||||
freeReplayGainInfo(data->replayGainInfo);
|
||||
@@ -51,81 +51,93 @@ static void oggflac_cleanup(InputStream * inStream,
|
||||
closeInputStream(inStream);
|
||||
}
|
||||
|
||||
static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(
|
||||
const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
FLAC__byte buf[], unsigned * bytes, void * fdata) {
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(const
|
||||
OggFLAC__SeekableStreamDecoder
|
||||
* decoder,
|
||||
FLAC__byte buf[],
|
||||
unsigned *bytes,
|
||||
void *fdata)
|
||||
{
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
size_t r;
|
||||
|
||||
while (1) {
|
||||
r = readFromInputStream(data->inStream,(void *)buf,1,*bytes);
|
||||
r = readFromInputStream(data->inStream, (void *)buf, 1, *bytes);
|
||||
if (r == 0 && !inputStreamAtEOF(data->inStream) &&
|
||||
!data->dc->stop)
|
||||
!data->dc->stop)
|
||||
my_usleep(10000);
|
||||
else
|
||||
break;
|
||||
}
|
||||
*bytes = r;
|
||||
|
||||
|
||||
if (r == 0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop)
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
}
|
||||
|
||||
static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(
|
||||
const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
FLAC__uint64 offset, void * fdata)
|
||||
static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(const
|
||||
OggFLAC__SeekableStreamDecoder
|
||||
* decoder,
|
||||
FLAC__uint64 offset,
|
||||
void *fdata)
|
||||
{
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
|
||||
if(seekInputStream(data->inStream,offset,SEEK_SET)<0) {
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) {
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(
|
||||
const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
FLAC__uint64 * offset, void * fdata)
|
||||
static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(const
|
||||
OggFLAC__SeekableStreamDecoder
|
||||
* decoder,
|
||||
FLAC__uint64 *
|
||||
offset, void *fdata)
|
||||
{
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
|
||||
*offset = (long)(data->inStream->offset);
|
||||
*offset = (long)(data->inStream->offset);
|
||||
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(
|
||||
const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
FLAC__uint64 * length, void * fdata)
|
||||
static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(const
|
||||
OggFLAC__SeekableStreamDecoder
|
||||
* decoder,
|
||||
FLAC__uint64 *
|
||||
length,
|
||||
void *fdata)
|
||||
{
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
|
||||
*length = (size_t)(data->inStream->size);
|
||||
*length = (size_t) (data->inStream->size);
|
||||
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__bool of_EOF_cb(const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
void * fdata) {
|
||||
FlacData * data = (FlacData *) fdata;
|
||||
void *fdata)
|
||||
{
|
||||
FlacData *data = (FlacData *) fdata;
|
||||
|
||||
if (inputStreamAtEOF(data->inStream) == 1)
|
||||
return true;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void of_error_cb(const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
FLAC__StreamDecoderErrorStatus status, void *fdata)
|
||||
static void of_error_cb(const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
FLAC__StreamDecoderErrorStatus status, void *fdata)
|
||||
{
|
||||
flac_error_common_cb("oggflac",status,(FlacData *) fdata);
|
||||
flac_error_common_cb("oggflac", status, (FlacData *) fdata);
|
||||
}
|
||||
|
||||
static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
|
||||
static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
|
||||
{
|
||||
switch(state) {
|
||||
switch (state) {
|
||||
case OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
|
||||
ERROR("oggflac allocation error\n");
|
||||
break;
|
||||
@@ -154,21 +166,23 @@ static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus oggflacWrite(
|
||||
const OggFLAC__SeekableStreamDecoder *decoder,
|
||||
const FLAC__Frame *frame, const FLAC__int32 * const buf[],
|
||||
void * vdata)
|
||||
static FLAC__StreamDecoderWriteStatus oggflacWrite(const
|
||||
OggFLAC__SeekableStreamDecoder
|
||||
* decoder,
|
||||
const FLAC__Frame * frame,
|
||||
const FLAC__int32 *
|
||||
const buf[], void *vdata)
|
||||
{
|
||||
FlacData * data = (FlacData *)vdata;
|
||||
FlacData *data = (FlacData *) vdata;
|
||||
FLAC__uint32 samples = frame->header.blocksize;
|
||||
FLAC__uint16 u16;
|
||||
unsigned char * uc;
|
||||
unsigned char *uc;
|
||||
int c_samp, c_chan, d_samp;
|
||||
int i;
|
||||
float timeChange;
|
||||
|
||||
timeChange = ((float)samples)/frame->header.sample_rate;
|
||||
data->time+= timeChange;
|
||||
|
||||
timeChange = ((float)samples) / frame->header.sample_rate;
|
||||
data->time += timeChange;
|
||||
|
||||
/* ogg123 uses a complicated method of calculating bitrate
|
||||
* with averaging which I'm not too fond of.
|
||||
@@ -177,24 +191,26 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(
|
||||
*
|
||||
* this does not give an accurate bitrate:
|
||||
* (bytes_last_read was set in the read callback)
|
||||
data->bitRate = ((8.0 * data->bytes_last_read *
|
||||
frame->header.sample_rate)
|
||||
/((float)samples * 1000)) + 0.5;
|
||||
*/
|
||||
|
||||
for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
|
||||
for(c_chan = 0; c_chan < frame->header.channels;
|
||||
c_chan++, d_samp++) {
|
||||
data->bitRate = ((8.0 * data->bytes_last_read *
|
||||
frame->header.sample_rate)
|
||||
/((float)samples * 1000)) + 0.5;
|
||||
*/
|
||||
|
||||
for (c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
|
||||
for (c_chan = 0; c_chan < frame->header.channels;
|
||||
c_chan++, d_samp++) {
|
||||
u16 = buf[c_chan][c_samp];
|
||||
uc = (unsigned char *)&u16;
|
||||
for(i=0;i<(data->dc->audioFormat.bits/8);i++) {
|
||||
if(data->chunk_length>=FLAC_CHUNK_SIZE) {
|
||||
if(flacSendChunk(data)<0) {
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
for (i = 0; i < (data->dc->audioFormat.bits / 8); i++) {
|
||||
if (data->chunk_length >= FLAC_CHUNK_SIZE) {
|
||||
if (flacSendChunk(data) < 0) {
|
||||
return
|
||||
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
data->chunk_length = 0;
|
||||
if(data->dc->seek) {
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
if (data->dc->seek) {
|
||||
return
|
||||
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
}
|
||||
data->chunk[data->chunk_length++] = *(uc++);
|
||||
@@ -206,106 +222,104 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(
|
||||
}
|
||||
|
||||
/* used by TagDup */
|
||||
static void of_metadata_dup_cb(
|
||||
const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
const FLAC__StreamMetadata *block, void *vdata)
|
||||
static void of_metadata_dup_cb(const OggFLAC__SeekableStreamDecoder * decoder,
|
||||
const FLAC__StreamMetadata * block, void *vdata)
|
||||
{
|
||||
FlacData * data = (FlacData *)vdata;
|
||||
FlacData *data = (FlacData *) vdata;
|
||||
|
||||
switch(block->type) {
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
if (!data->tag) data->tag = newMpdTag();
|
||||
switch (block->type) {
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
if (!data->tag)
|
||||
data->tag = newMpdTag();
|
||||
data->tag->time = ((float)block->data.stream_info.
|
||||
total_samples) /
|
||||
block->data.stream_info.sample_rate +
|
||||
0.5;
|
||||
total_samples) /
|
||||
block->data.stream_info.sample_rate + 0.5;
|
||||
return;
|
||||
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
|
||||
copyVorbisCommentBlockToMpdTag(block,data->tag);
|
||||
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
|
||||
copyVorbisCommentBlockToMpdTag(block, data->tag);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* used by decode */
|
||||
static void of_metadata_decode_cb(const OggFLAC__SeekableStreamDecoder * dec,
|
||||
const FLAC__StreamMetadata *block, void *vdata)
|
||||
const FLAC__StreamMetadata * block,
|
||||
void *vdata)
|
||||
{
|
||||
flac_metadata_common_cb(block, (FlacData *)vdata);
|
||||
flac_metadata_common_cb(block, (FlacData *) vdata);
|
||||
}
|
||||
|
||||
static OggFLAC__SeekableStreamDecoder * full_decoder_init_and_read_metadata(
|
||||
FlacData * data,
|
||||
unsigned int metadata_only)
|
||||
static OggFLAC__SeekableStreamDecoder
|
||||
*full_decoder_init_and_read_metadata(FlacData * data,
|
||||
unsigned int metadata_only)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder * decoder = NULL;
|
||||
OggFLAC__SeekableStreamDecoder *decoder = NULL;
|
||||
unsigned int s = 1;
|
||||
|
||||
if (!(decoder = OggFLAC__seekable_stream_decoder_new()))
|
||||
return NULL;
|
||||
|
||||
if (metadata_only) {
|
||||
s &= OggFLAC__seekable_stream_decoder_set_metadata_callback(
|
||||
decoder, of_metadata_dup_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_metadata_respond(
|
||||
decoder,
|
||||
FLAC__METADATA_TYPE_STREAMINFO);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_metadata_callback
|
||||
(decoder, of_metadata_dup_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_metadata_respond
|
||||
(decoder, FLAC__METADATA_TYPE_STREAMINFO);
|
||||
} else {
|
||||
s &= OggFLAC__seekable_stream_decoder_set_metadata_callback(
|
||||
decoder, of_metadata_decode_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_metadata_callback
|
||||
(decoder, of_metadata_decode_cb);
|
||||
}
|
||||
|
||||
|
||||
s &= OggFLAC__seekable_stream_decoder_set_read_callback(decoder,
|
||||
of_read_cb);
|
||||
of_read_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_seek_callback(decoder,
|
||||
of_seek_cb);
|
||||
of_seek_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_tell_callback(decoder,
|
||||
of_tell_cb);
|
||||
of_tell_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_length_callback(decoder,
|
||||
of_length_cb);
|
||||
of_length_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_eof_callback(decoder,
|
||||
of_EOF_cb);
|
||||
of_EOF_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_write_callback(decoder,
|
||||
oggflacWrite);
|
||||
oggflacWrite);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder,
|
||||
FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_error_callback(decoder,
|
||||
of_error_cb);
|
||||
of_error_cb);
|
||||
s &= OggFLAC__seekable_stream_decoder_set_client_data(decoder,
|
||||
(void *)data);
|
||||
(void *)data);
|
||||
|
||||
if (!s) {
|
||||
ERROR("oggflac problem before init()\n");
|
||||
goto fail;
|
||||
}
|
||||
if (OggFLAC__seekable_stream_decoder_init(decoder) !=
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_OK)
|
||||
{
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_OK) {
|
||||
ERROR("oggflac problem doing init()\n");
|
||||
goto fail;
|
||||
}
|
||||
if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(
|
||||
decoder)) {
|
||||
if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata
|
||||
(decoder)) {
|
||||
ERROR("oggflac problem reading metadata\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return decoder;
|
||||
return decoder;
|
||||
|
||||
fail:
|
||||
oggflacPrintErroredState(
|
||||
OggFLAC__seekable_stream_decoder_get_state(decoder));
|
||||
fail:
|
||||
oggflacPrintErroredState(OggFLAC__seekable_stream_decoder_get_state
|
||||
(decoder));
|
||||
OggFLAC__seekable_stream_decoder_delete(decoder);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* public functions: */
|
||||
static MpdTag * oggflac_TagDup(char * file)
|
||||
static MpdTag *oggflac_TagDup(char *file)
|
||||
{
|
||||
InputStream inStream;
|
||||
OggFLAC__SeekableStreamDecoder * decoder;
|
||||
OggFLAC__SeekableStreamDecoder *decoder;
|
||||
FlacData data;
|
||||
|
||||
|
||||
if (openInputStream(&inStream, file) < 0)
|
||||
return NULL;
|
||||
if (ogg_stream_type_detect(&inStream) != FLAC) {
|
||||
@@ -317,10 +331,10 @@ static MpdTag * oggflac_TagDup(char * file)
|
||||
|
||||
/* errors here won't matter,
|
||||
* data.tag will be set or unset, that's all we care about */
|
||||
decoder = full_decoder_init_and_read_metadata(&data,1);
|
||||
|
||||
decoder = full_decoder_init_and_read_metadata(&data, 1);
|
||||
|
||||
oggflac_cleanup(&inStream, &data, decoder);
|
||||
|
||||
|
||||
return data.tag;
|
||||
}
|
||||
|
||||
@@ -330,51 +344,49 @@ static unsigned int oggflac_try_decode(InputStream * inStream)
|
||||
}
|
||||
|
||||
static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
InputStream * inStream)
|
||||
InputStream * inStream)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder * decoder = NULL;
|
||||
OggFLAC__SeekableStreamDecoder *decoder = NULL;
|
||||
FlacData data;
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
init_FlacData(&data, cb, dc, inStream);
|
||||
|
||||
if(!(decoder = full_decoder_init_and_read_metadata(&data,0))){
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
if (!(decoder = full_decoder_init_and_read_metadata(&data, 0))) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
|
||||
while(1) {
|
||||
while (1) {
|
||||
OggFLAC__seekable_stream_decoder_process_single(decoder);
|
||||
if(OggFLAC__seekable_stream_decoder_get_state(decoder)!=
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_OK)
|
||||
{
|
||||
if (OggFLAC__seekable_stream_decoder_get_state(decoder) !=
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_OK) {
|
||||
break;
|
||||
}
|
||||
if(dc->seek) {
|
||||
FLAC__uint64 sampleToSeek = dc->seekWhere*
|
||||
dc->audioFormat.sampleRate+0.5;
|
||||
if(OggFLAC__seekable_stream_decoder_seek_absolute(
|
||||
decoder, sampleToSeek))
|
||||
{
|
||||
clearOutputBuffer(cb);
|
||||
data.time = ((float)sampleToSeek)/
|
||||
dc->audioFormat.sampleRate;
|
||||
if (dc->seek) {
|
||||
FLAC__uint64 sampleToSeek = dc->seekWhere *
|
||||
dc->audioFormat.sampleRate + 0.5;
|
||||
if (OggFLAC__seekable_stream_decoder_seek_absolute
|
||||
(decoder, sampleToSeek)) {
|
||||
clearOutputBuffer(cb);
|
||||
data.time = ((float)sampleToSeek) /
|
||||
dc->audioFormat.sampleRate;
|
||||
data.position = 0;
|
||||
}
|
||||
else dc->seekError = 1;
|
||||
} else
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!dc->stop) {
|
||||
oggflacPrintErroredState(
|
||||
OggFLAC__seekable_stream_decoder_get_state(decoder));
|
||||
|
||||
if (!dc->stop) {
|
||||
oggflacPrintErroredState
|
||||
(OggFLAC__seekable_stream_decoder_get_state(decoder));
|
||||
OggFLAC__seekable_stream_decoder_finish(decoder);
|
||||
}
|
||||
/* send last little bit */
|
||||
if(data.chunk_length>0 && !dc->stop) {
|
||||
if (data.chunk_length > 0 && !dc->stop) {
|
||||
flacSendChunk(&data);
|
||||
flushOutputBuffer(data.cb);
|
||||
}
|
||||
@@ -382,17 +394,16 @@ static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
oggflac_cleanup(inStream, &data, decoder);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * oggflac_Suffixes[] = {"ogg", NULL};
|
||||
static char * oggflac_mime_types[] = {"application/ogg", NULL};
|
||||
static char *oggflac_Suffixes[] = { "ogg", NULL };
|
||||
static char *oggflac_mime_types[] = { "application/ogg", NULL };
|
||||
|
||||
InputPlugin oggflacPlugin =
|
||||
{
|
||||
InputPlugin oggflacPlugin = {
|
||||
"oggflac",
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -405,10 +416,9 @@ InputPlugin oggflacPlugin =
|
||||
oggflac_mime_types
|
||||
};
|
||||
|
||||
#else /* !HAVE_FLAC */
|
||||
#else /* !HAVE_FLAC */
|
||||
|
||||
InputPlugin oggflacPlugin =
|
||||
{
|
||||
InputPlugin oggflacPlugin = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -421,5 +431,4 @@ InputPlugin oggflacPlugin =
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif /* HAVE_OGGFLAC */
|
||||
|
||||
#endif /* HAVE_OGGFLAC */
|
||||
|
@@ -50,7 +50,7 @@
|
||||
#define ov_time_total(VF, I) ((double)ov_time_total(VF, I)/1000)
|
||||
#define ov_time_tell(VF) ((double)ov_time_tell(VF)/1000)
|
||||
#define ov_time_seek_page(VF, S) (ov_time_seek_page(VF, (S)*1000))
|
||||
#endif /* HAVE_TREMOR */
|
||||
#endif /* HAVE_TREMOR */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@@ -61,158 +61,165 @@
|
||||
#endif
|
||||
|
||||
typedef struct _OggCallbackData {
|
||||
InputStream * inStream;
|
||||
DecoderControl * dc;
|
||||
InputStream *inStream;
|
||||
DecoderControl *dc;
|
||||
} OggCallbackData;
|
||||
|
||||
static size_t ogg_read_cb(void * ptr, size_t size, size_t nmemb, void * vdata)
|
||||
static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *vdata)
|
||||
{
|
||||
size_t ret = 0;
|
||||
OggCallbackData * data = (OggCallbackData *)vdata;
|
||||
OggCallbackData *data = (OggCallbackData *) vdata;
|
||||
|
||||
while(1) {
|
||||
ret = readFromInputStream(data->inStream,ptr,size,nmemb);
|
||||
if(ret == 0 && !inputStreamAtEOF(data->inStream) &&
|
||||
!data->dc->stop)
|
||||
{
|
||||
my_usleep(10000);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
errno = 0;
|
||||
/*if(ret<0) errno = ((InputStream *)inStream)->error;*/
|
||||
while (1) {
|
||||
ret = readFromInputStream(data->inStream, ptr, size, nmemb);
|
||||
if (ret == 0 && !inputStreamAtEOF(data->inStream) &&
|
||||
!data->dc->stop) {
|
||||
my_usleep(10000);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
errno = 0;
|
||||
/*if(ret<0) errno = ((InputStream *)inStream)->error; */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ogg_seek_cb(void * vdata, ogg_int64_t offset, int whence) {
|
||||
OggCallbackData * data = (OggCallbackData *)vdata;
|
||||
static int ogg_seek_cb(void *vdata, ogg_int64_t offset, int whence)
|
||||
{
|
||||
OggCallbackData *data = (OggCallbackData *) vdata;
|
||||
|
||||
return seekInputStream(data->inStream,offset,whence);
|
||||
return seekInputStream(data->inStream, offset, whence);
|
||||
}
|
||||
|
||||
static int ogg_close_cb(void * vdata) {
|
||||
OggCallbackData * data = (OggCallbackData *)vdata;
|
||||
static int ogg_close_cb(void *vdata)
|
||||
{
|
||||
OggCallbackData *data = (OggCallbackData *) vdata;
|
||||
|
||||
return closeInputStream(data->inStream);
|
||||
}
|
||||
|
||||
static long ogg_tell_cb(void * vdata) {
|
||||
OggCallbackData * data = (OggCallbackData *)vdata;
|
||||
static long ogg_tell_cb(void *vdata)
|
||||
{
|
||||
OggCallbackData *data = (OggCallbackData *) vdata;
|
||||
|
||||
return (long)(data->inStream->offset);
|
||||
}
|
||||
|
||||
static char * ogg_parseComment(char * comment, char * needle) {
|
||||
int len = strlen(needle);
|
||||
static char *ogg_parseComment(char *comment, char *needle)
|
||||
{
|
||||
int len = strlen(needle);
|
||||
|
||||
if(strncasecmp(comment, needle, len) == 0 && *(comment+len) == '=') {
|
||||
return comment+len+1;
|
||||
if (strncasecmp(comment, needle, len) == 0 && *(comment + len) == '=') {
|
||||
return comment + len + 1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ogg_getReplayGainInfo(char ** comments, ReplayGainInfo ** infoPtr) {
|
||||
char * temp;
|
||||
static void ogg_getReplayGainInfo(char **comments, ReplayGainInfo ** infoPtr)
|
||||
{
|
||||
char *temp;
|
||||
int found = 0;
|
||||
|
||||
if(*infoPtr) freeReplayGainInfo(*infoPtr);
|
||||
if (*infoPtr)
|
||||
freeReplayGainInfo(*infoPtr);
|
||||
*infoPtr = newReplayGainInfo();
|
||||
|
||||
while(*comments) {
|
||||
if((temp = ogg_parseComment(*comments,"replaygain_track_gain")))
|
||||
{
|
||||
(*infoPtr)->trackGain = atof(temp);
|
||||
while (*comments) {
|
||||
if ((temp =
|
||||
ogg_parseComment(*comments, "replaygain_track_gain"))) {
|
||||
(*infoPtr)->trackGain = atof(temp);
|
||||
found = 1;
|
||||
}
|
||||
else if((temp = ogg_parseComment(*comments,
|
||||
"replaygain_album_gain")))
|
||||
{
|
||||
(*infoPtr)->albumGain = atof(temp);
|
||||
} else if ((temp = ogg_parseComment(*comments,
|
||||
"replaygain_album_gain"))) {
|
||||
(*infoPtr)->albumGain = atof(temp);
|
||||
found = 1;
|
||||
}
|
||||
else if((temp = ogg_parseComment(*comments,
|
||||
"replaygain_track_peak")))
|
||||
{
|
||||
(*infoPtr)->trackPeak = atof(temp);
|
||||
} else if ((temp = ogg_parseComment(*comments,
|
||||
"replaygain_track_peak"))) {
|
||||
(*infoPtr)->trackPeak = atof(temp);
|
||||
found = 1;
|
||||
}
|
||||
else if((temp = ogg_parseComment(*comments,
|
||||
"replaygain_album_peak")))
|
||||
{
|
||||
(*infoPtr)->albumPeak = atof(temp);
|
||||
} else if ((temp = ogg_parseComment(*comments,
|
||||
"replaygain_album_peak"))) {
|
||||
(*infoPtr)->albumPeak = atof(temp);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
comments++;
|
||||
}
|
||||
comments++;
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
if (!found) {
|
||||
freeReplayGainInfo(*infoPtr);
|
||||
*infoPtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char * VORBIS_COMMENT_TRACK_KEY = "tracknumber";
|
||||
static const char * VORBIS_COMMENT_DISC_KEY = "discnumber";
|
||||
static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber";
|
||||
static const char *VORBIS_COMMENT_DISC_KEY = "discnumber";
|
||||
|
||||
static unsigned int ogg_parseCommentAddToTag(char * comment,
|
||||
unsigned int itemType, MpdTag ** tag)
|
||||
static unsigned int ogg_parseCommentAddToTag(char *comment,
|
||||
unsigned int itemType,
|
||||
MpdTag ** tag)
|
||||
{
|
||||
const char * needle;
|
||||
const char *needle;
|
||||
unsigned int len;
|
||||
switch (itemType) {
|
||||
case TAG_ITEM_TRACK: needle = VORBIS_COMMENT_TRACK_KEY; break;
|
||||
case TAG_ITEM_DISC: needle = VORBIS_COMMENT_DISC_KEY; break;
|
||||
default: needle = mpdTagItemKeys[itemType];
|
||||
case TAG_ITEM_TRACK:
|
||||
needle = VORBIS_COMMENT_TRACK_KEY;
|
||||
break;
|
||||
case TAG_ITEM_DISC:
|
||||
needle = VORBIS_COMMENT_DISC_KEY;
|
||||
break;
|
||||
default:
|
||||
needle = mpdTagItemKeys[itemType];
|
||||
}
|
||||
len = strlen(needle);
|
||||
|
||||
if(strncasecmp(comment, needle, len) == 0 && *(comment+len) == '=') {
|
||||
if (strncasecmp(comment, needle, len) == 0 && *(comment + len) == '=') {
|
||||
if (!*tag)
|
||||
*tag = newMpdTag();
|
||||
|
||||
addItemToMpdTag(*tag, itemType, comment+len+1);
|
||||
|
||||
|
||||
addItemToMpdTag(*tag, itemType, comment + len + 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MpdTag * oggCommentsParse(char ** comments) {
|
||||
MpdTag * tag = NULL;
|
||||
|
||||
while(*comments) {
|
||||
static MpdTag *oggCommentsParse(char **comments)
|
||||
{
|
||||
MpdTag *tag = NULL;
|
||||
|
||||
while (*comments) {
|
||||
int j;
|
||||
for (j = TAG_NUM_OF_ITEM_TYPES; --j >= 0; ) {
|
||||
for (j = TAG_NUM_OF_ITEM_TYPES; --j >= 0;) {
|
||||
if (ogg_parseCommentAddToTag(*comments, j, &tag))
|
||||
break;
|
||||
}
|
||||
comments++;
|
||||
}
|
||||
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
static void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName,
|
||||
char ** comments)
|
||||
static void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char *streamName,
|
||||
char **comments)
|
||||
{
|
||||
MpdTag * tag;
|
||||
MpdTag *tag;
|
||||
|
||||
tag = oggCommentsParse(comments);
|
||||
if(!tag && streamName) {
|
||||
if (!tag && streamName) {
|
||||
tag = newMpdTag();
|
||||
}
|
||||
if(!tag) return;
|
||||
if (!tag)
|
||||
return;
|
||||
|
||||
/*if(tag->artist) printf("Artist: %s\n", tag->artist);
|
||||
if(tag->album) printf("Album: %s\n", tag->album);
|
||||
if(tag->track) printf("Track: %s\n", tag->track);
|
||||
if(tag->title) printf("Title: %s\n", tag->title);*/
|
||||
if(tag->album) printf("Album: %s\n", tag->album);
|
||||
if(tag->track) printf("Track: %s\n", tag->track);
|
||||
if(tag->title) printf("Title: %s\n", tag->title); */
|
||||
|
||||
if(streamName) {
|
||||
if (streamName) {
|
||||
clearItemsFromMpdTag(tag, TAG_ITEM_NAME);
|
||||
addItemToMpdTag(tag, TAG_ITEM_NAME, streamName);
|
||||
}
|
||||
@@ -224,11 +231,11 @@ static void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName,
|
||||
|
||||
/* public */
|
||||
static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
InputStream * inStream)
|
||||
InputStream * inStream)
|
||||
{
|
||||
OggVorbis_File vf;
|
||||
ov_callbacks callbacks;
|
||||
OggCallbackData data;
|
||||
OggCallbackData data;
|
||||
int current_section;
|
||||
int prev_section = -1;
|
||||
int eof = 0;
|
||||
@@ -238,22 +245,22 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
int chunkpos = 0;
|
||||
long bitRate = 0;
|
||||
long test;
|
||||
ReplayGainInfo * replayGainInfo = NULL;
|
||||
char ** comments;
|
||||
char * errorStr;
|
||||
ReplayGainInfo *replayGainInfo = NULL;
|
||||
char **comments;
|
||||
char *errorStr;
|
||||
|
||||
data.inStream = inStream;
|
||||
data.dc = dc;
|
||||
data.inStream = inStream;
|
||||
data.dc = dc;
|
||||
|
||||
callbacks.read_func = ogg_read_cb;
|
||||
callbacks.seek_func = ogg_seek_cb;
|
||||
callbacks.close_func = ogg_close_cb;
|
||||
callbacks.tell_func = ogg_tell_cb;
|
||||
|
||||
if((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) {
|
||||
|
||||
if ((ret = ov_open_callbacks(&data, &vf, NULL, 0, callbacks)) < 0) {
|
||||
closeInputStream(inStream);
|
||||
if(!dc->stop) {
|
||||
switch(ret) {
|
||||
if (!dc->stop) {
|
||||
switch (ret) {
|
||||
case OV_EREAD:
|
||||
errorStr = "read error";
|
||||
break;
|
||||
@@ -273,123 +280,127 @@ static int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
|
||||
errorStr = "unknown error";
|
||||
break;
|
||||
}
|
||||
ERROR("Error decoding Ogg Vorbis stream: %s\n",
|
||||
ERROR("Error decoding Ogg Vorbis stream: %s\n",
|
||||
errorStr);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
} else {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
dc->totalTime = ov_time_total(&vf,-1);
|
||||
if(dc->totalTime < 0) dc->totalTime = 0;
|
||||
|
||||
dc->totalTime = ov_time_total(&vf, -1);
|
||||
if (dc->totalTime < 0)
|
||||
dc->totalTime = 0;
|
||||
|
||||
dc->audioFormat.bits = 16;
|
||||
|
||||
while(!eof) {
|
||||
if(dc->seek) {
|
||||
if(0 == ov_time_seek_page(&vf,dc->seekWhere)) {
|
||||
clearOutputBuffer(cb);
|
||||
chunkpos = 0;
|
||||
}
|
||||
else dc->seekError = 1;
|
||||
while (!eof) {
|
||||
if (dc->seek) {
|
||||
if (0 == ov_time_seek_page(&vf, dc->seekWhere)) {
|
||||
clearOutputBuffer(cb);
|
||||
chunkpos = 0;
|
||||
} else
|
||||
dc->seekError = 1;
|
||||
dc->seek = 0;
|
||||
}
|
||||
ret = ov_read(&vf, chunk+chunkpos,
|
||||
OGG_CHUNK_SIZE-chunkpos,
|
||||
OGG_DECODE_USE_BIGENDIAN,
|
||||
2, 1, ¤t_section);
|
||||
ret = ov_read(&vf, chunk + chunkpos,
|
||||
OGG_CHUNK_SIZE - chunkpos,
|
||||
OGG_DECODE_USE_BIGENDIAN, 2, 1, ¤t_section);
|
||||
|
||||
if(current_section!=prev_section) {
|
||||
/*printf("new song!\n");*/
|
||||
vorbis_info *vi=ov_info(&vf,-1);
|
||||
if (current_section != prev_section) {
|
||||
/*printf("new song!\n"); */
|
||||
vorbis_info *vi = ov_info(&vf, -1);
|
||||
dc->audioFormat.channels = vi->channels;
|
||||
dc->audioFormat.sampleRate = vi->rate;
|
||||
if(dc->state == DECODE_STATE_START) {
|
||||
getOutputAudioFormat(&(dc->audioFormat),
|
||||
&(cb->audioFormat));
|
||||
if (dc->state == DECODE_STATE_START) {
|
||||
getOutputAudioFormat(&(dc->audioFormat),
|
||||
&(cb->audioFormat));
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
}
|
||||
comments = ov_comment(&vf, -1)->user_comments;
|
||||
putOggCommentsIntoOutputBuffer(cb, inStream->metaName,
|
||||
comments);
|
||||
ogg_getReplayGainInfo(comments, &replayGainInfo);
|
||||
comments);
|
||||
ogg_getReplayGainInfo(comments, &replayGainInfo);
|
||||
}
|
||||
|
||||
prev_section = current_section;
|
||||
|
||||
if(ret <= 0 && ret != OV_HOLE) {
|
||||
if (ret <= 0 && ret != OV_HOLE) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
if(ret == OV_HOLE) ret = 0;
|
||||
if (ret == OV_HOLE)
|
||||
ret = 0;
|
||||
|
||||
chunkpos+=ret;
|
||||
chunkpos += ret;
|
||||
|
||||
if(chunkpos >= OGG_CHUNK_SIZE) {
|
||||
if((test = ov_bitrate_instant(&vf))>0) {
|
||||
bitRate = test/1000;
|
||||
if (chunkpos >= OGG_CHUNK_SIZE) {
|
||||
if ((test = ov_bitrate_instant(&vf)) > 0) {
|
||||
bitRate = test / 1000;
|
||||
}
|
||||
sendDataToOutputBuffer(cb, inStream, dc,
|
||||
inStream->seekable,
|
||||
chunk, chunkpos,
|
||||
ov_pcm_tell(&vf)/
|
||||
dc->audioFormat.sampleRate,
|
||||
bitRate,
|
||||
replayGainInfo);
|
||||
sendDataToOutputBuffer(cb, inStream, dc,
|
||||
inStream->seekable,
|
||||
chunk, chunkpos,
|
||||
ov_pcm_tell(&vf) /
|
||||
dc->audioFormat.sampleRate,
|
||||
bitRate, replayGainInfo);
|
||||
chunkpos = 0;
|
||||
if(dc->stop) break;
|
||||
if (dc->stop)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!dc->stop && chunkpos > 0) {
|
||||
if (!dc->stop && chunkpos > 0) {
|
||||
sendDataToOutputBuffer(cb, NULL, dc, inStream->seekable,
|
||||
chunk, chunkpos,
|
||||
ov_time_tell(&vf), bitRate, replayGainInfo);
|
||||
chunk, chunkpos,
|
||||
ov_time_tell(&vf), bitRate,
|
||||
replayGainInfo);
|
||||
}
|
||||
|
||||
if(replayGainInfo) freeReplayGainInfo(replayGainInfo);
|
||||
if (replayGainInfo)
|
||||
freeReplayGainInfo(replayGainInfo);
|
||||
|
||||
ov_clear(&vf);
|
||||
|
||||
flushOutputBuffer(cb);
|
||||
|
||||
if(dc->stop) {
|
||||
if (dc->stop) {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
}
|
||||
else dc->state = DECODE_STATE_STOP;
|
||||
} else
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MpdTag * oggvorbis_TagDup(char * file) {
|
||||
MpdTag * ret = NULL;
|
||||
FILE * fp;
|
||||
static MpdTag *oggvorbis_TagDup(char *file)
|
||||
{
|
||||
MpdTag *ret = NULL;
|
||||
FILE *fp;
|
||||
OggVorbis_File vf;
|
||||
|
||||
fp = fopen(file,"r");
|
||||
if(!fp)
|
||||
{
|
||||
DEBUG("oggTagDup: Failed to open file: '%s', %s\n", file, strerror(errno));
|
||||
return NULL;
|
||||
fp = fopen(file, "r");
|
||||
if (!fp) {
|
||||
DEBUG("oggTagDup: Failed to open file: '%s', %s\n", file,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if(ov_open(fp,&vf,NULL,0)<0) {
|
||||
if (ov_open(fp, &vf, NULL, 0) < 0) {
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = oggCommentsParse(ov_comment(&vf,-1)->user_comments);
|
||||
ret = oggCommentsParse(ov_comment(&vf, -1)->user_comments);
|
||||
|
||||
if(!ret) ret = newMpdTag();
|
||||
ret->time = (int)(ov_time_total(&vf,-1)+0.5);
|
||||
if (!ret)
|
||||
ret = newMpdTag();
|
||||
ret->time = (int)(ov_time_total(&vf, -1) + 0.5);
|
||||
|
||||
ov_clear(&vf);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int oggvorbis_try_decode(InputStream * inStream)
|
||||
@@ -397,12 +408,10 @@ static unsigned int oggvorbis_try_decode(InputStream * inStream)
|
||||
return (ogg_stream_type_detect(inStream) == VORBIS) ? 1 : 0;
|
||||
}
|
||||
|
||||
static char *oggvorbis_Suffixes[] = { "ogg", NULL };
|
||||
static char *oggvorbis_MimeTypes[] = { "application/ogg", NULL };
|
||||
|
||||
static char * oggvorbis_Suffixes[] = {"ogg", NULL};
|
||||
static char * oggvorbis_MimeTypes[] = {"application/ogg", NULL};
|
||||
|
||||
InputPlugin oggvorbisPlugin =
|
||||
{
|
||||
InputPlugin oggvorbisPlugin = {
|
||||
"oggvorbis",
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -415,10 +424,9 @@ InputPlugin oggvorbisPlugin =
|
||||
oggvorbis_MimeTypes
|
||||
};
|
||||
|
||||
#else /* !HAVE_OGGVORBIS */
|
||||
#else /* !HAVE_OGGVORBIS */
|
||||
|
||||
InputPlugin oggvorbisPlugin =
|
||||
{
|
||||
InputPlugin oggvorbisPlugin = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -431,4 +439,4 @@ InputPlugin oggvorbisPlugin =
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif /* HAVE_OGGVORBIS */
|
||||
#endif /* HAVE_OGGVORBIS */
|
||||
|
Reference in New Issue
Block a user