diff --git a/src/Makefile.am b/src/Makefile.am index 3b6717936..2d19a13ff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,13 +5,13 @@ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \ tag.h player.h listen.h conf.h ogg_decode.h volume.h flac_decode.h \ audio.h playerData.h stats.h myfprintf.h sig_handlers.h decode.h log.h \ audiofile_decode.h charConv.h permission.h mpd_types.h pcm_utils.h \ - mp4_decode.h aac_decode.h signal_check.h utf8.h + mp4_decode.h aac_decode.h signal_check.h utf8.h inputStream.h mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \ song.c list.c directory.c tables.c utils.c path.c mp3_decode.c \ tag.c player.c listen.c conf.c ogg_decode.c volume.c flac_decode.c \ audio.c playerData.c stats.c myfprintf.c sig_handlers.c decode.c log.c \ audiofile_decode.c charConv.c permission.c pcm_utils.c mp4_decode.c \ - aac_decode.c signal_check.c utf8.c $(mpd_headers) + aac_decode.c signal_check.c utf8.c inputStream.c $(mpd_headers) mpd_CFLAGS = $(MPD_CFLAGS) mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB) $(MP4FF_LIB) diff --git a/src/inputStream.c b/src/inputStream.c new file mode 100644 index 000000000..0856dd125 --- /dev/null +++ b/src/inputStream.c @@ -0,0 +1,78 @@ +/* the Music Player Daemon (MPD) + * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) + * This project's homepage is: http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "inputStream.h" + +#include +#include +#include +#include + +int initInputStreamFromFile(InputStream * inStream, char * filename) { + inStream->fp = fopen(filename,"r"); + if(!inStream->fp) { + inStream->error = errno; + return -1; + } + + inStream->offset = 0; + + fseek(inStream->fp,0,SEEK_END); + inStream->size = ftell(inStream->fp); + fseek(inStream->fp,0,SEEK_SET); + + return 0; +} + +int seekInputStream(InputStream * inStream, long offset) { + if(offset<0) { + inStream->error = EINVAL; + return -1; + } + + if(fseek(inStream->fp,offset,SEEK_SET)==0) { + inStream->offset = offset; + } + else { + inStream->error = errno; + return -1; + } + + return 0; +} + +size_t fillBufferFromInputStream(InputStream * inStream, char * buffer, + size_t buflen) +{ + size_t readSize; + + readSize = fread(buffer,1,buflen,inStream->fp); + + if(readSize>0) inStream->offset+=readSize; + + return readSize; +} + +int finishInputStream(InputStream * inStream) { + if(fclose(inStream->fp)<0) { + inStream->error = errno; + } + else return -1; + + return 0; +} diff --git a/src/inputStream.h b/src/inputStream.h new file mode 100644 index 000000000..2f11da044 --- /dev/null +++ b/src/inputStream.h @@ -0,0 +1,41 @@ +/* the Music Player Daemon (MPD) + * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) + * This project's homepage is: http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef INPUT_STREAM_H +#define INPUT_STREAM_H + +#include +#include + +typedef struct _InputStream { + FILE * fp; + int error; + long offset; + size_t size; +} InputStream; + +/* if an error occurs for these 3 functions, then -1 is returned and errno + for the input stream is set */ +int initInputStreamFromFile(InputStream * inStream, char * filename); +int seekInputStream(InputStream * inStream, long offset); +int finishInputStream(InputStream * inStream); + +size_t fillBufferFromInputStream(InputStream * inStream, char * buffer, + size_t buflen); + +#endif diff --git a/src/mp3_decode.c b/src/mp3_decode.c index faa124ef9..58cd62a52 100644 --- a/src/mp3_decode.c +++ b/src/mp3_decode.c @@ -36,6 +36,7 @@ #include "playerData.h" #include "log.h" #include "utils.h" +#include "inputStream.h" #include #include @@ -111,7 +112,6 @@ signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample, struct au /* decoder stuff is based on madlld */ typedef struct _mp3DecodeData { - FILE * fp; struct mad_stream stream; struct mad_frame frame; struct mad_synth synth; @@ -126,28 +126,36 @@ typedef struct _mp3DecodeData { long * frameOffset; mad_timer_t * times; long highestFrame; - long currentOffset; long maxFrames; long currentFrame; int flush; unsigned long bitRate; + InputStream inStream; } mp3DecodeData; -void initMp3DecodeData(mp3DecodeData * data) { +int initMp3DecodeData(mp3DecodeData * data, char * file) { + int ret; + + while(((ret = initInputStreamFromFile(&(data->inStream),file))<0) && + data->inStream.error==EINTR); + if(ret<0) return -1; + data->outputPtr = data->outputBuffer; data->outputBufferEnd = data->outputBuffer+CHUNK_SIZE; data->muteFrame = 0; - data->currentOffset = 0; data->highestFrame = 0; data->maxFrames = 0; data->frameOffset = NULL; data->times = NULL; data->currentFrame = 0; data->flush = 1; + mad_stream_init(&data->stream); mad_frame_init(&data->frame); mad_synth_init(&data->synth); mad_timer_reset(&data->timer); + + return 0; } int fillMp3InputBuffer(mp3DecodeData * data, long offset) { @@ -156,9 +164,7 @@ int fillMp3InputBuffer(mp3DecodeData * data, long offset) { unsigned char * readStart; if(offset>=0) { - if(fseek(data->fp,offset,SEEK_SET)==0) { - data->currentOffset = offset; - } + seekInputStream(&(data->inStream),offset); } if(offset==-1 && (data->stream).next_frame!=NULL) { @@ -173,11 +179,10 @@ int fillMp3InputBuffer(mp3DecodeData * data, long offset) { remaining = 0; } - readSize = fread(readStart,1,readSize,data->fp); + readSize = fillBufferFromInputStream(&(data->inStream),readStart, + readSize); if(readSize<=0) return -1; - data->currentOffset+=readSize; - mad_stream_buffer(&data->stream,data->readBuffer,readSize+remaining); (data->stream).error = 0; @@ -316,7 +321,6 @@ fail: } int decodeFirstFrame(mp3DecodeData * data) { - struct stat filestat; struct xing xing; int ret; int skip; @@ -345,18 +349,17 @@ int decodeFirstFrame(mp3DecodeData * data) { } } else { - size_t offset = data->currentOffset; + 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; - fstat(fileno(data->fp),&filestat); if(data->stream.this_frame!=NULL) { offset-= data->stream.bufend-data->stream.this_frame; } else { offset-= data->stream.bufend-data->stream.buffer; } - data->totalTime = ((filestat.st_size-offset)*8.0)/ + data->totalTime = ((data->inStream.size-offset)*8.0)/ (data->frame).header.bitrate; data->maxFrames = data->totalTime/frameTime+FRAMES_CUSHION; } @@ -372,7 +375,8 @@ void mp3DecodeDataFinalize(mp3DecodeData * data) { mad_frame_finish(&data->frame); mad_stream_finish(&data->stream); - if(data->fp) fclose(data->fp); + while(finishInputStream(&(data->inStream))<0 && + data->inStream.error==EINTR); if(data->frameOffset) free(data->frameOffset); if(data->times) free(data->times); } @@ -382,10 +386,7 @@ int getMp3TotalTime(char * file) { mp3DecodeData data; int ret; - while(!(data.fp = fopen(file,"r")) && errno==EINTR); - if(!data.fp) return -1; - - initMp3DecodeData(&data); + if(initMp3DecodeData(&data,file)<0) return -1; if(decodeFirstFrame(&data)<0) ret = -1; else ret = data.totalTime+0.5; mp3DecodeDataFinalize(&data); @@ -394,11 +395,10 @@ int getMp3TotalTime(char * file) { } int openMp3(char * file, mp3DecodeData * data) { - if((data->fp = fopen(file,"r"))<=0) { + if(initMp3DecodeData(data,file) < 0) { ERROR("problems opening \"%s\"\n",file); return -1; } - initMp3DecodeData(data); if(decodeFirstFrame(data)<0) { mp3DecodeDataFinalize(data); return -1; @@ -440,8 +440,7 @@ int mp3Read(mp3DecodeData * data, Buffer * cb, DecoderControl * dc) { { mad_timer_add(&data->timer,(data->frame).header.duration); data->bitRate = (data->frame).header.bitrate; - data->frameOffset[data->currentFrame] = - data->currentOffset; + data->frameOffset[data->currentFrame] = data->inStream.offset; if(data->stream.this_frame!=NULL) { data->frameOffset[data->currentFrame]-= data->stream.bufend-