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:
Warren Dukes 2004-05-18 13:13:55 +00:00
parent 6c24180516
commit c51ad71efa
7 changed files with 157 additions and 116 deletions

View File

@ -26,6 +26,7 @@
#include "path.h" #include "path.h"
#include "log.h" #include "log.h"
#include "sig_handlers.h" #include "sig_handlers.h"
#include "ls.h"
#ifdef HAVE_MAD #ifdef HAVE_MAD
#include "mp3_decode.h" #include "mp3_decode.h"
@ -213,10 +214,90 @@ void decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
return; \ 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 decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
int pid; int pid;
int ret;
decode_pid = &(pc->decode_pid); decode_pid = &(pc->decode_pid);
blockSignals(); blockSignals();
@ -227,51 +308,7 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
unblockSignals(); unblockSignals();
while(1) { while(1) {
if(dc->start) { if(dc->start) decodeStart(pc, cb, dc);
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;
}
}
else if(dc->stop) { else if(dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;

View File

@ -27,19 +27,22 @@
#include <stdio.h> #include <stdio.h>
#include <sys/param.h> #include <sys/param.h>
#define DECODE_TYPE_MP3 0 #define DECODE_TYPE_FILE 0
#define DECODE_TYPE_OGG 1 #define DECODE_TYPE_URL 1
#define DECODE_TYPE_FLAC 2
#define DECODE_TYPE_AUDIOFILE 3
#define DECODE_TYPE_MP4 4
#define DECODE_TYPE_AAC 5
#define DECODE_STATE_STOP 0 #define DECODE_STATE_STOP 0
#define DECODE_STATE_DECODE 1 #define DECODE_STATE_DECODE 1
#define DECODE_ERROR_NOERROR 0 #define DECODE_ERROR_NOERROR 0
#define DECODE_ERROR_UNKTYPE 1 #define DECODE_ERROR_UNKTYPE -10
#define DECODE_ERROR_FILE 2 #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 { typedef struct _DecoderControl {
volatile mpd_sint8 state; volatile mpd_sint8 state;

View File

@ -381,11 +381,13 @@ static int getHTTPHello(InputStream * inStream) {
*temp = '\r'; *temp = '\r';
} }
else if(0 == strncmp(cur, "\r\nContent-Type:", 15)) { 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; if(!temp) break;
while(*temp2 && *temp2==' ') temp2++;
*temp = '\0'; *temp = '\0';
if(inStream->mime) free(inStream->mime); if(inStream->mime) free(inStream->mime);
inStream->mime = strdup(cur+15); inStream->mime = strdup(temp2);
*temp = '\r'; *temp = '\r';
} }
@ -455,13 +457,15 @@ size_t inputStream_httpRead(InputStream * inStream, void * ptr, size_t size,
return 0; 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); memcpy(ptr, data->buffer, readed);
data->buflen -= readed; data->buflen -= readed;
memmove(data->buffer, data->buffer+readed, data->buflen); memmove(data->buffer, data->buffer+readed, data->buflen);
inStream->offset+= readed; inStream->offset+= readed;
}
return readed; return readed;
} }
@ -536,22 +540,17 @@ int inputStream_httpBuffer(InputStream * inStream) {
return 0; return 0;
} }
if(ret == 1) { if(ret == 0) return 0;
readed = recv(data->sock,
data->buffer+data->buflen,
HTTP_BUFFER_SIZE-1-data->buflen, 0);
if(readed < 0 && (errno == EAGAIN || readed = recv(data->sock, data->buffer+data->buflen,
errno == EINTR)) HTTP_BUFFER_SIZE-1-data->buflen, 0);
{
readed = 0; if(readed < 0 && (errno == EAGAIN || errno == EINTR));
} else if(readed <= 0) {
else if(readed <= 0) { close(data->sock);
close(data->sock); data->connState = HTTP_CONN_STATE_CLOSED;
data->connState = HTTP_CONN_STATE_CLOSED;
}
else data->buflen += readed;
} }
else data->buflen += readed;
} }
return 0; return 0;

View File

