aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/decode.c129
-rw-r--r--src/decode.h19
-rw-r--r--src/inputStream_http.c41
-rw-r--r--src/mp3_decode.c45
-rw-r--r--src/mp3_decode.h3
-rw-r--r--src/player.c33
-rw-r--r--src/player.h1
7 files changed, 156 insertions, 115 deletions
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,65 +214,101 @@ void decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
return; \
}
-int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
-
- int pid;
- int ret;
- decode_pid = &(pc->decode_pid);
+void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
+ int ret;
+ InputStream inStream;
- blockSignals();
- pid = fork();
+ strncpy(dc->file,pc->file,MAXPATHLEN);
+ dc->file[MAXPATHLEN] = '\0';
- if(pid==0) {
- /* CHILD */
- unblockSignals();
+ if(openInputStream(&inStream,dc->file) < 0) {
+ dc->error = DECODE_ERROR_FILE;
+ dc->start = 0;
+ dc->stop = 0;
+ dc->state = DECODE_STATE_STOP;
+ return;
+ }
- while(1) {
- if(dc->start) {
- strncpy(dc->file,pc->file,MAXPATHLEN);
- dc->file[MAXPATHLEN] = '\0';
- switch(pc->decodeType) {
+ while(!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0);
+
+ switch(pc->decodeType) {
+ case DECODE_TYPE_URL:
#ifdef HAVE_MAD
- case DECODE_TYPE_MP3:
- ret = mp3_decode(cb,dc);
- break;
+ 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
- case DECODE_TYPE_AAC:
- ret = aac_decode(cb,dc);
- break;
- case DECODE_TYPE_MP4:
- ret = mp4_decode(cb,dc);
- break;
+ 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
- case DECODE_TYPE_OGG:
- ret = ogg_decode(cb,dc);
- break;
+ if(pc->fileSuffix == DECODE_SUFFIX_OGG) {
+ closeInputStream(&inStream);
+ ret = ogg_decode(cb,dc);
+ break;
+ }
#endif
#ifdef HAVE_FLAC
- case DECODE_TYPE_FLAC:
- ret = flac_decode(cb,dc);
- break;
+ if(pc->fileSuffix == DECODE_SUFFIX_FLAC) {
+ closeInputStream(&inStream);
+ ret = flac_decode(cb,dc);
+ break;
+ }
#endif
#ifdef HAVE_AUDIOFILE
- case DECODE_TYPE_AUDIOFILE:
- ret = audiofile_decode(cb,dc);
- break;
+ if(pc->fileSuffix == DECODE_SUFFIX_WAVE) {
+ closeInputStream(&inStream);
+ 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;
- }
- }
+ 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;
+ decode_pid = &(pc->decode_pid);
+
+ blockSignals();
+ pid = fork();
+
+ if(pid==0) {
+ /* CHILD */
+ unblockSignals();
+
+ while(1) {
+ 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 <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;
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_SUFFIX_OGG;
#endif
-#ifdef HAVE_OGG
- if(hasOggSuffix(utf8file)) return DECODE_TYPE_OGG;
+#ifdef HAVE_FAAD
+ if(hasAacSuffix(utf8file)) return DECODE_SUFFIX_AAC;
+ if(hasMp4Suffix(utf8file)) return DECODE_SUFFIX_MP4;
#endif
-#ifdef HAVE_FLAC
- if(hasFlacSuffix(utf8file)) return DECODE_TYPE_FLAC;
+#ifdef HAVE_FLAC
+ if(hasFlacSuffix(utf8file)) return DECODE_SUFFIX_FLAC;
#endif
#ifdef HAVE_AUDIOFILE
- if(hasWaveSuffix(utf8file)) return DECODE_TYPE_AUDIOFILE;
-#endif
-#ifdef HAVE_FAAD
- if(hasAacSuffix(utf8file)) return DECODE_TYPE_AAC;
- if(hasMp4Suffix(utf8file)) return DECODE_TYPE_MP4;
+ if(hasWaveSuffix(utf8file)) return DECODE_SUFFIX_WAVE;
#endif
- return -1;
+ 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;