decoder/mpg123: new decoder plugin based on libmpg123

Still missing:
- seeking
- tags
- streaming
- encodings other than MPG123_ENC_SIGNED_16
This commit is contained in:
Max Kellermann 2009-08-26 20:08:13 +02:00
parent df0c26a394
commit bff4c54ece
6 changed files with 243 additions and 0 deletions

View File

@ -69,6 +69,9 @@ MAD - http://www.underbit.com/products/mad/
For MP3 support. You will need libmad, and optionally libid3tag if you want For MP3 support. You will need libmad, and optionally libid3tag if you want
ID3 tag support. ID3 tag support.
libmpg123 - http://www.mpg123.de/
Alternative for MP3 support.
Ogg Vorbis - http://www.xiph.org/ogg/vorbis/ Ogg Vorbis - http://www.xiph.org/ogg/vorbis/
For Ogg Vorbis support. You will need libogg and libvorbis. For Ogg Vorbis support. You will need libogg and libvorbis.

View File

@ -348,6 +348,7 @@ DECODER_CFLAGS = \
$(WILDMIDI_CFLAGS) \ $(WILDMIDI_CFLAGS) \
$(WAVPACK_CFLAGS) \ $(WAVPACK_CFLAGS) \
$(MAD_CFLAGS) \ $(MAD_CFLAGS) \
$(MPG123_CFLAGS) \
$(FFMPEG_CFLAGS) \ $(FFMPEG_CFLAGS) \
$(CUE_CFLAGS) $(CUE_CFLAGS)
@ -362,6 +363,7 @@ DECODER_LIBS = \
$(WILDMIDI_LIBS) \ $(WILDMIDI_LIBS) \
$(WAVPACK_LIBS) \ $(WAVPACK_LIBS) \
$(MAD_LIBS) \ $(MAD_LIBS) \
$(MPG123_LIBS) \
$(MP4FF_LIBS) \ $(MP4FF_LIBS) \
$(FFMPEG_LIBS) \ $(FFMPEG_LIBS) \
$(CUE_LIBS) $(CUE_LIBS)
@ -374,6 +376,10 @@ if HAVE_MAD
DECODER_SRC += src/decoder/mad_plugin.c DECODER_SRC += src/decoder/mad_plugin.c
endif endif
if HAVE_MPG123
DECODER_SRC += src/decoder/mpg123_decoder_plugin.c
endif
if HAVE_MPCDEC if HAVE_MPCDEC
DECODER_SRC += src/decoder/mpcdec_plugin.c DECODER_SRC += src/decoder/mpcdec_plugin.c
endif endif

1
NEWS
View File

@ -14,6 +14,7 @@ ver 0.16 (20??/??/??)
- ffmpeg: convert metadata to generic format - ffmpeg: convert metadata to generic format
- sndfile: new decoder plugin based on libsndfile - sndfile: new decoder plugin based on libsndfile
- flac: load external cue sheet when no internal one - flac: load external cue sheet when no internal one
- mpg123: new decoder plugin based on libmpg123
* encoders: * encoders:
- twolame: new encoder plugin based on libtwolame - twolame: new encoder plugin based on libtwolame
* output: * output:

View File

