aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarren Dukes <warren.dukes@gmail.com>2004-06-01 12:50:15 +0000
committerWarren Dukes <warren.dukes@gmail.com>2004-06-01 12:50:15 +0000
commit16da97e4c80b375f6976690e0a04102eff0a6bbd (patch)
tree67c3380dd8c9cdb4b478c6dbda14bbd47ecf953f
parent16fcd1eceac6806853b32a7fb35305cafec521c1 (diff)
downloadmpd-16da97e4c80b375f6976690e0a04102eff0a6bbd.tar.gz
mpd-16da97e4c80b375f6976690e0a04102eff0a6bbd.tar.xz
mpd-16da97e4c80b375f6976690e0a04102eff0a6bbd.zip
parsing mp3 id3v2 tags on the fly for streams
git-svn-id: https://svn.musicpd.org/mpd/trunk@1281 09075e82-0dd4-0310-85a5-a0d7c8717e4f
-rw-r--r--TODO5
-rw-r--r--src/decode.c2
-rw-r--r--src/inputPlugins/mp3_plugin.c88
-rw-r--r--src/tag.c49
-rw-r--r--src/tag.h11
5 files changed, 118 insertions, 37 deletions
diff --git a/TODO b/TODO
index db9abaadc..3027f1105 100644
--- a/TODO
+++ b/TODO
@@ -1,9 +1,6 @@
1) play streams
a) put some sort of error reporting for streaming/inputStream!
- b) parse metadata on the fly in decoders
- c) command for dealing with the changing metadata, currentsonginfo
- or something
- d) in songinfo add a metadata tag item for indicating stream
+ b) in songinfo add a metadata tag item for indicating stream
2) http stuff
a) allow http proxy
diff --git a/src/decode.c b/src/decode.c
index e5c1bfa03..4d04e4c74 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -608,7 +608,7 @@ void decode() {
strncpy(dc->metadata+pos, string, \
DECODE_METADATA_LENGTH-1-pos); \
element = pos; \
- pos += slen; \
+ pos += slen+1; \
} \
}
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index 8f57fb590..d0d98b045 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -196,7 +196,56 @@ int fillMp3InputBuffer(mp3DecodeData * data) {
return 0;
}
-int decodeNextFrameHeader(mp3DecodeData * data) {
+#ifdef HAVE_ID3TAG
+static MpdTag * mp3_parseId3Tag(mp3DecodeData * data, signed long tagsize) {
+ MpdTag * ret = NULL;
+ struct id3_tag * id3Tag = NULL;
+ id3_length_t count;
+ id3_byte_t const *id3_data;
+ id3_byte_t * allocated = NULL;
+
+ count = data->stream.bufend - data->stream.this_frame;
+
+ if(tagsize <= count) {
+ id3_data = data->stream.this_frame;
+ mad_stream_skip(&(data->stream), tagsize);
+ }
+ else {
+ allocated = malloc(tagsize);
+ if(!allocated) goto fail;
+
+ memcpy(allocated, data->stream.this_frame, count);
+ mad_stream_skip(&(data->stream), count);
+
+ while(count < tagsize) {
+ int len;
+
+ len = readFromInputStream(data->inStream,
+ allocated+count, (size_t)1,
+ tagsize-count);
+ if(len <= 0 && inputStreamAtEOF(data->inStream)) {
+ break;
+ }
+ else if(len <= 0) my_usleep(10000);
+ else count += len;
+ }
+
+ if(count != tagsize) goto fail;
+
+ id3_data = allocated;
+ }
+
+ id3Tag = id3_tag_parse(id3_data, tagsize);
+
+ ret = parseId3Tag(id3Tag);
+
+fail:
+ if(allocated) free(allocated);
+ return ret;
+}
+#endif
+
+int decodeNextFrameHeader(mp3DecodeData * data, MpdTag ** tag) {
if((data->stream).buffer==NULL || (data->stream).error==MAD_ERROR_BUFLEN) {
if(fillMp3InputBuffer(data) < 0) {
return DECODE_BREAK;
@@ -211,13 +260,23 @@ int decodeNextFrameHeader(mp3DecodeData * data) {
(data->stream).this_frame,
(data->stream).bufend-
(data->stream).this_frame);
+
+ printf("HERE 1\n");
if(tagsize>0) {
- mad_stream_skip(&(data->stream),tagsize);
+ printf("HERE 1-1\n");
+ if(tag) *tag =mp3_parseId3Tag(data, tagsize);
+ else {
+ mad_stream_skip(&(data->stream),
+ tagsize);
+ }
+ printf("HERE 1-2\n");
return DECODE_CONT;
}
+ printf("HERE 2\n");
}
#endif
if(MAD_RECOVERABLE((data->stream).error)) {
+ if(tag) printf("AHHH\n");
return DECODE_SKIP;
}
else {
@@ -331,7 +390,9 @@ fail:
return 0;
}
-int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc) {
+int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
+ MpdTag ** tag)
+{
struct xing xing;
int ret;
int skip;
@@ -341,7 +402,7 @@ int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc) {
while(1) {
skip = 0;
- while((ret = decodeNextFrameHeader(data))==DECODE_CONT &&
+ while((ret = decodeNextFrameHeader(data, tag))==DECODE_CONT &&
(!dc || !dc->stop));
if(ret==DECODE_SKIP) skip = 1;
else if(ret==DECODE_BREAK || (dc && dc->stop)) return -1;
@@ -409,7 +470,7 @@ int getMp3TotalTime(char * file) {
if(openInputStream(&inStream, file) < 0) return -1;
initMp3DecodeData(&data,&inStream);
data.stream.options |= MAD_OPTION_IGNORECRC;
- if(decodeFirstFrame(&data, NULL)<0) ret = -1;
+ if(decodeFirstFrame(&data, NULL, NULL)<0) ret = -1;
else ret = data.totalTime+0.5;
mp3DecodeDataFinalize(&data);
@@ -417,12 +478,14 @@ int getMp3TotalTime(char * file) {
}
int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data,
- DecoderControl * dc)
+ DecoderControl * dc, MpdTag ** tag)
{
initMp3DecodeData(data, inStream);
data->stream.options |= MAD_OPTION_IGNORECRC;
- if(decodeFirstFrame(data, dc)<0) {
+ *tag = NULL;
+ if(decodeFirstFrame(data, dc, tag)<0) {
mp3DecodeDataFinalize(data);
+ if(tag && *tag) freeMpdTag(*tag);
return -1;
}
@@ -540,7 +603,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
while(1) {
skip = 0;
- while((ret = decodeNextFrameHeader(data))==DECODE_CONT &&
+ while((ret = decodeNextFrameHeader(data, NULL))==DECODE_CONT &&
!dc->stop && !dc->seek);
if(ret==DECODE_BREAK || dc->stop || dc->seek) break;
else if(ret==DECODE_SKIP) skip = 1;
@@ -565,8 +628,9 @@ void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, AudioFormat * af) {
int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) {
mp3DecodeData data;
+ MpdTag * tag;
- if(openMp3FromInputStream(inStream, &data, dc) < 0) {
+ if(openMp3FromInputStream(inStream, &data, dc, &tag) < 0) {
closeInputStream(inStream);
if(!dc->stop) {
ERROR("Input does not appear to be a mp3 bit stream.\n");
@@ -583,6 +647,12 @@ int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) {
getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat));
dc->totalTime = data.totalTime;
+
+ if(tag) {
+ copyMpdTagToDecoderControlMetadata(dc, tag);
+ freeMpdTag(tag);
+ }
+
dc->state = DECODE_STATE_DECODE;
while(mp3Read(&data,cb,dc)!=DECODE_BREAK);
diff --git a/src/tag.c b/src/tag.c
index ae9d41040..50c1dcd86 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -37,13 +37,6 @@
#include <FLAC/file_decoder.h>
#include <FLAC/metadata.h>
#endif
-#ifdef HAVE_ID3TAG
-#ifdef USE_MPD_ID3TAG
-#include "libid3tag/id3tag.h"
-#else
-#include <id3tag.h>
-#endif
-#endif
void printMpdTag(FILE * fp, MpdTag * tag) {
if(tag->artist) myfprintf(fp,"Artist: %s\n",tag->artist);
@@ -95,25 +88,11 @@ char * getID3Info(struct id3_tag * tag, char * id) {
}
#endif
-MpdTag * id3Dup(char * file) {
- MpdTag * ret = NULL;
#ifdef HAVE_ID3TAG
- struct id3_file * id3_file;
- struct id3_tag * tag;
+MpdTag * parseId3Tag(struct id3_tag * tag) {
+ MpdTag * ret = NULL;
char * str;
- id3_file = id3_file_open(file, ID3_FILE_MODE_READONLY);
-
- if(!id3_file) {
- return NULL;
- }
-
- tag = id3_file_tag(id3_file);
- if(!tag) {
- id3_file_close(id3_file);
- return NULL;
- }
-
str = getID3Info(tag,ID3_FRAME_ARTIST);
if(str) {
if(!ret) ret = newMpdTag();
@@ -142,6 +121,30 @@ MpdTag * id3Dup(char * file) {
ret->track = str;
}
+ return ret;
+}
+#endif
+
+MpdTag * id3Dup(char * file) {
+ MpdTag * ret = NULL;
+#ifdef HAVE_ID3TAG
+ struct id3_file * id3_file;
+ struct id3_tag * tag;
+
+ id3_file = id3_file_open(file, ID3_FILE_MODE_READONLY);
+
+ if(!id3_file) {
+ return NULL;
+ }
+
+ tag = id3_file_tag(id3_file);
+ if(!tag) {
+ id3_file_close(id3_file);
+ return NULL;
+ }
+
+ ret = parseId3Tag(tag);
+
id3_file_close(id3_file);
#endif
diff --git a/src/tag.h b/src/tag.h
index 87cac2b97..225b3189e 100644
--- a/src/tag.h
+++ b/src/tag.h
@@ -22,6 +22,13 @@
#include "../config.h"
#include <stdio.h>
+#ifdef HAVE_ID3TAG
+#ifdef USE_MPD_ID3TAG
+#include "libid3tag/id3tag.h"
+#else
+#include <id3tag.h>
+#endif
+#endif
typedef struct _MpdTag {
char * artist;
@@ -31,6 +38,10 @@ typedef struct _MpdTag {
int time;
} MpdTag;
+#ifdef HAVE_ID3TAG
+MpdTag * parseId3Tag(struct id3_tag *);
+#endif
+
MpdTag * id3Dup(char * file);
MpdTag * newMpdTag();