rework stuff so that we can use mime-type of streams to detect type of file
git-svn-id: https://svn.musicpd.org/mpd/trunk@1062 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
6c24180516
commit
c51ad71efa
129
src/decode.c
129
src/decode.c
|
@ -26,6 +26,7 @@
|
|||
#include "path.h"
|
||||
#include "log.h"
|
||||
#include "sig_handlers.h"
|
||||
#include "ls.h"
|
||||
|
||||
#ifdef HAVE_MAD
|
||||
#include "mp3_decode.h"
|
||||
|
@ -213,10 +214,90 @@ void decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
|
|||
return; \
|
||||
}
|
||||
|
||||
void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
|
||||
int ret;
|
||||
InputStream inStream;
|
||||
|
||||
strncpy(dc->file,pc->file,MAXPATHLEN);
|
||||
dc->file[MAXPATHLEN] = '\0';
|
||||
|
||||
if(openInputStream(&inStream,dc->file) < 0) {
|
||||
dc->error = DECODE_ERROR_FILE;
|
||||
dc->start = 0;
|
||||
dc->stop = 0;
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
return;
|
||||
}
|
||||
|
||||
while(!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0);
|
||||
|
||||
switch(pc->decodeType) {
|
||||
case DECODE_TYPE_URL:
|
||||
#ifdef HAVE_MAD
|
||||
if(pc->fileSuffix == DECODE_SUFFIX_MP3 || (inStream.mime &&
|
||||
0 == strcmp(inStream.mime, "audio/mpeg")))
|
||||
{
|
||||
ret = mp3_decode(cb,dc,&inStream);
|
||||
}
|
||||
else ret = DECODE_ERROR_UNKTYPE;
|
||||
break;
|
||||
#endif
|
||||
case DECODE_TYPE_FILE:
|
||||
#ifdef HAVE_MAD
|
||||
if(pc->fileSuffix == DECODE_SUFFIX_MP3) {
|
||||
ret = mp3_decode(cb, dc, &inStream);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_FAAD
|
||||
if(pc->fileSuffix == DECODE_SUFFIX_AAC) {
|
||||
closeInputStream(&inStream);
|
||||
ret = aac_decode(cb,dc);
|
||||
break;
|
||||
}
|
||||
if(pc->fileSuffix == DECODE_SUFFIX_MP4) {
|
||||
closeInputStream(&inStream);
|
||||
ret = mp4_decode(cb,dc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_OGG
|
||||
if(pc->fileSuffix == DECODE_SUFFIX_OGG) {
|
||||
closeInputStream(&inStream);
|
||||
ret = ogg_decode(cb,dc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_FLAC
|
||||
if(pc->fileSuffix == DECODE_SUFFIX_FLAC) {
|
||||
closeInputStream(&inStream);
|
||||
ret = flac_decode(cb,dc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_AUDIOFILE
|
||||
if(pc->fileSuffix == DECODE_SUFFIX_WAVE) {
|
||||
closeInputStream(&inStream);
|
||||
ret = audiofile_decode(cb,dc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
ret = DECODE_ERROR_UNKTYPE;
|
||||
}
|
||||
if(ret<0) {
|
||||
strncpy(pc->erroredFile, dc->file, MAXPATHLEN);
|
||||
pc->erroredFile[MAXPATHLEN] = '\0';
|
||||
if(ret != DECODE_ERROR_UNKTYPE) dc->error = DECODE_ERROR_FILE;
|
||||
dc->start = 0;
|
||||
dc->stop = 0;
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
|
||||
|
||||
int pid;
|
||||
int ret;
|
||||
decode_pid = &(pc->decode_pid);
|
||||
|
||||
blockSignals();
|
||||
|
@ -227,51 +308,7 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
|
|||
unblockSignals();
|
||||
|
||||
while(1) {
|
||||
if(dc->start) {
|
||||
strncpy(dc->file,pc->file,MAXPATHLEN);
|
||||
dc->file[MAXPATHLEN] = '\0';
|
||||
switch(pc->decodeType) {
|
||||
#ifdef HAVE_MAD
|
||||
case DECODE_TYPE_MP3:
|
||||
ret = mp3_decode(cb,dc);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_FAAD
|
||||
case DECODE_TYPE_AAC:
|
||||
ret = aac_decode(cb,dc);
|
||||
break;
|
||||
case DECODE_TYPE_MP4:
|
||||
ret = mp4_decode(cb,dc);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_OGG
|
||||
case DECODE_TYPE_OGG:
|
||||
ret = ogg_decode(cb,dc);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_FLAC
|
||||
case DECODE_TYPE_FLAC:
|
||||
ret = flac_decode(cb,dc);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_AUDIOFILE
|
||||
case DECODE_TYPE_AUDIOFILE:
|
||||
ret = audiofile_decode(cb,dc);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret = DECODE_ERROR_UNKTYPE;
|
||||
strncpy(pc->erroredFile,dc->file,
|
||||
MAXPATHLEN);
|
||||
pc->erroredFile[MAXPATHLEN] = '\0';
|
||||
}
|
||||
if(ret<0) {
|
||||
dc->error = DECODE_ERROR_FILE;
|
||||
dc->start = 0;
|
||||
dc->stop = 0;
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
}
|
||||
}
|
||||
if(dc->start) decodeStart(pc, cb, dc);
|
||||
else if(dc->stop) {
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->stop = 0;
|
||||
|
|
19
src/decode.h
19
src/decode.h
|
@ -27,19 +27,22 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#define DECODE_TYPE_MP3 0
|
||||
#define DECODE_TYPE_OGG 1
|
||||
#define DECODE_TYPE_FLAC 2
|
||||
#define DECODE_TYPE_AUDIOFILE 3
|
||||
#define DECODE_TYPE_MP4 4
|
||||
#define DECODE_TYPE_AAC 5
|
||||
#define DECODE_TYPE_FILE 0
|
||||
#define DECODE_TYPE_URL 1
|
||||
|
||||
#define DECODE_STATE_STOP 0
|
||||
#define DECODE_STATE_DECODE 1
|
||||
|
||||
#define DECODE_ERROR_NOERROR 0
|
||||
#define DECODE_ERROR_UNKTYPE 1
|
||||
#define DECODE_ERROR_FILE 2
|
||||
#define DECODE_ERROR_UNKTYPE -10
|
||||
#define DECODE_ERROR_FILE -20
|
||||
|
||||
#define DECODE_SUFFIX_MP3 1
|
||||
#define DECODE_SUFFIX_OGG 2
|
||||
#define DECODE_SUFFIX_FLAC 3
|
||||
#define DECODE_SUFFIX_AAC 4
|
||||
#define DECODE_SUFFIX_MP4 5
|
||||
#define DECODE_SUFFIX_WAVE 6
|
||||
|
||||
typedef struct _DecoderControl {
|
||||
volatile mpd_sint8 state;
|
||||
|
|
|
@ -381,11 +381,13 @@ static int getHTTPHello(InputStream * inStream) {
|
|||
*temp = '\r';
|
||||
}
|
||||
else if(0 == strncmp(cur, "\r\nContent-Type:", 15)) {
|
||||
char * temp = strstr(cur+15,"\r\n");
|
||||
char * temp2 = cur+15;
|
||||
char * temp = strstr(temp2,"\r\n");
|
||||
if(!temp) break;
|
||||
while(*temp2 && *temp2==' ') temp2++;
|
||||
*temp = '\0';
|
||||
if(inStream->mime) free(inStream->mime);
|
||||
inStream->mime = strdup(cur+15);
|
||||
inStream->mime = strdup(temp2);
|
||||
*temp = '\r';
|
||||
}
|
||||
|
||||
|
@ -455,13 +457,15 @@ size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
readed = inlen > data->buflen ? data->buflen : inlen;
|
||||
if(data->buflen > 0) {
|
||||
readed = inlen > data->buflen ? data->buflen : inlen;
|
||||
|
||||
memcpy(ptr, data->buffer, readed);
|
||||
data->buflen -= readed;
|
||||
memmove(data->buffer, data->buffer+readed, data->buflen);
|
||||
memcpy(ptr, data->buffer, readed);
|
||||
data->buflen -= readed;
|
||||
memmove(data->buffer, data->buffer+readed, data->buflen);
|
||||
|
||||
inStream->offset+= readed;
|
||||
inStream->offset+= readed;
|
||||
}
|
||||
|
||||
return readed;
|
||||
}
|
||||
|
@ -536,22 +540,17 @@ int inputStream_httpBuffer(InputStream * inStream) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if(ret == 1) {
|
||||
readed = recv(data->sock,
|
||||
data->buffer+data->buflen,
|
||||
HTTP_BUFFER_SIZE-1-data->buflen, 0);
|
||||
if(ret == 0) return 0;
|
||||
|
||||
if(readed < 0 && (errno == EAGAIN ||
|
||||
errno == EINTR))
|
||||
{
|
||||
readed = 0;
|
||||
}
|
||||
else if(readed <= 0) {
|
||||
close(data->sock);
|
||||
data->connState = HTTP_CONN_STATE_CLOSED;
|
||||
}
|
||||
else data->buflen += readed;
|
||||
readed = recv(data->sock, data->buffer+data->buflen,
|
||||
HTTP_BUFFER_SIZE-1-data->buflen, 0);
|
||||
|
||||
if(readed < 0 && (errno == EAGAIN || errno == EINTR));
|
||||
else if(readed <= 0) {
|
||||
close(data->sock);
|
||||
data->connState = HTTP_CONN_STATE_CLOSED;
|
||||
}
|
||||
else data->buflen += readed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -133,16 +133,10 @@ typedef struct _mp3DecodeData {
|
|||
long currentFrame;
|
||||
int flush;
|
||||
unsigned long bitRate;
|
||||
InputStream inStream;
|
||||
InputStream * inStream;
|
||||
} mp3DecodeData;
|
||||
|
||||
int initMp3DecodeData(mp3DecodeData * data, char * file) {
|
||||
int ret;
|
||||
|
||||
/*while(((*/ret = openInputStream(&(data->inStream),file)/*)<0)) &&
|
||||
data->inStream.error==EINTR)*/;
|
||||
if(ret<0) return -1;
|
||||
|
||||
void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream) {
|
||||
data->outputPtr = data->outputBuffer;
|
||||
data->outputBufferEnd = data->outputBuffer+MP3_DATA_OUTPUT_BUFFER_SIZE;
|
||||
data->muteFrame = 0;
|
||||
|
@ -152,14 +146,13 @@ int initMp3DecodeData(mp3DecodeData * data, char * file) {
|
|||
data->times = NULL;
|
||||
data->currentFrame = 0;
|
||||
data->flush = 1;
|
||||
data->inStream = inStream;
|
||||
|
||||
mad_stream_init(&data->stream);
|
||||
data->stream.options |= MAD_OPTION_IGNORECRC;
|
||||
mad_frame_init(&data->frame);
|
||||
mad_synth_init(&data->synth);
|
||||
mad_timer_reset(&data->timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fillMp3InputBuffer(mp3DecodeData * data, long offset) {
|
||||
|
@ -169,7 +162,7 @@ int fillMp3InputBuffer(mp3DecodeData * data, long offset) {
|
|||
unsigned char * readStart;
|
||||
|
||||
if(offset>=0) {
|
||||
if(seekInputStream(&(data->inStream),offset,SEEK_SET) < 0) {
|
||||
if(seekInputStream(data->inStream,offset,SEEK_SET) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -187,8 +180,8 @@ int fillMp3InputBuffer(mp3DecodeData * data, long offset) {
|
|||
}
|
||||
|
||||
readed = 0;
|
||||
while(readed == 0 && !inputStreamAtEOF(&(data->inStream))) {
|
||||
readed = readFromInputStream(&(data->inStream), readStart, 1,
|
||||
while(readed == 0 && !inputStreamAtEOF(data->inStream)) {
|
||||
readed = readFromInputStream(data->inStream, readStart, 1,
|
||||
readSize);
|
||||
}
|
||||
if(readed<=0) return -1;
|
||||
|
@ -359,7 +352,7 @@ int decodeFirstFrame(mp3DecodeData * data) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
size_t offset = data->inStream.offset;
|
||||
size_t offset = data->inStream->offset;
|
||||
mad_timer_t duration = data->frame.header.duration;
|
||||
float frameTime = ((float)mad_timer_count(duration,
|
||||
MAD_UNITS_MILLISECONDS))/1000;
|
||||
|
@ -369,8 +362,9 @@ int decodeFirstFrame(mp3DecodeData * data) {
|
|||
else {
|
||||
offset-= data->stream.bufend-data->stream.buffer;
|
||||
}
|
||||
data->totalTime = ((data->inStream.size-offset)*8.0)/
|
||||
data->totalTime = ((data->inStream->size-offset)*8.0)/
|
||||
(data->frame).header.bitrate;
|
||||
if(data->totalTime < 0) data->totalTime = 0;
|
||||
data->maxFrames = data->totalTime/frameTime+FRAMES_CUSHION;
|
||||
}
|
||||
|
||||
|
@ -385,18 +379,19 @@ void mp3DecodeDataFinalize(mp3DecodeData * data) {
|
|||
mad_frame_finish(&data->frame);
|
||||
mad_stream_finish(&data->stream);
|
||||
|
||||
while(closeInputStream(&(data->inStream))<0 &&
|
||||
data->inStream.error==EINTR);
|
||||
closeInputStream(data->inStream);
|
||||
if(data->frameOffset) free(data->frameOffset);
|
||||
if(data->times) free(data->times);
|
||||
}
|
||||
|
||||
/* this is primarily used for getting total time for tags */
|
||||
int getMp3TotalTime(char * file) {
|
||||
InputStream inStream;
|
||||
mp3DecodeData data;
|
||||
int ret;
|
||||
|
||||
if(initMp3DecodeData(&data,file)<0) return -1;
|
||||
if(openInputStream(&inStream, file) < 0) return -1;
|
||||
initMp3DecodeData(&data,&inStream);
|
||||
if(decodeFirstFrame(&data)<0) ret = -1;
|
||||
else ret = data.totalTime+0.5;
|
||||
mp3DecodeDataFinalize(&data);
|
||||
|
@ -404,11 +399,8 @@ int getMp3TotalTime(char * file) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int openMp3(char * file, mp3DecodeData * data) {
|
||||
if(initMp3DecodeData(data,file) < 0) {
|
||||
ERROR("problems opening \"%s\"\n",file);
|
||||
return -1;
|
||||
}
|
||||
int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data) {
|
||||
initMp3DecodeData(data, inStream);
|
||||
if(decodeFirstFrame(data)<0) {
|
||||
mp3DecodeDataFinalize(data);
|
||||
return -1;
|
||||
|
@ -428,7 +420,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
|
|||
{
|
||||
mad_timer_add(&data->timer,(data->frame).header.duration);
|
||||
data->bitRate = (data->frame).header.bitrate;
|
||||
data->frameOffset[data->currentFrame] = data->inStream.offset;
|
||||
data->frameOffset[data->currentFrame] = data->inStream->offset;
|
||||
if(data->stream.this_frame!=NULL) {
|
||||
data->frameOffset[data->currentFrame]-=
|
||||
data->stream.bufend-
|
||||
|
@ -535,11 +527,12 @@ void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, AudioFormat * af) {
|
|||
af->channels = MAD_NCHANNELS(&(data->frame).header);
|
||||
}
|
||||
|
||||
int mp3_decode(OutputBuffer * cb, DecoderControl * dc) {
|
||||
int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) {
|
||||
mp3DecodeData data;
|
||||
|
||||
if(openMp3(dc->file,&data) < 0) {
|
||||
if(openMp3FromInputStream(inStream, &data) < 0) {
|
||||
ERROR("Input does not appear to be a mp3 bit stream.\n");
|
||||
closeInputStream(inStream);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,12 @@
|
|||
#ifdef HAVE_MAD
|
||||
|
||||
#include "playerData.h"
|
||||
#include "inputStream.h"
|
||||
|
||||
/* this is primarily used in tag.c */
|
||||
int getMp3TotalTime(char * file);
|
||||
|
||||
int mp3_decode(OutputBuffer * cb, DecoderControl * dc);
|
||||
int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
35
src/player.c
35
src/player.c
|
@ -161,25 +161,29 @@ int playerInit() {
|
|||
}
|
||||
|
||||
int playerGetDecodeType(char * utf8file) {
|
||||
if(isRemoteUrl(utf8file)) return DECODE_TYPE_MP3;
|
||||
if(!isFile(utf8file,NULL)) return -1;
|
||||
if(isRemoteUrl(utf8file)) return DECODE_TYPE_URL;
|
||||
if(isFile(utf8file,NULL)) return DECODE_TYPE_FILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int playerGetSuffix(char * utf8file) {
|
||||
#ifdef HAVE_MAD
|
||||
if(hasMp3Suffix(utf8file)) return DECODE_TYPE_MP3;
|
||||
if(hasMp3Suffix(utf8file)) return DECODE_SUFFIX_MP3;
|
||||
#endif
|
||||
#ifdef HAVE_OGG
|
||||
if(hasOggSuffix(utf8file)) return DECODE_TYPE_OGG;
|
||||
#endif
|
||||
#ifdef HAVE_FLAC
|
||||
if(hasFlacSuffix(utf8file)) return DECODE_TYPE_FLAC;
|
||||
#endif
|
||||
#ifdef HAVE_AUDIOFILE
|
||||
if(hasWaveSuffix(utf8file)) return DECODE_TYPE_AUDIOFILE;
|
||||
#ifdef HAVE_OGG
|
||||
if(hasOggSuffix(utf8file)) return DECODE_SUFFIX_OGG;
|
||||
#endif
|
||||
#ifdef HAVE_FAAD
|
||||
if(hasAacSuffix(utf8file)) return DECODE_TYPE_AAC;
|
||||
if(hasMp4Suffix(utf8file)) return DECODE_TYPE_MP4;
|
||||
if(hasAacSuffix(utf8file)) return DECODE_SUFFIX_AAC;
|
||||
if(hasMp4Suffix(utf8file)) return DECODE_SUFFIX_MP4;
|
||||
#endif
|
||||
return -1;
|
||||
#ifdef HAVE_FLAC
|
||||
if(hasFlacSuffix(utf8file)) return DECODE_SUFFIX_FLAC;
|
||||
#endif
|
||||
#ifdef HAVE_AUDIOFILE
|
||||
if(hasWaveSuffix(utf8file)) return DECODE_SUFFIX_WAVE;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int playerPlay(FILE * fp, char * utf8file) {
|
||||
|
@ -208,6 +212,7 @@ int playerPlay(FILE * fp, char * utf8file) {
|
|||
return 0;
|
||||
}
|
||||
pc->decodeType = decodeType;
|
||||
pc->fileSuffix = playerGetSuffix(utf8file);
|
||||
|
||||
if(isRemoteUrl(utf8file)) {
|
||||
strncpy(pc->file,utf8file,MAXPATHLEN);
|
||||
|
@ -366,6 +371,7 @@ int queueSong(char * utf8file) {
|
|||
decodeType = playerGetDecodeType(utf8file);
|
||||
if(decodeType < 0) return -1;
|
||||
pc->decodeType = decodeType;
|
||||
pc->fileSuffix = playerGetSuffix(utf8file);
|
||||
|
||||
pc->queueState = PLAYER_QUEUE_FULL;
|
||||
return 0;
|
||||
|
@ -428,6 +434,7 @@ int playerSeek(FILE * fp, char * utf8file, float time) {
|
|||
return -1;
|
||||
}
|
||||
pc->decodeType = decodeType;
|
||||
pc->fileSuffix = playerGetSuffix(utf8file);
|
||||
|
||||
strncpy(pc->file,file,MAXPATHLEN);
|
||||
pc->file[MAXPATHLEN] = '\0';
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
typedef struct _PlayerControl {
|
||||
volatile mpd_sint8 decodeType;
|
||||
volatile mpd_sint8 fileSuffix;
|
||||
volatile mpd_sint8 stop;
|
||||
volatile mpd_sint8 play;
|
||||
volatile mpd_sint8 pause;
|
||||
|
|
Loading…
Reference in New Issue