From fe0b751c8278ab07a350cd4d363743b734f4f830 Mon Sep 17 00:00:00 2001
From: Warren Dukes <warren.dukes@gmail.com>
Date: Tue, 1 Jun 2004 11:18:25 +0000
Subject: [PATCH] ogg voribs comment parsing on the fly in the decoder

git-svn-id: https://svn.musicpd.org/mpd/trunk@1279 09075e82-0dd4-0310-85a5-a0d7c8717e4f
---
 src/decode.c                  | 33 +++++++++++-
 src/decode.h                  |  5 ++
 src/inputPlugins/ogg_plugin.c | 94 ++++++++++++++++++++++-------------
 src/player.c                  |  8 +++
 src/player.h                  |  2 +
 src/playerData.c              |  4 ++
 6 files changed, 111 insertions(+), 35 deletions(-)

diff --git a/src/decode.c b/src/decode.c
index d403c5e25..e5c1bfa03 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -118,6 +118,8 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) {
                                                 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; \
@@ -265,6 +267,8 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
         dc->metadataSet = 0;
         memset(dc->metadata, 0, DECODE_METADATA_LENGTH);
         dc->title = -1;
+        dc->album = -1;
+        dc->artist = -1;
 
         strncpy(dc->utf8url, pc->utf8url, MAXPATHLEN);
 	dc->utf8url[MAXPATHLEN] = '\0';
@@ -595,4 +599,31 @@ void decode() {
 
         decodeParent(pc, dc, cb);
 }
-/* vim:set shiftwidth=8 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(dc->metadata+pos, string, \
+                                DECODE_METADATA_LENGTH-1-pos); \
+		element = pos; \
+		pos += slen; \
+	} \
+}
+
+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 fbd2fbbb2..a0c4332ba 100644
--- a/src/decode.h
+++ b/src/decode.h
@@ -20,6 +20,7 @@
 #define DECODE_H
 
 #include "../config.h"
+#include "tag.h"
 
 #include "mpd_types.h"
 #include "audio.h"
@@ -63,11 +64,15 @@ typedef struct _DecoderControl {
         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/ogg_plugin.c b/src/inputPlugins/ogg_plugin.c
index bb062dd10..8e42dec55 100644
--- a/src/inputPlugins/ogg_plugin.c
+++ b/src/inputPlugins/ogg_plugin.c
@@ -165,6 +165,61 @@ float ogg_getReplayGainScale(char ** comments) {
         return 1.0;
 }
 
+MpdTag * oggCommentsParse(char ** comments) {
+	MpdTag * ret = NULL;
+	char * temp;
+
+	while(*comments) {
+                if((temp = ogg_parseComment(*comments,"artist"))) {
+			if(!ret) ret = newMpdTag();
+			if(!ret->artist) {
+				ret->artist = strdup(temp);
+				stripReturnChar(ret->artist);
+			}
+		} 
+                else if((temp = ogg_parseComment(*comments,"title"))) {
+			if(!ret) ret = newMpdTag();
+			if(!ret->title) {
+				ret->title = strdup(temp);
+				stripReturnChar(ret->title);
+			}
+		}
+                else if((temp = ogg_parseComment(*comments,"album"))) {
+			if(!ret) ret = newMpdTag();
+			if(!ret->album) {
+				ret->album = strdup(temp);
+				stripReturnChar(ret->album);
+			}
+		}
+                else if((temp = ogg_parseComment(*comments,"tracknumber"))) {
+			if(!ret) ret = newMpdTag();
+			if(!ret->track) {
+				ret->track = strdup(temp);
+				stripReturnChar(ret->track);
+			}
+		}
+
+		comments++;
+	}
+
+	return ret;
+}
+
+void putOggCommentsIntoDecoderControlMetadata(DecoderControl * dc,
+		char ** comments)
+{
+	MpdTag * tag;
+
+	if(dc->metadataSet) return;
+
+	tag = oggCommentsParse(comments);
+	if(!tag) return;
+
+	copyMpdTagToDecoderControlMetadata(dc, tag);
+
+	freeMpdTag(tag);
+}
+
 int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
 {
 	OggVorbis_File vf;
@@ -215,6 +270,8 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
 
 	comments = ov_comment(&vf, -1)->user_comments;
 
+	putOggCommentsIntoDecoderControlMetadata(dc, comments);
+
 	dc->state = DECODE_STATE_DECODE;
 
         replayGainScale = ogg_getReplayGainScale(comments);
@@ -281,8 +338,6 @@ MpdTag * oggTagDup(char * file) {
 	MpdTag * ret = NULL;
 	FILE * fp;
 	OggVorbis_File vf;
-	char ** comments;
-	char * temp;
 
 	fp = fopen(file,"r"); 
 	if(!fp) return NULL;
@@ -291,40 +346,11 @@ MpdTag * oggTagDup(char * file) {
 		return NULL;
 	}
 
-	ret = newMpdTag();
+	ret = oggCommentsParse(ov_comment(&vf,-1)->user_comments);
+
+	if(!ret) ret = newMpdTag();
 	ret->time = (int)(ov_time_total(&vf,-1)+0.5);
 
-	comments = ov_comment(&vf,-1)->user_comments;
-
-	while(*comments) {
-                if((temp = ogg_parseComment(*comments,"artist"))) {
-			if(!ret->artist) {
-				ret->artist = strdup(temp);
-				stripReturnChar(ret->artist);
-			}
-		} 
-                else if((temp = ogg_parseComment(*comments,"title"))) {
-			if(!ret->title) {
-				ret->title = strdup(temp);
-				stripReturnChar(ret->title);
-			}
-		}
-                else if((temp = ogg_parseComment(*comments,"album"))) {
-			if(!ret->album) {
-				ret->album = strdup(temp);
-				stripReturnChar(ret->album);
-			}
-		}
-                else if((temp = ogg_parseComment(*comments,"tracknumber"))) {
-			if(!ret->track) {
-				ret->track = strdup(temp);
-				stripReturnChar(ret->track);
-			}
-		}
-
-		comments++;
-	}
-
 	ov_clear(&vf);
 
 	return ret;	
diff --git a/src/player.c b/src/player.c
index 7a6442991..9427ddf21 100644
--- a/src/player.c
+++ b/src/player.c
@@ -56,6 +56,8 @@ 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;
         }
 }
 
@@ -489,6 +491,12 @@ Song * playerCurrentDecodeSong() {
                 if(pc->title >= 0) {
                         song->tag->title = strdup(pc->title + pc->metadata);
                 }
+                if(pc->artist >= 0) {
+                        song->tag->artist = strdup(pc->artist + pc->metadata);
+                }
+                if(pc->album >= 0) {
+                        song->tag->album = strdup(pc->album + pc->metadata);
+                }
                 validateUtf8Tag(song->tag);
                 resetPlayerMetadata();
                 return song;
diff --git a/src/player.h b/src/player.h
index e7d21f7b9..9b9647c59 100644
--- a/src/player.h
+++ b/src/player.h
@@ -87,6 +87,8 @@ typedef struct _PlayerControl {
         volatile mpd_sint8 metadataState;
         char metadata[DECODE_METADATA_LENGTH];
         volatile mpd_sint16 title;
+        volatile mpd_sint16 artist;
+        volatile mpd_sint16 album;
 } PlayerControl;
 
 void clearPlayerPid();
diff --git a/src/playerData.c b/src/playerData.c
index d78a208b4..2dbdace0d 100644
--- a/src/playerData.c
+++ b/src/playerData.c
@@ -118,6 +118,8 @@ void initPlayerData() {
 	playerData_pd->playerControl.totalPlayTime = 0;
 	playerData_pd->playerControl.decode_pid = 0;
 	playerData_pd->playerControl.title = -1;
+	playerData_pd->playerControl.artist = -1;
+	playerData_pd->playerControl.album = -1;
 	playerData_pd->playerControl.metadataState = 
                         PLAYER_METADATA_STATE_WRITE;
 
@@ -130,6 +132,8 @@ void initPlayerData() {
 	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;
 }