Commit 16da97e4 authored by Warren Dukes's avatar Warren Dukes

parsing mp3 id3v2 tags on the fly for streams

git-svn-id: https://svn.musicpd.org/mpd/trunk@1281 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent 16fcd1ec
1) play streams 1) play streams
a) put some sort of error reporting for streaming/inputStream! a) put some sort of error reporting for streaming/inputStream!
b) parse metadata on the fly in decoders b) in songinfo add a metadata tag item for indicating stream
c) command for dealing with the changing metadata, currentsonginfo
or something
d) in songinfo add a metadata tag item for indicating stream
2) http stuff 2) http stuff
a) allow http proxy a) allow http proxy
......
...@@ -608,7 +608,7 @@ void decode() { ...@@ -608,7 +608,7 @@ void decode() {
strncpy(dc->metadata+pos, string, \ strncpy(dc->metadata+pos, string, \
DECODE_METADATA_LENGTH-1-pos); \ DECODE_METADATA_LENGTH-1-pos); \
element = pos; \ element = pos; \
pos += slen; \ pos += slen+1; \
} \ } \
} }
......
...@@ -196,7 +196,56 @@ int fillMp3InputBuffer(mp3DecodeData * data) { ...@@ -196,7 +196,56 @@ int fillMp3InputBuffer(mp3DecodeData * data) {
return 0; 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((data->stream).buffer==NULL || (data->stream).error==MAD_ERROR_BUFLEN) {
if(fillMp3InputBuffer(data) < 0) { if(fillMp3InputBuffer(data) < 0) {
return DECODE_BREAK; return DECODE_BREAK;
...@@ -211,13 +260,23 @@ int decodeNextFrameHeader(mp3DecodeData * data) { ...@@ -211,13 +260,23 @@ int decodeNextFrameHeader(mp3DecodeData * data) {
(data->stream).this_frame, (data->stream).this_frame,
(data->stream).bufend- (data->stream).bufend-
(data->stream).this_frame); (data->stream).this_frame);
printf("HERE 1\n");
if(tagsize>0) { 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; return DECODE_CONT;
} }
printf("HERE 2\n");
} }
#endif #endif
if(MAD_RECOVERABLE((data->stream).error)) { if(MAD_RECOVERABLE((data->stream).error)) {
if(tag) printf("AHHH\n");
return DECODE_SKIP; return DECODE_SKIP;
} }
else { else {
...@@ -331,7 +390,9 @@ fail: ...@@ -331,7 +390,9 @@ fail:
return 0; return 0;
} }
int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc) { int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
MpdTag ** tag)
{
struct xing xing; struct xing xing;
int ret; int ret;
int skip; int skip;
...@@ -341,7 +402,7 @@ int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc) { ...@@ -341,7 +402,7 @@ int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc) {
while(1) { while(1) {
skip = 0; skip = 0;
while((ret = decodeNextFrameHeader(data))==DECODE_CONT && while((ret = decodeNextFrameHeader(data, tag))==DECODE_CONT &&
(!dc || !dc->stop)); (!dc || !dc->stop));
if(ret==DECODE_SKIP) skip = 1; if(ret==DECODE_SKIP) skip = 1;
else if(ret==DECODE_BREAK || (dc && dc->stop)) return -1; else if(ret==DECODE_BREAK || (dc && dc->stop)) return -1;
...@@ -409,7 +470,7 @@ int getMp3TotalTime(char * file) { ...@@ -409,7 +470,7 @@ int getMp3TotalTime(char * file) {
if(openInputStream(&inStream, file) < 0) return -1; if(openInputStream(&inStream, file) < 0) return -1;
initMp3DecodeData(&data,&inStream); initMp3DecodeData(&data,&inStream);
data.stream.options |= MAD_OPTION_IGNORECRC; 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; else ret = data.totalTime+0.5;
mp3DecodeDataFinalize(&data); mp3DecodeDataFinalize(&data);
...@@ -417,12 +478,14 @@ int getMp3TotalTime(char * file) { ...@@ -417,12 +478,14 @@ int getMp3TotalTime(char * file) {
} }
int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data, int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data,
DecoderControl * dc) DecoderControl * dc, MpdTag ** tag)
{ {
initMp3DecodeData(data, inStream); initMp3DecodeData(data, inStream);
data->stream.options |= MAD_OPTION_IGNORECRC; data->stream.options |= MAD_OPTION_IGNORECRC;
if(decodeFirstFrame(data, dc)<0) { *tag = NULL;
if(decodeFirstFrame(data, dc, tag)<0) {
mp3DecodeDataFinalize(data); mp3DecodeDataFinalize(data);
if(tag && *tag) freeMpdTag(*tag);
return -1; return -1;
} }
...@@ -540,7 +603,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) { ...@@ -540,7 +603,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
while(1) { while(1) {
skip = 0; skip = 0;
while((ret = decodeNextFrameHeader(data))==DECODE_CONT && while((ret = decodeNextFrameHeader(data, NULL))==DECODE_CONT &&
!dc->stop && !dc->seek); !dc->stop && !dc->seek);
if(ret==DECODE_BREAK || dc->stop || dc->seek) break; if(ret==DECODE_BREAK || dc->stop || dc->seek) break;
else if(ret==DECODE_SKIP) skip = 1; else if(ret==DECODE_SKIP) skip = 1;
...@@ -565,8 +628,9 @@ void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, AudioFormat * af) { ...@@ -565,8 +628,9 @@ void initAudioFormatFromMp3DecodeData(mp3DecodeData * data, AudioFormat * af) {
int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) { int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) {
mp3DecodeData data; mp3DecodeData data;
MpdTag * tag;
if(openMp3FromInputStream(inStream, &data, dc) < 0) { if(openMp3FromInputStream(inStream, &data, dc, &tag) < 0) {
closeInputStream(inStream); closeInputStream(inStream);
if(!dc->stop) { if(!dc->stop) {
ERROR("Input does not appear to be a mp3 bit stream.\n"); 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) { ...@@ -583,6 +647,12 @@ int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) {
getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat)); getOutputAudioFormat(&(dc->audioFormat), &(cb->audioFormat));
dc->totalTime = data.totalTime; dc->totalTime = data.totalTime;
if(tag) {
copyMpdTagToDecoderControlMetadata(dc, tag);
freeMpdTag(tag);
}
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
while(mp3Read(&data,cb,dc)!=DECODE_BREAK); while(mp3Read(&data,cb,dc)!=DECODE_BREAK);
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
#include <FLAC/file_decoder.h> #include <FLAC/file_decoder.h>
#include <FLAC/metadata.h> #include <FLAC/metadata.h>
#endif #endif
#ifdef HAVE_ID3TAG
#ifdef USE_MPD_ID3TAG
#include "libid3tag/id3tag.h"
#else
#include <id3tag.h>
#endif
#endif
void printMpdTag(FILE * fp, MpdTag * tag) { void printMpdTag(FILE * fp, MpdTag * tag) {
if(tag->artist) myfprintf(fp,"Artist: %s\n",tag->artist); if(tag->artist) myfprintf(fp,"Artist: %s\n",tag->artist);
...@@ -95,25 +88,11 @@ char * getID3Info(struct id3_tag * tag, char * id) { ...@@ -95,25 +88,11 @@ char * getID3Info(struct id3_tag * tag, char * id) {
} }
#endif #endif
MpdTag * id3Dup(char * file) {
MpdTag * ret = NULL;
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
struct id3_file * id3_file; MpdTag * parseId3Tag(struct id3_tag * tag) {
struct id3_tag * tag; MpdTag * ret = NULL;
char * str; 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); str = getID3Info(tag,ID3_FRAME_ARTIST);
if(str) { if(str) {
if(!ret) ret = newMpdTag(); if(!ret) ret = newMpdTag();
...@@ -142,6 +121,30 @@ MpdTag * id3Dup(char * file) { ...@@ -142,6 +121,30 @@ MpdTag * id3Dup(char * file) {
ret->track = str; 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); id3_file_close(id3_file);
#endif #endif
......
...@@ -22,6 +22,13 @@ ...@@ -22,6 +22,13 @@
#include "../config.h" #include "../config.h"
#include <stdio.h> #include <stdio.h>
#ifdef HAVE_ID3TAG
#ifdef USE_MPD_ID3TAG
#include "libid3tag/id3tag.h"
#else
#include <id3tag.h>
#endif
#endif
typedef struct _MpdTag { typedef struct _MpdTag {
char * artist; char * artist;
...@@ -31,6 +38,10 @@ typedef struct _MpdTag { ...@@ -31,6 +38,10 @@ typedef struct _MpdTag {
int time; int time;
} MpdTag; } MpdTag;
#ifdef HAVE_ID3TAG
MpdTag * parseId3Tag(struct id3_tag *);
#endif
MpdTag * id3Dup(char * file); MpdTag * id3Dup(char * file);
MpdTag * newMpdTag(); MpdTag * newMpdTag();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment