aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarren Dukes <warren.dukes@gmail.com>2004-06-06 19:41:03 +0000
committerWarren Dukes <warren.dukes@gmail.com>2004-06-06 19:41:03 +0000
commitb29f73c819ff8445b71963d883364e315b7a12d8 (patch)
tree772690e7472972ea3e78bb7b354ff4b903a8e4f3
parent4e53282469de4fea4b8daaec67298bd3394f34bd (diff)
downloadmpd-b29f73c819ff8445b71963d883364e315b7a12d8.tar.gz
mpd-b29f73c819ff8445b71963d883364e315b7a12d8.tar.xz
mpd-b29f73c819ff8445b71963d883364e315b7a12d8.zip
mechanism for updating metadata while decoding
vorbis comments are updated on the fly for streams need to decode icy metadata buffering of metadata needs to be hardened, to ensure that player has already read a particular metachunk or passed over it git-svn-id: https://svn.musicpd.org/mpd/trunk@1358 09075e82-0dd4-0310-85a5-a0d7c8717e4f
-rw-r--r--src/Makefile.am4
-rw-r--r--src/decode.c88
-rw-r--r--src/decode.h2
-rw-r--r--src/metadataChunk.c46
-rw-r--r--src/metadataChunk.h22
-rw-r--r--src/outputBuffer.c48
-rw-r--r--src/outputBuffer.h12
-rw-r--r--src/player.c26
-rw-r--r--src/player.h7
-rw-r--r--src/playerData.c15
-rw-r--r--src/playlist.c4
-rw-r--r--src/tag.c2
-rw-r--r--src/tag.h1
13 files changed, 143 insertions, 134 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index de55f202a..e602248c1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,7 @@ mpd_headers = buffer2array.h interface.h command.h playlist.h ls.h \
charConv.h permission.h mpd_types.h pcm_utils.h \
signal_check.h utf8.h inputStream.h \
outputBuffer.h replayGain.h inputStream_file.h inputStream_http.h \
- inputPlugin.h
+ inputPlugin.h metadataChunk.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 \
tag.c player.c listen.c conf.c volume.c \
@@ -21,7 +21,7 @@ mpd_SOURCES = main.c buffer2array.c interface.c command.c playlist.c ls.c \
charConv.c permission.c pcm_utils.c \
signal_check.c utf8.c inputStream.c outputBuffer.c \
replayGain.c inputStream_file.c inputStream_http.c inputPlugin.c \
- $(mpd_headers) $(mpd_inputPlugins)
+ metadataChunk.c $(mpd_headers) $(mpd_inputPlugins)
mpd_CFLAGS = $(MPD_CFLAGS)
mpd_LDADD = $(MPD_LIBS) $(ID3_LIB) $(MAD_LIB) $(MP4FF_LIB)
diff --git a/src/decode.c b/src/decode.c
index 99a4bd784..8053f44fa 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -260,12 +260,7 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return;
}
- cb->metadataSet = 0;
- memset(cb->metadata, 0, DECODE_METADATA_LENGTH);
- cb->name = -1;
- cb->title = -1;
- cb->album = -1;
- cb->artist = -1;
+ copyMpdTagToOutputBuffer(cb, NULL);
strncpy(dc->utf8url, pc->utf8url, MAXPATHLEN);
dc->utf8url[MAXPATHLEN] = '\0';
@@ -292,13 +287,14 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return;
}
- /*if(inStream.metaTitle) {
- strncpy(cb->metadata, inStream.metaTitle,
- DECODE_METADATA_LENGTH-1);
- cb->name = 0;
- cb->metaChunk = cb->end;
- cb->metadataSet = 1;
- }*/
+ if(inStream.metaTitle) {
+ MpdTag * tag = newMpdTag();
+ tag->name = strdup(inStream.metaTitle);
+ copyMpdTagToOutputBuffer(cb, tag);
+ freeMpdTag(tag);
+ }
+
+ /* reset Metadata in OutputBuffer */
ret = DECODE_ERROR_UNKTYPE;
if(isRemoteUrl(dc->utf8url)) {
@@ -403,42 +399,25 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
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 handleMetadata(OutputBuffer * cb, PlayerControl * pc) {
+ static int previous = -1;
+
+ if(cb->begin!=cb->end || cb->wrap) {
+ int meta = cb->metaChunk[cb->begin];
+ if( meta != previous ) {
+ if( meta >= 0 && pc->metadataState ==
+ PLAYER_METADATA_STATE_WRITE)
+ {
+ printf("METADATA!, copying it.\n");
+ memcpy(&(pc->metadataChunk),
+ cb->metadataChunks+meta,
+ sizeof(MetadataChunk));
+ pc->metadataState =
+ PLAYER_METADATA_STATE_READ;
+ previous = meta;
+ }
+ }
+ }
}
void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
@@ -453,13 +432,6 @@ 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);
@@ -473,15 +445,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();
+ handleMetadata(cb, pc);
if(dc->state==DECODE_STATE_STOP &&
pc->queueState==PLAYER_QUEUE_FULL &&
pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
@@ -643,7 +614,6 @@ void decode() {
cb->begin = 0;
cb->end = 0;
cb->wrap = 0;
- cb->metadataSet = 0;
pc = &(getPlayerData()->playerControl);
dc = &(getPlayerData()->decoderControl);
dc->error = 0;
diff --git a/src/decode.h b/src/decode.h
index 4c2043b53..874e82303 100644
--- a/src/decode.h
+++ b/src/decode.h
@@ -46,8 +46,6 @@
#define DECODE_SUFFIX_MP4 5
#define DECODE_SUFFIX_WAVE 6
-#define DECODE_METADATA_LENGTH 8192
-
typedef struct _DecoderControl {
volatile mpd_sint8 state;
volatile mpd_sint8 stop;
diff --git a/src/metadataChunk.c b/src/metadataChunk.c
new file mode 100644
index 000000000..1deab3d90
--- /dev/null
+++ b/src/metadataChunk.c
@@ -0,0 +1,46 @@
+#include "metadataChunk.h"
+
+#include <string.h>
+
+void initMetadataChunk(MetadataChunk * chunk) {
+ memset(chunk, 0, sizeof(MetadataChunk));
+
+ chunk->name = -1;
+ chunk->artist = -1;
+ chunk->album = -1;
+ chunk->title = -1;
+}
+
+MpdTag * metadataChunkToMpdTagDup(MetadataChunk * chunk) {
+ MpdTag * ret = newMpdTag();
+
+ if(chunk->name >= 0) ret->name = strdup(chunk->buffer+chunk->name);
+ if(chunk->artist >= 0) ret->artist = strdup(chunk->buffer+chunk->artist);
+ if(chunk->album >= 0) ret->album = strdup(chunk->buffer+chunk->album);
+ if(chunk->title >= 0) ret->title = strdup(chunk->buffer+chunk->title);
+
+ return ret;
+}
+
+#define copyStringToChunk(string, element) { \
+ if(string && (slen = strlen(string)) && \
+ pos < METADATA_BUFFER_LENGTH-1) \
+ { \
+ strncpy(chunk->buffer+pos, string, \
+ METADATA_BUFFER_LENGTH-1-pos); \
+ element = pos; \
+ pos += slen+1; \
+ } \
+}
+
+void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk) {
+ int pos = 0;
+ int slen;
+
+ initMetadataChunk(chunk);
+
+ copyStringToChunk(tag->name, chunk->name);
+ copyStringToChunk(tag->title, chunk->title);
+ copyStringToChunk(tag->artist, chunk->artist);
+ copyStringToChunk(tag->album, chunk->album);
+}
diff --git a/src/metadataChunk.h b/src/metadataChunk.h
new file mode 100644
index 000000000..05e1c907e
--- /dev/null
+++ b/src/metadataChunk.h
@@ -0,0 +1,22 @@
+#ifndef METADATA_CHUNK_H
+#define METADATA_CHUNK_H
+
+#define METADATA_BUFFER_LENGTH 1024
+
+#include "tag.h"
+
+typedef struct _MetadataChunk {
+ int name;
+ int title;
+ int artist;
+ int album;
+ char buffer[METADATA_BUFFER_LENGTH];
+} MetadataChunk;
+
+void initMetadataChunk(MetadataChunk *);
+
+MpdTag * metadataChunkToMpdTagDup(MetadataChunk * chunk);
+
+void copyMpdTagToMetadataChunk(MpdTag * tag, MetadataChunk * chunk);
+
+#endif
diff --git a/src/outputBuffer.c b/src/outputBuffer.c
index 194e3af8a..d0a98b692 100644
--- a/src/outputBuffer.c
+++ b/src/outputBuffer.c
@@ -26,6 +26,9 @@
static mpd_sint16 currentChunk = -1;
+static mpd_sint8 currentMetaChunk = -1;
+static mpd_sint8 sendMetaChunk = 0;
+
void clearOutputBuffer(OutputBuffer * cb) {
currentChunk = -1;
cb->end = cb->begin;
@@ -95,6 +98,13 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
currentChunk = cb->end;
cb->chunkSize[currentChunk] = 0;
+
+ if(sendMetaChunk) {
+ cb->metaChunk[currentChunk] = currentMetaChunk;
+ }
+ else cb->metaChunk[currentChunk] = -1;
+ cb->bitRate[currentChunk] = bitRate;
+ cb->times[currentChunk] = time;
}
chunkLeft = CHUNK_SIZE-cb->chunkSize[currentChunk];
@@ -104,9 +114,6 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
cb->chunkSize[currentChunk],
data, dataToSend);
cb->chunkSize[currentChunk]+= dataToSend;
- cb->bitRate[currentChunk] = bitRate;
- cb->times[currentChunk] = time;
-
datalen-= dataToSend;
data+= dataToSend;
@@ -118,32 +125,19 @@ int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
return 0;
}
-/* 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;
+ printf("copyMpdTagToOB called\n");
+
+ if(!cb->acceptMetadata || !tag) {
+ sendMetaChunk = 0;
+ return;
+ }
- if(!cb->acceptMetadata) return;
- if(!tag) return;
+ sendMetaChunk = 1;
+ currentMetaChunk++;
+ if(currentMetaChunk >= BUFFERED_METACHUNKS) currentMetaChunk = 0;
- 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);
+ printMpdTag(stdout, tag);
- cb->metaChunk = cb->end;
- cb->metadataSet = 1;
+ copyMpdTagToMetadataChunk(tag, &(cb->metadataChunks[currentMetaChunk]));
}
diff --git a/src/outputBuffer.h b/src/outputBuffer.h
index 71136b363..a7e5bb171 100644
--- a/src/outputBuffer.h
+++ b/src/outputBuffer.h
@@ -23,10 +23,13 @@
#include "decode.h"
#include "audio.h"
#include "inputStream.h"
+#include "metadataChunk.h"
#define OUTPUT_BUFFER_DC_STOP -1
#define OUTPUT_BUFFER_DC_SEEK -2
+#define BUFFERED_METACHUNKS 25
+
typedef struct _OutputBuffer {
char * volatile chunks;
mpd_uint16 * volatile chunkSize;
@@ -37,13 +40,8 @@ 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;
+ MetadataChunk metadataChunks[BUFFERED_METACHUNKS];
+ mpd_sint8 * volatile metaChunk;
volatile mpd_sint8 acceptMetadata;
} OutputBuffer;
diff --git a/src/player.c b/src/player.c
index 587a5501d..e6da9aeb9 100644
--- a/src/player.c
+++ b/src/player.c
@@ -55,9 +55,6 @@ static void resetPlayerMetadata() {
if(pc->metadataState == PLAYER_METADATA_STATE_READ) {
pc->metadataState = PLAYER_METADATA_STATE_WRITE;
- pc->title = -1;
- pc->artist = -1;
- pc->album = -1;
}
}
@@ -75,8 +72,6 @@ void resetPlayer() {
getPlayerData()->playerControl.seek = 0;
getPlayerData()->playerControl.metadataState =
PLAYER_METADATA_STATE_WRITE;
- getPlayerData()->playerControl.title = -1;
- /* kill decode process if it got left running */
pid = getPlayerData()->playerControl.decode_pid;
if(pid>0) kill(pid,SIGTERM);
getPlayerData()->playerControl.decode_pid = 0;
@@ -474,31 +469,24 @@ void playerCycleLogFiles() {
/* this actually creates a dupe of the current metadata */
Song * playerCurrentDecodeSong() {
static Song * song = NULL;
- static char * prev = NULL;
+ static MetadataChunk * prev = NULL;
PlayerControl * pc = &(getPlayerData()->playerControl);
if(pc->metadataState == PLAYER_METADATA_STATE_READ &&
((!song || strcmp(song->utf8url, pc->currentUrl))
- || (!prev || strcmp(prev,pc->metadata))))
+ || (!prev || memcmp(prev, &(pc->metadataChunk),
+ sizeof(MetadataChunk)))))
{
+ printf("metadata in the PLAYER!\n");
if(song) freeJustSong(song);
song = newNullSong();
- song->tag = newMpdTag();
if(song->utf8url) free(song->utf8url);
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);
- }
- if(pc->album >= 0) {
- song->tag->album = strdup(pc->album + pc->metadata);
- }
+ song->tag = metadataChunkToMpdTagDup(&(pc->metadataChunk));
validateUtf8Tag(song->tag);
if(prev) free(prev);
- prev = strdup(pc->metadata);
+ prev = malloc(sizeof(MetadataChunk));
+ memcpy(prev, &(pc->metadataChunk), sizeof(MetadataChunk));
resetPlayerMetadata();
return song;
}
diff --git a/src/player.h b/src/player.h
index 5e8d90e97..6453bd372 100644
--- a/src/player.h
+++ b/src/player.h
@@ -24,6 +24,7 @@
#include "decode.h"
#include "mpd_types.h"
#include "song.h"
+#include "metadataChunk.h"
#include <stdio.h>
#include <sys/param.h>
@@ -84,11 +85,7 @@ typedef struct _PlayerControl {
volatile int decode_pid;
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;
+ MetadataChunk metadataChunk;
} PlayerControl;
void clearPlayerPid();
diff --git a/src/playerData.c b/src/playerData.c
index 4950a2c7e..5804f306c 100644
--- a/src/playerData.c
+++ b/src/playerData.c
@@ -73,6 +73,7 @@ void initPlayerData() {
allocationSize+= buffered_chunks*sizeof(float); /*for times*/
allocationSize+= buffered_chunks*sizeof(mpd_sint16); /*for chunkSize*/
allocationSize+= buffered_chunks*sizeof(mpd_sint16); /*for bitRate*/
+ allocationSize+= buffered_chunks*sizeof(mpd_sint8); /*for metaChunk*/
allocationSize+= sizeof(PlayerData); /*for playerData struct*/
if((shmid = shmget(IPC_PRIVATE,allocationSize,IPC_CREAT|0600))<0) {
@@ -95,8 +96,10 @@ void initPlayerData() {
buffered_chunks*CHUNK_SIZE);
buffer->bitRate = (mpd_uint16 *)(((char *)buffer->chunkSize)+
buffered_chunks*sizeof(mpd_sint16));
- buffer->times = (float *)(((char *)buffer->bitRate)+
+ buffer->metaChunk = (mpd_sint8 *)(((char *)buffer->bitRate)+
buffered_chunks*sizeof(mpd_sint16));
+ buffer->times = (float *)(((char *)buffer->metaChunk)+
+ buffered_chunks*sizeof(mpd_sint8));
playerData_pd->playerControl.stop = 0;
playerData_pd->playerControl.pause = 0;
@@ -111,16 +114,10 @@ void initPlayerData() {
memset(playerData_pd->playerControl.utf8url, 0, MAXPATHLEN+1);
memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN+1);
memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN+1);
- memset(playerData_pd->playerControl.metadata, 0,
- DECODE_METADATA_LENGTH);
playerData_pd->playerControl.crossFade = crossfade;
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;
playerData_pd->playerControl.metadataState =
PLAYER_METADATA_STATE_WRITE;
@@ -130,9 +127,6 @@ 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->buffer.metadata, 0, DECODE_METADATA_LENGTH);
- playerData_pd->buffer.metadataSet = 0;
}
PlayerData * getPlayerData() {
@@ -142,4 +136,3 @@ PlayerData * getPlayerData() {
void freePlayerData() {
shmdt(playerData_pd);
}
-/* vim:set shiftwidth=4 tabstop=8 expandtab: */
diff --git a/src/playlist.c b/src/playlist.c
index dd261cfd2..4b6fa5205 100644
--- a/src/playlist.c
+++ b/src/playlist.c
@@ -802,15 +802,19 @@ void syncCurrentPlayerDecodeMetadata() {
songNum = playlist.order[playlist.current];
song = playlist.songs[songNum];
+ printf("HERE 1\n");
+
if(song->type == SONG_TYPE_URL &&
0 == strcmp(song->utf8url, songPlayer->utf8url) &&
!mpdTagsAreEqual(song->tag, songPlayer->tag))
{
+ printf("HERE 1-1\n");
if(song->tag) freeMpdTag(song->tag);
song->tag = mpdTagDup(songPlayer->tag);
playlist.songMod[songNum] = playlist.version;
incrPlaylistVersion();
}
+ printf("HERE 2\n");
}
void syncPlayerAndPlaylist() {
diff --git a/src/tag.c b/src/tag.c
index 729ccb0f6..afb9d7a70 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -169,7 +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->name) free(tag->name);
if(tag->track) free(tag->track);
}
diff --git a/src/tag.h b/src/tag.h
index 841791ae0..06129b767 100644
--- a/src/tag.h
+++ b/src/tag.h
@@ -60,4 +60,3 @@ void validateUtf8Tag(MpdTag * tag);
int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2);
#endif
-/* vim:set shiftwidth=4 tabstop=8 expandtab: */