@ -133,16 +133,10 @@ typedef struct _mp3DecodeData {
long currentFrame; long currentFrame;
int flush; int flush;
unsigned long bitRate; unsigned long bitRate;
InputStream inStream; InputStream * inStream;
} mp3DecodeData; } mp3DecodeData;
int initMp3DecodeData(mp3DecodeData * data, char * file) { void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream) {
int ret;
/*while(((*/ret = openInputStream(&(data->inStream),file)/*)<0)) &&
data->inStream.error==EINTR)*/;
if(ret<0) return -1;
data->outputPtr = data->outputBuffer; data->outputPtr = data->outputBuffer;
data->outputBufferEnd = data->outputBuffer+MP3_DATA_OUTPUT_BUFFER_SIZE; data->outputBufferEnd = data->outputBuffer+MP3_DATA_OUTPUT_BUFFER_SIZE;
data->muteFrame = 0; data->muteFrame = 0;
@ -152,14 +146,13 @@ int initMp3DecodeData(mp3DecodeData * data, char * file) {
data->times = NULL; data->times = NULL;
data->currentFrame = 0; data->currentFrame = 0;
data->flush = 1; data->flush = 1;
data->inStream = inStream;
mad_stream_init(&data->stream); mad_stream_init(&data->stream);
data->stream.options |= MAD_OPTION_IGNORECRC; data->stream.options |= MAD_OPTION_IGNORECRC;
mad_frame_init(&data->frame); mad_frame_init(&data->frame);
mad_synth_init(&data->synth); mad_synth_init(&data->synth);
mad_timer_reset(&data->timer); mad_timer_reset(&data->timer);
return 0;
} }
int fillMp3InputBuffer(mp3DecodeData * data, long offset) { int fillMp3InputBuffer(mp3DecodeData * data, long offset) {
@ -169,7 +162,7 @@ int fillMp3InputBuffer(mp3DecodeData * data, long offset) {
unsigned char * readStart; unsigned char * readStart;
if(offset>=0) { if(offset>=0) {
if(seekInputStream(&(data->inStream),offset,SEEK_SET) < 0) { if(seekInputStream(data->inStream,offset,SEEK_SET) < 0) {
return -1; return -1;
} }
} }
@ -187,8 +180,8 @@ int fillMp3InputBuffer(mp3DecodeData * data, long offset) {
} }
readed = 0; readed = 0;
while(readed == 0 && !inputStreamAtEOF(&(data->inStream))) { while(readed == 0 && !inputStreamAtEOF(data->inStream)) {
readed = readFromInputStream(&(data->inStream), readStart, 1, readed = readFromInputStream(data->inStream, readStart, 1,
readSize); readSize);
} }
if(readed<=0) return -1; if(readed<=0) return -1;
@ -359,7 +352,7 @@ int decodeFirstFrame(mp3DecodeData * data) {
} }
} }
else { else {
size_t offset = data->inStream.offset; size_t offset = data->inStream->offset;
mad_timer_t duration = data->frame.header.duration; mad_timer_t duration = data->frame.header.duration;
float frameTime = ((float)mad_timer_count(duration, float frameTime = ((float)mad_timer_count(duration,
MAD_UNITS_MILLISECONDS))/1000; MAD_UNITS_MILLISECONDS))/1000;
@ -369,8 +362,9 @@ int decodeFirstFrame(mp3DecodeData * data) {
else { else {
offset-= data->stream.bufend-data->stream.buffer; 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; (data->frame).header.bitrate;
if(data->totalTime < 0) data->totalTime = 0;
data->maxFrames = data->totalTime/frameTime+FRAMES_CUSHION; data->maxFrames = data->totalTime/frameTime+FRAMES_CUSHION;
} }
@ -385,18 +379,19 @@ void mp3DecodeDataFinalize(mp3DecodeData * data) {
mad_frame_finish(&data->frame); mad_frame_finish(&data->frame);
mad_stream_finish(&data->stream); mad_stream_finish(&data->stream);
while(closeInputStream(&(data->inStream))<0 && closeInputStream(data->inStream);
data->inStream.error==EINTR);
if(data->frameOffset) free(data->frameOffset); if(data->frameOffset) free(data->frameOffset);
if(data->times) free(data->times); if(data->times) free(data->times);
} }
/* this is primarily used for getting total time for tags */ /* this is primarily used for getting total time for tags */
int getMp3TotalTime(char * file) { int getMp3TotalTime(char * file) {
InputStream inStream;
mp3DecodeData data; mp3DecodeData data;
int ret; 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; if(decodeFirstFrame(&data)<0) ret = -1;
else ret = data.totalTime+0.5; else ret = data.totalTime+0.5;
mp3DecodeDataFinalize(&data); mp3DecodeDataFinalize(&data);
@ -404,11 +399,8 @@ int getMp3TotalTime(char * file) {
return ret; return ret;
} }
int openMp3(char * file, mp3DecodeData * data) { int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data) {
if(initMp3DecodeData(data,file) < 0) { initMp3DecodeData(data, inStream);
ERROR("problems opening \"%s\"\n",file);
return -1;
}
if(decodeFirstFrame(data)<0) { if(decodeFirstFrame(data)<0) {
mp3DecodeDataFinalize(data); mp3DecodeDataFinalize(data);
return -1; return -1;
@ -428,7 +420,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
{ {
mad_timer_add(&data->timer,(data->frame).header.duration); mad_timer_add(&data->timer,(data->frame).header.duration);
data->bitRate = (data->frame).header.bitrate; 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) { if(data->stream.this_frame!=NULL) {
data->frameOffset[data->currentFrame]-= data->frameOffset[data->currentFrame]-=
data->stream.bufend- data->stream.bufend-
@ -535,11 +527,12 @@ void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, AudioFormat * af) {
af->channels = MAD_NCHANNELS(&(data->frame).header); 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; 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"); ERROR("Input does not appear to be a mp3 bit stream.\n");
closeInputStream(inStream);
return -1; return -1;
} }

View File

@ -24,11 +24,12 @@
#ifdef HAVE_MAD #ifdef HAVE_MAD
#include "playerData.h" #include "playerData.h"
#include "inputStream.h"
/* this is primarily used in tag.c */ /* this is primarily used in tag.c */
int getMp3TotalTime(char * file); int getMp3TotalTime(char * file);
int mp3_decode(OutputBuffer * cb, DecoderControl * dc); int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream);
#endif #endif

View File

@ -161,25 +161,29 @@ int playerInit() {
} }
int playerGetDecodeType(char * utf8file) { int playerGetDecodeType(char * utf8file) {
if(isRemoteUrl(utf8file)) return DECODE_TYPE_MP3; if(isRemoteUrl(utf8file)) return DECODE_TYPE_URL;
if(!isFile(utf8file,NULL)) return -1; if(isFile(utf8file,NULL)) return DECODE_TYPE_FILE;
return -1;
}
int playerGetSuffix(char * utf8file) {
#ifdef HAVE_MAD #ifdef HAVE_MAD
if(hasMp3Suffix(utf8file)) return DECODE_TYPE_MP3; if(hasMp3Suffix(utf8file)) return DECODE_SUFFIX_MP3;
#endif #endif
#ifdef HAVE_OGG #ifdef HAVE_OGG
if(hasOggSuffix(utf8file)) return DECODE_TYPE_OGG; if(hasOggSuffix(utf8file)) return DECODE_SUFFIX_OGG;
#endif
#ifdef HAVE_FLAC
if(hasFlacSuffix(utf8file)) return DECODE_TYPE_FLAC;
#endif
#ifdef HAVE_AUDIOFILE
if(hasWaveSuffix(utf8file)) return DECODE_TYPE_AUDIOFILE;
#endif #endif
#ifdef HAVE_FAAD #ifdef HAVE_FAAD
if(hasAacSuffix(utf8file)) return DECODE_TYPE_AAC; if(hasAacSuffix(utf8file)) return DECODE_SUFFIX_AAC;
if(hasMp4Suffix(utf8file)) return DECODE_TYPE_MP4; if(hasMp4Suffix(utf8file)) return DECODE_SUFFIX_MP4;
#endif #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) { int playerPlay(FILE * fp, char * utf8file) {
@ -208,6 +212,7 @@ int playerPlay(FILE * fp, char * utf8file) {
return 0; return 0;
} }
pc->decodeType = decodeType; pc->decodeType = decodeType;
pc->fileSuffix = playerGetSuffix(utf8file);
if(isRemoteUrl(utf8file)) { if(isRemoteUrl(utf8file)) {
strncpy(pc->file,utf8file,MAXPATHLEN); strncpy(pc->file,utf8file,MAXPATHLEN);
@ -366,6 +371,7 @@ int queueSong(char * utf8file) {
decodeType = playerGetDecodeType(utf8file); decodeType = playerGetDecodeType(utf8file);
if(decodeType < 0) return -1; if(decodeType < 0) return -1;
pc->decodeType = decodeType; pc->decodeType = decodeType;
pc->fileSuffix = playerGetSuffix(utf8file);
pc->queueState = PLAYER_QUEUE_FULL; pc->queueState = PLAYER_QUEUE_FULL;
return 0; return 0;
@ -428,6 +434,7 @@ int playerSeek(FILE * fp, char * utf8file, float time) {
return -1; return -1;
} }
pc->decodeType = decodeType; pc->decodeType = decodeType;
pc->fileSuffix = playerGetSuffix(utf8file);
strncpy(pc->file,file,MAXPATHLEN); strncpy(pc->file,file,MAXPATHLEN);
pc->file[MAXPATHLEN] = '\0'; pc->file[MAXPATHLEN] = '\0';

View File

@ -52,6 +52,7 @@
typedef struct _PlayerControl { typedef struct _PlayerControl {
volatile mpd_sint8 decodeType; volatile mpd_sint8 decodeType;
volatile mpd_sint8 fileSuffix;
volatile mpd_sint8 stop; volatile mpd_sint8 stop;
volatile mpd_sint8 play; volatile mpd_sint8 play;
volatile mpd_sint8 pause; volatile mpd_sint8 pause;