aboutsummaryrefslogtreecommitdiffstats
path: root/src/inputPlugins
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2006-03-16 06:52:46 +0000
committerEric Wong <normalperson@yhbt.net>2006-03-16 06:52:46 +0000
commit69635022133488e6b19569fb59b16c4658a244eb (patch)
treea7149e6a5a82017ae3821c801433c8794f796aec /src/inputPlugins
parentd7e846bdc2d848525ebd4251c4c5d9c5fe0d2705 (diff)
downloadmpd-69635022133488e6b19569fb59b16c4658a244eb.tar.gz
mpd-69635022133488e6b19569fb59b16c4658a244eb.tar.xz
mpd-69635022133488e6b19569fb59b16c4658a244eb.zip
merge with mpd/trunk up to r3925
git-svn-id: https://svn.musicpd.org/mpd/trunk@3926 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to 'src/inputPlugins')
-rw-r--r--src/inputPlugins/_flac_common.c195
-rw-r--r--src/inputPlugins/_flac_common.h77
-rw-r--r--src/inputPlugins/_ogg_common.c65
-rw-r--r--src/inputPlugins/_ogg_common.h35
-rw-r--r--src/inputPlugins/aac_plugin.c2
-rw-r--r--src/inputPlugins/audiofile_plugin.c2
-rw-r--r--src/inputPlugins/flac_plugin.c258
-rw-r--r--src/inputPlugins/mod_plugin.c2
-rw-r--r--src/inputPlugins/mp3_plugin.c2
-rw-r--r--src/inputPlugins/mp4_plugin.c2
-rw-r--r--src/inputPlugins/mpc_plugin.c2
-rw-r--r--src/inputPlugins/oggflac_plugin.c426
-rw-r--r--src/inputPlugins/oggvorbis_plugin.c (renamed from src/inputPlugins/ogg_plugin.c)126
13 files changed, 908 insertions, 286 deletions
diff --git a/src/inputPlugins/_flac_common.c b/src/inputPlugins/_flac_common.c
new file mode 100644
index 000000000..f6a470ed2
--- /dev/null
+++ b/src/inputPlugins/_flac_common.c
@@ -0,0 +1,195 @@
+/* the Music Player Daemon (MPD)
+ * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * Common data structures and functions used by FLAC and OggFLAC
+ * (c) 2005 by Eric Wong <normalperson@yhbt.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../inputPlugin.h"
+
+#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC)
+
+#include "_flac_common.h"
+
+#include "../log.h"
+#include "../tag.h"
+#include "../inputStream.h"
+#include "../outputBuffer.h"
+#include "../decode.h"
+#include "../replayGain.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <FLAC/format.h>
+#include <FLAC/metadata.h>
+
+void init_FlacData (FlacData * data, OutputBuffer * cb,
+ DecoderControl * dc, InputStream * inStream)
+{
+ data->chunk_length = 0;
+ data->time = 0;
+ data->position = 0;
+ data->bitRate = 0;
+ data->cb = cb;
+ data->dc = dc;
+ data->inStream = inStream;
+ data->replayGainInfo = NULL;
+ data->tag = NULL;
+}
+
+static int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block,
+ char * cmnt, float * fl)
+{
+ int offset = FLAC__metadata_object_vorbiscomment_find_entry_from(
+ block,0,cmnt);
+
+ if(offset >= 0) {
+ size_t pos = strlen(cmnt)+1; /* 1 is for '=' */
+ int len = block->data.vorbis_comment.comments[offset].length
+ -pos;
+ if(len > 0) {
+ unsigned char tmp;
+ unsigned char * dup = &(block->data.vorbis_comment.
+ comments[offset].entry[pos]);
+ tmp = dup[len];
+ dup[len] = '\0';
+ *fl = atof((char *)dup);
+ dup[len] = tmp;
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* replaygain stuff by AliasMrJones */
+static void flacParseReplayGain(const FLAC__StreamMetadata *block,
+ FlacData * data) {
+ unsigned int found = 0;
+
+ if (data->replayGainInfo)
+ freeReplayGainInfo(data->replayGainInfo);
+
+ data->replayGainInfo = newReplayGainInfo();
+
+ found &= flacFindVorbisCommentFloat(block,"replaygain_album_gain",
+ &data->replayGainInfo->albumGain);
+ found &= flacFindVorbisCommentFloat(block,"replaygain_album_peak",
+ &data->replayGainInfo->albumPeak);
+ found &= flacFindVorbisCommentFloat(block,"replaygain_track_gain",
+ &data->replayGainInfo->trackGain);
+ found &= flacFindVorbisCommentFloat(block,"replaygain_track_peak",
+ &data->replayGainInfo->trackPeak);
+
+ if (!found) {
+ freeReplayGainInfo(data->replayGainInfo);
+ data->replayGainInfo = NULL;
+ }
+}
+
+/* tracknumber is used in VCs, MPD uses "track" ..., all the other
+ * tag names match */
+static const char * VORBIS_COMMENT_TRACK_KEY = "tracknumber";
+
+static unsigned int commentMatchesAddToTag(
+ const FLAC__StreamMetadata_VorbisComment_Entry * entry,
+ unsigned int itemType,
+ MpdTag ** tag)
+{
+ const char * str = (itemType == TAG_ITEM_TRACK) ?
+ VORBIS_COMMENT_TRACK_KEY : mpdTagItemKeys[itemType];
+ size_t slen = strlen(str);
+ int vlen = entry->length - slen - 1;
+
+ if ((vlen > 0) && (0 == strncasecmp(str,(char *)entry->entry, slen))
+ && (*(entry->entry + slen) == '=')) {
+ if (!*tag)
+ *tag = newMpdTag();
+
+ addItemToMpdTagWithLen(*tag, itemType,
+ (char *)(entry->entry+slen + 1), vlen);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
+ MpdTag * tag)
+{
+ unsigned int i, j;
+ FLAC__StreamMetadata_VorbisComment_Entry *comments;
+
+ comments = block->data.vorbis_comment.comments;
+
+ for (i = block->data.vorbis_comment.num_comments; i != 0; --i) {
+ for (j = TAG_NUM_OF_ITEM_TYPES; j--; ) {
+ if (commentMatchesAddToTag(comments, j, &tag))
+ break;
+ }
+ comments++;
+ }
+
+ return tag;
+}
+
+void flac_metadata_common_cb(const FLAC__StreamMetadata *block, FlacData *data)
+{
+ DecoderControl *dc = data->dc;
+ const FLAC__StreamMetadata_StreamInfo *si = &(block->data.stream_info);
+
+ switch(block->type) {
+ case FLAC__METADATA_TYPE_STREAMINFO:
+ dc->audioFormat.bits = si->bits_per_sample;
+ dc->audioFormat.sampleRate = si->sample_rate;
+ dc->audioFormat.channels = si->channels;
+ dc->totalTime = ((float)si->total_samples) / (si->sample_rate);
+ getOutputAudioFormat(&(dc->audioFormat),
+ &(data->cb->audioFormat));
+ break;
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ flacParseReplayGain(block,data);
+ default:
+ break;
+ }
+}
+
+void flac_error_common_cb( const char * plugin,
+ const FLAC__StreamDecoderErrorStatus status,
+ FlacData *data)
+{
+ if(data->dc->stop) return;
+
+ switch(status) {
+ case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
+ ERROR("%s lost sync\n", plugin);
+ break;
+ case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
+ ERROR("bad %s header\n", plugin);
+ break;
+ case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
+ ERROR("%s crc mismatch\n", plugin);
+ break;
+ default:
+ ERROR("unknown %s error\n",plugin);
+ }
+}
+
+#endif /* HAVE_FLAC || HAVE_OGGFLAC */
diff --git a/src/inputPlugins/_flac_common.h b/src/inputPlugins/_flac_common.h
new file mode 100644
index 000000000..830d3bfc0
--- /dev/null
+++ b/src/inputPlugins/_flac_common.h
@@ -0,0 +1,77 @@
+/* the Music Player Daemon (MPD)
+ * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * Common data structures and functions used by FLAC and OggFLAC
+ * (c) 2005 by Eric Wong <normalperson@yhbt.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _FLAC_COMMON_H
+#define _FLAC_COMMON_H
+
+#include "../inputPlugin.h"
+
+#if defined(HAVE_FLAC) || defined(HAVE_OGGFLAC)
+
+#include "../tag.h"
+#include "../inputStream.h"
+#include "../outputBuffer.h"
+#include "../decode.h"
+#include <FLAC/seekable_stream_decoder.h>
+#include <FLAC/metadata.h>
+
+#define FLAC_CHUNK_SIZE 4080
+
+typedef struct {
+ unsigned char chunk[FLAC_CHUNK_SIZE];
+ int chunk_length;
+ float time;
+ int bitRate;
+ FLAC__uint64 position;
+ OutputBuffer * cb;
+ DecoderControl * dc;
+ InputStream * inStream;
+ ReplayGainInfo * replayGainInfo;
+ MpdTag * tag;
+} FlacData;
+
+/* initializes a given FlacData struct */
+void init_FlacData (FlacData * data, OutputBuffer * cb,
+ DecoderControl * dc, InputStream * inStream);
+void flac_metadata_common_cb( const FLAC__StreamMetadata *block,
+ FlacData *data);
+void flac_error_common_cb( const char * plugin,
+ FLAC__StreamDecoderErrorStatus status,
+ FlacData *data);
+
+MpdTag * copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
+ MpdTag * tag);
+
+static inline int flacSendChunk(FlacData * data)
+{
+ if (sendDataToOutputBuffer(data->cb, NULL, data->dc, 1, data->chunk,
+ data->chunk_length, data->time, data->bitRate,
+ data->replayGainInfo) == OUTPUT_BUFFER_DC_STOP)
+ return -1;
+
+ return 0;
+}
+
+
+#endif /* HAVE_FLAC || HAVE_OGGFLAC */
+
+#endif /* _FLAC_COMMON_H */
+
diff --git a/src/inputPlugins/_ogg_common.c b/src/inputPlugins/_ogg_common.c
new file mode 100644
index 000000000..fb0bb19e0
--- /dev/null
+++ b/src/inputPlugins/_ogg_common.c
@@ -0,0 +1,65 @@
+/* the Music Player Daemon (MPD)
+ * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC)
+ * (c) 2005 by Eric Wong <normalperson@yhbt.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../inputPlugin.h"
+
+#if defined(HAVE_OGGFLAC) || defined(HAVE_OGGVORBIS)
+
+#include "../utils.h"
+#include "_ogg_common.h"
+
+#include <string.h>
+
+ogg_stream_type ogg_stream_type_detect(InputStream * inStream)
+{
+ /* oggflac detection based on code in ogg123 and this post
+ * http://lists.xiph.org/pipermail/flac/2004-December/000393.html
+ * ogg123 trunk still doesn't have this patch as of June 2005 */
+ unsigned char buf[41];
+ size_t r, to_read = 41;
+
+ seekInputStream(inStream, 0, SEEK_SET);
+
+ while (to_read) {
+ r = readFromInputStream(inStream, buf, 1, to_read);
+ if (r < 0)
+ break;
+ to_read -= r;
+ if (!r && !inputStreamAtEOF(inStream))
+ my_usleep(10000);
+ else
+ break;
+ }
+
+ seekInputStream(inStream, 0, SEEK_SET);
+
+ if (r >= 32 && memcmp(buf, "OggS", 4) == 0 && (
+ (memcmp(buf+29, "FLAC", 4) == 0
+ && memcmp(buf+37, "fLaC", 4) == 0)
+ || (memcmp(buf+28, "FLAC", 4) == 0)
+ || (memcmp(buf+28, "fLaC", 4) == 0))) {
+ return FLAC;
+ }
+ return VORBIS;
+}
+
+#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */
+
diff --git a/src/inputPlugins/_ogg_common.h b/src/inputPlugins/_ogg_common.h
new file mode 100644
index 000000000..4cd7fda41
--- /dev/null
+++ b/src/inputPlugins/_ogg_common.h
@@ -0,0 +1,35 @@
+/* the Music Player Daemon (MPD)
+ * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC)
+ * (c) 2005 by Eric Wong <normalperson@yhbt.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _OGG_COMMON_H
+#define _OGG_COMMON_H
+
+#include "../inputPlugin.h"
+
+#if defined(HAVE_OGGFLAC) || defined(HAVE_OGGVORBIS)
+
+typedef enum _ogg_stream_type { VORBIS, FLAC } ogg_stream_type;
+
+ogg_stream_type ogg_stream_type_detect(InputStream * inStream);
+
+#endif /* defined(HAVE_OGGFLAC || defined(HAVE_OGGVORBIS) */
+
+#endif /* _OGG_COMMON_H */
diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c
index e368f3089..3fb5f4742 100644
--- a/src/inputPlugins/aac_plugin.c
+++ b/src/inputPlugins/aac_plugin.c
@@ -418,6 +418,7 @@ InputPlugin aacPlugin =
{
"aac",
NULL,
+ NULL,
NULL,
NULL,
aac_decode,
@@ -435,6 +436,7 @@ InputPlugin aacPlugin =
NULL,
NULL,
NULL,
+ NULL,
NULL,
NULL,
0,
diff --git a/src/inputPlugins/audiofile_plugin.c b/src/inputPlugins/audiofile_plugin.c
index adc279b60..d212eaf47 100644
--- a/src/inputPlugins/audiofile_plugin.c
+++ b/src/inputPlugins/audiofile_plugin.c
@@ -163,6 +163,7 @@ InputPlugin audiofilePlugin =
NULL,
NULL,
NULL,
+ NULL,
audiofile_decode,
audiofileTagDup,
INPUT_PLUGIN_STREAM_FILE,
@@ -176,6 +177,7 @@ InputPlugin audiofilePlugin =
{
NULL,
NULL,
+ NULL,
NULL,
NULL,
NULL,
diff --git a/src/inputPlugins/flac_plugin.c b/src/inputPlugins/flac_plugin.c
index 455394888..242dc6f22 100644
--- a/src/inputPlugins/flac_plugin.c
+++ b/src/inputPlugins/flac_plugin.c
@@ -20,6 +20,8 @@
#ifdef HAVE_FLAC
+#include "_flac_common.h"
+
#include "../utils.h"
#include "../log.h"
#include "../pcm_utils.h"
@@ -34,22 +36,8 @@
#include <FLAC/seekable_stream_decoder.h>
#include <FLAC/metadata.h>
-typedef struct {
-#define FLAC_CHUNK_SIZE 4080
- unsigned char chunk[FLAC_CHUNK_SIZE];
- int chunk_length;
- float time;
- int bitRate;
- FLAC__uint64 position;
- OutputBuffer * cb;
- DecoderControl * dc;
- InputStream * inStream;
- ReplayGainInfo * replayGainInfo;
-} FlacData;
-
/* this code is based on flac123, from flac-tools */
-int flacSendChunk(FlacData * data);
void flacError(const FLAC__SeekableStreamDecoder *,
FLAC__StreamDecoderErrorStatus, void *);
void flacPrintErroredState(FLAC__SeekableStreamDecoderState state);
@@ -75,14 +63,7 @@ int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
int status = 1;
int ret =0;
- data.chunk_length = 0;
- data.time = 0;
- data.position = 0;
- data.bitRate = 0;
- data.cb = cb;
- data.dc = dc;
- data.inStream = inStream;
- data.replayGainInfo = NULL;
+ init_FlacData(&data, cb, dc, inStream);
if(!(flacDec = FLAC__seekable_stream_decoder_new())) {
ret = -1;
@@ -176,19 +157,16 @@ int flac_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
dc->seek = 0;
} */
- if(dc->stop) {
- dc->state = DECODE_STATE_STOP;
- dc->stop = 0;
- }
- else dc->state = DECODE_STATE_STOP;
+ dc->state = DECODE_STATE_STOP;
+ dc->stop = 0;
fail:
if(data.replayGainInfo) freeReplayGainInfo(data.replayGainInfo);
- closeInputStream(inStream);
-
if(flacDec) FLAC__seekable_stream_decoder_delete(flacDec);
+ closeInputStream(inStream);
+
return ret;
}
@@ -250,35 +228,17 @@ FLAC__SeekableStreamDecoderLengthStatus flacLength(
}
FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, void * fdata) {
- FlacData * data = (FlacData *) fdata;
-
- switch(inputStreamAtEOF(data->inStream)) {
- case 1:
+ FlacData * data = (FlacData *) fdata;
+
+ if (inputStreamAtEOF(data->inStream) == 1)
return true;
- default:
- return false;
- }
+ return false;
}
void flacError(const FLAC__SeekableStreamDecoder *dec,
FLAC__StreamDecoderErrorStatus status, void *fdata)
{
- FlacData * data = (FlacData *) fdata;
- if(data->dc->stop) return;
-
- switch(status) {
- case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
- ERROR("flac lost sync\n");
- break;
- case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
- ERROR("bad header\n");
- break;
- case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
- ERROR("crc mismatch\n");
- break;
- default:
- ERROR("unknown flac error\n");
- }
+ flac_error_common_cb("flac",status,(FlacData *) fdata);
}
void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
@@ -312,93 +272,10 @@ void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
}
}
-int flacFindVorbisCommentFloat(const FLAC__StreamMetadata * block, char * cmnt,
- float * fl)
-{
- int offset = FLAC__metadata_object_vorbiscomment_find_entry_from(
- block,0,cmnt);
-
- if(offset >= 0) {
- int pos = strlen(cmnt)+1; /* 1 is for '=' */
- int len = block->data.vorbis_comment.comments[offset].length
- -pos;
- if(len > 0) {
- char * dup = malloc(len+1);
- memcpy(dup,&(block->data.vorbis_comment.comments[offset].entry[pos]),len);
- dup[len] = '\0';
- *fl = atof(dup);
- free(dup);
- return 1;
- }
- }
-
- return 0;
-}
-
-/* replaygain stuff by AliasMrJones */
-void flacParseReplayGain(const FLAC__StreamMetadata *block, FlacData * data) {
- int found = 0;
-
- if(NULL != data->replayGainInfo) {
- freeReplayGainInfo(data->replayGainInfo);
- data->replayGainInfo = NULL;
- }
-
- data->replayGainInfo = newReplayGainInfo();
-
- found &= flacFindVorbisCommentFloat(block,"replaygain_album_gain",
- &data->replayGainInfo->albumGain);
- found &= flacFindVorbisCommentFloat(block,"replaygain_album_peak",
- &data->replayGainInfo->albumPeak);
- found &= flacFindVorbisCommentFloat(block,"replaygain_track_gain",
- &data->replayGainInfo->trackGain);
- found &= flacFindVorbisCommentFloat(block,"replaygain_track_peak",
- &data->replayGainInfo->trackPeak);
-
- if(!found) {
- freeReplayGainInfo(data->replayGainInfo);
- data->replayGainInfo = NULL;
- }
-}
-
void flacMetadata(const FLAC__SeekableStreamDecoder *dec,
const FLAC__StreamMetadata *block, void *vdata)
{
- FlacData * data = (FlacData *)vdata;
-
- switch(block->type) {
- case FLAC__METADATA_TYPE_STREAMINFO:
- data->dc->audioFormat.bits =
- block->data.stream_info.bits_per_sample;
- data->dc->audioFormat.sampleRate =
- block->data.stream_info.sample_rate;
- data->dc->audioFormat.channels =
- block->data.stream_info.channels;
- data->dc->totalTime =
- ((float)block->data.stream_info.total_samples)/
- data->dc->audioFormat.sampleRate;
- getOutputAudioFormat(&(data->dc->audioFormat),
- &(data->cb->audioFormat));
- break;
- case FLAC__METADATA_TYPE_VORBIS_COMMENT:
- flacParseReplayGain(block,data);
- default:
- break;
- }
-}
-
-int flacSendChunk(FlacData * data) {
- switch(sendDataToOutputBuffer(data->cb, NULL, data->dc, 1, data->chunk,
- data->chunk_length, data->time, data->bitRate,
- data->replayGainInfo))
- {
- case OUTPUT_BUFFER_DC_STOP:
- return -1;
- default:
- return 0;
- }
-
- return 0;
+ flac_metadata_common_cb(block, (FlacData *)vdata);
}
FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec,
@@ -447,79 +324,6 @@ FLAC__StreamDecoderWriteStatus flacWrite(const FLAC__SeekableStreamDecoder *dec,
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
-static int commentMatchesAddToTag(
- char * str,
- FLAC__StreamMetadata_VorbisComment_Entry * entry,
- int itemType,
- MpdTag ** tag)
-{
- int slen = strlen(str);
- int vlen = entry->length - slen;
-
- if( vlen <= 0 ) return 0;
-
- if( 0 == strncasecmp(str, entry->entry, slen) ) {
- if(*tag == NULL) *tag = newMpdTag();
- addItemToMpdTagWithLen(*tag, itemType,
- entry->entry+slen, vlen);
- return 1;
- }
-
- return 0;
-}
-
-
-static MpdTag * copyVorbisCommentBlockToMpdTag(FLAC__StreamMetadata * block,
- MpdTag * tag)
-{
- int i;
-
- for(i = 0; i < block->data.vorbis_comment.num_comments; i++) {
- if(commentMatchesAddToTag(
- "artist=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_ARTIST,
- &tag));
- else if(commentMatchesAddToTag(
- "title=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_TITLE,
- &tag));
- else if(commentMatchesAddToTag(
- "album=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_ALBUM,
- &tag));
- else if(commentMatchesAddToTag(
- "tracknumber=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_TRACK,
- &tag));
- else if(commentMatchesAddToTag(
- "genre=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_GENRE,
- &tag));
- else if(commentMatchesAddToTag(
- "date=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_DATE,
- &tag));
- else if(commentMatchesAddToTag(
- "composer=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_COMPOSER,
- &tag));
- else if(commentMatchesAddToTag(
- "performer=",
- block->data.vorbis_comment.comments+i,
- TAG_ITEM_PERFORMER,
- &tag));
- }
-
- return tag;
-}
-
MpdTag * flacMetadataDup(char * file, int * vorbisCommentFound) {
MpdTag * ret = NULL;
FLAC__Metadata_SimpleIterator * it;
@@ -594,30 +398,32 @@ char * flac_mime_types[] = {"application/x-flac", NULL};
InputPlugin flacPlugin =
{
- "flac",
- NULL,
+ "flac",
+ NULL,
NULL,
- flac_decode,
NULL,
- flacTagDup,
- INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
- flacSuffixes,
- flac_mime_types
+ flac_decode,
+ NULL,
+ flacTagDup,
+ INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
+ flacSuffixes,
+ flac_mime_types
};
-#else
+#else /* !HAVE_FLAC */
InputPlugin flacPlugin =
-{
- NULL,
- NULL,
- NULL,
- NULL,
+{
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
NULL,
NULL,
- 0,
- NULL,
- NULL,
};
-#endif
+#endif /* HAVE_FLAC */
diff --git a/src/inputPlugins/mod_plugin.c b/src/inputPlugins/mod_plugin.c
index 547f4af4a..8b5a245a0 100644
--- a/src/inputPlugins/mod_plugin.c
+++ b/src/inputPlugins/mod_plugin.c
@@ -259,6 +259,7 @@ InputPlugin modPlugin =
NULL,
mod_finishMikMod,
NULL,
+ NULL,
mod_decode,
modTagDup,
INPUT_PLUGIN_STREAM_FILE,
@@ -273,6 +274,7 @@ InputPlugin modPlugin =
NULL,
NULL,
NULL,
+ NULL,
NULL,
NULL,
NULL,
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index 0657f25b1..8a73ed85d 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -820,6 +820,7 @@ InputPlugin mp3Plugin =
"mp3",
NULL,
NULL,
+ NULL,
mp3_decode,
NULL,
mp3_tagDup,
@@ -837,6 +838,7 @@ InputPlugin mp3Plugin =
NULL,
NULL,
NULL,
+ NULL,
0,
NULL,
NULL
diff --git a/src/inputPlugins/mp4_plugin.c b/src/inputPlugins/mp4_plugin.c
index a1af848c5..e41c054c0 100644
--- a/src/inputPlugins/mp4_plugin.c
+++ b/src/inputPlugins/mp4_plugin.c
@@ -431,6 +431,7 @@ InputPlugin mp4Plugin =
NULL,
NULL,
NULL,
+ NULL,
mp4_decode,
mp4TagDup,
INPUT_PLUGIN_STREAM_FILE,
@@ -447,6 +448,7 @@ InputPlugin mp4Plugin =
NULL,
NULL,
NULL,
+ NULL,
NULL,
0,
NULL,
diff --git a/src/inputPlugins/mpc_plugin.c b/src/inputPlugins/mpc_plugin.c
index 335c5c368..01a165c44 100644
--- a/src/inputPlugins/mpc_plugin.c
+++ b/src/inputPlugins/mpc_plugin.c
@@ -336,6 +336,7 @@ InputPlugin mpcPlugin =
"mpc",
NULL,
NULL,
+ NULL,
mpc_decode,
NULL,
mpcTagDup,
@@ -351,6 +352,7 @@ InputPlugin mpcPlugin =
NULL,
NULL,
NULL,
+ NULL,
NULL,
NULL,
NULL,
diff --git a/src/inputPlugins/oggflac_plugin.c b/src/inputPlugins/oggflac_plugin.c
new file mode 100644
index 000000000..25f9a3cdb
--- /dev/null
+++ b/src/inputPlugins/oggflac_plugin.c
@@ -0,0 +1,426 @@
+/* the Music Player Daemon (MPD)
+ * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
+ * This project's homepage is: http://www.musicpd.org
+ *
+ * OggFLAC support (half-stolen from flac_plugin.c :))
+ * (c) 2005 by Eric Wong <normalperson@yhbt.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "../inputPlugin.h"
+
+#ifdef HAVE_OGGFLAC
+
+#include "_flac_common.h"
+#include "_ogg_common.h"
+
+#include "../utils.h"
+#include "../log.h"
+#include "../pcm_utils.h"
+#include "../inputStream.h"
+#include "../outputBuffer.h"
+#include "../replayGain.h"
+#include "../audio.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <OggFLAC/seekable_stream_decoder.h>
+#include <FLAC/metadata.h>
+
+static void oggflac_cleanup(InputStream * inStream,
+ FlacData * data,
+ OggFLAC__SeekableStreamDecoder * decoder)
+{
+ if (data->replayGainInfo)
+ freeReplayGainInfo(data->replayGainInfo);
+ if (decoder)
+ OggFLAC__seekable_stream_decoder_delete(decoder);
+ closeInputStream(inStream);
+}
+
+static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(
+ const OggFLAC__SeekableStreamDecoder * decoder,
+ FLAC__byte buf[], unsigned * bytes, void * fdata) {
+ FlacData * data = (FlacData *) fdata;
+ size_t r;
+
+ while (1) {
+ r = readFromInputStream(data->inStream,(void *)buf,1,*bytes);
+ if (r == 0 && !inputStreamAtEOF(data->inStream) &&
+ !data->dc->stop)
+ my_usleep(10000);
+ else
+ break;
+ }
+ *bytes = r;
+
+ if (r == 0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop)
+ return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
+
+ return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
+}
+
+static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(
+ const OggFLAC__SeekableStreamDecoder * decoder,
+ FLAC__uint64 offset, void * fdata)
+{
+ FlacData * data = (FlacData *) fdata;
+
+ if(seekInputStream(data->inStream,offset,SEEK_SET)<0) {
+ return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
+ }
+
+ return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(
+ const OggFLAC__SeekableStreamDecoder * decoder,
+ FLAC__uint64 * offset, void * fdata)
+{
+ FlacData * data = (FlacData *) fdata;
+
+ *offset = (long)(data->inStream->offset);
+
+ return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
+}
+
+static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(
+ const OggFLAC__SeekableStreamDecoder * decoder,
+ FLAC__uint64 * length, void * fdata)
+{
+ FlacData * data = (FlacData *) fdata;
+
+ *length = (size_t)(data->inStream->size);
+
+ return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
+}
+
+static FLAC__bool of_EOF_cb(const OggFLAC__SeekableStreamDecoder * decoder,
+ void * fdata) {
+ FlacData * data = (FlacData *) fdata;
+
+ if (inputStreamAtEOF(data->inStream) == 1)
+ return true;
+ return false;
+}
+
+static void of_error_cb(const OggFLAC__SeekableStreamDecoder * decoder,
+ FLAC__StreamDecoderErrorStatus status, void *fdata)
+{
+ flac_error_common_cb("oggflac",status,(FlacData *) fdata);
+}
+
+static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
+{
+ switch(state) {
+ case OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
+ ERROR("oggflac allocation error\n");
+ break;
+ case OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR:
+ ERROR("oggflac read error\n");
+ break;
+ case OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR:
+ ERROR("oggflac seek error\n");
+ break;
+ case OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR:
+ ERROR("oggflac seekable stream error\n");
+ break;
+ case OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED:
+ ERROR("oggflac decoder already initialized\n");
+ break;
+ case OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK:
+ ERROR("invalid oggflac callback\n");
+ break;
+ case OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED:
+ ERROR("oggflac decoder uninitialized\n");
+ break;
+ case OggFLAC__SEEKABLE_STREAM_DECODER_OK:
+ case OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING:
+ case OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM:
+ break;
+ }
+}
+
+static FLAC__StreamDecoderWriteStatus oggflacWrite(
+ const OggFLAC__SeekableStreamDecoder *decoder,
+ const FLAC__Frame *frame, const FLAC__int32 * const buf[],
+ void * vdata)
+{
+ FlacData * data = (FlacData *)vdata;
+ FLAC__uint32 samples = frame->header.blocksize;
+ FLAC__uint16 u16;
+ unsigned char * uc;
+ int c_samp, c_chan, d_samp;
+ int i;
+ float timeChange;
+ const int bytesPerSample = data->dc->audioFormat.bits/8;
+
+ timeChange = ((float)samples)/frame->header.sample_rate;
+ data->time+= timeChange;
+
+ /* ogg123 uses a complicated method of calculating bitrate
+ * with averaging which I'm not too fond of.
+ * (waste of memory/CPU cycles, especially given this is _lossless_)
+ * a get_decode_position() is not available in OggFLAC, either
+ *
+ * this does not give an accurate bitrate:
+ * (bytes_last_read was set in the read callback)
+ data->bitRate = ((8.0 * data->bytes_last_read *
+ frame->header.sample_rate)
+ /((float)samples * 1000)) + 0.5;
+ */
+
+ for(c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) {
+ for(c_chan = 0; c_chan < frame->header.channels;
+ c_chan++, d_samp++) {
+ u16 = buf[c_chan][c_samp];
+ uc = (unsigned char *)&u16;
+ for(i=0;i<(data->dc->audioFormat.bits/8);i++) {
+ if(data->chunk_length>=FLAC_CHUNK_SIZE) {
+ if(flacSendChunk(data)<0) {
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+ data->chunk_length = 0;
+ if(data->dc->seek) {
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+ }
+ }
+ data->chunk[data->chunk_length++] = *(uc++);
+ }
+ }
+ }
+
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+/* used by TagDup */
+static void of_metadata_dup_cb(
+ const OggFLAC__SeekableStreamDecoder * decoder,
+ const FLAC__StreamMetadata *block, void *vdata)
+{
+ FlacData * data = (FlacData *)vdata;
+
+ switch(block->type) {
+ case FLAC__METADATA_TYPE_STREAMINFO:
+ if (!data->tag) data->tag = newMpdTag();
+ data->tag->time = ((float)block->data.stream_info.
+ total_samples) /
+ block->data.stream_info.sample_rate +
+ 0.5;
+ return;
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ copyVorbisCommentBlockToMpdTag(block,data->tag);
+ default:
+ break;
+ }
+}
+
+/* used by decode */
+static void of_metadata_decode_cb(const OggFLAC__SeekableStreamDecoder * dec,
+ const FLAC__StreamMetadata *block, void *vdata)
+{
+ flac_metadata_common_cb(block, (FlacData *)vdata);
+}
+
+static OggFLAC__SeekableStreamDecoder * full_decoder_init_and_read_metadata(
+ FlacData * data,
+ unsigned int metadata_only)
+{
+ OggFLAC__SeekableStreamDecoder * decoder = NULL;
+ unsigned int s = 1;
+
+ if (!(decoder = OggFLAC__seekable_stream_decoder_new()))
+ return NULL;
+
+ if (metadata_only) {
+ s &= OggFLAC__seekable_stream_decoder_set_metadata_callback(
+ decoder, of_metadata_dup_cb);
+ s &= OggFLAC__seekable_stream_decoder_set_metadata_respond(
+ decoder,
+ FLAC__METADATA_TYPE_STREAMINFO);
+ } else {
+ s &= OggFLAC__seekable_stream_decoder_set_metadata_callback(
+ decoder, of_metadata_decode_cb);
+ }
+
+ s &= OggFLAC__seekable_stream_decoder_set_read_callback(decoder,
+ of_read_cb);
+ s &= OggFLAC__seekable_stream_decoder_set_seek_callback(decoder,
+ of_seek_cb);
+ s &= OggFLAC__seekable_stream_decoder_set_tell_callback(decoder,
+ of_tell_cb);
+ s &= OggFLAC__seekable_stream_decoder_set_length_callback(decoder,
+ of_length_cb);
+ s &= OggFLAC__seekable_stream_decoder_set_eof_callback(decoder,
+ of_EOF_cb);
+ s &= OggFLAC__seekable_stream_decoder_set_write_callback(decoder,
+ oggflacWrite);
+ s &= OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder,
+ FLAC__METADATA_TYPE_VORBIS_COMMENT);
+ s &= OggFLAC__seekable_stream_decoder_set_error_callback(decoder,
+ of_error_cb);
+ s &= OggFLAC__seekable_stream_decoder_set_client_data(decoder,
+ (void *)data);
+
+ if (!s) {
+ ERROR("oggflac problem before init()\n");
+ goto fail;
+ }
+ if (OggFLAC__seekable_stream_decoder_init(decoder) !=
+ OggFLAC__SEEKABLE_STREAM_DECODER_OK)
+ {
+ ERROR("oggflac problem doing init()\n");
+ goto fail;
+ }
+ if (!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(
+ decoder)) {
+ ERROR("oggflac problem reading metadata\n");
+ goto fail;
+ }
+
+ return decoder;
+
+fail:
+ oggflacPrintErroredState(
+ OggFLAC__seekable_stream_decoder_get_state(decoder));
+ OggFLAC__seekable_stream_decoder_delete(decoder);
+ return NULL;
+}
+
+/* public functions: */
+static MpdTag * oggflac_TagDup(char * file)
+{
+ InputStream inStream;
+ OggFLAC__SeekableStreamDecoder * decoder;
+ FlacData data;
+
+ if (openInputStream(&inStream, file) < 0)
+ return NULL;
+ if (ogg_stream_type_detect(&inStream) != FLAC) {
+ closeInputStream(&inStream);
+ return NULL;
+ }
+
+ init_FlacData(&data, NULL, NULL, &inStream);
+
+ /* errors here won't matter,
+ * data.tag will be set or unset, that's all we care about */
+ decoder = full_decoder_init_and_read_metadata(&data,1);
+
+ oggflac_cleanup(&inStream, &data, decoder);
+
+ return data.tag;
+}
+
+static unsigned int oggflac_try_decode(InputStream * inStream)
+{
+ return (ogg_stream_type_detect(inStream) == FLAC) ? 1 : 0;
+}
+
+static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc,
+ InputStream * inStream)
+{
+ OggFLAC__SeekableStreamDecoder * decoder = NULL;
+ FlacData data;
+ int ret = 0;
+
+ init_FlacData(&data, cb, dc, inStream);
+
+ if(!(decoder = full_decoder_init_and_read_metadata(&data,0))){
+ ret = -1;
+ goto fail;
+ }
+
+ dc->state = DECODE_STATE_DECODE;
+
+ while(1) {
+ OggFLAC__seekable_stream_decoder_process_single(decoder);
+ if(OggFLAC__seekable_stream_decoder_get_state(decoder)!=
+ OggFLAC__SEEKABLE_STREAM_DECODER_OK)
+ {
+ break;
+ }
+ if(dc->seek) {
+ FLAC__uint64 sampleToSeek = dc->seekWhere*
+ dc->audioFormat.sampleRate+0.5;
+ if(OggFLAC__seekable_stream_decoder_seek_absolute(
+ decoder, sampleToSeek))
+ {
+ clearOutputBuffer(cb);
+ data.time = ((float)sampleToSeek)/
+ dc->audioFormat.sampleRate;
+ data.position = 0;
+ }
+ else dc->seekError = 1;
+ dc->seek = 0;
+ }
+ }
+
+ if(!dc->stop) {
+ oggflacPrintErroredState(
+ OggFLAC__seekable_stream_decoder_get_state(decoder));
+ OggFLAC__seekable_stream_decoder_finish(decoder);
+ }
+ /* send last little bit */
+ if(data.chunk_length>0 && !dc->stop) {
+ flacSendChunk(&data);
+ flushOutputBuffer(data.cb);
+ }
+
+ dc->state = DECODE_STATE_STOP;
+ dc->stop = 0;
+
+fail:
+ oggflac_cleanup(inStream, &data, decoder);
+
+ return ret;
+}
+
+static char * oggflac_Suffixes[] = {"ogg", NULL};
+static char * oggflac_mime_types[] = {"application/ogg", NULL};
+
+InputPlugin oggflacPlugin =
+{
+ "oggflac",
+ NULL,
+ NULL,
+ oggflac_try_decode,
+ oggflac_decode,
+ NULL,
+ oggflac_TagDup,
+ INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
+ oggflac_Suffixes,
+ oggflac_mime_types
+};
+
+#else /* !HAVE_FLAC */
+
+InputPlugin oggflacPlugin =
+{
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+};
+
+#endif /* HAVE_OGGFLAC */
+
diff --git a/src/inputPlugins/ogg_plugin.c b/src/inputPlugins/oggvorbis_plugin.c
index abadca388..63bac411e 100644
--- a/src/inputPlugins/ogg_plugin.c
+++ b/src/inputPlugins/oggvorbis_plugin.c
@@ -16,9 +16,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/* TODO 'ogg' should probably be replaced with 'oggvorbis' in all instances */
+
#include "../inputPlugin.h"
-#ifdef HAVE_OGG
+#ifdef HAVE_OGGVORBIS
+
+#include "_ogg_common.h"
#include "../utils.h"
#include "../audio.h"
@@ -99,7 +103,7 @@ long ogg_tell_cb(void * vdata) {
return (long)(data->inStream->offset);
}
-char * ogg_parseComment(char * comment, char * needle) {
+static inline char * ogg_parseComment(char * comment, char * needle) {
int len = strlen(needle);
if(strncasecmp(comment, needle, len) == 0 && *(comment+len) == '=') {
@@ -150,48 +154,40 @@ void ogg_getReplayGainInfo(char ** comments, ReplayGainInfo ** infoPtr) {
}
}
-MpdTag * oggCommentsParse(char ** comments) {
- MpdTag * ret = NULL;
- char * temp;
+static const char * VORBIS_COMMENT_TRACK_KEY = "tracknumber";
+
+static inline unsigned int ogg_parseCommentAddToTag(char * comment,
+ unsigned int itemType, MpdTag ** tag)
+{
+ const char * needle = (itemType == TAG_ITEM_TRACK) ?
+ VORBIS_COMMENT_TRACK_KEY : mpdTagItemKeys[itemType];
+ unsigned int len = strlen(needle);
+
+ if(strncasecmp(comment, needle, len) == 0 && *(comment+len) == '=') {
+ if (!*tag)
+ *tag = newMpdTag();
+
+ addItemToMpdTag(*tag, itemType, comment+len+1);
+
+ return 1;
+ }
+
+ return 0;
+}
+static MpdTag * oggCommentsParse(char ** comments) {
+ MpdTag * tag = NULL;
+
while(*comments) {
- if((temp = ogg_parseComment(*comments,"artist"))) {
- if(!ret) ret = newMpdTag();
- addItemToMpdTag(ret, TAG_ITEM_ARTIST, temp);
- }
- else if((temp = ogg_parseComment(*comments,"title"))) {
- if(!ret) ret = newMpdTag();
- addItemToMpdTag(ret, TAG_ITEM_TITLE, temp);
- }
- else if((temp = ogg_parseComment(*comments,"album"))) {
- if(!ret) ret = newMpdTag();
- addItemToMpdTag(ret, TAG_ITEM_ALBUM, temp);
- }
- else if((temp = ogg_parseComment(*comments,"tracknumber"))) {
- if(!ret) ret = newMpdTag();
- addItemToMpdTag(ret, TAG_ITEM_TRACK, temp);
- }
- else if((temp = ogg_parseComment(*comments,"genre"))) {
- if(!ret) ret = newMpdTag();
- addItemToMpdTag(ret, TAG_ITEM_GENRE, temp);
- }
- else if((temp = ogg_parseComment(*comments,"date"))) {
- if(!ret) ret = newMpdTag();
- addItemToMpdTag(ret, TAG_ITEM_DATE, temp);
- }
- else if((temp = ogg_parseComment(*comments,"composer"))) {
- if(!ret) ret = newMpdTag();
- addItemToMpdTag(ret, TAG_ITEM_COMPOSER, temp);
- }
- else if((temp = ogg_parseComment(*comments,"performer"))) {
- if(!ret) ret = newMpdTag();
- addItemToMpdTag(ret, TAG_ITEM_PERFORMER, temp);
+ unsigned int j;
+ for (j = TAG_NUM_OF_ITEM_TYPES; j--; ) {
+ if (ogg_parseCommentAddToTag(*comments, j, &tag))
+ break;
}
-
comments++;
}
-
- return ret;
+
+ return tag;
}
void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName,
@@ -220,7 +216,9 @@ void putOggCommentsIntoOutputBuffer(OutputBuffer * cb, char * streamName,
freeMpdTag(tag);
}
-int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
+/* public */
+int oggvorbis_decode(OutputBuffer * cb, DecoderControl * dc,
+ InputStream * inStream)
{
OggVorbis_File vf;
ov_callbacks callbacks;
@@ -360,7 +358,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream)
return 0;
}
-MpdTag * oggTagDup(char * file) {
+MpdTag * oggvorbis_TagDup(char * file) {
MpdTag * ret = NULL;
FILE * fp;
OggVorbis_File vf;
@@ -386,35 +384,43 @@ MpdTag * oggTagDup(char * file) {
return ret;
}
-char * oggSuffixes[] = {"ogg", NULL};
-char * oggMimeTypes[] = {"application/ogg", NULL};
+static unsigned int oggvorbis_try_decode(InputStream * inStream)
+{
+ return (ogg_stream_type_detect(inStream) == VORBIS) ? 1 : 0;
+}
+
-InputPlugin oggPlugin =
+static char * oggvorbis_Suffixes[] = {"ogg", NULL};
+static char * oggvorbis_MimeTypes[] = {"application/ogg", NULL};
+
+InputPlugin oggvorbisPlugin =
{
- "ogg",
+ "oggvorbis",
+ NULL,
NULL,
+ oggvorbis_try_decode,
+ oggvorbis_decode,
NULL,
- ogg_decode,
- NULL,
- oggTagDup,
- INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
- oggSuffixes,
- oggMimeTypes
+ oggvorbis_TagDup,
+ INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
+ oggvorbis_Suffixes,
+ oggvorbis_MimeTypes
};
-#else
+#else /* !HAVE_OGGVORBIS */
-InputPlugin oggPlugin =
+InputPlugin oggvorbisPlugin =
{
NULL,
NULL,
NULL,
- NULL,
- NULL,
- NULL,
- 0,
- NULL,
- NULL
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ NULL,
};
-#endif
+#endif /* HAVE_OGGVORBIS */