@ -427,6 +427,18 @@ if test x$enable_mad = xyes; then
fi fi
AM_CONDITIONAL(HAVE_MAD, test x$enable_mad = xyes) AM_CONDITIONAL(HAVE_MAD, test x$enable_mad = xyes)
AC_ARG_ENABLE(mpg123,
AS_HELP_STRING([--enable-mpg123],
[enable libmpg123 decoder plugin]),,
enable_mpg123=auto)
MPD_AUTO_PKG(mpg123, MPG123, [libmpg123],
[libmpg123 decoder plugin], [libmpg123 not found])
if test x$enable_mpg123 = xyes; then
AC_DEFINE(HAVE_MPG123, 1, [Define to use libmpg123])
fi
AM_CONDITIONAL(HAVE_MPG123, test x$enable_mpg123 = xyes)
AC_ARG_ENABLE(mikmod, AC_ARG_ENABLE(mikmod,
AS_HELP_STRING([--enable-mikmod], AS_HELP_STRING([--enable-mikmod],
[enable the mikmod decoder (default: disable)]),, [enable the mikmod decoder (default: disable)]),,
@ -1411,6 +1423,12 @@ else
echo " MAD mp3 decoder support .......disabled" echo " MAD mp3 decoder support .......disabled"
fi fi
if test x$enable_mpg123 = xyes; then
echo " libmpg123 decoder support .....enabled"
else
echo " libmpg123 decoder support .....disabled"
fi
if test x$enable_mp4 = xyes; then if test x$enable_mp4 = xyes; then
echo " MP4 support ...................enabled" echo " MP4 support ...................enabled"
else else
@ -1474,6 +1492,7 @@ fi
if if
test x$enable_mad = xno && test x$enable_mad = xno &&
test x$enable_mpg123 = xno &&
test x$enable_vorbis = xno && test x$enable_vorbis = xno &&
test x$enable_flac = xno && test x$enable_flac = xno &&
test x$enable_oggflac = xno && test x$enable_oggflac = xno &&

View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2003-2009 The Music Player Daemon Project
* http://www.musicpd.org
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "decoder_api.h"
#include <glib.h>
#include <mpg123.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "mpg123"
static bool
mpd_mpg123_init(G_GNUC_UNUSED const struct config_param *param)
{
mpg123_init();
return true;
}
static void
mpd_mpg123_finish(void)
{
mpg123_exit();
}
/**
* Opens a file with an existing #mpg123_handle.
*
* @param handle a handle which was created before; on error, this
* function will not free it
* @param audio_format this parameter is filled after successful
* return
* @return true on success
*/
static bool
mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
struct audio_format *audio_format)
{
char *path_dup;
int error;
int channels, encoding;
long rate;
/* mpg123_open() wants a writable string :-( */
path_dup = g_strdup(path_fs);
error = mpg123_open(handle, path_dup);
g_free(path_dup);
if (error != MPG123_OK) {
g_warning("libmpg123 failed to open %s: %s",
path_fs, mpg123_plain_strerror(error));
return false;
}
/* obtain the audio format */
error = mpg123_getformat(handle, &rate, &channels, &encoding);
if (error != MPG123_OK) {
g_warning("mpg123_getformat() failed: %s",
mpg123_plain_strerror(error));
return false;
}
if (encoding != MPG123_ENC_SIGNED_16) {
/* other formats not yet implemented */
g_warning("expected MPG123_ENC_SIGNED_16, got %d", encoding);
return false;
}
audio_format_init(audio_format, rate, 16, channels);
if (!audio_format_valid(audio_format)) {
g_warning("invalid audio format");
return false;
}
return true;
}
static void
mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs)
{
struct audio_format audio_format;
mpg123_handle *handle;
int error;
off_t num_samples, position;
enum decoder_command cmd;
/* open the file */
handle = mpg123_new(NULL, &error);
if (handle == NULL) {
g_warning("mpg123_new() failed: %s",
mpg123_plain_strerror(error));
return;
}
if (!mpd_mpg123_open(handle, path_fs, &audio_format)) {
mpg123_delete(handle);
return;
}
num_samples = mpg123_length(handle);
/* tell MPD core we're ready */
decoder_initialized(decoder, &audio_format, false,
(float)num_samples /
(float)audio_format.sample_rate);
/* the decoder main loop */
do {
unsigned char buffer[8192];
size_t nbytes;
position = mpg123_tell(handle);
/* decode */
error = mpg123_read(handle, buffer, sizeof(buffer), &nbytes);
if (error != MPG123_OK) {
if (error != MPG123_DONE)
g_warning("mpg123_read() failed: %s",
mpg123_plain_strerror(error));
break;
}
/* send to MPD */
cmd = decoder_data(decoder, NULL, buffer, nbytes,
(float)position /
(float)audio_format.sample_rate,
0, NULL);
/* seeking not yet implemented */
} while (cmd == DECODE_COMMAND_NONE);
/* cleanup */
mpg123_delete(handle);
}
static struct tag *
mpd_mpg123_tag_dup(const char *path_fs)
{
struct audio_format audio_format;
mpg123_handle *handle;
int error;
off_t num_samples;
struct tag *tag;
handle = mpg123_new(NULL, &error);
if (handle == NULL) {
g_warning("mpg123_new() failed: %s",
mpg123_plain_strerror(error));
return NULL;
}
if (!mpd_mpg123_open(handle, path_fs, &audio_format)) {
mpg123_delete(handle);
return NULL;
}
num_samples = mpg123_length(handle);
if (num_samples <= 0) {
mpg123_delete(handle);
return NULL;
}
tag = tag_new();
tag->time = num_samples / audio_format.sample_rate;
/* ID3 tag support not yet implemented */
mpg123_delete(handle);
return tag;
}
static const char *const mpg123_suffixes[] = {
"mp3",
NULL
};
const struct decoder_plugin mpg123_decoder_plugin = {
.name = "mpg123",
.init = mpd_mpg123_init,
.finish = mpd_mpg123_finish,
.file_decode = mpd_mpg123_file_decode,
/* streaming not yet implemented */
.tag_dup = mpd_mpg123_tag_dup,
.suffixes = mpg123_suffixes,
};

View File

@ -28,6 +28,7 @@
#include <string.h> #include <string.h>
extern const struct decoder_plugin mad_decoder_plugin; extern const struct decoder_plugin mad_decoder_plugin;
extern const struct decoder_plugin mpg123_decoder_plugin;
extern const struct decoder_plugin vorbis_decoder_plugin; extern const struct decoder_plugin vorbis_decoder_plugin;
extern const struct decoder_plugin flac_decoder_plugin; extern const struct decoder_plugin flac_decoder_plugin;
extern const struct decoder_plugin oggflac_decoder_plugin; extern const struct decoder_plugin oggflac_decoder_plugin;
@ -48,6 +49,9 @@ static const struct decoder_plugin *const decoder_plugins[] = {
#ifdef HAVE_MAD #ifdef HAVE_MAD
&mad_decoder_plugin, &mad_decoder_plugin,
#endif #endif
#ifdef HAVE_MPG123
&mpg123_decoder_plugin,
#endif
#ifdef ENABLE_VORBIS_DECODER #ifdef ENABLE_VORBIS_DECODER
&vorbis_decoder_plugin, &vorbis_decoder_plugin,
#endif #endif