diff --git a/src/decode.c b/src/decode.c index 8ab215a4a..c990edc9e 100644 --- a/src/decode.c +++ b/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; diff --git a/src/decode.h b/src/decode.h index 39c6ec34d..a766efd44 100644 --- a/src/decode.h +++ b/src/decode.h @@ -27,19 +27,22 @@ #include #include -#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; diff --git a/src/inputStream_http.c b/src/inputStream_http.c index c2c1b0904..9d0909ba2 100644 --- a/src/inputStream_http.c +++ b/src/inputStream_http.c @@ -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; diff --git a/src/mp3_decode.c b/src/mp3_decode.c index 15f423e4a..0658f3d41 100644 --- a/src/mp3_decode.c +++ b/src/mp3_decode.c @@ -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; } diff --git a/src/mp3_decode.h b/src/mp3_decode.h index c50df55c1..e33cd60c3 100644 --- a/src/mp3_decode.h +++ b/src/mp3_decode.h @@ -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 diff --git a/src/player.c b/src/player.c index 7f28670bf..a05b43b14 100644 --- a/src/player.c +++ b/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'; diff --git a/src/player.h b/src/player.h index 45ec3b6bc..a47b2c356 100644 --- a/src/player.h +++ b/src/player.h @@ -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;