From 4e53282469de4fea4b8daaec67298bd3394f34bd Mon Sep 17 00:00:00 2001 From: Warren Dukes Date: Sun, 6 Jun 2004 16:42:14 +0000 Subject: todo update git-svn-id: https://svn.musicpd.org/mpd/trunk@1352 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- TODO | 23 +++++--- src/decode.c | 122 +++++++++++++++++++++++++----------------- src/decode.h | 9 +--- src/inputPlugins/mp3_plugin.c | 6 ++- src/inputPlugins/ogg_plugin.c | 23 +++++--- src/outputBuffer.c | 31 ++++++++++- src/outputBuffer.h | 11 +++- src/pcm_utils.c | 2 - src/player.c | 9 ++-- src/player.h | 1 + src/playerData.c | 10 ++-- src/song.c | 5 ++ src/tag.c | 6 +++ src/tag.h | 1 + 14 files changed, 175 insertions(+), 84 deletions(-) diff --git a/TODO b/TODO index 0ea67b84d..387dce3a2 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,20 @@ -1) Parse icymetadata - -2) Put a new metadata entry for icyName for Song's - -3) handle changes in audioFormat in a single stream/file, - esp need for vorbis streams +1) Construct a small metadata buffer + a) MetadataChunk struct + 1) functions for converting between block and MpdTag + 2) char * buffer + 3) positions ints for name, title, artist, album + b) MetadataChunk buffer in OutputBuffer + 1) deal with incrementing and finding a free buffer Chunk + the decoder element + 2) corresponding metachunk # for each audio chunk + c) player proccess + 1) if not metachunk be sure to clear the current metadata + in playerControl + 2) if it is, if WRITE, then write do pc->metadataChunk + +2) Parse icymetadata + +3) Put a new metadata entry for icyName for Song's 4) put some sort of error reporting for streaming/inputStream! diff --git a/src/decode.c b/src/decode.c index decc313ae..99a4bd784 100644 --- a/src/decode.c +++ b/src/decode.c @@ -112,17 +112,6 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) { quitDecode(pc,dc); \ return; \ } \ - if(pc->metadataState == PLAYER_METADATA_STATE_WRITE && \ - dc->metadataSet) \ - { \ - memcpy(pc->metadata, dc->metadata, \ - DECODE_METADATA_LENGTH); \ - pc->metadata[DECODE_METADATA_LENGTH-1] = '\0'; \ - pc->title = dc->title; \ - pc->artist = dc->artist; \ - pc->album = dc->album; \ - } \ - pc->metadataState = PLAYER_METADATA_STATE_READ; \ pc->totalTime = dc->totalTime; \ pc->sampleRate = dc->audioFormat.sampleRate; \ pc->bits = dc->audioFormat.bits; \ @@ -271,11 +260,12 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { return; } - dc->metadataSet = 0; - memset(dc->metadata, 0, DECODE_METADATA_LENGTH); - dc->title = -1; - dc->album = -1; - dc->artist = -1; + cb->metadataSet = 0; + memset(cb->metadata, 0, DECODE_METADATA_LENGTH); + cb->name = -1; + cb->title = -1; + cb->album = -1; + cb->artist = -1; strncpy(dc->utf8url, pc->utf8url, MAXPATHLEN); dc->utf8url[MAXPATHLEN] = '\0'; @@ -302,15 +292,17 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { return; } - if(inStream.metaTitle) { - strncpy(dc->metadata, inStream.metaTitle, + /*if(inStream.metaTitle) { + strncpy(cb->metadata, inStream.metaTitle, DECODE_METADATA_LENGTH-1); - dc->title = 0; - dc->metadataSet = 1; - } + cb->name = 0; + cb->metaChunk = cb->end; + cb->metadataSet = 1; + }*/ ret = DECODE_ERROR_UNKTYPE; if(isRemoteUrl(dc->utf8url)) { + cb->acceptMetadata = 1; plugin = getInputPluginFromMimeType(inStream.mime); if(plugin == NULL) { plugin = getInputPluginFromSuffix( @@ -328,6 +320,7 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { } } else { + cb->acceptMetadata = 0; plugin = getInputPluginFromSuffix(getSuffix(dc->utf8url)); if(plugin && (plugin->streamTypes && INPUT_PLUGIN_STREAM_FILE)) { @@ -399,6 +392,55 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { return 0; } +#define copyMetadata() { \ + memcpy(pc->metadata, metadata, DECODE_METADATA_LENGTH); \ + pc->name = name; \ + pc->title = title; \ + pc->artist = artist; \ + pc->album = album; \ + gotMetadata = 0; \ + pc->metadataState = PLAYER_METADATA_STATE_READ; \ + kill(getppid(), SIGUSR1); \ +} + +/* do some fancier shit here, like put metadata in a linked list metadata +buffer, and assign it to current and whether current is written */ +#define handleMetadata() { \ + if(cb->metadataSet) {\ + gotMetadata = 1;\ + memcpy(metadata, cb->metadata, DECODE_METADATA_LENGTH); \ + artist = cb->artist; \ + name = cb->name; \ + title = cb->title; \ + album = cb->album; \ + metaChunk = cb->metaChunk; \ + cb->metadataSet = 0; \ + } \ + if(gotMetadata) { \ + int end = cb->end; \ + if(end > cb->begin && (metaChunk < cb->begin || \ + metaChunk > end)) \ + { \ + gotMetadata = 0; \ + } \ + else if(cb->begin > end && (metaChunk > cb->begin && \ + metaChunk < end)) \ + { \ + gotMetadata = 0; \ + } \ + else if(pc->metadataState == PLAYER_METADATA_STATE_WRITE) { \ + if(end > metaChunk && metaChunk <= cb->begin ) { \ + copyMetadata(); \ + } \ + else if(metaChunk >= end && (cb->begin >= metaChunk || \ + cb->begin < end)) \ + { \ + copyMetadata(); \ + } \ + } \ + } \ +} + void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { int pause = 0; int quit = 0; @@ -411,6 +453,13 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { int decodeWaitedOn = 0; char silence[CHUNK_SIZE]; double sizeToTime = 0.0; + char metadata[DECODE_METADATA_LENGTH]; + mpd_sint16 name = -1; + mpd_sint16 title = -1; + mpd_sint16 artist = -1; + mpd_sint16 album = -1; + mpd_sint16 metaChunk = -1; + int gotMetadata = 0; memset(silence,0,CHUNK_SIZE); @@ -424,12 +473,14 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { dc->state!=DECODE_STATE_STOP) { processDecodeInput(); + handleMetadata(); if(quit) return; my_usleep(10000); } while(!quit) { processDecodeInput(); + handleMetadata(); handleDecodeStart(); if(dc->state==DECODE_STATE_STOP && pc->queueState==PLAYER_QUEUE_FULL && @@ -592,6 +643,7 @@ void decode() { cb->begin = 0; cb->end = 0; cb->wrap = 0; + cb->metadataSet = 0; pc = &(getPlayerData()->playerControl); dc = &(getPlayerData()->decoderControl); dc->error = 0; @@ -606,31 +658,3 @@ void decode() { decodeParent(pc, dc, cb); } - -/* this is stuff for inputPlugins to use! */ -#define copyStringToMetadata(string, element) { \ - if(string && (slen = strlen(string)) && \ - pos < DECODE_METADATA_LENGTH-1) \ - { \ - strncpy(dc->metadata+pos, string, \ - DECODE_METADATA_LENGTH-1-pos); \ - element = pos; \ - pos += slen+1; \ - } \ -} - -void copyMpdTagToDecoderControlMetadata(DecoderControl * dc, MpdTag * tag) { - int pos = 0; - int slen; - - if(dc->metadataSet) return; - if(!tag) return; - - memset(dc->metadata, 0, DECODE_METADATA_LENGTH); - - copyStringToMetadata(tag->title, dc->title); - copyStringToMetadata(tag->artist, dc->artist); - copyStringToMetadata(tag->album, dc->album); - - dc->metadataSet = 1; -} diff --git a/src/decode.h b/src/decode.h index a0c4332ba..4c2043b53 100644 --- a/src/decode.h +++ b/src/decode.h @@ -46,7 +46,7 @@ #define DECODE_SUFFIX_MP4 5 #define DECODE_SUFFIX_WAVE 6 -#define DECODE_METADATA_LENGTH 4096 +#define DECODE_METADATA_LENGTH 8192 typedef struct _DecoderControl { volatile mpd_sint8 state; @@ -61,18 +61,11 @@ typedef struct _DecoderControl { AudioFormat audioFormat; char utf8url[MAXPATHLEN+1]; volatile float totalTime; - volatile mpd_sint8 metadataSet; - char metadata[DECODE_METADATA_LENGTH]; - volatile mpd_sint16 title; - volatile mpd_sint16 artist; - volatile mpd_sint16 album; } DecoderControl; void decodeSigHandler(int sig); void decode(); -void copyMpdTagToDecoderControlMetadata(DecoderControl * dc, MpdTag * tag); - #endif /* vim:set shiftwidth=4 tabstop=8 expandtab: */ diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c index a73276c74..f2ad57500 100644 --- a/src/inputPlugins/mp3_plugin.c +++ b/src/inputPlugins/mp3_plugin.c @@ -644,7 +644,11 @@ int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) { dc->totalTime = data.totalTime; if(tag) { - copyMpdTagToDecoderControlMetadata(dc, tag); + if(inStream->metaTitle) { + if(tag->name) free(tag->name); + tag->name = strdup(inStream->metaTitle); + } + copyMpdTagToOutputBuffer(cb, tag); freeMpdTag(tag); } diff --git a/src/inputPlugins/ogg_plugin.c b/src/inputPlugins/ogg_plugin.c index 9a27ad712..a79c0d876 100644 --- a/src/inputPlugins/ogg_plugin.c +++ b/src/inputPlugins/ogg_plugin.c @@ -200,21 +200,26 @@ MpdTag * oggCommentsParse(char ** comments) { return ret; } -void putOggCommentsIntoDecoderControlMetadata(DecoderControl * dc, - char ** comments) +void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName, + char ** comments) { MpdTag * tag; tag = oggCommentsParse(comments); if(!tag) return; - copyMpdTagToDecoderControlMetadata(dc, tag); - /*if(tag->artist) printf("Artist: %s\n", tag->artist); if(tag->album) printf("Album: %s\n", tag->album); if(tag->track) printf("Track: %s\n", tag->track); if(tag->title) printf("Title: %s\n", tag->title);*/ + if(streamName) { + if(tag->name) free(tag->name); + tag->name = strdup(streamName); + } + + copyMpdTagToOutputBuffer(cb, tag); + freeMpdTag(tag); } @@ -280,10 +285,14 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) vorbis_info *vi=ov_info(&vf,-1); dc->audioFormat.channels = vi->channels; dc->audioFormat.sampleRate = vi->rate; - getOutputAudioFormat(&(dc->audioFormat),&(cb->audioFormat)); + if(dc->state == DECODE_STATE_START) { + getOutputAudioFormat(&(dc->audioFormat), + &(cb->audioFormat)); + dc->state = DECODE_STATE_DECODE; + } comments = ov_comment(&vf, -1)->user_comments; - putOggCommentsIntoDecoderControlMetadata(dc, comments); - dc->state = DECODE_STATE_DECODE; + putOggCommentsIntoOutputBuffer(cb, inStream->metaTitle, + comments); replayGainScale = ogg_getReplayGainScale(comments); } diff --git a/src/outputBuffer.c b/src/outputBuffer.c index 41932faa5..194e3af8a 100644 --- a/src/outputBuffer.c +++ b/src/outputBuffer.c @@ -117,4 +117,33 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, return 0; } -/* vim:set shiftwidth=4 tabstop=8 expandtab: */ + +/* this is stuff for inputPlugins to use! */ +#define copyStringToMetadata(string, element) { \ + if(string && (slen = strlen(string)) && \ + pos < DECODE_METADATA_LENGTH-1) \ + { \ + strncpy(cb->metadata+pos, string, \ + DECODE_METADATA_LENGTH-1-pos); \ + element = pos; \ + pos += slen+1; \ + } \ +} + +void copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag) { + int pos = 0; + int slen; + + if(!cb->acceptMetadata) return; + if(!tag) return; + + memset(cb->metadata, 0, DECODE_METADATA_LENGTH); + + copyStringToMetadata(tag->name, cb->name); + copyStringToMetadata(tag->artist, cb->artist); + copyStringToMetadata(tag->title, cb->title); + copyStringToMetadata(tag->album, cb->album); + + cb->metaChunk = cb->end; + cb->metadataSet = 1; +} diff --git a/src/outputBuffer.h b/src/outputBuffer.h index 90cc6906b..71136b363 100644 --- a/src/outputBuffer.h +++ b/src/outputBuffer.h @@ -37,6 +37,14 @@ typedef struct _OutputBuffer { mpd_sint16 volatile next; mpd_sint8 volatile wrap; AudioFormat audioFormat; + volatile mpd_sint8 metadataSet; + char metadata[DECODE_METADATA_LENGTH]; + volatile mpd_sint16 title; + volatile mpd_sint16 artist; + volatile mpd_sint16 album; + volatile mpd_sint16 name; + volatile mpd_uint16 metaChunk; + volatile mpd_sint8 acceptMetadata; } OutputBuffer; void clearOutputBuffer(OutputBuffer * cb); @@ -49,5 +57,6 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream, DecoderControl * dc, int seekable, char * data, long datalen, float time, mpd_uint16 bitRate); +void copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag); + #endif -/* vim:set shiftwidth=4 tabstop=8 expandtab: */ diff --git a/src/pcm_utils.c b/src/pcm_utils.c index e0ebf2ecb..e9beeeead 100644 --- a/src/pcm_utils.c +++ b/src/pcm_utils.c @@ -281,5 +281,3 @@ size_t pcm_sizeOfOutputBufferForAudioFormatConversion(AudioFormat * inFormat, return outSize; } - -/* vim:set shiftwidth=8 tabstop=8 expandtab: */ diff --git a/src/player.c b/src/player.c index cda88fff4..587a5501d 100644 --- a/src/player.c +++ b/src/player.c @@ -474,10 +474,12 @@ void playerCycleLogFiles() { /* this actually creates a dupe of the current metadata */ Song * playerCurrentDecodeSong() { static Song * song = NULL; + static char * prev = NULL; PlayerControl * pc = &(getPlayerData()->playerControl); if(pc->metadataState == PLAYER_METADATA_STATE_READ && - (!song || strcmp(song->utf8url, pc->currentUrl))) + ((!song || strcmp(song->utf8url, pc->currentUrl)) + || (!prev || strcmp(prev,pc->metadata)))) { if(song) freeJustSong(song); song = newNullSong(); @@ -486,6 +488,7 @@ Song * playerCurrentDecodeSong() { song->utf8url = strdup(pc->currentUrl); if(pc->title >= 0) { song->tag->title = strdup(pc->title + pc->metadata); + /*printf("player title: %s\n", song->tag->title);*/ } if(pc->artist >= 0) { song->tag->artist = strdup(pc->artist + pc->metadata); @@ -494,11 +497,11 @@ Song * playerCurrentDecodeSong() { song->tag->album = strdup(pc->album + pc->metadata); } validateUtf8Tag(song->tag); + if(prev) free(prev); + prev = strdup(pc->metadata); resetPlayerMetadata(); return song; } return NULL; } - -/* vim:set shiftwidth=4 tabstop=8 expandtab: */ diff --git a/src/player.h b/src/player.h index 11f408fdc..5e8d90e97 100644 --- a/src/player.h +++ b/src/player.h @@ -85,6 +85,7 @@ typedef struct _PlayerControl { volatile mpd_sint8 cycleLogFiles; volatile mpd_sint8 metadataState; char metadata[DECODE_METADATA_LENGTH]; + volatile mpd_sint16 name; volatile mpd_sint16 title; volatile mpd_sint16 artist; volatile mpd_sint16 album; diff --git a/src/playerData.c b/src/playerData.c index 2dbdace0d..4950a2c7e 100644 --- a/src/playerData.c +++ b/src/playerData.c @@ -117,6 +117,7 @@ void initPlayerData() { playerData_pd->playerControl.softwareVolume = 1000; playerData_pd->playerControl.totalPlayTime = 0; playerData_pd->playerControl.decode_pid = 0; + playerData_pd->playerControl.name = -1; playerData_pd->playerControl.title = -1; playerData_pd->playerControl.artist = -1; playerData_pd->playerControl.album = -1; @@ -129,12 +130,9 @@ void initPlayerData() { playerData_pd->decoderControl.seek = 0; playerData_pd->decoderControl.error = DECODE_ERROR_NOERROR; memset(playerData_pd->decoderControl.utf8url, 0, MAXPATHLEN+1); - memset(playerData_pd->decoderControl.metadata, 0, - DECODE_METADATA_LENGTH); - playerData_pd->decoderControl.title = -1; - playerData_pd->decoderControl.artist = -1; - playerData_pd->decoderControl.album = -1; - playerData_pd->decoderControl.metadataSet = 0; + + memset(playerData_pd->buffer.metadata, 0, DECODE_METADATA_LENGTH); + playerData_pd->buffer.metadataSet = 0; } PlayerData * getPlayerData() { diff --git a/src/song.c b/src/song.c index ed88f1f60..41e3d4b66 100644 --- a/src/song.c +++ b/src/song.c @@ -34,6 +34,7 @@ #define SONG_ALBUM "Album: " #define SONG_TRACK "Track: " #define SONG_TITLE "Title: " +#define SONG_NAME "Name: " #define SONG_TIME "Time: " #define SONG_MTIME "mtime: " @@ -235,6 +236,10 @@ void readSongInfoIntoList(FILE * fp, SongList * list) { if(!song->tag) song->tag = newMpdTag(); song->tag->title = strdup(&(buffer[strlen(SONG_TITLE)])); } + else if(0==strncmp(SONG_NAME,buffer,strlen(SONG_NAME))) { + if(!song->tag) song->tag = newMpdTag(); + song->tag->name = strdup(&(buffer[strlen(SONG_NAME)])); + } else if(0==strncmp(SONG_TIME,buffer,strlen(SONG_TIME))) { if(!song->tag) song->tag = newMpdTag(); song->tag->time = atoi(&(buffer[strlen(SONG_TIME)])); diff --git a/src/tag.c b/src/tag.c index c6bd1ffa8..729ccb0f6 100644 --- a/src/tag.c +++ b/src/tag.c @@ -43,6 +43,7 @@ void printMpdTag(FILE * fp, MpdTag * tag) { if(tag->album) myfprintf(fp,"Album: %s\n",tag->album); if(tag->track) myfprintf(fp,"Track: %s\n",tag->track); if(tag->title) myfprintf(fp,"Title: %s\n",tag->title); + if(tag->name) myfprintf(fp,"Name: %s\n",tag->name); if(tag->time>=0) myfprintf(fp,"Time: %i\n",tag->time); } @@ -62,6 +63,7 @@ void validateUtf8Tag(MpdTag * tag) { fixUtf8(tag->album); fixUtf8(tag->track); fixUtf8(tag->title); + fixUtf8(tag->name); } #ifdef HAVE_ID3TAG @@ -158,6 +160,7 @@ MpdTag * newMpdTag() { ret->artist = NULL; ret->title = NULL; ret->track = NULL; + ret->name = NULL; ret->time = -1; return ret; } @@ -166,6 +169,7 @@ void clearMpdTag(MpdTag * tag) { if(tag->artist) free(tag->artist); if(tag->album) free(tag->album); if(tag->title) free(tag->title); + if(tag->name) free(tag->title); if(tag->track) free(tag->track); } @@ -183,6 +187,7 @@ MpdTag * mpdTagDup(MpdTag * tag) { if(tag->album) ret->album = strdup(tag->album); if(tag->title) ret->title = strdup(tag->title); if(tag->track) ret->track = strdup(tag->track); + if(tag->name) ret->name = strdup(tag->name); ret->time = tag->time; } @@ -208,6 +213,7 @@ int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) { if(!mpdTagStringsAreEqual(tag1->album, tag2->album)) return 0; if(!mpdTagStringsAreEqual(tag1->track, tag2->track)) return 0; if(!mpdTagStringsAreEqual(tag1->title, tag2->title)) return 0; + if(!mpdTagStringsAreEqual(tag1->name, tag2->name)) return 0; return 1; } diff --git a/src/tag.h b/src/tag.h index 225b3189e..841791ae0 100644 --- a/src/tag.h +++ b/src/tag.h @@ -35,6 +35,7 @@ typedef struct _MpdTag { char * album; char * track; char * title; + char * name; int time; } MpdTag; -- cgit v1.2.3