aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2013-04-21 11:01:39 +0200
committerAnton Khirnov <anton@khirnov.net>2013-11-04 10:52:50 +0100
commit0ab207aae7becf128a4324a58a97f961f2f015eb (patch)
tree667341db6eb0d0e011e2ec895aafcbc161f59cd9
parent550ace8556074a1450df6649a0dbb13ca0542999 (diff)
Drop all decode plugins except for ffmpeg.
-rw-r--r--Makefile.am135
-rw-r--r--configure.ac392
-rw-r--r--src/decoder/_flac_common.c229
-rw-r--r--src/decoder/_flac_common.h105
-rw-r--r--src/decoder/_ogg_common.c44
-rw-r--r--src/decoder/_ogg_common.h33
-rw-r--r--src/decoder/audiofile_decoder_plugin.c258
-rw-r--r--src/decoder/dsdiff_decoder_plugin.c397
-rw-r--r--src/decoder/dsdiff_decoder_plugin.h25
-rw-r--r--src/decoder/dsdlib.c112
-rw-r--r--src/decoder/dsdlib.h42
-rw-r--r--src/decoder/dsf_decoder_plugin.c338
-rw-r--r--src/decoder/dsf_decoder_plugin.h25
-rw-r--r--src/decoder/faad_decoder_plugin.c515
-rw-r--r--src/decoder/flac_compat.h114
-rw-r--r--src/decoder/flac_decoder_plugin.c486
-rw-r--r--src/decoder/flac_metadata.c323
-rw-r--r--src/decoder/flac_metadata.h64
-rw-r--r--src/decoder/flac_pcm.c110
-rw-r--r--src/decoder/flac_pcm.h33
-rw-r--r--src/decoder/fluidsynth_decoder_plugin.c244
-rw-r--r--src/decoder/gme_decoder_plugin.c257
-rw-r--r--src/decoder/mad_decoder_plugin.c1204
-rw-r--r--src/decoder/mikmod_decoder_plugin.c235
-rw-r--r--src/decoder/modplug_decoder_plugin.c194
-rw-r--r--src/decoder/mp4ff_decoder_plugin.c448
-rw-r--r--src/decoder/mpcdec_decoder_plugin.c347
-rw-r--r--src/decoder/mpg123_decoder_plugin.c245
-rw-r--r--src/decoder/pcm_decoder_plugin.c105
-rw-r--r--src/decoder/pcm_decoder_plugin.h33
-rw-r--r--src/decoder/sidplay_decoder_plugin.cxx432
-rw-r--r--src/decoder/sndfile_decoder_plugin.c255
-rw-r--r--src/decoder/vorbis_comments.c156
-rw-r--r--src/decoder/vorbis_comments.h40
-rw-r--r--src/decoder/vorbis_decoder_plugin.c314
-rw-r--r--src/decoder/wavpack_decoder_plugin.c600
-rw-r--r--src/decoder/wildmidi_decoder_plugin.c150
-rw-r--r--src/decoder_list.c76
38 files changed, 10 insertions, 9105 deletions
diff --git a/Makefile.am b/Makefile.am
index 332b51d9..8ba4ab4e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -95,12 +95,6 @@ mpd_headers = \
src/gcc.h \
src/decoder_list.h \
src/decoder_print.h \
- src/decoder/flac_compat.h \
- src/decoder/flac_metadata.h \
- src/decoder/flac_pcm.h \
- src/decoder/_flac_common.h \
- src/decoder/_ogg_common.h \
- src/decoder/pcm_decoder_plugin.h \
src/input_init.h \
src/input_plugin.h \
src/input_registry.h \
@@ -491,128 +485,18 @@ endif
# decoder plugins
libdecoder_plugins_a_SOURCES = \
- src/decoder/pcm_decoder_plugin.c \
- src/decoder/dsdiff_decoder_plugin.c \
- src/decoder/dsdiff_decoder_plugin.h \
- src/decoder/dsf_decoder_plugin.c \
- src/decoder/dsf_decoder_plugin.h \
- src/decoder/dsdlib.c \
- src/decoder/dsdlib.h \
src/decoder_buffer.c \
src/decoder_plugin.c \
src/decoder_list.c
libdecoder_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \
- $(VORBIS_CFLAGS) $(TREMOR_CFLAGS) \
- $(patsubst -I%/FLAC,-I%,$(FLAC_CFLAGS)) \
- $(SNDFILE_CFLAGS) \
- $(AUDIOFILE_CFLAGS) \
- $(LIBMIKMOD_CFLAGS) \
- $(GME_CFLAGS) \
- $(SIDPLAY_CFLAGS) \
- $(FLUIDSYNTH_CFLAGS) \
- $(WILDMIDI_CFLAGS) \
- $(WAVPACK_CFLAGS) \
- $(MAD_CFLAGS) \
- $(MPG123_CFLAGS) \
- $(FFMPEG_CFLAGS) \
- $(MPCDEC_CFLAGS) \
- $(FAAD_CFLAGS)
+ $(FFMPEG_CFLAGS)
DECODER_LIBS = \
libdecoder_plugins.a \
- $(VORBIS_LIBS) $(TREMOR_LIBS) \
- $(FLAC_LIBS) \
- $(SNDFILE_LIBS) \
- $(AUDIOFILE_LIBS) $(LIBMIKMOD_LIBS) \
- $(GME_LIBS) \
- $(SIDPLAY_LIBS) \
- $(FLUIDSYNTH_LIBS) \
- $(WILDMIDI_LIBS) \
- $(WAVPACK_LIBS) \
- $(MAD_LIBS) \
- $(MPG123_LIBS) \
- $(MP4FF_LIBS) \
- $(FFMPEG_LIBS) \
- $(MPCDEC_LIBS) \
- $(FAAD_LIBS)
+ $(FFMPEG_LIBS)
DECODER_SRC =
-if HAVE_MAD
-libdecoder_plugins_a_SOURCES += src/decoder/mad_decoder_plugin.c
-endif
-
-if HAVE_MPG123
-libdecoder_plugins_a_SOURCES += src/decoder/mpg123_decoder_plugin.c
-endif
-
-if HAVE_MPCDEC
-libdecoder_plugins_a_SOURCES += src/decoder/mpcdec_decoder_plugin.c
-endif
-
-if HAVE_WAVPACK
-libdecoder_plugins_a_SOURCES += src/decoder/wavpack_decoder_plugin.c
-endif
-
-if HAVE_FAAD
-libdecoder_plugins_a_SOURCES += src/decoder/faad_decoder_plugin.c
-endif
-
-if HAVE_MP4
-libdecoder_plugins_a_SOURCES += src/decoder/mp4ff_decoder_plugin.c
-endif
-
-if HAVE_OGG_COMMON
-libdecoder_plugins_a_SOURCES += src/decoder/_ogg_common.c
-endif
-
-if HAVE_FLAC_COMMON
-libdecoder_plugins_a_SOURCES += \
- src/decoder/flac_metadata.c \
- src/decoder/flac_pcm.c \
- src/decoder/_flac_common.c
-endif
-
-if ENABLE_VORBIS_DECODER
-libdecoder_plugins_a_SOURCES += \
- src/decoder/vorbis_comments.c \
- src/decoder/vorbis_comments.h \
- src/decoder/vorbis_decoder_plugin.c
-endif
-
-if HAVE_FLAC
-libdecoder_plugins_a_SOURCES += src/decoder/flac_decoder_plugin.c
-endif
-
-if HAVE_AUDIOFILE
-libdecoder_plugins_a_SOURCES += src/decoder/audiofile_decoder_plugin.c
-endif
-
-if ENABLE_MIKMOD_DECODER
-libdecoder_plugins_a_SOURCES += src/decoder/mikmod_decoder_plugin.c
-endif
-
-if HAVE_MODPLUG
-libmodplug_decoder_plugin_a_SOURCES = src/decoder/modplug_decoder_plugin.c
-libmodplug_decoder_plugin_a_CFLAGS = $(src_mpd_CFLAGS) $(MODPLUG_CFLAGS)
-libmodplug_decoder_plugin_a_CPPFLAGS = $(src_mpd_CPPFLAGS)
-noinst_LIBRARIES += libmodplug_decoder_plugin.a
-DECODER_LIBS += libmodplug_decoder_plugin.a $(MODPLUG_LIBS)
-endif
-
-if ENABLE_SIDPLAY
-libdecoder_plugins_a_SOURCES += src/decoder/sidplay_decoder_plugin.cxx
-DECODER_SRC += src/dummy.cxx
-endif
-
-if ENABLE_FLUIDSYNTH
-libdecoder_plugins_a_SOURCES += src/decoder/fluidsynth_decoder_plugin.c
-endif
-
-if ENABLE_WILDMIDI
-libdecoder_plugins_a_SOURCES += src/decoder/wildmidi_decoder_plugin.c
-endif
-
if HAVE_FFMPEG
libdecoder_plugins_a_SOURCES += \
src/decoder/ffmpeg_metadata.c \
@@ -620,14 +504,6 @@ libdecoder_plugins_a_SOURCES += \
src/decoder/ffmpeg_decoder_plugin.c
endif
-if ENABLE_SNDFILE
-libdecoder_plugins_a_SOURCES += src/decoder/sndfile_decoder_plugin.c
-endif
-
-if HAVE_GME
-libdecoder_plugins_a_SOURCES += src/decoder/gme_decoder_plugin.c
-endif
-
# encoder plugins
if ENABLE_ENCODER
@@ -637,7 +513,6 @@ noinst_LIBRARIES += libencoder_plugins.a
libencoder_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \
$(LAME_CFLAGS) \
$(TWOLAME_CFLAGS) \
- $(patsubst -I%/FLAC,-I%,$(FLAC_CFLAGS)) \
$(VORBISENC_CFLAGS)
ENCODER_LIBS = \
@@ -1072,12 +947,6 @@ test_dump_playlist_SOURCES = test/dump_playlist.c \
src/timer.c \
src/fd_util.c
-if HAVE_FLAC
-test_dump_playlist_SOURCES += \
- src/replay_gain_info.c \
- src/decoder/flac_metadata.c
-endif
-
test_run_decoder_LDADD = \
$(DECODER_LIBS) \
libpcm.a \
diff --git a/configure.ac b/configure.ac
index 0b6c0fc4..37009e76 100644
--- a/configure.ac
+++ b/configure.ac
@@ -161,11 +161,6 @@ AC_ARG_ENABLE(ao,
[enable support for libao]),,
enable_ao=auto)
-AC_ARG_ENABLE(audiofile,
- AS_HELP_STRING([--enable-audiofile],
- [enable audiofile support (WAV and others)]),,
- enable_audiofile=auto)
-
AC_ARG_ENABLE(bzip2,
AS_HELP_STRING([--enable-bzip2],
[enable bzip2 archive support (default: disabled)]),,
@@ -210,21 +205,6 @@ AC_ARG_ENABLE(fifo,
[disable support for writing audio to a FIFO (default: enable)]),,
enable_fifo=yes)
-AC_ARG_ENABLE(flac,
- AS_HELP_STRING([--enable-flac],
- [enable FLAC decoder]),,
- enable_flac=auto)
-
-AC_ARG_ENABLE(fluidsynth,
- AS_HELP_STRING([--enable-fluidsynth],
- [enable MIDI support via fluidsynth (default: disable)]),,
- enable_fluidsynth=no)
-
-AC_ARG_ENABLE(gme,
- AS_HELP_STRING([--enable-gme],
- [enable Blargg's game music emulator plugin]),,
- enable_gme=auto)
-
AC_ARG_ENABLE(httpd-output,
AS_HELP_STRING([--enable-httpd-output],
[enables the HTTP server output]),,
@@ -286,36 +266,11 @@ AC_ARG_ENABLE(lsr,
[enable libsamplerate support]),,
enable_lsr=auto)
-AC_ARG_ENABLE(mad,
- AS_HELP_STRING([--enable-mad],
- [enable libmad mp3 decoder plugin]),,
- enable_mad=auto)
-
-AC_ARG_ENABLE(mikmod,
- AS_HELP_STRING([--enable-mikmod],
- [enable the mikmod decoder (default: disable)]),,
- enable_mikmod=no)
-
AC_ARG_ENABLE(mms,
AS_HELP_STRING([--enable-mms],
[enable the MMS protocol with libmms]),,
[enable_mms=auto])
-AC_ARG_ENABLE(modplug,
- AS_HELP_STRING([--enable-modplug],
- [enable modplug decoder plugin]),,
- enable_modplug=auto)
-
-AC_ARG_ENABLE(mpc,
- AS_HELP_STRING([--disable-mpc],
- [disable musepack (MPC) support (default: enable)]),,
- enable_mpc=yes)
-
-AC_ARG_ENABLE(mpg123,
- AS_HELP_STRING([--enable-mpg123],
- [enable libmpg123 decoder plugin]),,
- enable_mpg123=auto)
-
AC_ARG_ENABLE(mvp,
AS_HELP_STRING([--enable-mvp],
[enable support for Hauppauge Media MVP (default: disable)]),,
@@ -346,22 +301,11 @@ AC_ARG_ENABLE(recorder-output,
[enables the recorder file output plugin (default: disable)]),,
[enable_recorder_output=auto])
-AC_ARG_ENABLE(sidplay,
- AS_HELP_STRING([--enable-sidplay],
- [enable C64 SID support via libsidplay2]),,
- enable_sidplay=auto)
-
-
AC_ARG_ENABLE(shout,
AS_HELP_STRING([--enable-shout],
[enables the shoutcast streaming output]),,
[enable_shout=auto])
-AC_ARG_ENABLE(sndfile,
- AS_HELP_STRING([--enable-sndfile],
- [enable sndfile support]),,
- enable_sndfile=auto)
-
AC_ARG_ENABLE(solaris_output,
AS_HELP_STRING([--enable-solaris-output],
[enables the Solaris /dev/audio output]),,
@@ -387,11 +331,6 @@ AC_ARG_ENABLE(test,
[build the test programs (default: disabled)]),,
enable_test=no)
-AC_ARG_WITH(tremor,
- AS_HELP_STRING([--with-tremor=PFX],
- [use Tremor (vorbisidec) integer Ogg Vorbis decoder (with optional prefix)]),,
- with_tremor=no)
-
AC_ARG_ENABLE(twolame-encoder,
AS_HELP_STRING([--enable-twolame-encoder],
[enable the TwoLAME mp2 encoder]),,
@@ -402,11 +341,6 @@ AC_ARG_ENABLE(un,
[disable support for clients connecting via unix domain sockets (default: enable)]),,
[enable_un=yes])
-AC_ARG_ENABLE(vorbis,
- AS_HELP_STRING([--enable-vorbis],
- [enable Ogg Vorbis decoder]),,
- enable_vorbis=auto)
-
AC_ARG_ENABLE(vorbis-encoder,
AS_HELP_STRING([--enable-vorbis-encoder],
[enable the Ogg Vorbis encoder]),,
@@ -417,21 +351,11 @@ AC_ARG_ENABLE(wave-encoder,
[enable the PCM wave encoder]),,
enable_wave_encoder=yes)
-AC_ARG_ENABLE(wavpack,
- AS_HELP_STRING([--enable-wavpack],
- [enable WavPack support]),,
- enable_wavpack=auto)
-
AC_ARG_ENABLE(werror,
AS_HELP_STRING([--enable-werror],
[treat warnings as errors (default: disabled)]),,
enable_werror=no)
-AC_ARG_ENABLE(wildmidi,
- AS_HELP_STRING([--enable-wildmidi],
- [enable MIDI support via wildmidi (default: disable)]),,
- enable_wildmidi=no)
-
AC_ARG_WITH(zeroconf,
AS_HELP_STRING([--with-zeroconf=@<:@auto|avahi|bonjour|no@:>@],
[enable zeroconf backend (default=auto)]),,
@@ -806,20 +730,6 @@ dnl ---------------------------------------------------------------------------
dnl Decoder Plugins
dnl ---------------------------------------------------------------------------
-dnl -------------------------------- audiofile --------------------------------
-MPD_AUTO_PKG(audiofile, AUDIOFILE, [audiofile >= 0.1.7],
- [audiofile decoder plugin], [libaudiofile not found])
-AM_CONDITIONAL(HAVE_AUDIOFILE, test x$enable_audiofile = xyes)
-if test x$enable_audiofile = xyes; then
- AC_DEFINE(HAVE_AUDIOFILE, 1, [Define for audiofile support])
-fi
-
-dnl ----------------------------------- FAAD ----------------------------------
-AM_PATH_FAAD()
-
-AM_CONDITIONAL(HAVE_FAAD, test x$enable_aac = xyes)
-AM_CONDITIONAL(HAVE_MP4, test x$enable_mp4 = xyes)
-
dnl ---------------------------------- ffmpeg ---------------------------------
MPD_AUTO_PKG(ffmpeg, FFMPEG, [libavformat >= 52.31 libavcodec >= 52.20 libavutil >= 49.15],
[ffmpeg decoder library], [libavformat+libavcodec+libavutil not found])
@@ -830,281 +740,6 @@ fi
AM_CONDITIONAL(HAVE_FFMPEG, test x$enable_ffmpeg = xyes)
-dnl ----------------------------------- FLAC ----------------------------------
-
-MPD_AUTO_PKG(flac, FLAC, [flac >= 1.1],
- [FLAC decoder], [libFLAC not found])
-
-if test x$enable_flac = xyes; then
- AC_DEFINE(HAVE_FLAC, 1, [Define for FLAC support])
-fi
-
-AM_CONDITIONAL(HAVE_FLAC, test x$enable_flac = xyes)
-
-enable_flac_encoder=$enable_flac
-
-dnl -------------------------------- FluidSynth -------------------------------
-if test x$enable_fluidsynth = xyes; then
- PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth],
- AC_DEFINE(ENABLE_FLUIDSYNTH, 1, [Define for fluidsynth support]),
- enable_fluidsynth=no)
-fi
-
-AM_CONDITIONAL(ENABLE_FLUIDSYNTH, test x$enable_fluidsynth = xyes)
-
-dnl ---------------------------------- libgme ---------------------------------
-MPD_AUTO_PKG(gme, GME, [libgme],
- [gme decoder plugin], [libgme not found])
-AM_CONDITIONAL(HAVE_GME, test x$enable_gme = xyes)
-if test x$enable_gme = xyes; then
- AC_DEFINE(HAVE_GME, 1, [Define for gme support])
-fi
-
-dnl ---------------------------------- libmad ---------------------------------
-MPD_AUTO_PKG_LIB(mad, MAD, [mad],
- mad, mad_stream_init, [-lmad], [],
- [libmad MP3 decoder plugin], [libmad not found])
-if test x$enable_mad = xyes; then
- AC_DEFINE(HAVE_MAD, 1, [Define to use libmad])
-fi
-AM_CONDITIONAL(HAVE_MAD, test x$enable_mad = xyes)
-
-enable_shout2="$enable_shout"
-MPD_AUTO_PKG(shout, SHOUT, [shout],
- [shout output plugin], [libshout not found])
-if test x$enable_shout = xyes && test x$enable_shout2 = xauto; then
- enable_shout=auto
-fi
-
-dnl -------------------------------- libmpg123 --------------------------------
-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)
-
-dnl -------------------------------- libmikmod --------------------------------
-if test x$enable_mikmod = xyes; then
- AC_PATH_PROG(LIBMIKMOD_CONFIG, libmikmod-config)
- if test x$LIBMIKMOD_CONFIG != x ; then
- AC_SUBST(LIBMIKMOD_CFLAGS, `$LIBMIKMOD_CONFIG --cflags`)
- AC_SUBST(LIBMIKMOD_LIBS, `$LIBMIKMOD_CONFIG --libs`)
- AC_DEFINE(ENABLE_MIKMOD_DECODER, 1, [Define for mikmod support])
- else
- enable_mikmod=no
- fi
-fi
-
-AM_CONDITIONAL(ENABLE_MIKMOD_DECODER, test x$enable_mikmod = xyes)
-
-dnl -------------------------------- libmodplug -------------------------------
-found_modplug=$HAVE_CXX
-MPD_AUTO_PRE(modplug, [modplug decoder plugin], [No C++ compiler found])
-
-MPD_AUTO_PKG(modplug, MODPLUG, [libmodplug],
- [modplug decoder plugin], [libmodplug not found])
-
-if test x$enable_modplug = xyes; then
- AC_DEFINE(HAVE_MODPLUG, 1, [Define for modplug support])
-fi
-AM_CONDITIONAL(HAVE_MODPLUG, test x$enable_modplug = xyes)
-
-dnl -------------------------------- libsndfile -------------------------------
-dnl See above test, which may disable this.
-MPD_AUTO_PKG(sndfile, SNDFILE, [sndfile],
- [libsndfile decoder plugin], [libsndfile not found])
-
-if test x$enable_sndfile = xyes; then
- AC_DEFINE(ENABLE_SNDFILE, 1, [Define to enable the sndfile decoder plugin])
-fi
-AM_CONDITIONAL(ENABLE_SNDFILE, test x$enable_sndfile = xyes)
-
-dnl --------------------------------- musepack --------------------------------
-if test x$enable_mpc = xyes; then
- oldcflags=$CFLAGS
- oldlibs=$LIBS
- oldcppflags=$CPPFLAGS
- AC_CHECK_LIB(mpcdec,main,
- MPCDEC_LIBS="$MPCDEC_LIBS -lmpcdec",
- enable_mpc=no)
- CFLAGS=$oldcflags
- LIBS=$oldlibs
- CPPFLAGS=$oldcppflags
-
- if test x$enable_mpc = xyes; then
- AC_CHECK_HEADER([mpc/mpcdec.h],
- [AC_DEFINE(HAVE_MPCDEC,1,
- [Define to use libmpcdec for MPC decoding])],
- [AC_CHECK_HEADER(mpcdec/mpcdec.h,
- [AC_DEFINE(MPC_IS_OLD_API, 1,
- [Define if an old pre-SV8 libmpcdec is used])]
- )]
- )
- else
- AC_MSG_WARN([mpcdec lib needed for MPC support -- disabling MPC support])
- fi
-fi
-
-AC_SUBST(MPCDEC_LIBS)
-AC_SUBST(MPCDEC_CFLAGS)
-AM_CONDITIONAL(HAVE_MPCDEC, test x$enable_mpc = xyes)
-
-dnl -------------------------------- Ogg Tremor -------------------------------
-if test x$with_tremor = xyes || test x$with_tremor = xno; then
- enable_tremor="$with_tremor"
-else
- tremor_prefix="$with_tremor"
- enable_tremor=yes
-fi
-
-if test x$enable_tremor = xyes; then
- if test "x$tremor_libraries" != "x" ; then
- TREMOR_LIBS="-L$tremor_libraries"
- elif test "x$tremor_prefix" != "x" ; then
- TREMOR_LIBS="-L$tremor_prefix/lib"
- fi
- TREMOR_LIBS="$TREMOR_LIBS -lvorbisidec"
- if test "x$tremor_includes" != "x" ; then
- TREMOR_CFLAGS="-I$tremor_includes"
- elif test "x$tremor_prefix" != "x" ; then
- TREMOR_CFLAGS="-I$tremor_prefix/include"
- fi
- ac_save_CFLAGS="$CFLAGS"
- ac_save_LIBS="$LIBS"
- CFLAGS="$CFLAGS $TREMOR_CFLAGS"
- LIBS="$LIBS $TREMOR_LIBS"
- AC_CHECK_LIB(vorbisidec,ov_read,,enable_tremor=no;
- AC_MSG_WARN([vorbisidec lib needed for ogg support with tremor -- disabling ogg support]))
- CFLAGS="$ac_save_CFLAGS"
- LIBS="$ac_save_LIBS"
-fi
-
-if test x$enable_tremor = xyes; then
- AC_DEFINE(HAVE_TREMOR,1,
- [Define to use tremor (libvorbisidec) for ogg support])
- AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support])
-else
- TREMOR_CFLAGS=
- TREMOR_LIBS=
-fi
-
-AC_SUBST(TREMOR_CFLAGS)
-AC_SUBST(TREMOR_LIBS)
-
-dnl -------------------------------- Ogg Vorbis -------------------------------
-
-if test x$enable_tremor = xyes; then
- if test x$enable_vorbis = xyes; then
- AC_MSG_WARN(["OggTremor detected, could not enable Vorbis."])
- fi
- enable_vorbis=no
-fi
-
-MPD_AUTO_PKG(vorbis, VORBIS, [vorbis vorbisfile ogg],
- [Ogg Vorbis decoder], [libvorbis not found])
-if test x$enable_vorbis = xyes; then
- AC_DEFINE(ENABLE_VORBIS_DECODER, 1, [Define for Ogg Vorbis support])
-fi
-
-AM_CONDITIONAL(ENABLE_VORBIS_DECODER, test x$enable_vorbis = xyes || test x$enable_tremor = xyes)
-
-dnl --------------------------------- sidplay ---------------------------------
-found_sidplay=$HAVE_CXX
-MPD_AUTO_PRE(sidplay, [sidplay decoder plugin], [No C++ compiler found])
-
-if test x$enable_sidplay != xno; then
- # we're not using pkg-config here
- # because libsidplay2's .pc file requires libtool
- AC_CHECK_LIB([sidplay2],[main],[found_sidplay=yes],[found_sidplay=no],[])
-
- MPD_AUTO_PRE(sidplay, [sidplay decoder plugin],
- [libsidplay2 not found])
-fi
-
-if test x$enable_sidplay != xno; then
- AC_CHECK_LIB([resid-builder], [main],
- [found_sidplay=yes], [found_sidplay=no])
-
- if test x$found_sidplay = xyes; then
- AC_CHECK_LIB([sidutils],[main],[],[found_sidplay=no],[])
- fi
-
- MPD_AUTO_RESULT(sidplay, [sidplay decoder plugin],
- [libresid-builder or libsidutils not found])
-fi
-
-if test x$enable_sidplay = xyes; then
- AC_SUBST(SIDPLAY_LIBS,"-lsidplay2 -lresid-builder -lsidutils")
- AC_SUBST(SIDPLAY_CFLAGS,)
-
- AC_DEFINE(ENABLE_SIDPLAY, 1, [Define for libsidplay2 support])
-fi
-
-AM_CONDITIONAL(ENABLE_SIDPLAY, test x$enable_sidplay = xyes)
-
-dnl --------------------------------- wavpack ---------------------------------
-MPD_AUTO_PKG(wavpack, WAVPACK, [wavpack],
- [WavPack decoder plugin], [libwavpack not found])
-AM_CONDITIONAL(HAVE_WAVPACK, test x$enable_wavpack = xyes)
-if test x$enable_wavpack = xyes; then
- AC_DEFINE([HAVE_WAVPACK], 1, [Define to enable WavPack support])
-fi
-
-dnl --------------------------------- WildMidi --------------------------------
-if test x$enable_wildmidi = xyes; then
- oldcflags=$CFLAGS
- oldlibs=$LIBS
- oldcppflags=$CPPFLAGS
-
- AC_CHECK_LIB(WildMidi, WildMidi_Init,,
- AC_MSG_ERROR([libwildmidi not found]))
-
- AC_CHECK_LIB(WildMidi, WildMidi_SampledSeek,
- [AC_DEFINE(HAVE_WILDMIDI_SAMPLED_SEEK, 1,
- [Defined if WildMidi_SampledSeek() is available (libwildmidi <= 0.2.2)])])
-
- CFLAGS=$oldcflags
- LIBS=$oldlibs
- CPPFLAGS=$oldcppflags
-
- AC_SUBST(WILDMIDI_LIBS,-lWildMidi)
- AC_SUBST(WILDMIDI_CFLAGS,)
-
- AC_DEFINE(ENABLE_WILDMIDI, 1, [Define for wildmidi support])
-fi
-
-AM_CONDITIONAL(ENABLE_WILDMIDI, test x$enable_wildmidi = xyes)
-
-dnl ------------------------ Post Decoder Plugins Tests -----------------------
-
-if
- test x$enable_aac = xno &&
- test x$enable_audiofile = xno &&
- test x$enable_ffmpeg = xno &&
- test x$enable_flac = xno &&
- test x$enable_fluidsynth = xno &&
- test x$enable_mad = xno &&
- test x$enable_mikmod = xno; then
- test x$enable_modplug = xno &&
- test x$enable_mp4 = xno &&
- test x$enable_mpc = xno &&
- test x$enable_mpg123 = xno &&
- test x$enable_sidplay = xno &&
- test x$enable_tremor = xno &&
- test x$enable_vorbis = xno &&
- test x$enable_wavpack = xno &&
- test x$enable_wildmidi = xno &&
-
- AC_MSG_ERROR([No input plugins supported!])
-fi
-
-AM_CONDITIONAL(HAVE_OGG_COMMON,
- test x$enable_vorbis = xyes || test x$enable_tremor = xyes || test x$enable_flac = xyes)
-
-AM_CONDITIONAL(HAVE_FLAC_COMMON,
- test x$enable_flac = xyes)
-
dnl ---------------------------------------------------------------------------
dnl Encoders for Streaming Audio Output Plugins
dnl ---------------------------------------------------------------------------
@@ -1291,6 +926,14 @@ if test x$enable_jack = xyes; then
LIBS=$old_LIBS
fi
+enable_shout2="$enable_shout"
+MPD_AUTO_PKG(shout, SHOUT, [shout],
+ [shout output plugin], [libshout not found])
+if test x$enable_shout = xyes && test x$enable_shout2 = xauto; then
+ enable_shout=auto
+fi
+
+
AM_CONDITIONAL(HAVE_JACK, test x$enable_jack = xyes)
dnl ---------------------------------- libao ----------------------------------
@@ -1539,26 +1182,7 @@ results(tcp, "TCP")
results(un,[UNIX Domain Sockets])
printf '\nFile format support:\n\t'
-results(aac, [AAC])
-results(sidplay, [C64 SID])
results(ffmpeg, [FFMPEG])
-results(flac, [FLAC])
-results(fluidsynth, [FluidSynth])
-results(gme, [GME])
-results(sndfile, [libsndfile])
-printf '\n\t'
-results(mikmod, [MikMod])
-results(modplug, [MODPLUG])
-results(mad, [MAD])
-results(mpg123, [MPG123])
-results(mp4, [MP4])
-results(mpc, [Musepack])
-printf '\n\t'
-results(tremor, [OggTremor])
-results(vorbis, [OggVorbis])
-results(audiofile, [WAVE])
-results(wavpack, [WavPack])
-results(wildmidi, [WildMidi])
printf '\nOther features:\n\t'
results(lsr, [libsamplerate])
diff --git a/src/decoder/_flac_common.c b/src/decoder/_flac_common.c
deleted file mode 100644
index bab3995f..00000000
--- a/src/decoder/_flac_common.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-/*
- * Common data structures and functions used by FLAC and OggFLAC
- */
-
-#include "config.h"
-#include "_flac_common.h"
-#include "flac_metadata.h"
-#include "flac_pcm.h"
-#include "audio_check.h"
-
-#include <glib.h>
-
-#include <assert.h>
-
-void
-flac_data_init(struct flac_data *data, struct decoder * decoder,
- struct input_stream *input_stream)
-{
- pcm_buffer_init(&data->buffer);
-
- data->unsupported = false;
- data->initialized = false;
- data->total_frames = 0;
- data->first_frame = 0;
- data->next_frame = 0;
-
- data->position = 0;
- data->decoder = decoder;
- data->input_stream = input_stream;
- data->tag = NULL;
-}
-
-void
-flac_data_deinit(struct flac_data *data)
-{
- pcm_buffer_deinit(&data->buffer);
-
- if (data->tag != NULL)
- tag_free(data->tag);
-}
-
-static enum sample_format
-flac_sample_format(unsigned bits_per_sample)
-{
- switch (bits_per_sample) {
- case 8:
- return SAMPLE_FORMAT_S8;
-
- case 16:
- return SAMPLE_FORMAT_S16;
-
- case 24:
- return SAMPLE_FORMAT_S24_P32;
-
- case 32:
- return SAMPLE_FORMAT_S32;
-
- default:
- return SAMPLE_FORMAT_UNDEFINED;
- }
-}
-
-static void
-flac_got_stream_info(struct flac_data *data,
- const FLAC__StreamMetadata_StreamInfo *stream_info)
-{
- if (data->initialized || data->unsupported)
- return;
-
- GError *error = NULL;
- if (!audio_format_init_checked(&data->audio_format,
- stream_info->sample_rate,
- flac_sample_format(stream_info->bits_per_sample),
- stream_info->channels, &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- data->unsupported = true;
- return;
- }
-
- data->frame_size = audio_format_frame_size(&data->audio_format);
-
- if (data->total_frames == 0)
- data->total_frames = stream_info->total_samples;
-
- data->initialized = true;
-}
-
-void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
- struct flac_data *data)
-{
- if (data->unsupported)
- return;
-
- struct replay_gain_info rgi;
- char *mixramp_start;
- char *mixramp_end;
- float replay_gain_db = 0;
-
- switch (block->type) {
- case FLAC__METADATA_TYPE_STREAMINFO:
- flac_got_stream_info(data, &block->data.stream_info);
- break;
-
- case FLAC__METADATA_TYPE_VORBIS_COMMENT:
- if (flac_parse_replay_gain(&rgi, block))
- replay_gain_db = decoder_replay_gain(data->decoder, &rgi);
- if (flac_parse_mixramp(&mixramp_start, &mixramp_end, block)) {
- g_debug("setting mixramp_tags");
- decoder_mixramp(data->decoder, replay_gain_db,
- mixramp_start, mixramp_end);
- }
-
- if (data->tag != NULL)
- flac_vorbis_comments_to_tag(data->tag, NULL,
- &block->data.vorbis_comment);
-
- default:
- break;
- }
-}
-
-void flac_error_common_cb(const FLAC__StreamDecoderErrorStatus status,
- struct flac_data *data)
-{
- if (decoder_get_command(data->decoder) == DECODE_COMMAND_STOP)
- return;
-
- g_warning("%s", FLAC__StreamDecoderErrorStatusString[status]);
-}
-
-/**
- * This function attempts to call decoder_initialized() in case there
- * was no STREAMINFO block. This is allowed for nonseekable streams,
- * where the server sends us only a part of the file, without
- * providing the STREAMINFO block from the beginning of the file
- * (e.g. when seeking with SqueezeBox Server).
- */
-static bool
-flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header)
-{
- if (data->unsupported)
- return false;
-
- GError *error = NULL;
- if (!audio_format_init_checked(&data->audio_format,
- header->sample_rate,
- flac_sample_format(header->bits_per_sample),
- header->channels, &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- data->unsupported = true;
- return false;
- }
-
- data->frame_size = audio_format_frame_size(&data->audio_format);
-
- decoder_initialized(data->decoder, &data->audio_format,
- data->input_stream->seekable,
- (float)data->total_frames /
- (float)data->audio_format.sample_rate);
-
- data->initialized = true;
-
- return true;
-}
-
-FLAC__StreamDecoderWriteStatus
-flac_common_write(struct flac_data *data, const FLAC__Frame * frame,
- const FLAC__int32 *const buf[],
- FLAC__uint64 nbytes)
-{
- enum decoder_command cmd;
- void *buffer;
- unsigned bit_rate;
-
- if (!data->initialized && !flac_got_first_frame(data, &frame->header))
- return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
-
- size_t buffer_size = frame->header.blocksize * data->frame_size;
- buffer = pcm_buffer_get(&data->buffer, buffer_size);
-
- flac_convert(buffer, frame->header.channels,
- data->audio_format.format, buf,
- 0, frame->header.blocksize);
-
- if (nbytes > 0)
- bit_rate = nbytes * 8 * frame->header.sample_rate /
- (1000 * frame->header.blocksize);
- else
- bit_rate = 0;
-
- cmd = decoder_data(data->decoder, data->input_stream,
- buffer, buffer_size,
- bit_rate);
- data->next_frame += frame->header.blocksize;
- switch (cmd) {
- case DECODE_COMMAND_NONE:
- case DECODE_COMMAND_START:
- break;
-
- case DECODE_COMMAND_STOP:
- return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
-
- case DECODE_COMMAND_SEEK:
- return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
- }
-
- return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
-}
diff --git a/src/decoder/_flac_common.h b/src/decoder/_flac_common.h
deleted file mode 100644
index 0d90ba65..00000000
--- a/src/decoder/_flac_common.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-/*
- * Common data structures and functions used by FLAC and OggFLAC
- */
-
-#ifndef MPD_FLAC_COMMON_H
-#define MPD_FLAC_COMMON_H
-
-#include "decoder_api.h"
-#include "pcm_buffer.h"
-
-#include <glib.h>
-
-#include <FLAC/stream_decoder.h>
-#include <FLAC/metadata.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "flac"
-
-struct flac_data {
- struct pcm_buffer buffer;
-
- /**
- * The size of one frame in the output buffer.
- */
- unsigned frame_size;
-
- /**
- * Has decoder_initialized() been called yet?
- */
- bool initialized;
-
- /**
- * Does the FLAC file contain an unsupported audio format?
- */
- bool unsupported;
-
- /**
- * The validated audio format of the FLAC file. This
- * attribute is defined if "initialized" is true.
- */
- struct audio_format audio_format;
-
- /**
- * The total number of frames in this song. The decoder
- * plugin may initialize this attribute to override the value
- * provided by libFLAC (e.g. for sub songs from a CUE sheet).
- */
- FLAC__uint64 total_frames;
-
- /**
- * The number of the first frame in this song. This is only
- * non-zero if playing sub songs from a CUE sheet.
- */
- FLAC__uint64 first_frame;
-
- /**
- * The number of the next frame which is going to be decoded.
- */
- FLAC__uint64 next_frame;
-
- FLAC__uint64 position;
- struct decoder *decoder;
- struct input_stream *input_stream;
- struct tag *tag;
-};
-
-/* initializes a given FlacData struct */
-void
-flac_data_init(struct flac_data *data, struct decoder * decoder,
- struct input_stream *input_stream);
-
-void
-flac_data_deinit(struct flac_data *data);
-
-void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
- struct flac_data *data);
-
-void flac_error_common_cb(FLAC__StreamDecoderErrorStatus status,
- struct flac_data *data);
-
-FLAC__StreamDecoderWriteStatus
-flac_common_write(struct flac_data *data, const FLAC__Frame * frame,
- const FLAC__int32 *const buf[],
- FLAC__uint64 nbytes);
-
-#endif /* _FLAC_COMMON_H */
diff --git a/src/decoder/_ogg_common.c b/src/decoder/_ogg_common.c
deleted file mode 100644
index bedd3de6..00000000
--- a/src/decoder/_ogg_common.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-/*
- * Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC)
- */
-
-#include "config.h"
-#include "_ogg_common.h"
-
-ogg_stream_type ogg_stream_type_detect(struct input_stream *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;
-
- r = decoder_read(NULL, inStream, buf, sizeof(buf));
- 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;
-}
diff --git a/src/decoder/_ogg_common.h b/src/decoder/_ogg_common.h
deleted file mode 100644
index 85e4ebba..00000000
--- a/src/decoder/_ogg_common.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-/*
- * Common functions used for Ogg data streams (Ogg-Vorbis and OggFLAC)
- */
-
-#ifndef MPD_OGG_COMMON_H
-#define MPD_OGG_COMMON_H
-
-#include "decoder_api.h"
-
-typedef enum _ogg_stream_type { VORBIS, FLAC } ogg_stream_type;
-
-ogg_stream_type ogg_stream_type_detect(struct input_stream *inStream);
-
-#endif /* _OGG_COMMON_H */
diff --git a/src/decoder/audiofile_decoder_plugin.c b/src/decoder/audiofile_decoder_plugin.c
deleted file mode 100644
index b344795e..00000000
--- a/src/decoder/audiofile_decoder_plugin.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "audio_check.h"
-#include "tag_handler.h"
-
-#include <audiofile.h>
-#include <af_vfs.h>
-#include <assert.h>
-#include <glib.h>
-#include <stdio.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "audiofile"
-
-/* pick 1020 since its devisible for 8,16,24, and 32-bit audio */
-#define CHUNK_SIZE 1020
-
-static int audiofile_get_duration(const char *file)
-{
- int total_time;
- AFfilehandle af_fp = afOpenFile(file, "r", NULL);
- if (af_fp == AF_NULL_FILEHANDLE) {
- return -1;
- }
- total_time = (int)
- ((double)afGetFrameCount(af_fp, AF_DEFAULT_TRACK)
- / afGetRate(af_fp, AF_DEFAULT_TRACK));
- afCloseFile(af_fp);
- return total_time;
-}
-
-static ssize_t
-audiofile_file_read(AFvirtualfile *vfile, void *data, size_t length)
-{
- struct input_stream *is = (struct input_stream *) vfile->closure;
- GError *error = NULL;
- size_t nbytes;
-
- nbytes = input_stream_lock_read(is, data, length, &error);
- if (nbytes == 0 && error != NULL) {
- g_warning("%s", error->message);
- g_error_free(error);
- return -1;
- }
-
- return nbytes;
-}
-
-static AFfileoffset
-audiofile_file_length(AFvirtualfile *vfile)
-{
- struct input_stream *is = (struct input_stream *) vfile->closure;
- return is->size;
-}
-
-static AFfileoffset
-audiofile_file_tell(AFvirtualfile *vfile)
-{
- struct input_stream *is = (struct input_stream *) vfile->closure;
- return is->offset;
-}
-
-static void
-audiofile_file_destroy(AFvirtualfile *vfile)
-{
- assert(vfile->closure != NULL);
-
- vfile->closure = NULL;
-}
-
-static AFfileoffset
-audiofile_file_seek(AFvirtualfile *vfile, AFfileoffset offset, int is_relative)
-{
- struct input_stream *is = (struct input_stream *) vfile->closure;
- int whence = (is_relative ? SEEK_CUR : SEEK_SET);
- if (input_stream_lock_seek(is, offset, whence, NULL)) {
- return is->offset;
- } else {
- return -1;
- }
-}
-
-static AFvirtualfile *
-setup_virtual_fops(struct input_stream *stream)
-{
- AFvirtualfile *vf = g_malloc(sizeof(AFvirtualfile));
- vf->closure = stream;
- vf->write = NULL;
- vf->read = audiofile_file_read;
- vf->length = audiofile_file_length;
- vf->destroy = audiofile_file_destroy;
- vf->seek = audiofile_file_seek;
- vf->tell = audiofile_file_tell;
- return vf;
-}
-
-static enum sample_format
-audiofile_bits_to_sample_format(int bits)
-{
- switch (bits) {
- case 8:
- return SAMPLE_FORMAT_S8;
-
- case 16:
- return SAMPLE_FORMAT_S16;
-
- case 24:
- return SAMPLE_FORMAT_S24_P32;
-
- case 32:
- return SAMPLE_FORMAT_S32;
- }
-
- return SAMPLE_FORMAT_UNDEFINED;
-}
-
-static enum sample_format
-audiofile_setup_sample_format(AFfilehandle af_fp)
-{
- int fs, bits;
-
- afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
- if (!audio_valid_sample_format(audiofile_bits_to_sample_format(bits))) {
- g_debug("input file has %d bit samples, converting to 16",
- bits);
- bits = 16;
- }
-
- afSetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK,
- AF_SAMPFMT_TWOSCOMP, bits);
- afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
-
- return audiofile_bits_to_sample_format(bits);
-}
-
-static void
-audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
-{
- GError *error = NULL;
- AFvirtualfile *vf;
- int fs, frame_count;
- AFfilehandle af_fp;
- struct audio_format audio_format;
- float total_time;
- uint16_t bit_rate;
- int ret;
- char chunk[CHUNK_SIZE];
- enum decoder_command cmd;
-
- if (!is->seekable) {
- g_warning("not seekable");
- return;
- }
-
- vf = setup_virtual_fops(is);
-
- af_fp = afOpenVirtualFile(vf, "r", NULL);
- if (af_fp == AF_NULL_FILEHANDLE) {
- g_warning("failed to input stream\n");
- return;
- }
-
- if (!audio_format_init_checked(&audio_format,
- afGetRate(af_fp, AF_DEFAULT_TRACK),
- audiofile_setup_sample_format(af_fp),
- afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK),
- &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- afCloseFile(af_fp);
- return;
- }
-
- frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);
-
- total_time = ((float)frame_count / (float)audio_format.sample_rate);
-
- bit_rate = (uint16_t)(is->size * 8.0 / total_time / 1000.0 + 0.5);
-
- fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);
-
- decoder_initialized(decoder, &audio_format, true, total_time);
-
- do {
- ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,
- CHUNK_SIZE / fs);
- if (ret <= 0)
- break;
-
- cmd = decoder_data(decoder, NULL,
- chunk, ret * fs,
- bit_rate);
-
- if (cmd == DECODE_COMMAND_SEEK) {
- AFframecount frame = decoder_seek_where(decoder) *
- audio_format.sample_rate;
- afSeekFrame(af_fp, AF_DEFAULT_TRACK, frame);
-
- decoder_command_finished(decoder);
- cmd = DECODE_COMMAND_NONE;
- }
- } while (cmd == DECODE_COMMAND_NONE);
-
- afCloseFile(af_fp);
-}
-
-static bool
-audiofile_scan_file(const char *file,
- const struct tag_handler *handler, void *handler_ctx)
-{
- int total_time = audiofile_get_duration(file);
-
- if (total_time < 0) {
- g_debug("Failed to get total song time from: %s\n",
- file);
- return false;
- }
-
- tag_handler_invoke_duration(handler, handler_ctx, total_time);
- return true;
-}
-
-static const char *const audiofile_suffixes[] = {
- "wav", "au", "aiff", "aif", NULL
-};
-
-static const char *const audiofile_mime_types[] = {
- "audio/x-wav",
- "audio/x-aiff",
- NULL
-};
-
-const struct decoder_plugin audiofile_decoder_plugin = {
- .name = "audiofile",
- .stream_decode = audiofile_stream_decode,
- .scan_file = audiofile_scan_file,
- .suffixes = audiofile_suffixes,
- .mime_types = audiofile_mime_types,
-};
diff --git a/src/decoder/dsdiff_decoder_plugin.c b/src/decoder/dsdiff_decoder_plugin.c
deleted file mode 100644
index 84471fb3..00000000
--- a/src/decoder/dsdiff_decoder_plugin.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2003-2012 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.
- */
-
-/* \file
- *
- * This plugin decodes DSDIFF data (SACD) embedded in DFF files.
- * The DFF code was modeled after the specification found here:
- * http://www.sonicstudio.com/pdf/dsd/DSDIFF_1.5_Spec.pdf
- *
- * All functions common to both DSD decoders have been moved to dsdlib
- */
-
-#include "config.h"
-#include "dsdiff_decoder_plugin.h"
-#include "decoder_api.h"
-#include "audio_check.h"
-#include "util/bit_reverse.h"
-#include "tag_handler.h"
-#include "dsdlib.h"
-#include "tag_handler.h"
-
-#include <unistd.h>
-#include <stdio.h> /* for SEEK_SET, SEEK_CUR */
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "dsdiff"
-
-struct dsdiff_header {
- struct dsdlib_id id;
- uint32_t size_high, size_low;
- struct dsdlib_id format;
-};
-
-struct dsdiff_chunk_header {
- struct dsdlib_id id;
- uint32_t size_high, size_low;
-};
-
-struct dsdiff_metadata {
- unsigned sample_rate, channels;
- bool bitreverse;
- uint64_t chunk_size;
-};
-
-static bool lsbitfirst;
-
-static bool
-dsdiff_init(const struct config_param *param)
-{
- lsbitfirst = config_get_block_bool(param, "lsbitfirst", false);
- return true;
-}
-
-/**
- * Read the "size" attribute from the specified header, converting it
- * to the host byte order if needed.
- */
-G_GNUC_CONST
-static uint64_t
-dsdiff_chunk_size(const struct dsdiff_chunk_header *header)
-{
- return (((uint64_t)GUINT32_FROM_BE(header->size_high)) << 32) |
- ((uint64_t)GUINT32_FROM_BE(header->size_low));
-}
-
-static bool
-dsdiff_read_id(struct decoder *decoder, struct input_stream *is,
- struct dsdlib_id *id)
-{
- return dsdlib_read(decoder, is, id, sizeof(*id));
-}
-
-static bool
-dsdiff_read_chunk_header(struct decoder *decoder, struct input_stream *is,
- struct dsdiff_chunk_header *header)
-{
- return dsdlib_read(decoder, is, header, sizeof(*header));
-}
-
-static bool
-dsdiff_read_payload(struct decoder *decoder, struct input_stream *is,
- const struct dsdiff_chunk_header *header,
- void *data, size_t length)
-{
- uint64_t size = dsdiff_chunk_size(header);
- if (size != (uint64_t)length)
- return false;
-
- size_t nbytes = decoder_read(decoder, is, data, length);
- return nbytes == length;
-}
-
-/**
- * Read and parse a "SND" chunk inside "PROP".
- */
-static bool
-dsdiff_read_prop_snd(struct decoder *decoder, struct input_stream *is,
- struct dsdiff_metadata *metadata,
- goffset end_offset)
-{
- struct dsdiff_chunk_header header;
- while ((goffset)(is->offset + sizeof(header)) <= end_offset) {
- if (!dsdiff_read_chunk_header(decoder, is, &header))
- return false;
-
- goffset chunk_end_offset =
- is->offset + dsdiff_chunk_size(&header);
- if (chunk_end_offset > end_offset)
- return false;
-
- if (dsdlib_id_equals(&header.id, "FS ")) {
- uint32_t sample_rate;
- if (!dsdiff_read_payload(decoder, is, &header,
- &sample_rate,
- sizeof(sample_rate)))
- return false;
-
- metadata->sample_rate = GUINT32_FROM_BE(sample_rate);
- } else if (dsdlib_id_equals(&header.id, "CHNL")) {
- uint16_t channels;
- if (dsdiff_chunk_size(&header) < sizeof(channels) ||
- !dsdlib_read(decoder, is,
- &channels, sizeof(channels)) ||
- !dsdlib_skip_to(decoder, is, chunk_end_offset))
- return false;
-
- metadata->channels = GUINT16_FROM_BE(channels);
- } else if (dsdlib_id_equals(&header.id, "CMPR")) {
- struct dsdlib_id type;
- if (dsdiff_chunk_size(&header) < sizeof(type) ||
- !dsdlib_read(decoder, is,
- &type, sizeof(type)) ||
- !dsdlib_skip_to(decoder, is, chunk_end_offset))
- return false;
-
- if (!dsdlib_id_equals(&type, "DSD "))
- /* only uncompressed DSD audio data
- is implemented */
- return false;
- } else {
- /* ignore unknown chunk */
-
- if (!dsdlib_skip_to(decoder, is, chunk_end_offset))
- return false;
- }
- }
-
- return is->offset == end_offset;
-}
-
-/**
- * Read and parse a "PROP" chunk.
- */
-static bool
-dsdiff_read_prop(struct decoder *decoder, struct input_stream *is,
- struct dsdiff_metadata *metadata,
- const struct dsdiff_chunk_header *prop_header)
-{
- uint64_t prop_size = dsdiff_chunk_size(prop_header);
- goffset end_offset = is->offset + prop_size;
-
- struct dsdlib_id prop_id;
- if (prop_size < sizeof(prop_id) ||
- !dsdiff_read_id(decoder, is, &prop_id))
- return false;
-
- if (dsdlib_id_equals(&prop_id, "SND "))
- return dsdiff_read_prop_snd(decoder, is, metadata, end_offset);
- else
- /* ignore unknown PROP chunk */
- return dsdlib_skip_to(decoder, is, end_offset);
-}
-
-/**
- * Read and parse all metadata chunks at the beginning. Stop when the
- * first "DSD" chunk is seen, and return its header in the
- * "chunk_header" parameter.
- */
-static bool
-dsdiff_read_metadata(struct decoder *decoder, struct input_stream *is,
- struct dsdiff_metadata *metadata,
- struct dsdiff_chunk_header *chunk_header)
-{
- struct dsdiff_header header;
- if (!dsdlib_read(decoder, is, &header, sizeof(header)) ||
- !dsdlib_id_equals(&header.id, "FRM8") ||
- !dsdlib_id_equals(&header.format, "DSD "))
- return false;
-
- while (true) {
- if (!dsdiff_read_chunk_header(decoder, is,
- chunk_header))
- return false;
-
- if (dsdlib_id_equals(&chunk_header->id, "PROP")) {
- if (!dsdiff_read_prop(decoder, is, metadata,
- chunk_header))
- return false;
- } else if (dsdlib_id_equals(&chunk_header->id, "DSD ")) {
- uint64_t chunk_size;
- chunk_size = dsdiff_chunk_size(chunk_header);
- metadata->chunk_size = chunk_size;
- return true;
- } else {
- /* ignore unknown chunk */
- uint64_t chunk_size;
- chunk_size = dsdiff_chunk_size(chunk_header);
- goffset chunk_end_offset = is->offset + chunk_size;
-
- if (!dsdlib_skip_to(decoder, is, chunk_end_offset))
- return false;
- }
- }
-}
-
-static void
-bit_reverse_buffer(uint8_t *p, uint8_t *end)
-{
- for (; p < end; ++p)
- *p = bit_reverse(*p);
-}
-
-/**
- * Decode one "DSD" chunk.
- */
-static bool
-dsdiff_decode_chunk(struct decoder *decoder, struct input_stream *is,
- unsigned channels,
- uint64_t chunk_size)
-{
- uint8_t buffer[8192];
-
- const size_t sample_size = sizeof(buffer[0]);
- const size_t frame_size = channels * sample_size;
- const unsigned buffer_frames = sizeof(buffer) / frame_size;
- const unsigned buffer_samples = buffer_frames * frame_size;
- const size_t buffer_size = buffer_samples * sample_size;
-
- while (chunk_size > 0) {
- /* see how much aligned data from the remaining chunk
- fits into the local buffer */
- unsigned now_frames = buffer_frames;
- size_t now_size = buffer_size;
- if (chunk_size < (uint64_t)now_size) {
- now_frames = (unsigned)chunk_size / frame_size;
- now_size = now_frames * frame_size;
- }
-
- size_t nbytes = decoder_read(decoder, is, buffer, now_size);
- if (nbytes != now_size)
- return false;
-
- chunk_size -= nbytes;
-
- if (lsbitfirst)
- bit_reverse_buffer(buffer, buffer + nbytes);
-
- enum decoder_command cmd =
- decoder_data(decoder, is, buffer, nbytes, 0);
- switch (cmd) {
- case DECODE_COMMAND_NONE:
- break;
-
- case DECODE_COMMAND_START:
- case DECODE_COMMAND_STOP:
- return false;
-
- case DECODE_COMMAND_SEEK:
-
- /* Not implemented yet */
- decoder_seek_error(decoder);
- break;
- }
- }
- return dsdlib_skip(decoder, is, chunk_size);
-}
-
-static void
-dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
-{
- struct dsdiff_metadata metadata = {
- .sample_rate = 0,
- .channels = 0,
- };
-
- struct dsdiff_chunk_header chunk_header;
- /* check if it is is a proper DFF file */
- if (!dsdiff_read_metadata(decoder, is, &metadata, &chunk_header))
- return;
-
- GError *error = NULL;
- struct audio_format audio_format;
- if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
- SAMPLE_FORMAT_DSD,
- metadata.channels, &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- return;
- }
-
- /* calculate song time from DSD chunk size and sample frequency */
- uint64_t chunk_size = metadata.chunk_size;
- float songtime = ((chunk_size / metadata.channels) * 8) /
- (float) metadata.sample_rate;
-
- /* success: file was recognized */
- decoder_initialized(decoder, &audio_format, false, songtime);
-
- /* every iteration of the following loop decodes one "DSD"
- chunk from a DFF file */
-
- while (true) {
- chunk_size = dsdiff_chunk_size(&chunk_header);
-
- if (dsdlib_id_equals(&chunk_header.id, "DSD ")) {
- if (!dsdiff_decode_chunk(decoder, is,
- metadata.channels,
- chunk_size))
- break;
- } else {
- /* ignore other chunks */
- if (!dsdlib_skip(decoder, is, chunk_size))
- break;
- }
-
- /* read next chunk header; the first one was read by
- dsdiff_read_metadata() */
- if (!dsdiff_read_chunk_header(decoder,
- is, &chunk_header))
- break;
- }
-}
-
-static bool
-dsdiff_scan_stream(struct input_stream *is,
- G_GNUC_UNUSED const struct tag_handler *handler,
- G_GNUC_UNUSED void *handler_ctx)
-{
- struct dsdiff_metadata metadata = {
- .sample_rate = 0,
- .channels = 0,
- };
-
- struct dsdiff_chunk_header chunk_header;
- /* First check for DFF metadata */
- if (!dsdiff_read_metadata(NULL, is, &metadata, &chunk_header))
- return false;
-
- struct audio_format audio_format;
- if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
- SAMPLE_FORMAT_DSD,
- metadata.channels, NULL))
- /* refuse to parse files which we cannot play anyway */
- return false;
-
- /* calculate song time and add as tag */
- unsigned songtime = ((metadata.chunk_size / metadata.channels) * 8) /
- metadata.sample_rate;
- tag_handler_invoke_duration(handler, handler_ctx, songtime);
-
- return true;
-}
-
-static const char *const dsdiff_suffixes[] = {
- "dff",
- NULL
-};
-
-static const char *const dsdiff_mime_types[] = {
- "application/x-dff",
- NULL
-};
-
-const struct decoder_plugin dsdiff_decoder_plugin = {
- .name = "dsdiff",
- .init = dsdiff_init,
- .stream_decode = dsdiff_stream_decode,
- .scan_stream = dsdiff_scan_stream,
- .suffixes = dsdiff_suffixes,
- .mime_types = dsdiff_mime_types,
-};
diff --git a/src/decoder/dsdiff_decoder_plugin.h b/src/decoder/dsdiff_decoder_plugin.h
deleted file mode 100644
index 452f9050..00000000
--- a/src/decoder/dsdiff_decoder_plugin.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2003-2012 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.
- */
-
-#ifndef MPD_DECODER_DSDIFF_H
-#define MPD_DECODER_DSDIFF_H
-
-extern const struct decoder_plugin dsdiff_decoder_plugin;
-
-#endif
diff --git a/src/decoder/dsdlib.c b/src/decoder/dsdlib.c
deleted file mode 100644
index 3df9497c..00000000
--- a/src/decoder/dsdlib.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-/* \file
- *
- * This file contains functions used by the DSF and DSDIFF decoders.
- *
- */
-
-#include "config.h"
-#include "dsf_decoder_plugin.h"
-#include "decoder_api.h"
-#include "util/bit_reverse.h"
-#include "dsdlib.h"
-#include "dsdiff_decoder_plugin.h"
-
-#include <unistd.h>
-#include <stdio.h> /* for SEEK_SET, SEEK_CUR */
-
-bool
-dsdlib_id_equals(const struct dsdlib_id *id, const char *s)
-{
- assert(id != NULL);
- assert(s != NULL);
- assert(strlen(s) == sizeof(id->value));
-
- return memcmp(id->value, s, sizeof(id->value)) == 0;
-}
-
-bool
-dsdlib_read(struct decoder *decoder, struct input_stream *is,
- void *data, size_t length)
-{
- size_t nbytes = decoder_read(decoder, is, data, length);
- return nbytes == length;
-}
-
-/**
- * Skip the #input_stream to the specified offset.
- */
-bool
-dsdlib_skip_to(struct decoder *decoder, struct input_stream *is,
- goffset offset)
-{
- if (is->seekable)
- return input_stream_seek(is, offset, SEEK_SET, NULL);
-
- if (is->offset > offset)
- return false;
-
- char buffer[8192];
- while (is->offset < offset) {
- size_t length = sizeof(buffer);
- if (offset - is->offset < (goffset)length)
- length = offset - is->offset;
-
- size_t nbytes = decoder_read(decoder, is, buffer, length);
- if (nbytes == 0)
- return false;
- }
-
- assert(is->offset == offset);
- return true;
-}
-
-/**
- * Skip some bytes from the #input_stream.
- */
-bool
-dsdlib_skip(struct decoder *decoder, struct input_stream *is,
- goffset delta)
-{
- assert(delta >= 0);
-
- if (delta == 0)
- return true;
-
- if (is->seekable)
- return input_stream_seek(is, delta, SEEK_CUR, NULL);
-
- char buffer[8192];
- while (delta > 0) {
- size_t length = sizeof(buffer);
- if ((goffset)length > delta)
- length = delta;
-
- size_t nbytes = decoder_read(decoder, is, buffer, length);
- if (nbytes == 0)
- return false;
-
- delta -= nbytes;
- }
-
- return true;
-}
-
diff --git a/src/decoder/dsdlib.h b/src/decoder/dsdlib.h
deleted file mode 100644
index d9675f5f..00000000
--- a/src/decoder/dsdlib.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef MPD_DECODER_DSDLIB_H
-#define MPD_DECODER_DSDLIB_H
-
-struct dsdlib_id {
- char value[4];
-};
-
-bool
-dsdlib_id_equals(const struct dsdlib_id *id, const char *s);
-
-bool
-dsdlib_read(struct decoder *decoder, struct input_stream *is,
- void *data, size_t length);
-
-bool
-dsdlib_skip_to(struct decoder *decoder, struct input_stream *is,
- goffset offset);
-
-bool
-dsdlib_skip(struct decoder *decoder, struct input_stream *is,
- goffset delta);
-
-#endif
diff --git a/src/decoder/dsf_decoder_plugin.c b/src/decoder/dsf_decoder_plugin.c
deleted file mode 100644
index c0107eb3..00000000
--- a/src/decoder/dsf_decoder_plugin.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-/* \file
- *
- * This plugin decodes DSDIFF data (SACD) embedded in DSF files.
- *
- * The DSF code was created using the specification found here:
- * http://dsd-guide.com/sonys-dsf-file-format-spec
- *
- * All functions common to both DSD decoders have been moved to dsdlib
- */
-
-#include "config.h"
-#include "dsf_decoder_plugin.h"
-#include "decoder_api.h"
-#include "audio_check.h"
-#include "util/bit_reverse.h"
-#include "dsdlib.h"
-#include "tag_handler.h"
-
-#include <unistd.h>
-#include <stdio.h> /* for SEEK_SET, SEEK_CUR */
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "dsf"
-
-struct dsf_metadata {
- unsigned sample_rate, channels;
- bool bitreverse;
- uint64_t chunk_size;
-};
-
-struct dsf_header {
- /** DSF header id: "DSD " */
- struct dsdlib_id id;
- /** DSD chunk size, including id = 28 */
- uint32_t size_low, size_high;
- /** total file size */
- uint32_t fsize_low, fsize_high;
- /** pointer to id3v2 metadata, should be at the end of the file */
- uint32_t pmeta_low, pmeta_high;
-};
-/** DSF file fmt chunk */
-struct dsf_fmt_chunk {
-
- /** id: "fmt " */
- struct dsdlib_id id;
- /** fmt chunk size, including id, normally 52 */
- uint32_t size_low, size_high;
- /** version of this format = 1 */
- uint32_t version;
- /** 0: DSD raw */
- uint32_t formatid;
- /** channel type, 1 = mono, 2 = stereo, 3 = 3 channels, etc */
- uint32_t channeltype;
- /** Channel number, 1 = mono, 2 = stereo, ... 6 = 6 channels */
- uint32_t channelnum;
- /** sample frequency: 2822400, 5644800 */
- uint32_t sample_freq;
- /** bits per sample 1 or 8 */
- uint32_t bitssample;
- /** Sample count per channel in bytes */
- uint32_t scnt_low, scnt_high;
- /** block size per channel = 4096 */
- uint32_t block_size;
- /** reserved, should be all zero */
- uint32_t reserved;
-};
-
-struct dsf_data_chunk {
- struct dsdlib_id id;
- /** "data" chunk size, includes header (id+size) */
- uint32_t size_low, size_high;
-};
-
-/**
- * Read and parse all needed metadata chunks for DSF files.
- */
-static bool
-dsf_read_metadata(struct decoder *decoder, struct input_stream *is,
- struct dsf_metadata *metadata)
-{
- uint64_t chunk_size;
- struct dsf_header dsf_header;
- if (!dsdlib_read(decoder, is, &dsf_header, sizeof(dsf_header)) ||
- !dsdlib_id_equals(&dsf_header.id, "DSD "))
- return false;
-
- chunk_size = (((uint64_t)GUINT32_FROM_LE(dsf_header.size_high)) << 32) |
- ((uint64_t)GUINT32_FROM_LE(dsf_header.size_low));
-
- if (sizeof(dsf_header) != chunk_size)
- return false;
-
- /* read the 'fmt ' chunk of the DSF file */
- struct dsf_fmt_chunk dsf_fmt_chunk;
- if (!dsdlib_read(decoder, is, &dsf_fmt_chunk, sizeof(dsf_fmt_chunk)) ||
- !dsdlib_id_equals(&dsf_fmt_chunk.id, "fmt "))
- return false;
-
- uint64_t fmt_chunk_size;
- fmt_chunk_size = (((uint64_t)GUINT32_FROM_LE(dsf_fmt_chunk.size_high)) << 32) |
- ((uint64_t)GUINT32_FROM_LE(dsf_fmt_chunk.size_low));
-
- if (fmt_chunk_size != sizeof(dsf_fmt_chunk))
- return false;
-
- uint32_t samplefreq = (uint32_t)GUINT32_FROM_LE(dsf_fmt_chunk.sample_freq);
-
- /* for now, only support version 1 of the standard, DSD raw stereo
- files with a sample freq of 2822400 Hz */
-
- if (dsf_fmt_chunk.version != 1 || dsf_fmt_chunk.formatid != 0
- || dsf_fmt_chunk.channeltype != 2
- || dsf_fmt_chunk.channelnum != 2
- || samplefreq != 2822400)
- return false;
-
- uint32_t chblksize = (uint32_t)GUINT32_FROM_LE(dsf_fmt_chunk.block_size);
- /* according to the spec block size should always be 4096 */
- if (chblksize != 4096)
- return false;
-
- /* read the 'data' chunk of the DSF file */
- struct dsf_data_chunk data_chunk;
- if (!dsdlib_read(decoder, is, &data_chunk, sizeof(data_chunk)) ||
- !dsdlib_id_equals(&data_chunk.id, "data"))
- return false;
-
- /* data size of DSF files are padded to multiple of 4096,
- we use the actual data size as chunk size */
-
- uint64_t data_size;
- data_size = (((uint64_t)GUINT32_FROM_LE(data_chunk.size_high)) << 32) |
- ((uint64_t)GUINT32_FROM_LE(data_chunk.size_low));
- data_size -= sizeof(data_chunk);
-
- metadata->chunk_size = data_size;
- metadata->channels = (unsigned) dsf_fmt_chunk.channelnum;
- metadata->sample_rate = samplefreq;
-
- /* check bits per sample format, determine if bitreverse is needed */
- metadata->bitreverse = dsf_fmt_chunk.bitssample == 1;
- return true;
-}
-
-static void
-bit_reverse_buffer(uint8_t *p, uint8_t *end)
-{
- for (; p < end; ++p)
- *p = bit_reverse(*p);
-}
-
-/**
- * DSF data is build up of alternating 4096 blocks of DSD samples for left and
- * right. Convert the buffer holding 1 block of 4096 DSD left samples and 1
- * block of 4096 DSD right samples to 8k of samples in normal PCM left/right
- * order.
- */
-static void
-dsf_to_pcm_order(uint8_t *dest, uint8_t *scratch, size_t nrbytes)
-{
- for (unsigned i = 0, j = 0; i < (unsigned)nrbytes; i += 2) {
- scratch[i] = *(dest+j);
- j++;
- }
-
- for (unsigned i = 1, j = 0; i < (unsigned) nrbytes; i += 2) {
- scratch[i] = *(dest+4096+j);
- j++;
- }
-
- for (unsigned i = 0; i < (unsigned)nrbytes; i++) {
- *dest = scratch[i];
- dest++;
- }
-}
-
-/**
- * Decode one complete DSF 'data' chunk i.e. a complete song
- */
-static bool
-dsf_decode_chunk(struct decoder *decoder, struct input_stream *is,
- unsigned channels,
- uint64_t chunk_size,
- bool bitreverse)
-{
- uint8_t buffer[8192];
-
- /* scratch buffer for DSF samples to convert to the needed
- normal left/right regime of samples */
- uint8_t dsf_scratch_buffer[8192];
-
- const size_t sample_size = sizeof(buffer[0]);
- const size_t frame_size = channels * sample_size;
- const unsigned buffer_frames = sizeof(buffer) / frame_size;
- const unsigned buffer_samples = buffer_frames * frame_size;
- const size_t buffer_size = buffer_samples * sample_size;
-
- while (chunk_size > 0) {
- /* see how much aligned data from the remaining chunk
- fits into the local buffer */
- unsigned now_frames = buffer_frames;
- size_t now_size = buffer_size;
- if (chunk_size < (uint64_t)now_size) {
- now_frames = (unsigned)chunk_size / frame_size;
- now_size = now_frames * frame_size;
- }
-
- size_t nbytes = decoder_read(decoder, is, buffer, now_size);
- if (nbytes != now_size)
- return false;
-
- chunk_size -= nbytes;
-
- if (bitreverse)
- bit_reverse_buffer(buffer, buffer + nbytes);
-
- dsf_to_pcm_order(buffer, dsf_scratch_buffer, nbytes);
-
- enum decoder_command cmd =
- decoder_data(decoder, is, buffer, nbytes, 0);
- switch (cmd) {
- case DECODE_COMMAND_NONE:
- break;
-
- case DECODE_COMMAND_START:
- case DECODE_COMMAND_STOP:
- return false;
-
- case DECODE_COMMAND_SEEK:
-
- /* not implemented yet */
- decoder_seek_error(decoder);
- break;
- }
- }
- return dsdlib_skip(decoder, is, chunk_size);
-}
-
-static void
-dsf_stream_decode(struct decoder *decoder, struct input_stream *is)
-{
- struct dsf_metadata metadata = {
- .sample_rate = 0,
- .channels = 0,
- };
-
- /* check if it is a proper DSF file */
- if (!dsf_read_metadata(decoder, is, &metadata))
- return;
-
- GError *error = NULL;
- struct audio_format audio_format;
- if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
- SAMPLE_FORMAT_DSD,
- metadata.channels, &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- return;
- }
- /* Calculate song time from DSD chunk size and sample frequency */
- uint64_t chunk_size = metadata.chunk_size;
- float songtime = ((chunk_size / metadata.channels) * 8) /
- (float) metadata.sample_rate;
-
- /* success: file was recognized */
- decoder_initialized(decoder, &audio_format, false, songtime);
-
- if (!dsf_decode_chunk(decoder, is, metadata.channels,
- metadata.chunk_size,
- metadata.bitreverse))
- return;
-}
-
-static bool
-dsf_scan_stream(struct input_stream *is,
- G_GNUC_UNUSED const struct tag_handler *handler,
- G_GNUC_UNUSED void *handler_ctx)
-{
- struct dsf_metadata metadata = {
- .sample_rate = 0,
- .channels = 0,
- };
-
- /* check DSF metadata */
- if (!dsf_read_metadata(NULL, is, &metadata))
- return false;
-
- struct audio_format audio_format;
- if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
- SAMPLE_FORMAT_DSD,
- metadata.channels, NULL))
- /* refuse to parse files which we cannot play anyway */
- return false;
-
- /* calculate song time and add as tag */
- unsigned songtime = ((metadata.chunk_size / metadata.channels) * 8) /
- metadata.sample_rate;
- tag_handler_invoke_duration(handler, handler_ctx, songtime);
-
- return true;
-}
-
-static const char *const dsf_suffixes[] = {
- "dsf",
- NULL
-};
-
-static const char *const dsf_mime_types[] = {
- "application/x-dsf",
- NULL
-};
-
-const struct decoder_plugin dsf_decoder_plugin = {
- .name = "dsf",
- .stream_decode = dsf_stream_decode,
- .scan_stream = dsf_scan_stream,
- .suffixes = dsf_suffixes,
- .mime_types = dsf_mime_types,
-};
diff --git a/src/decoder/dsf_decoder_plugin.h b/src/decoder/dsf_decoder_plugin.h
deleted file mode 100644
index 401d3fed..00000000
--- a/src/decoder/dsf_decoder_plugin.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef MPD_DECODER_DSF_H
-#define MPD_DECODER_DSF_H
-
-extern const struct decoder_plugin dsf_decoder_plugin;
-
-#endif
diff --git a/src/decoder/faad_decoder_plugin.c b/src/decoder/faad_decoder_plugin.c
deleted file mode 100644
index 911f033b..00000000
--- a/src/decoder/faad_decoder_plugin.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "decoder_buffer.h"
-#include "audio_check.h"
-#include "tag_handler.h"
-
-#define AAC_MAX_CHANNELS 6
-
-#include <assert.h>
-#include <unistd.h>
-#include <faad.h>
-#include <glib.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "faad"
-
-static const unsigned adts_sample_rates[] =
- { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
- 16000, 12000, 11025, 8000, 7350, 0, 0, 0
-};
-
-/**
- * The GLib quark used for errors reported by this plugin.
- */
-static inline GQuark
-faad_decoder_quark(void)
-{
- return g_quark_from_static_string("faad");
-}
-
-/**
- * Check whether the buffer head is an AAC frame, and return the frame
- * length. Returns 0 if it is not a frame.
- */
-static size_t
-adts_check_frame(const unsigned char *data)
-{
- /* check syncword */
- if (!((data[0] == 0xFF) && ((data[1] & 0xF6) == 0xF0)))
- return 0;
-
- return (((unsigned int)data[3] & 0x3) << 11) |
- (((unsigned int)data[4]) << 3) |
- (data[5] >> 5);
-}
-
-/**
- * Find the next AAC frame in the buffer. Returns 0 if no frame is
- * found or if not enough data is available.
- */
-static size_t
-adts_find_frame(struct decoder_buffer *buffer)
-{
- const unsigned char *data, *p;
- size_t length, frame_length;
- bool ret;
-
- while (true) {
- data = decoder_buffer_read(buffer, &length);
- if (data == NULL || length < 8) {
- /* not enough data yet */
- ret = decoder_buffer_fill(buffer);
- if (!ret)
- /* failed */
- return 0;
-
- continue;
- }
-
- /* find the 0xff marker */
- p = memchr(data, 0xff, length);
- if (p == NULL) {
- /* no marker - discard the buffer */
- decoder_buffer_consume(buffer, length);
- continue;
- }
-
- if (p > data) {
- /* discard data before 0xff */
- decoder_buffer_consume(buffer, p - data);
- continue;
- }
-
- /* is it a frame? */
- frame_length = adts_check_frame(data);
- if (frame_length == 0) {
- /* it's just some random 0xff byte; discard it
- and continue searching */
- decoder_buffer_consume(buffer, 1);
- continue;
- }
-
- if (length < frame_length) {
- /* available buffer size is smaller than the
- frame will be - attempt to read more
- data */
- ret = decoder_buffer_fill(buffer);
- if (!ret) {
- /* not enough data; discard this frame
- to prevent a possible buffer
- overflow */
- data = decoder_buffer_read(buffer, &length);
- if (data != NULL)
- decoder_buffer_consume(buffer, length);
- }
-
- continue;
- }
-
- /* found a full frame! */
- return frame_length;
- }
-}
-
-static float
-adts_song_duration(struct decoder_buffer *buffer)
-{
- unsigned int frames, frame_length;
- unsigned sample_rate = 0;
- float frames_per_second;
-
- /* Read all frames to ensure correct time and bitrate */
- for (frames = 0;; frames++) {
- frame_length = adts_find_frame(buffer);
- if (frame_length == 0)
- break;
-
-
- if (frames == 0) {
- const unsigned char *data;
- size_t buffer_length;
-
- data = decoder_buffer_read(buffer, &buffer_length);
- assert(data != NULL);
- assert(frame_length <= buffer_length);
-
- sample_rate = adts_sample_rates[(data[2] & 0x3c) >> 2];
- }
-
- decoder_buffer_consume(buffer, frame_length);
- }
-
- frames_per_second = (float)sample_rate / 1024.0;
- if (frames_per_second <= 0)
- return -1;
-
- return (float)frames / frames_per_second;
-}
-
-static float
-faad_song_duration(struct decoder_buffer *buffer, struct input_stream *is)
-{
- size_t fileread;
- size_t tagsize;
- const unsigned char *data;
- size_t length;
- bool success;
-
- fileread = is->size >= 0 ? is->size : 0;
-
- decoder_buffer_fill(buffer);
- data = decoder_buffer_read(buffer, &length);
- if (data == NULL)
- return -1;
-
- tagsize = 0;
- if (length >= 10 && !memcmp(data, "ID3", 3)) {
- /* skip the ID3 tag */
-
- tagsize = (data[6] << 21) | (data[7] << 14) |
- (data[8] << 7) | (data[9] << 0);
-
- tagsize += 10;
-
- success = decoder_buffer_skip(buffer, tagsize) &&
- decoder_buffer_fill(buffer);
- if (!success)
- return -1;
-
- data = decoder_buffer_read(buffer, &length);
- if (data == NULL)
- return -1;
- }
-
- if (is->seekable && length >= 2 &&
- data[0] == 0xFF && ((data[1] & 0xF6) == 0xF0)) {
- /* obtain the duration from the ADTS header */
- float song_length = adts_song_duration(buffer);
-
- input_stream_lock_seek(is, tagsize, SEEK_SET, NULL);
-
- data = decoder_buffer_read(buffer, &length);
- if (data != NULL)
- decoder_buffer_consume(buffer, length);
- decoder_buffer_fill(buffer);
-
- return song_length;
- } else if (length >= 5 && memcmp(data, "ADIF", 4) == 0) {
- /* obtain the duration from the ADIF header */
- unsigned bit_rate;
- size_t skip_size = (data[4] & 0x80) ? 9 : 0;
-
- if (8 + skip_size > length)
- /* not enough data yet; skip parsing this
- header */
- return -1;
-
- bit_rate = ((data[4 + skip_size] & 0x0F) << 19) |
- (data[5 + skip_size] << 11) |
- (data[6 + skip_size] << 3) |
- (data[7 + skip_size] & 0xE0);
-
- if (fileread != 0 && bit_rate != 0)
- return fileread * 8.0 / bit_rate;
- else
- return fileread;
- } else
- return -1;
-}
-
-/**
- * Wrapper for faacDecInit() which works around some API
- * inconsistencies in libfaad.
- */
-static bool
-faad_decoder_init(faacDecHandle decoder, struct decoder_buffer *buffer,
- struct audio_format *audio_format, GError **error_r)
-{
- union {
- /* deconst hack for libfaad */
- const void *in;
- void *out;
- } u;
- size_t length;
- int32_t nbytes;
- uint32_t sample_rate;
- uint8_t channels;
-#ifdef HAVE_FAAD_LONG
- /* neaacdec.h declares all arguments as "unsigned long", but
- internally expects uint32_t pointers. To avoid gcc
- warnings, use this workaround. */
- unsigned long *sample_rate_p = (unsigned long *)(void *)&sample_rate;
-#else
- uint32_t *sample_rate_p = &sample_rate;
-#endif
-
- u.in = decoder_buffer_read(buffer, &length);
- if (u.in == NULL) {
- g_set_error(error_r, faad_decoder_quark(), 0,
- "Empty file");
- return false;
- }
-
- nbytes = faacDecInit(decoder, u.out,
-#ifdef HAVE_FAAD_BUFLEN_FUNCS
- length,
-#endif
- sample_rate_p, &channels);
- if (nbytes < 0) {
- g_set_error(error_r, faad_decoder_quark(), 0,
- "Not an AAC stream");
- return false;
- }
-
- decoder_buffer_consume(buffer, nbytes);
-
- return audio_format_init_checked(audio_format, sample_rate,
- SAMPLE_FORMAT_S16, channels, error_r);
-}
-
-/**
- * Wrapper for faacDecDecode() which works around some API
- * inconsistencies in libfaad.
- */
-static const void *
-faad_decoder_decode(faacDecHandle decoder, struct decoder_buffer *buffer,
- faacDecFrameInfo *frame_info)
-{
- union {
- /* deconst hack for libfaad */
- const void *in;
- void *out;
- } u;
- size_t length;
- void *result;
-
- u.in = decoder_buffer_read(buffer, &length);
- if (u.in == NULL)
- return NULL;
-
- result = faacDecDecode(decoder, frame_info,
- u.out
-#ifdef HAVE_FAAD_BUFLEN_FUNCS
- , length
-#endif
- );
-
- return result;
-}
-
-/**
- * Get a song file's total playing time in seconds, as a float.
- * Returns 0 if the duration is unknown, and a negative value if the
- * file is invalid.
- */
-static float
-faad_get_file_time_float(struct input_stream *is)
-{
- struct decoder_buffer *buffer;
- float length;
- faacDecHandle decoder;
- faacDecConfigurationPtr config;
-
- buffer = decoder_buffer_new(NULL, is,
- FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
- length = faad_song_duration(buffer, is);
-
- if (length < 0) {
- bool ret;
- struct audio_format audio_format;
-
- decoder = faacDecOpen();
-
- config = faacDecGetCurrentConfiguration(decoder);
- config->outputFormat = FAAD_FMT_16BIT;
- faacDecSetConfiguration(decoder, config);
-
- decoder_buffer_fill(buffer);
-
- ret = faad_decoder_init(decoder, buffer, &audio_format, NULL);
- if (ret)
- length = 0;
-
- faacDecClose(decoder);
- }
-
- decoder_buffer_free(buffer);
-
- return length;
-}
-
-/**
- * Get a song file's total playing time in seconds, as an int.
- * Returns 0 if the duration is unknown, and a negative value if the
- * file is invalid.
- */
-static int
-faad_get_file_time(struct input_stream *is)
-{
- int file_time = -1;
- float length;
-
- if ((length = faad_get_file_time_float(is)) >= 0)
- file_time = length + 0.5;
-
- return file_time;
-}
-
-static void
-faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
-{
- GError *error = NULL;
- float total_time = 0;
- faacDecHandle decoder;
- struct audio_format audio_format;
- faacDecConfigurationPtr config;
- bool ret;
- uint16_t bit_rate = 0;
- struct decoder_buffer *buffer;
- enum decoder_command cmd;
-
- buffer = decoder_buffer_new(mpd_decoder, is,
- FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
- total_time = faad_song_duration(buffer, is);
-
- /* create the libfaad decoder */
-
- decoder = faacDecOpen();
-
- config = faacDecGetCurrentConfiguration(decoder);
- config->outputFormat = FAAD_FMT_16BIT;
-#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX
- config->downMatrix = 1;
-#endif
-#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
- config->dontUpSampleImplicitSBR = 0;
-#endif
- faacDecSetConfiguration(decoder, config);
-
- while (!decoder_buffer_is_full(buffer) &&
- !input_stream_lock_eof(is) &&
- decoder_get_command(mpd_decoder) == DECODE_COMMAND_NONE) {
- adts_find_frame(buffer);
- decoder_buffer_fill(buffer);
- }
-
- /* initialize it */
-
- ret = faad_decoder_init(decoder, buffer, &audio_format, &error);
- if (!ret) {
- g_warning("%s", error->message);
- g_error_free(error);
- faacDecClose(decoder);
- return;
- }
-
- /* initialize the MPD core */
-
- decoder_initialized(mpd_decoder, &audio_format, false, total_time);
-
- /* the decoder loop */
-
- do {
- size_t frame_size;
- const void *decoded;
- faacDecFrameInfo frame_info;
-
- /* find the next frame */
-
- frame_size = adts_find_frame(buffer);
- if (frame_size == 0)
- /* end of file */
- break;
-
- /* decode it */
-
- decoded = faad_decoder_decode(decoder, buffer, &frame_info);
-
- if (frame_info.error > 0) {
- g_warning("error decoding AAC stream: %s\n",
- faacDecGetErrorMessage(frame_info.error));
- break;
- }
-
- if (frame_info.channels != audio_format.channels) {
- g_warning("channel count changed from %u to %u",
- audio_format.channels, frame_info.channels);
- break;
- }
-
-#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
- if (frame_info.samplerate != audio_format.sample_rate) {
- g_warning("sample rate changed from %u to %lu",
- audio_format.sample_rate,
- (unsigned long)frame_info.samplerate);
- break;
- }
-#endif
-
- decoder_buffer_consume(buffer, frame_info.bytesconsumed);
-
- /* update bit rate and position */
-
- if (frame_info.samples > 0) {
- bit_rate = frame_info.bytesconsumed * 8.0 *
- frame_info.channels * audio_format.sample_rate /
- frame_info.samples / 1000 + 0.5;
- }
-
- /* send PCM samples to MPD */
-
- cmd = decoder_data(mpd_decoder, is, decoded,
- (size_t)frame_info.samples * 2,
- bit_rate);
- } while (cmd != DECODE_COMMAND_STOP);
-
- /* cleanup */
-
- faacDecClose(decoder);
-}
-
-static bool
-faad_scan_stream(struct input_stream *is,
- const struct tag_handler *handler, void *handler_ctx)
-{
- int file_time = faad_get_file_time(is);
-
- if (file_time < 0)
- return false;
-
- tag_handler_invoke_duration(handler, handler_ctx, file_time);
- return true;
-}
-
-static const char *const faad_suffixes[] = { "aac", NULL };
-static const char *const faad_mime_types[] = {
- "audio/aac", "audio/aacp", NULL
-};
-
-const struct decoder_plugin faad_decoder_plugin = {
- .name = "faad",
- .stream_decode = faad_stream_decode,
- .scan_stream = faad_scan_stream,
- .suffixes = faad_suffixes,
- .mime_types = faad_mime_types,
-};
diff --git a/src/decoder/flac_compat.h b/src/decoder/flac_compat.h
deleted file mode 100644
index 9a30acc2..00000000
--- a/src/decoder/flac_compat.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-/*
- * Common data structures and functions used by FLAC and OggFLAC
- */
-
-#ifndef MPD_FLAC_COMPAT_H
-#define MPD_FLAC_COMPAT_H
-
-#include <FLAC/export.h>
-#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
-# include <FLAC/seekable_stream_decoder.h>
-
-/* starting with libFLAC 1.1.3, the SeekableStreamDecoder has been
- merged into the StreamDecoder. The following macros try to emulate
- the new API for libFLAC 1.1.2 by mapping MPD's StreamDecoder calls
- to the old SeekableStreamDecoder API. */
-
-#define FLAC__StreamDecoder FLAC__SeekableStreamDecoder
-#define FLAC__stream_decoder_new FLAC__seekable_stream_decoder_new
-#define FLAC__stream_decoder_get_decode_position FLAC__seekable_stream_decoder_get_decode_position
-#define FLAC__stream_decoder_get_state FLAC__seekable_stream_decoder_get_state
-#define FLAC__stream_decoder_process_single FLAC__seekable_stream_decoder_process_single
-#define FLAC__stream_decoder_process_until_end_of_metadata FLAC__seekable_stream_decoder_process_until_end_of_metadata
-#define FLAC__stream_decoder_seek_absolute FLAC__seekable_stream_decoder_seek_absolute
-#define FLAC__stream_decoder_finish FLAC__seekable_stream_decoder_finish
-#define FLAC__stream_decoder_delete FLAC__seekable_stream_decoder_delete
-
-#define FLAC__STREAM_DECODER_END_OF_STREAM FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
-
-typedef unsigned flac_read_status_size_t;
-
-#define FLAC__StreamDecoderReadStatus FLAC__SeekableStreamDecoderReadStatus
-#define FLAC__STREAM_DECODER_READ_STATUS_CONTINUE FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
-#define FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK
-#define FLAC__STREAM_DECODER_READ_STATUS_ABORT FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR
-
-#define FLAC__StreamDecoderSeekStatus FLAC__SeekableStreamDecoderSeekStatus
-#define FLAC__STREAM_DECODER_SEEK_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK
-#define FLAC__STREAM_DECODER_SEEK_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
-#define FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
-
-#define FLAC__StreamDecoderTellStatus FLAC__SeekableStreamDecoderTellStatus
-#define FLAC__STREAM_DECODER_TELL_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK
-#define FLAC__STREAM_DECODER_TELL_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
-#define FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
-
-#define FLAC__StreamDecoderLengthStatus FLAC__SeekableStreamDecoderLengthStatus
-#define FLAC__STREAM_DECODER_LENGTH_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK
-#define FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
-#define FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
-
-typedef enum {
- FLAC__STREAM_DECODER_INIT_STATUS_OK,
- FLAC__STREAM_DECODER_INIT_STATUS_ERROR,
-} FLAC__StreamDecoderInitStatus;
-
-static inline FLAC__StreamDecoderInitStatus
-FLAC__stream_decoder_init_stream(FLAC__SeekableStreamDecoder *decoder,
- FLAC__SeekableStreamDecoderReadCallback read_cb,
- FLAC__SeekableStreamDecoderSeekCallback seek_cb,
- FLAC__SeekableStreamDecoderTellCallback tell_cb,
- FLAC__SeekableStreamDecoderLengthCallback length_cb,
- FLAC__SeekableStreamDecoderEofCallback eof_cb,
- FLAC__SeekableStreamDecoderWriteCallback write_cb,
- FLAC__SeekableStreamDecoderMetadataCallback metadata_cb,
- FLAC__SeekableStreamDecoderErrorCallback error_cb,
- void *data)
-{
- return FLAC__seekable_stream_decoder_set_read_callback(decoder, read_cb) &&
- FLAC__seekable_stream_decoder_set_seek_callback(decoder, seek_cb) &&
- FLAC__seekable_stream_decoder_set_tell_callback(decoder, tell_cb) &&
- FLAC__seekable_stream_decoder_set_length_callback(decoder, length_cb) &&
- FLAC__seekable_stream_decoder_set_eof_callback(decoder, eof_cb) &&
- FLAC__seekable_stream_decoder_set_write_callback(decoder, write_cb) &&
- FLAC__seekable_stream_decoder_set_metadata_callback(decoder, metadata_cb) &&
- FLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT) &&
- FLAC__seekable_stream_decoder_set_error_callback(decoder, error_cb) &&
- FLAC__seekable_stream_decoder_set_client_data(decoder, data) &&
- FLAC__seekable_stream_decoder_init(decoder) == FLAC__SEEKABLE_STREAM_DECODER_OK
- ? FLAC__STREAM_DECODER_INIT_STATUS_OK
- : FLAC__STREAM_DECODER_INIT_STATUS_ERROR;
-}
-
-#else /* FLAC_API_VERSION_CURRENT > 7 */
-
-# include <FLAC/stream_decoder.h>
-
-# define flac_init(a,b,c,d,e,f,g,h,i,j) \
- (FLAC__stream_decoder_init_stream(a,b,c,d,e,f,g,h,i,j) \
- == FLAC__STREAM_DECODER_INIT_STATUS_OK)
-
-typedef size_t flac_read_status_size_t;
-
-#endif /* FLAC_API_VERSION_CURRENT >= 7 */
-
-#endif /* _FLAC_COMMON_H */
diff --git a/src/decoder/flac_decoder_plugin.c b/src/decoder/flac_decoder_plugin.c
deleted file mode 100644
index fb0b3502..00000000
--- a/src/decoder/flac_decoder_plugin.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h" /* must be first for large file support */
-#include "_flac_common.h"
-#include "flac_compat.h"
-#include "flac_metadata.h"
-
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
-#include "_ogg_common.h"
-#endif
-
-#include <glib.h>
-
-#include <assert.h>
-#include <unistd.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-/* this code was based on flac123, from flac-tools */
-
-static FLAC__StreamDecoderReadStatus
-flac_read_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__byte buf[], flac_read_status_size_t *bytes,
- void *fdata)
-{
- struct flac_data *data = fdata;
- size_t r;
-
- r = decoder_read(data->decoder, data->input_stream,
- (void *)buf, *bytes);
- *bytes = r;
-
- if (r == 0) {
- if (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE ||
- input_stream_lock_eof(data->input_stream))
- return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
- else
- return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
- }
-
- return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-}
-
-static FLAC__StreamDecoderSeekStatus
-flac_seek_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__uint64 offset, void *fdata)
-{
- struct flac_data *data = (struct flac_data *) fdata;
-
- if (!data->input_stream->seekable)
- return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
-
- if (!input_stream_lock_seek(data->input_stream, offset, SEEK_SET,
- NULL))
- return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
-
- return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-static FLAC__StreamDecoderTellStatus
-flac_tell_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__uint64 * offset, void *fdata)
-{
- struct flac_data *data = (struct flac_data *) fdata;
-
- if (!data->input_stream->seekable)
- return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
-
- *offset = (long)(data->input_stream->offset);
-
- return FLAC__STREAM_DECODER_TELL_STATUS_OK;
-}
-
-static FLAC__StreamDecoderLengthStatus
-flac_length_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__uint64 * length, void *fdata)
-{
- struct flac_data *data = (struct flac_data *) fdata;
-
- if (data->input_stream->size < 0)
- return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
-
- *length = (size_t) (data->input_stream->size);
-
- return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
-}
-
-static FLAC__bool
-flac_eof_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, void *fdata)
-{
- struct flac_data *data = (struct flac_data *) fdata;
-
- return (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE &&
- decoder_get_command(data->decoder) != DECODE_COMMAND_SEEK) ||
- input_stream_lock_eof(data->input_stream);
-}
-
-static void
-flac_error_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__StreamDecoderErrorStatus status, void *fdata)
-{
- flac_error_common_cb(status, (struct flac_data *) fdata);
-}
-
-#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
-static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state)
-{
- switch (state) {
- case FLAC__SEEKABLE_STREAM_DECODER_OK:
- case FLAC__SEEKABLE_STREAM_DECODER_SEEKING:
- case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM:
- return;
-
- case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
- case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR:
- case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR:
- case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR:
- case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED:
- case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK:
- case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED:
- break;
- }
-
- g_warning("%s\n", FLAC__SeekableStreamDecoderStateString[state]);
-}
-#else /* FLAC_API_VERSION_CURRENT >= 7 */
-static void flacPrintErroredState(FLAC__StreamDecoderState state)
-{
- switch (state) {
- case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
- case FLAC__STREAM_DECODER_READ_METADATA:
- case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
- case FLAC__STREAM_DECODER_READ_FRAME:
- case FLAC__STREAM_DECODER_END_OF_STREAM:
- return;
-
- case FLAC__STREAM_DECODER_OGG_ERROR:
- case FLAC__STREAM_DECODER_SEEK_ERROR:
- case FLAC__STREAM_DECODER_ABORTED:
- case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
- case FLAC__STREAM_DECODER_UNINITIALIZED:
- break;
- }
-
- g_warning("%s\n", FLAC__StreamDecoderStateString[state]);
-}
-#endif /* FLAC_API_VERSION_CURRENT >= 7 */
-
-static void flacMetadata(G_GNUC_UNUSED const FLAC__StreamDecoder * dec,
- const FLAC__StreamMetadata * block, void *vdata)
-{
- flac_metadata_common_cb(block, (struct flac_data *) vdata);
-}
-
-static FLAC__StreamDecoderWriteStatus
-flac_write_cb(const FLAC__StreamDecoder *dec, const FLAC__Frame *frame,
- const FLAC__int32 *const buf[], void *vdata)
-{
- struct flac_data *data = (struct flac_data *) vdata;
- FLAC__uint64 nbytes = 0;
-
- if (FLAC__stream_decoder_get_decode_position(dec, &nbytes)) {
- if (data->position > 0 && nbytes > data->position) {
- nbytes -= data->position;
- data->position += nbytes;
- } else {
- data->position = nbytes;
- nbytes = 0;
- }
- } else
- nbytes = 0;
-
- return flac_common_write(data, frame, buf, nbytes);
-}
-
-static bool
-flac_scan_file(const char *file,
- const struct tag_handler *handler, void *handler_ctx)
-{
- return flac_scan_file2(file, NULL, handler, handler_ctx);
-}
-
-/**
- * Some glue code around FLAC__stream_decoder_new().
- */
-static FLAC__StreamDecoder *
-flac_decoder_new(void)
-{
- FLAC__StreamDecoder *sd = FLAC__stream_decoder_new();
- if (sd == NULL) {
- g_warning("FLAC__stream_decoder_new() failed");
- return NULL;
- }
-
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
- if(!FLAC__stream_decoder_set_metadata_respond(sd, FLAC__METADATA_TYPE_VORBIS_COMMENT))
- g_debug("FLAC__stream_decoder_set_metadata_respond() has failed");
-#endif
-
- return sd;
-}
-
-static bool
-flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd,
- FLAC__uint64 duration)
-{
- data->total_frames = duration;
-
- if (!FLAC__stream_decoder_process_until_end_of_metadata(sd)) {
- g_warning("problem reading metadata");
- return false;
- }
-
- if (data->initialized) {
- /* done */
- decoder_initialized(data->decoder, &data->audio_format,
- data->input_stream->seekable,
- (float)data->total_frames /
- (float)data->audio_format.sample_rate);
- return true;
- }
-
- if (data->input_stream->seekable)
- /* allow the workaround below only for nonseekable
- streams*/
- return false;
-
- /* no stream_info packet found; try to initialize the decoder
- from the first frame header */
- FLAC__stream_decoder_process_single(sd);
- return data->initialized;
-}
-
-static void
-flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *flac_dec,
- FLAC__uint64 t_start, FLAC__uint64 t_end)
-{
- struct decoder *decoder = data->decoder;
- enum decoder_command cmd;
-
- data->first_frame = t_start;
-
- while (true) {
- if (data->tag != NULL && !tag_is_empty(data->tag)) {
- cmd = decoder_tag(data->decoder, data->input_stream,
- data->tag);
- tag_free(data->tag);
- data->tag = tag_new();
- } else
- cmd = decoder_get_command(decoder);
-
- if (cmd == DECODE_COMMAND_SEEK) {
- FLAC__uint64 seek_sample = t_start +
- decoder_seek_where(decoder) *
- data->audio_format.sample_rate;
- if (seek_sample >= t_start &&
- (t_end == 0 || seek_sample <= t_end) &&
- FLAC__stream_decoder_seek_absolute(flac_dec, seek_sample)) {
- data->next_frame = seek_sample;
- data->position = 0;
- decoder_command_finished(decoder);
- } else
- decoder_seek_error(decoder);
- } else if (cmd == DECODE_COMMAND_STOP ||
- FLAC__stream_decoder_get_state(flac_dec) == FLAC__STREAM_DECODER_END_OF_STREAM)
- break;
-
- if (t_end != 0 && data->next_frame >= t_end)
- /* end of this sub track */
- break;
-
- if (!FLAC__stream_decoder_process_single(flac_dec) &&
- decoder_get_command(decoder) == DECODE_COMMAND_NONE) {
- /* a failure that was not triggered by a
- decoder command */
- flacPrintErroredState(FLAC__stream_decoder_get_state(flac_dec));
- break;
- }
- }
-}
-
-static FLAC__StreamDecoderInitStatus
-stream_init_oggflac(FLAC__StreamDecoder *flac_dec, struct flac_data *data)
-{
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
- return FLAC__stream_decoder_init_ogg_stream(flac_dec,
- flac_read_cb,
- flac_seek_cb,
- flac_tell_cb,
- flac_length_cb,
- flac_eof_cb,
- flac_write_cb,
- flacMetadata,
- flac_error_cb,
- data);
-#else
- (void)flac_dec;
- (void)data;
-
- return FLAC__STREAM_DECODER_INIT_STATUS_ERROR;
-#endif
-}
-
-static FLAC__StreamDecoderInitStatus
-stream_init_flac(FLAC__StreamDecoder *flac_dec, struct flac_data *data)
-{
- return FLAC__stream_decoder_init_stream(flac_dec,
- flac_read_cb, flac_seek_cb,
- flac_tell_cb, flac_length_cb,
- flac_eof_cb, flac_write_cb,
- flacMetadata,
- flac_error_cb,
- data);
-}
-
-static FLAC__StreamDecoderInitStatus
-stream_init(FLAC__StreamDecoder *flac_dec, struct flac_data *data, bool is_ogg)
-{
- return is_ogg
- ? stream_init_oggflac(flac_dec, data)
- : stream_init_flac(flac_dec, data);
-}
-
-static void
-flac_decode_internal(struct decoder * decoder,
- struct input_stream *input_stream,
- bool is_ogg)
-{
- FLAC__StreamDecoder *flac_dec;
- struct flac_data data;
-
- flac_dec = flac_decoder_new();
- if (flac_dec == NULL)
- return;
-
- flac_data_init(&data, decoder, input_stream);
- data.tag = tag_new();
-
- FLAC__StreamDecoderInitStatus status =
- stream_init(flac_dec, &data, is_ogg);
- if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
- flac_data_deinit(&data);
- FLAC__stream_decoder_delete(flac_dec);
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
- g_warning("%s", FLAC__StreamDecoderInitStatusString[status]);
-#endif
- return;
- }
-
- if (!flac_decoder_initialize(&data, flac_dec, 0)) {
- flac_data_deinit(&data);
- FLAC__stream_decoder_finish(flac_dec);
- FLAC__stream_decoder_delete(flac_dec);
- return;
- }
-
- flac_decoder_loop(&data, flac_dec, 0, 0);
-
- flac_data_deinit(&data);
-
- FLAC__stream_decoder_finish(flac_dec);
- FLAC__stream_decoder_delete(flac_dec);
-}
-
-static void
-flac_decode(struct decoder * decoder, struct input_stream *input_stream)
-{
- flac_decode_internal(decoder, input_stream, false);
-}
-
-#ifndef HAVE_OGGFLAC
-
-static bool
-oggflac_init(G_GNUC_UNUSED const struct config_param *param)
-{
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
- return !!FLAC_API_SUPPORTS_OGG_FLAC;
-#else
- /* disable oggflac when libflac is too old */
- return false;
-#endif
-}
-
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
-
-static bool
-oggflac_scan_file(const char *file,
- const struct tag_handler *handler, void *handler_ctx)
-{
- FLAC__Metadata_Iterator *it;
- FLAC__StreamMetadata *block;
- FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
-
- if (!(FLAC__metadata_chain_read_ogg(chain, file))) {
- FLAC__metadata_chain_delete(chain);
- return false;
- }
-
- it = FLAC__metadata_iterator_new();
- FLAC__metadata_iterator_init(it, chain);
-
- do {
- if (!(block = FLAC__metadata_iterator_get_block(it)))
- break;
-
- flac_scan_metadata(NULL, block,
- handler, handler_ctx);
- } while (FLAC__metadata_iterator_next(it));
- FLAC__metadata_iterator_delete(it);
-
- FLAC__metadata_chain_delete(chain);
- return true;
-}
-
-static void
-oggflac_decode(struct decoder *decoder, struct input_stream *input_stream)
-{
- if (ogg_stream_type_detect(input_stream) != FLAC)
- return;
-
- /* rewind the stream, because ogg_stream_type_detect() has
- moved it */
- input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL);
-
- flac_decode_internal(decoder, input_stream, true);
-}
-
-static const char *const oggflac_suffixes[] = { "ogg", "oga", NULL };
-static const char *const oggflac_mime_types[] = {
- "application/ogg",
- "application/x-ogg",
- "audio/ogg",
- "audio/x-flac+ogg",
- "audio/x-ogg",
- NULL
-};
-
-#endif /* FLAC_API_VERSION_CURRENT >= 7 */
-
-const struct decoder_plugin oggflac_decoder_plugin = {
- .name = "oggflac",
- .init = oggflac_init,
-#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT > 7
- .stream_decode = oggflac_decode,
- .scan_file = oggflac_scan_file,
- .suffixes = oggflac_suffixes,
- .mime_types = oggflac_mime_types
-#endif
-};
-
-#endif /* HAVE_OGGFLAC */
-
-static const char *const flac_suffixes[] = { "flac", NULL };
-static const char *const flac_mime_types[] = {
- "application/flac",
- "application/x-flac",
- "audio/flac",
- "audio/x-flac",
- NULL
-};
-
-const struct decoder_plugin flac_decoder_plugin = {
- .name = "flac",
- .stream_decode = flac_decode,
- .scan_file = flac_scan_file,
- .suffixes = flac_suffixes,
- .mime_types = flac_mime_types,
-};
diff --git a/src/decoder/flac_metadata.c b/src/decoder/flac_metadata.c
deleted file mode 100644
index bd1eaf32..00000000
--- a/src/decoder/flac_metadata.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "flac_metadata.h"
-#include "replay_gain_info.h"
-#include "tag.h"
-#include "tag_handler.h"
-#include "tag_table.h"
-
-#include <glib.h>
-
-#include <assert.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-static bool
-flac_find_float_comment(const FLAC__StreamMetadata *block,
- const char *cmnt, float *fl)
-{
- int offset;
- size_t pos;
- int len;
- unsigned char tmp, *p;
-
- offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, 0,
- cmnt);
- if (offset < 0)
- return false;
-
- pos = strlen(cmnt) + 1; /* 1 is for '=' */
- len = block->data.vorbis_comment.comments[offset].length - pos;
- if (len <= 0)
- return false;
-
- p = &block->data.vorbis_comment.comments[offset].entry[pos];
- tmp = p[len];
- p[len] = '\0';
- *fl = (float)atof((char *)p);
- p[len] = tmp;
-
- return true;
-}
-
-bool
-flac_parse_replay_gain(struct replay_gain_info *rgi,
- const FLAC__StreamMetadata *block)
-{
- bool found = false;
-
- replay_gain_info_init(rgi);
-
- if (flac_find_float_comment(block, "replaygain_album_gain",
- &rgi->tuples[REPLAY_GAIN_ALBUM].gain))
- found = true;
- if (flac_find_float_comment(block, "replaygain_album_peak",
- &rgi->tuples[REPLAY_GAIN_ALBUM].peak))
- found = true;
- if (flac_find_float_comment(block, "replaygain_track_gain",
- &rgi->tuples[REPLAY_GAIN_TRACK].gain))
- found = true;
- if (flac_find_float_comment(block, "replaygain_track_peak",
- &rgi->tuples[REPLAY_GAIN_TRACK].peak))
- found = true;
-
- return found;
-}
-
-static bool
-flac_find_string_comment(const FLAC__StreamMetadata *block,
- const char *cmnt, char **str)
-{
- int offset;
- size_t pos;
- int len;
- const unsigned char *p;
-
- *str = NULL;
- offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, 0,
- cmnt);
- if (offset < 0)
- return false;
-
- pos = strlen(cmnt) + 1; /* 1 is for '=' */
- len = block->data.vorbis_comment.comments[offset].length - pos;
- if (len <= 0)
- return false;
-
- p = &block->data.vorbis_comment.comments[offset].entry[pos];
- *str = g_strndup((const char *)p, len);
-
- return true;
-}
-
-bool
-flac_parse_mixramp(char **mixramp_start, char **mixramp_end,
- const FLAC__StreamMetadata *block)
-{
- bool found = false;
-
- if (flac_find_string_comment(block, "mixramp_start", mixramp_start))
- found = true;
- if (flac_find_string_comment(block, "mixramp_end", mixramp_end))
- found = true;
-
- return found;
-}
-
-/**
- * Checks if the specified name matches the entry's name, and if yes,
- * returns the comment value (not null-temrinated).
- */
-static const char *
-flac_comment_value(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
- const char *name, const char *char_tnum, size_t *length_r)
-{
- size_t name_length = strlen(name);
- size_t char_tnum_length = 0;
- const char *comment = (const char*)entry->entry;
-
- if (entry->length <= name_length ||
- g_ascii_strncasecmp(comment, name, name_length) != 0)
- return NULL;
-
- if (char_tnum != NULL) {
- char_tnum_length = strlen(char_tnum);
- if (entry->length > name_length + char_tnum_length + 2 &&
- comment[name_length] == '[' &&
- g_ascii_strncasecmp(comment + name_length + 1,
- char_tnum, char_tnum_length) == 0 &&
- comment[name_length + char_tnum_length + 1] == ']')
- name_length = name_length + char_tnum_length + 2;
- else if (entry->length > name_length + char_tnum_length &&
- g_ascii_strncasecmp(comment + name_length,
- char_tnum, char_tnum_length) == 0)
- name_length = name_length + char_tnum_length;
- }
-
- if (comment[name_length] == '=') {
- *length_r = entry->length - name_length - 1;
- return comment + name_length + 1;
- }
-
- return NULL;
-}
-
-/**
- * Check if the comment's name equals the passed name, and if so, copy
- * the comment value into the tag.
- */
-static bool
-flac_copy_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry,
- const char *name, enum tag_type tag_type,
- const char *char_tnum,
- const struct tag_handler *handler, void *handler_ctx)
-{
- const char *value;
- size_t value_length;
-
- value = flac_comment_value(entry, name, char_tnum, &value_length);
- if (value != NULL) {
- char *p = g_strndup(value, value_length);
- tag_handler_invoke_tag(handler, handler_ctx, tag_type, p);
- g_free(p);
- return true;
- }
-
- return false;
-}
-
-static const struct tag_table flac_tags[] = {
- { "tracknumber", TAG_TRACK },
- { "discnumber", TAG_DISC },
- { "album artist", TAG_ALBUM_ARTIST },
- { NULL, TAG_NUM_OF_ITEM_TYPES }
-};
-
-static void
-flac_scan_comment(const char *char_tnum,
- const FLAC__StreamMetadata_VorbisComment_Entry *entry,
- const struct tag_handler *handler, void *handler_ctx)
-{
- if (handler->pair != NULL) {
- char *name = g_strdup((const char*)entry->entry);
- char *value = strchr(name, '=');
-
- if (value != NULL && value > name) {
- *value++ = 0;
- tag_handler_invoke_pair(handler, handler_ctx,
- name, value);
- }
-
- g_free(name);
- }
-
- for (const struct tag_table *i = flac_tags; i->name != NULL; ++i)
- if (flac_copy_comment(entry, i->name, i->type, char_tnum,
- handler, handler_ctx))
- return;
-
- for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
- if (flac_copy_comment(entry,
- tag_item_names[i], i, char_tnum,
- handler, handler_ctx))
- return;
-}
-
-static void
-flac_scan_comments(const char *char_tnum,
- const FLAC__StreamMetadata_VorbisComment *comment,
- const struct tag_handler *handler, void *handler_ctx)
-{
- for (unsigned i = 0; i < comment->num_comments; ++i)
- flac_scan_comment(char_tnum, &comment->comments[i],
- handler, handler_ctx);
-}
-
-void
-flac_scan_metadata(const char *track,
- const FLAC__StreamMetadata *block,
- const struct tag_handler *handler, void *handler_ctx)
-{
- switch (block->type) {
- case FLAC__METADATA_TYPE_VORBIS_COMMENT:
- flac_scan_comments(track, &block->data.vorbis_comment,
- handler, handler_ctx);
- break;
-
- case FLAC__METADATA_TYPE_STREAMINFO:
- if (block->data.stream_info.sample_rate > 0)
- tag_handler_invoke_duration(handler, handler_ctx,
- flac_duration(&block->data.stream_info));
- break;
-
- default:
- break;
- }
-}
-
-void
-flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum,
- const FLAC__StreamMetadata_VorbisComment *comment)
-{
- flac_scan_comments(char_tnum, comment,
- &add_tag_handler, tag);
-}
-
-bool
-flac_scan_file2(const char *file, const char *char_tnum,
- const struct tag_handler *handler, void *handler_ctx)
-{
- FLAC__Metadata_SimpleIterator *it;
- FLAC__StreamMetadata *block = NULL;
-
- it = FLAC__metadata_simple_iterator_new();
- if (!FLAC__metadata_simple_iterator_init(it, file, 1, 0)) {
- const char *err;
- FLAC_API FLAC__Metadata_SimpleIteratorStatus s;
-
- s = FLAC__metadata_simple_iterator_status(it);
-
- switch (s) { /* slightly more human-friendly messages: */
- case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT:
- err = "illegal input";
- break;
- case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE:
- err = "error opening file";
- break;
- case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE:
- err = "not a FLAC file";
- break;
- default:
- err = FLAC__Metadata_SimpleIteratorStatusString[s];
- }
- g_debug("Reading '%s' metadata gave the following error: %s\n",
- file, err);
- FLAC__metadata_simple_iterator_delete(it);
- return false;
- }
-
- do {
- block = FLAC__metadata_simple_iterator_get_block(it);
- if (!block)
- break;
-
- flac_scan_metadata(char_tnum, block, handler, handler_ctx);
- FLAC__metadata_object_delete(block);
- } while (FLAC__metadata_simple_iterator_next(it));
-
- FLAC__metadata_simple_iterator_delete(it);
-
- return true;
-}
-
-struct tag *
-flac_tag_load(const char *file, const char *char_tnum)
-{
- struct tag *tag = tag_new();
-
- if (!flac_scan_file2(file, char_tnum, &add_tag_handler, tag) ||
- tag_is_empty(tag)) {
- tag_free(tag);
- tag = NULL;
- }
-
- return tag;
-}
diff --git a/src/decoder/flac_metadata.h b/src/decoder/flac_metadata.h
deleted file mode 100644
index 3c463d5d..00000000
--- a/src/decoder/flac_metadata.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-#ifndef MPD_FLAC_METADATA_H
-#define MPD_FLAC_METADATA_H
-
-#include <assert.h>
-#include <stdbool.h>
-#include <FLAC/metadata.h>
-
-struct tag_handler;
-struct tag;
-struct replay_gain_info;
-
-static inline unsigned
-flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
-{
- assert(stream_info->sample_rate > 0);
-
- return (stream_info->total_samples + stream_info->sample_rate - 1) /
- stream_info->sample_rate;
-}
-
-bool
-flac_parse_replay_gain(struct replay_gain_info *rgi,
- const FLAC__StreamMetadata *block);
-
-bool
-flac_parse_mixramp(char **mixramp_start, char **mixramp_end,
- const FLAC__StreamMetadata *block);
-
-void
-flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum,
- const FLAC__StreamMetadata_VorbisComment *comment);
-
-void
-flac_scan_metadata(const char *track,
- const FLAC__StreamMetadata *block,
- const struct tag_handler *handler, void *handler_ctx);
-
-bool
-flac_scan_file2(const char *file, const char *char_tnum,
- const struct tag_handler *handler, void *handler_ctx);
-
-struct tag *
-flac_tag_load(const char *file, const char *char_tnum);
-
-#endif
diff --git a/src/decoder/flac_pcm.c b/src/decoder/flac_pcm.c
deleted file mode 100644
index 6964d8ac..00000000
--- a/src/decoder/flac_pcm.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "flac_pcm.h"
-
-#include <assert.h>
-
-static void flac_convert_stereo16(int16_t *dest,
- const FLAC__int32 * const buf[],
- unsigned int position, unsigned int end)
-{
- for (; position < end; ++position) {
- *dest++ = buf[0][position];
- *dest++ = buf[1][position];
- }
-}
-
-static void
-flac_convert_16(int16_t *dest,
- unsigned int num_channels,
- const FLAC__int32 * const buf[],
- unsigned int position, unsigned int end)
-{
- unsigned int c_chan;
-
- for (; position < end; ++position)
- for (c_chan = 0; c_chan < num_channels; c_chan++)
- *dest++ = buf[c_chan][position];
-}
-
-/**
- * Note: this function also handles 24 bit files!
- */
-static void
-flac_convert_32(int32_t *dest,
- unsigned int num_channels,
- const FLAC__int32 * const buf[],
- unsigned int position, unsigned int end)
-{
- unsigned int c_chan;
-
- for (; position < end; ++position)
- for (c_chan = 0; c_chan < num_channels; c_chan++)
- *dest++ = buf[c_chan][position];
-}
-
-static void
-flac_convert_8(int8_t *dest,
- unsigned int num_channels,
- const FLAC__int32 * const buf[],
- unsigned int position, unsigned int end)
-{
- unsigned int c_chan;
-
- for (; position < end; ++position)
- for (c_chan = 0; c_chan < num_channels; c_chan++)
- *dest++ = buf[c_chan][position];
-}
-
-void
-flac_convert(void *dest,
- unsigned int num_channels, enum sample_format sample_format,
- const FLAC__int32 *const buf[],
- unsigned int position, unsigned int end)
-{
- switch (sample_format) {
- case SAMPLE_FORMAT_S16:
- if (num_channels == 2)
- flac_convert_stereo16((int16_t*)dest, buf,
- position, end);
- else
- flac_convert_16((int16_t*)dest, num_channels, buf,
- position, end);
- break;
-
- case SAMPLE_FORMAT_S24_P32:
- case SAMPLE_FORMAT_S32:
- flac_convert_32((int32_t*)dest, num_channels, buf,
- position, end);
- break;
-
- case SAMPLE_FORMAT_S8:
- flac_convert_8((int8_t*)dest, num_channels, buf,
- position, end);
- break;
-
- case SAMPLE_FORMAT_FLOAT:
- case SAMPLE_FORMAT_DSD:
- case SAMPLE_FORMAT_UNDEFINED:
- /* unreachable */
- assert(false);
- }
-}
diff --git a/src/decoder/flac_pcm.h b/src/decoder/flac_pcm.h
deleted file mode 100644
index a931998c..00000000
--- a/src/decoder/flac_pcm.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-#ifndef MPD_FLAC_PCM_H
-#define MPD_FLAC_PCM_H
-
-#include "audio_format.h"
-
-#include <FLAC/ordinals.h>
-
-void
-flac_convert(void *dest,
- unsigned int num_channels, enum sample_format sample_format,
- const FLAC__int32 *const buf[],
- unsigned int position, unsigned int end);
-
-#endif
diff --git a/src/decoder/fluidsynth_decoder_plugin.c b/src/decoder/fluidsynth_decoder_plugin.c
deleted file mode 100644
index 085f84f1..00000000
--- a/src/decoder/fluidsynth_decoder_plugin.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-/*
- * WARNING! This plugin suffers from major shortcomings in the
- * libfluidsynth API, which render it practically unusable. For a
- * discussion, see the post on the fluidsynth mailing list:
- *
- * http://www.mail-archive.com/fluid-dev@nongnu.org/msg01099.html
- *
- */
-
-#include "config.h"
-#include "decoder_api.h"
-#include "timer.h"
-#include "conf.h"
-
-#include <glib.h>
-
-#include <fluidsynth.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "fluidsynth"
-
-/**
- * Convert a fluidsynth log level to a GLib log level.
- */
-static GLogLevelFlags
-fluidsynth_level_to_glib(enum fluid_log_level level)
-{
- switch (level) {
- case FLUID_PANIC:
- case FLUID_ERR:
- return G_LOG_LEVEL_CRITICAL;
-
- case FLUID_WARN:
- return G_LOG_LEVEL_WARNING;
-
- case FLUID_INFO:
- return G_LOG_LEVEL_INFO;
-
- case FLUID_DBG:
- case LAST_LOG_LEVEL:
- return G_LOG_LEVEL_DEBUG;
- }
-
- /* invalid fluidsynth log level */
- return G_LOG_LEVEL_MESSAGE;
-}
-
-/**
- * The fluidsynth logging callback. It forwards messages to the GLib
- * logging library.
- */
-static void
-fluidsynth_mpd_log_function(int level, char *message, G_GNUC_UNUSED void *data)
-{
- g_log(G_LOG_DOMAIN, fluidsynth_level_to_glib(level), "%s", message);
-}
-
-static bool
-fluidsynth_init(G_GNUC_UNUSED const struct config_param *param)
-{
- fluid_set_log_function(LAST_LOG_LEVEL,
- fluidsynth_mpd_log_function, NULL);
-
- return true;
-}
-
-static void
-fluidsynth_file_decode(struct decoder *decoder, const char *path_fs)
-{
- static const struct audio_format audio_format = {
- .sample_rate = 48000,
- .format = SAMPLE_FORMAT_S16,
- .channels = 2,
- };
- char setting_sample_rate[] = "synth.sample-rate";
- /*
- char setting_verbose[] = "synth.verbose";
- char setting_yes[] = "yes";
- */
- const char *soundfont_path;
- fluid_settings_t *settings;
- fluid_synth_t *synth;
- fluid_player_t *player;
- char *path_dup;
- int ret;
- struct timer *timer;
- enum decoder_command cmd;
-
- soundfont_path =
- config_get_string("soundfont",
- "/usr/share/sounds/sf2/FluidR3_GM.sf2");
-
- /* set up fluid settings */
-
- settings = new_fluid_settings();
- if (settings == NULL)
- return;
-
- fluid_settings_setnum(settings, setting_sample_rate, 48000);
-
- /*
- fluid_settings_setstr(settings, setting_verbose, setting_yes);
- */
-
- /* create the fluid synth */
-
- synth = new_fluid_synth(settings);
- if (synth == NULL) {
- delete_fluid_settings(settings);
- return;
- }
-
- ret = fluid_synth_sfload(synth, soundfont_path, true);
- if (ret < 0) {
- g_warning("fluid_synth_sfload() failed");
- delete_fluid_synth(synth);
- delete_fluid_settings(settings);
- return;
- }
-
- /* create the fluid player */
-
- player = new_fluid_player(synth);
- if (player == NULL) {
- delete_fluid_synth(synth);
- delete_fluid_settings(settings);
- return;
- }
-
- /* temporarily duplicate the path_fs string, because
- fluidsynth wants a writable string */
- path_dup = g_strdup(path_fs);
- ret = fluid_player_add(player, path_dup);
- g_free(path_dup);
- if (ret != 0) {
- g_warning("fluid_player_add() failed");
- delete_fluid_player(player);
- delete_fluid_synth(synth);
- delete_fluid_settings(settings);
- return;
- }
-
- /* start the player */
-
- ret = fluid_player_play(player);
- if (ret != 0) {
- g_warning("fluid_player_play() failed");
- delete_fluid_player(player);
- delete_fluid_synth(synth);
- delete_fluid_settings(settings);
- return;
- }
-
- /* set up a timer for synchronization; fluidsynth always
- decodes in real time, which forces us to synchronize */
- /* XXX is there any way to switch off real-time decoding? */
-
- timer = timer_new(&audio_format);
- timer_start(timer);
-
- /* initialization complete - announce the audio format to the
- MPD core */
-
- decoder_initialized(decoder, &audio_format, false, -1);
-
- do {
- int16_t buffer[2048];
- const unsigned max_frames = G_N_ELEMENTS(buffer) / 2;
-
- /* synchronize with the fluid player */
-
- timer_add(timer, sizeof(buffer));
- timer_sync(timer);
-
- /* read samples from fluidsynth and send them to the
- MPD core */
-
- ret = fluid_synth_write_s16(synth, max_frames,
- buffer, 0, 2,
- buffer, 1, 2);
- /* XXX how do we see whether the player is done? We
- can't access the private attribute
- player->status */
- if (ret != 0)
- break;
-
- cmd = decoder_data(decoder, NULL, buffer, sizeof(buffer),
- 0);
- } while (cmd == DECODE_COMMAND_NONE);
-
- /* clean up */
-
- timer_free(timer);
-
- fluid_player_stop(player);
- fluid_player_join(player);
-
- delete_fluid_player(player);
- delete_fluid_synth(synth);
- delete_fluid_settings(settings);
-}
-
-static bool
-fluidsynth_scan_file(const char *file,
- G_GNUC_UNUSED const struct tag_handler *handler,
- G_GNUC_UNUSED void *handler_ctx)
-{
- /* to be implemented */
- (void)file;
-
- return true;
-}
-
-static const char *const fluidsynth_suffixes[] = {
- "mid",
- NULL
-};
-
-const struct decoder_plugin fluidsynth_decoder_plugin = {
- .name = "fluidsynth",
- .init = fluidsynth_init,
- .file_decode = fluidsynth_file_decode,
- .scan_file = fluidsynth_scan_file,
- .suffixes = fluidsynth_suffixes,
-};
diff --git a/src/decoder/gme_decoder_plugin.c b/src/decoder/gme_decoder_plugin.c
deleted file mode 100644
index 237a1deb..00000000
--- a/src/decoder/gme_decoder_plugin.c
+++ /dev/null
@@ -1,257 +0,0 @@
-#include "config.h"
-#include "../decoder_api.h"
-#include "audio_check.h"
-#include "uri.h"
-#include "tag_handler.h"
-
-#include <glib.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <gme/gme.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "gme"
-
-#define SUBTUNE_PREFIX "tune_"
-
-enum {
- GME_SAMPLE_RATE = 44100,
- GME_CHANNELS = 2,
- GME_BUFFER_FRAMES = 2048,
- GME_BUFFER_SAMPLES = GME_BUFFER_FRAMES * GME_CHANNELS,
-};
-
-/**
- * returns the file path stripped of any /tune_xxx.* subtune
- * suffix
- */
-static char *
-get_container_name(const char *path_fs)
-{
- const char *subtune_suffix = uri_get_suffix(path_fs);
- char *path_container = g_strdup(path_fs);
- char *pat = g_strconcat("*/" SUBTUNE_PREFIX "???.", subtune_suffix, NULL);
- GPatternSpec *path_with_subtune = g_pattern_spec_new(pat);
- g_free(pat);
- if (!g_pattern_match(path_with_subtune,
- strlen(path_container), path_container, NULL)) {
- g_pattern_spec_free(path_with_subtune);
- return path_container;
- }
-
- char *ptr = g_strrstr(path_container, "/" SUBTUNE_PREFIX);
- if (ptr != NULL)
- *ptr='\0';
-
- g_pattern_spec_free(path_with_subtune);
- return path_container;
-}
-
-/**
- * returns tune number from file.nsf/tune_xxx.* style path or 0 if no subtune
- * is appended.
- */
-static int
-get_song_num(const char *path_fs)
-{
- const char *subtune_suffix = uri_get_suffix(path_fs);
- char *pat = g_strconcat("*/" SUBTUNE_PREFIX "???.", subtune_suffix, NULL);
- GPatternSpec *path_with_subtune = g_pattern_spec_new(pat);
- g_free(pat);
-
- if (g_pattern_match(path_with_subtune,
- strlen(path_fs), path_fs, NULL)) {
- char *sub = g_strrstr(path_fs, "/" SUBTUNE_PREFIX);
- g_pattern_spec_free(path_with_subtune);
- if(!sub)
- return 0;
-
- sub += strlen("/" SUBTUNE_PREFIX);
- int song_num = strtol(sub, NULL, 10);
-
- return song_num - 1;
- } else {
- g_pattern_spec_free(path_with_subtune);
- return 0;
- }
-}
-
-static char *
-gme_container_scan(const char *path_fs, const unsigned int tnum)
-{
- Music_Emu *emu;
- const char* gme_err;
- unsigned int num_songs;
-
- gme_err = gme_open_file(path_fs, &emu, GME_SAMPLE_RATE);
- if (gme_err != NULL) {
- g_warning("%s", gme_err);
- return NULL;
- }
-
- num_songs = gme_track_count(emu);
- /* if it only contains a single tune, don't treat as container */
- if (num_songs < 2)
- return NULL;
-
- const char *subtune_suffix = uri_get_suffix(path_fs);
- if (tnum <= num_songs){
- char *subtune = g_strdup_printf(
- SUBTUNE_PREFIX "%03u.%s", tnum, subtune_suffix);
- return subtune;
- } else
- return NULL;
-}
-
-static void
-gme_file_decode(struct decoder *decoder, const char *path_fs)
-{
- float song_len;
- Music_Emu *emu;
- gme_info_t *ti;
- struct audio_format audio_format;
- enum decoder_command cmd;
- short buf[GME_BUFFER_SAMPLES];
- const char* gme_err;
- char *path_container = get_container_name(path_fs);
- int song_num = get_song_num(path_fs);
-
- gme_err = gme_open_file(path_container, &emu, GME_SAMPLE_RATE);
- g_free(path_container);
- if (gme_err != NULL) {
- g_warning("%s", gme_err);
- return;
- }
-
- if((gme_err = gme_track_info(emu, &ti, song_num)) != NULL){
- g_warning("%s", gme_err);
- gme_delete(emu);
- return;
- }
-
- if(ti->length > 0)
- song_len = ti->length / 1000.0;
- else song_len = -1;
-
- /* initialize the MPD decoder */
-
- GError *error = NULL;
- if (!audio_format_init_checked(&audio_format, GME_SAMPLE_RATE,
- SAMPLE_FORMAT_S16, GME_CHANNELS,
- &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- gme_free_info(ti);
- gme_delete(emu);
- return;
- }
-
- decoder_initialized(decoder, &audio_format, true, song_len);
-
- if((gme_err = gme_start_track(emu, song_num)) != NULL)
- g_warning("%s", gme_err);
-
- if(ti->length > 0)
- gme_set_fade(emu, ti->length);
-
- /* play */
- do {
- gme_err = gme_play(emu, GME_BUFFER_SAMPLES, buf);
- if (gme_err != NULL) {
- g_warning("%s", gme_err);
- return;
- }
- cmd = decoder_data(decoder, NULL, buf, sizeof(buf), 0);
-
- if(cmd == DECODE_COMMAND_SEEK) {
- float where = decoder_seek_where(decoder);
- if((gme_err = gme_seek(emu, (int)where*1000)) != NULL)
- g_warning("%s", gme_err);
- decoder_command_finished(decoder);
- }
-
- if(gme_track_ended(emu))
- break;
- } while(cmd != DECODE_COMMAND_STOP);
-
- gme_free_info(ti);
- gme_delete(emu);
-}
-
-static bool
-gme_scan_file(const char *path_fs,
- const struct tag_handler *handler, void *handler_ctx)
-{
- Music_Emu *emu;
- gme_info_t *ti;
- const char* gme_err;
- char *path_container=get_container_name(path_fs);
- int song_num;
- song_num=get_song_num(path_fs);
-
- gme_err = gme_open_file(path_container, &emu, GME_SAMPLE_RATE);
- g_free(path_container);
- if (gme_err != NULL) {
- g_warning("%s", gme_err);
- return false;
- }
- if((gme_err = gme_track_info(emu, &ti, song_num)) != NULL){
- g_warning("%s", gme_err);
- gme_delete(emu);
- return false;
- }
-
- assert(ti != NULL);
-
- if(ti->length > 0)
- tag_handler_invoke_duration(handler, handler_ctx,
- ti->length / 100);
-
- if(ti->song != NULL){
- if(gme_track_count(emu) > 1){
- /* start numbering subtunes from 1 */
- char *tag_title=g_strdup_printf("%s (%d/%d)",
- ti->song, song_num+1, gme_track_count(emu));
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_TITLE, tag_title);
- g_free(tag_title);
- }else
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_TITLE, ti->song);
- }
- if(ti->author != NULL)
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_ARTIST, ti->author);
- if(ti->game != NULL)
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_ALBUM, ti->game);
- if(ti->comment != NULL)
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_COMMENT, ti->comment);
- if(ti->copyright != NULL)
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_DATE, ti->copyright);
-
- gme_free_info(ti);
- gme_delete(emu);
-
- return true;
-}
-
-static const char *const gme_suffixes[] = {
- "ay", "gbs", "gym", "hes", "kss", "nsf",
- "nsfe", "sap", "spc", "vgm", "vgz",
- NULL
-};
-
-extern const struct decoder_plugin gme_decoder_plugin;
-const struct decoder_plugin gme_decoder_plugin = {
- .name = "gme",
- .file_decode = gme_file_decode,
- .scan_file = gme_scan_file,
- .suffixes = gme_suffixes,
- .container_scan = gme_container_scan,
-};
diff --git a/src/decoder/mad_decoder_plugin.c b/src/decoder/mad_decoder_plugin.c
deleted file mode 100644
index a69284be..00000000
--- a/src/decoder/mad_decoder_plugin.c
+++ /dev/null
@@ -1,1204 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "conf.h"
-#include "tag_id3.h"
-#include "tag_rva2.h"
-#include "tag_handler.h"
-#include "audio_check.h"
-
-#include <assert.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <glib.h>
-#include <mad.h>
-
-#ifdef HAVE_ID3TAG
-#include <id3tag.h>
-#endif
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "mad"
-
-#define FRAMES_CUSHION 2000
-
-#define READ_BUFFER_SIZE 40960
-
-enum mp3_action {
- DECODE_SKIP = -3,
- DECODE_BREAK = -2,
- DECODE_CONT = -1,
- DECODE_OK = 0
-};
-
-enum muteframe {
- MUTEFRAME_NONE,
- MUTEFRAME_SKIP,
- MUTEFRAME_SEEK
-};
-
-/* the number of samples of silence the decoder inserts at start */
-#define DECODERDELAY 529
-
-#define DEFAULT_GAPLESS_MP3_PLAYBACK true
-
-static bool gapless_playback;
-
-static inline int32_t
-mad_fixed_to_24_sample(mad_fixed_t sample)
-{
- enum {
- bits = 24,
- MIN = -MAD_F_ONE,
- MAX = MAD_F_ONE - 1
- };
-
- /* round */
- sample = sample + (1L << (MAD_F_FRACBITS - bits));
-
- /* clip */
- if (sample > MAX)
- sample = MAX;
- else if (sample < MIN)
- sample = MIN;
-
- /* quantize */
- return sample >> (MAD_F_FRACBITS + 1 - bits);
-}
-
-static void
-mad_fixed_to_24_buffer(int32_t *dest, const struct mad_synth *synth,
- unsigned int start, unsigned int end,
- unsigned int num_channels)
-{
- unsigned int i, c;
-
- for (i = start; i < end; ++i) {
- for (c = 0; c < num_channels; ++c)
- *dest++ = mad_fixed_to_24_sample(synth->pcm.samples[c][i]);
- }
-}
-
-static bool
-mp3_plugin_init(G_GNUC_UNUSED const struct config_param *param)
-{
- gapless_playback = config_get_bool(CONF_GAPLESS_MP3_PLAYBACK,
- DEFAULT_GAPLESS_MP3_PLAYBACK);
- return true;
-}
-
-#define MP3_DATA_OUTPUT_BUFFER_SIZE 2048
-
-struct mp3_data {
- struct mad_stream stream;
- struct mad_frame frame;
- struct mad_synth synth;
- mad_timer_t timer;
- unsigned char input_buffer[READ_BUFFER_SIZE];
- int32_t output_buffer[MP3_DATA_OUTPUT_BUFFER_SIZE];
- float total_time;
- float elapsed_time;
- float seek_where;
- enum muteframe mute_frame;
- long *frame_offsets;
- mad_timer_t *times;
- unsigned long highest_frame;
- unsigned long max_frames;
- unsigned long current_frame;
- unsigned int drop_start_frames;
- unsigned int drop_end_frames;
- unsigned int drop_start_samples;
- unsigned int drop_end_samples;
- bool found_replay_gain;
- bool found_xing;
- bool found_first_frame;
- bool decoded_first_frame;
- unsigned long bit_rate;
- struct decoder *decoder;
- struct input_stream *input_stream;
- enum mad_layer layer;
-};
-
-static void
-mp3_data_init(struct mp3_data *data, struct decoder *decoder,
- struct input_stream *input_stream)
-{
- data->mute_frame = MUTEFRAME_NONE;
- data->highest_frame = 0;
- data->max_frames = 0;
- data->frame_offsets = NULL;
- data->times = NULL;
- data->current_frame = 0;
- data->drop_start_frames = 0;
- data->drop_end_frames = 0;
- data->drop_start_samples = 0;
- data->drop_end_samples = 0;
- data->found_replay_gain = false;
- data->found_xing = false;
- data->found_first_frame = false;
- data->decoded_first_frame = false;
- data->decoder = decoder;
- data->input_stream = input_stream;
- data->layer = 0;
-
- mad_stream_init(&data->stream);
- mad_stream_options(&data->stream, MAD_OPTION_IGNORECRC);
- mad_frame_init(&data->frame);
- mad_synth_init(&data->synth);
- mad_timer_reset(&data->timer);
-}
-
-static bool mp3_seek(struct mp3_data *data, long offset)
-{
- if (!input_stream_lock_seek(data->input_stream, offset, SEEK_SET, NULL))
- return false;
-
- mad_stream_buffer(&data->stream, data->input_buffer, 0);
- (data->stream).error = 0;
-
- return true;
-}
-
-static bool
-mp3_fill_buffer(struct mp3_data *data)
-{
- size_t remaining, length;
- unsigned char *dest;
-
- if (data->stream.next_frame != NULL) {
- remaining = data->stream.bufend - data->stream.next_frame;
- memmove(data->input_buffer, data->stream.next_frame,
- remaining);
- dest = (data->input_buffer) + remaining;
- length = READ_BUFFER_SIZE - remaining;
- } else {
- remaining = 0;
- length = READ_BUFFER_SIZE;
- dest = data->input_buffer;
- }
-
- /* we've exhausted the read buffer, so give up!, these potential
- * mp3 frames are way too big, and thus unlikely to be mp3 frames */
- if (length == 0)
- return false;
-
- length = decoder_read(data->decoder, data->input_stream, dest, length);
- if (length == 0)
- return false;
-
- mad_stream_buffer(&data->stream, data->input_buffer,
- length + remaining);
- (data->stream).error = 0;
-
- return true;
-}
-
-#ifdef HAVE_ID3TAG
-static bool
-parse_id3_replay_gain_info(struct replay_gain_info *replay_gain_info,
- struct id3_tag *tag)
-{
- int i;
- char *key;
- char *value;
- struct id3_frame *frame;
- bool found = false;
-
- replay_gain_info_init(replay_gain_info);
-
- for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) {
- if (frame->nfields < 3)
- continue;
-
- key = (char *)
- id3_ucs4_latin1duplicate(id3_field_getstring
- (&frame->fields[1]));
- value = (char *)
- id3_ucs4_latin1duplicate(id3_field_getstring
- (&frame->fields[2]));
-
- if (g_ascii_strcasecmp(key, "replaygain_track_gain") == 0) {
- replay_gain_info->tuples[REPLAY_GAIN_TRACK].gain = atof(value);
- found = true;
- } else if (g_ascii_strcasecmp(key, "replaygain_album_gain") == 0) {
- replay_gain_info->tuples[REPLAY_GAIN_ALBUM].gain = atof(value);
- found = true;
- } else if (g_ascii_strcasecmp(key, "replaygain_track_peak") == 0) {
- replay_gain_info->tuples[REPLAY_GAIN_TRACK].peak = atof(value);
- found = true;
- } else if (g_ascii_strcasecmp(key, "replaygain_album_peak") == 0) {
- replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak = atof(value);
- found = true;
- }
-
- free(key);
- free(value);
- }
-
- return found ||
- /* fall back on RVA2 if no replaygain tags found */
- tag_rva2_parse(tag, replay_gain_info);
-}
-#endif
-
-#ifdef HAVE_ID3TAG
-static bool
-parse_id3_mixramp(char **mixramp_start, char **mixramp_end,
- struct id3_tag *tag)
-{
- int i;
- char *key;
- char *value;
- struct id3_frame *frame;
- bool found = false;
-
- *mixramp_start = NULL;
- *mixramp_end = NULL;
-
- for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) {
- if (frame->nfields < 3)
- continue;
-
- key = (char *)
- id3_ucs4_latin1duplicate(id3_field_getstring
- (&frame->fields[1]));
- value = (char *)
- id3_ucs4_latin1duplicate(id3_field_getstring
- (&frame->fields[2]));
-
- if (g_ascii_strcasecmp(key, "mixramp_start") == 0) {
- *mixramp_start = g_strdup(value);
- found = true;
- } else if (g_ascii_strcasecmp(key, "mixramp_end") == 0) {
- *mixramp_end = g_strdup(value);
- found = true;
- }
-
- free(key);
- free(value);
- }
-
- return found;
-}
-#endif
-
-static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
- struct tag **mpd_tag)
-{
-#ifdef HAVE_ID3TAG
- struct id3_tag *id3_tag = NULL;
- id3_length_t count;
- id3_byte_t const *id3_data;
- id3_byte_t *allocated = NULL;
-
- count = data->stream.bufend - data->stream.this_frame;
-
- if (tagsize <= count) {
- id3_data = data->stream.this_frame;
- mad_stream_skip(&(data->stream), tagsize);
- } else {
- allocated = g_malloc(tagsize);
- memcpy(allocated, data->stream.this_frame, count);
- mad_stream_skip(&(data->stream), count);
-
- while (count < tagsize) {
- size_t len;
-
- len = decoder_read(data->decoder, data->input_stream,
- allocated + count, tagsize - count);
- if (len == 0)
- break;
- else
- count += len;
- }
-
- if (count != tagsize) {
- g_debug("error parsing ID3 tag");
- g_free(allocated);
- return;
- }
-
- id3_data = allocated;
- }
-
- id3_tag = id3_tag_parse(id3_data, tagsize);
- if (id3_tag == NULL) {
- g_free(allocated);
- return;
- }
-
- if (mpd_tag) {
- struct tag *tmp_tag = tag_id3_import(id3_tag);
- if (tmp_tag != NULL) {
- if (*mpd_tag != NULL)
- tag_free(*mpd_tag);
- *mpd_tag = tmp_tag;
- }
- }
-
- if (data->decoder != NULL) {
- struct replay_gain_info rgi;
- char *mixramp_start;
- char *mixramp_end;
- float replay_gain_db = 0;
-
- if (parse_id3_replay_gain_info(&rgi, id3_tag)) {
- replay_gain_db = decoder_replay_gain(data->decoder, &rgi);
- data->found_replay_gain = true;
- }
- if (parse_id3_mixramp(&mixramp_start, &mixramp_end, id3_tag)) {
- g_debug("setting mixramp_tags");
- decoder_mixramp(data->decoder, replay_gain_db,
- mixramp_start, mixramp_end);
- }
- }
-
- id3_tag_delete(id3_tag);
-
- g_free(allocated);
-#else /* !HAVE_ID3TAG */
- (void)mpd_tag;
-
- /* This code is enabled when libid3tag is disabled. Instead
- of parsing the ID3 frame, it just skips it. */
-
- size_t count = data->stream.bufend - data->stream.this_frame;
-
- if (tagsize <= count) {
- mad_stream_skip(&data->stream, tagsize);
- } else {
- mad_stream_skip(&data->stream, count);
-
- while (count < tagsize) {
- size_t len = tagsize - count;
- char ignored[1024];
- if (len > sizeof(ignored))
- len = sizeof(ignored);
-
- len = decoder_read(data->decoder, data->input_stream,
- ignored, len);
- if (len == 0)
- break;
- else
- count += len;
- }
- }
-#endif
-}
-
-#ifndef HAVE_ID3TAG
-/**
- * This function emulates libid3tag when it is disabled. Instead of
- * doing a real analyzation of the frame, it just checks whether the
- * frame begins with the string "ID3". If so, it returns the length
- * of the ID3 frame.
- */
-static signed long
-id3_tag_query(const void *p0, size_t length)
-{
- const char *p = p0;
-
- return length >= 10 && memcmp(p, "ID3", 3) == 0
- ? (p[8] << 7) + p[9] + 10
- : 0;
-}
-#endif /* !HAVE_ID3TAG */
-
-static enum mp3_action
-decode_next_frame_header(struct mp3_data *data, G_GNUC_UNUSED struct tag **tag)
-{
- enum mad_layer layer;
-
- if ((data->stream).buffer == NULL
- || (data->stream).error == MAD_ERROR_BUFLEN) {
- if (!mp3_fill_buffer(data))
- return DECODE_BREAK;
- }
- if (mad_header_decode(&data->frame.header, &data->stream)) {
- if ((data->stream).error == MAD_ERROR_LOSTSYNC &&
- (data->stream).this_frame) {
- signed long tagsize = id3_tag_query((data->stream).
- this_frame,
- (data->stream).
- bufend -
- (data->stream).
- this_frame);
-
- if (tagsize > 0) {
- if (tag && !(*tag)) {
- mp3_parse_id3(data, (size_t)tagsize,
- tag);
- } else {
- mad_stream_skip(&(data->stream),
- tagsize);
- }
- return DECODE_CONT;
- }
- }
- if (MAD_RECOVERABLE((data->stream).error)) {
- return DECODE_SKIP;
- } else {
- if ((data->stream).error == MAD_ERROR_BUFLEN)
- return DECODE_CONT;
- else {
- g_warning("unrecoverable frame level error "
- "(%s).\n",
- mad_stream_errorstr(&data->stream));
- return DECODE_BREAK;
- }
- }
- }
-
- layer = data->frame.header.layer;
- if (!data->layer) {
- if (layer != MAD_LAYER_II && layer != MAD_LAYER_III) {
- /* Only layer 2 and 3 have been tested to work */
- return DECODE_SKIP;
- }
- data->layer = layer;
- } else if (layer != data->layer) {
- /* Don't decode frames with a different layer than the first */
- return DECODE_SKIP;
- }
-
- return DECODE_OK;
-}
-
-static enum mp3_action
-decodeNextFrame(struct mp3_data *data)
-{
- if ((data->stream).buffer == NULL
- || (data->stream).error == MAD_ERROR_BUFLEN) {
- if (!mp3_fill_buffer(data))
- return DECODE_BREAK;
- }
- if (mad_frame_decode(&data->frame, &data->stream)) {
- if ((data->stream).error == MAD_ERROR_LOSTSYNC) {
- signed long tagsize = id3_tag_query((data->stream).
- this_frame,
- (data->stream).
- bufend -
- (data->stream).
- this_frame);
- if (tagsize > 0) {
- mad_stream_skip(&(data->stream), tagsize);
- return DECODE_CONT;
- }
- }
- if (MAD_RECOVERABLE((data->stream).error)) {
- return DECODE_SKIP;
- } else {
- if ((data->stream).error == MAD_ERROR_BUFLEN)
- return DECODE_CONT;
- else {
- g_warning("unrecoverable frame level error "
- "(%s).\n",
- mad_stream_errorstr(&data->stream));
- return DECODE_BREAK;
- }
- }
- }
-
- return DECODE_OK;
-}
-
-/* xing stuff stolen from alsaplayer, and heavily modified by jat */
-#define XI_MAGIC (('X' << 8) | 'i')
-#define NG_MAGIC (('n' << 8) | 'g')
-#define IN_MAGIC (('I' << 8) | 'n')
-#define FO_MAGIC (('f' << 8) | 'o')
-
-enum xing_magic {
- XING_MAGIC_XING, /* VBR */
- XING_MAGIC_INFO /* CBR */
-};
-
-struct xing {
- long flags; /* valid fields (see below) */
- unsigned long frames; /* total number of frames */
- unsigned long bytes; /* total number of bytes */
- unsigned char toc[100]; /* 100-point seek table */
- long scale; /* VBR quality */
- enum xing_magic magic; /* header magic */
-};
-
-enum {
- XING_FRAMES = 0x00000001L,
- XING_BYTES = 0x00000002L,
- XING_TOC = 0x00000004L,
- XING_SCALE = 0x00000008L
-};
-
-struct lame_version {
- unsigned major;
- unsigned minor;
-};
-
-struct lame {
- char encoder[10]; /* 9 byte encoder name/version ("LAME3.97b") */
- struct lame_version version; /* struct containing just the version */
- float peak; /* replaygain peak */
- float track_gain; /* replaygain track gain */
- float album_gain; /* replaygain album gain */
- int encoder_delay; /* # of added samples at start of mp3 */
- int encoder_padding; /* # of added samples at end of mp3 */
- int crc; /* CRC of the first 190 bytes of this frame */
-};
-
-static bool
-parse_xing(struct xing *xing, struct mad_bitptr *ptr, int *oldbitlen)
-{
- unsigned long bits;
- int bitlen;
- int bitsleft;
- int i;
-
- bitlen = *oldbitlen;
-
- if (bitlen < 16)
- return false;
-
- bits = mad_bit_read(ptr, 16);
- bitlen -= 16;
-
- if (bits == XI_MAGIC) {
- if (bitlen < 16)
- return false;
-
- if (mad_bit_read(ptr, 16) != NG_MAGIC)
- return false;
-
- bitlen -= 16;
- xing->magic = XING_MAGIC_XING;
- } else if (bits == IN_MAGIC) {
- if (bitlen < 16)
- return false;
-
- if (mad_bit_read(ptr, 16) != FO_MAGIC)
- return false;
-
- bitlen -= 16;
- xing->magic = XING_MAGIC_INFO;
- }
- else if (bits == NG_MAGIC) xing->magic = XING_MAGIC_XING;
- else if (bits == FO_MAGIC) xing->magic = XING_MAGIC_INFO;
- else
- return false;
-
- if (bitlen < 32)
- return false;
- xing->flags = mad_bit_read(ptr, 32);
- bitlen -= 32;
-
- if (xing->flags & XING_FRAMES) {
- if (bitlen < 32)
- return false;
- xing->frames = mad_bit_read(ptr, 32);
- bitlen -= 32;
- }
-
- if (xing->flags & XING_BYTES) {
- if (bitlen < 32)
- return false;
- xing->bytes = mad_bit_read(ptr, 32);
- bitlen -= 32;
- }
-
- if (xing->flags & XING_TOC) {
- if (bitlen < 800)
- return false;
- for (i = 0; i < 100; ++i) xing->toc[i] = mad_bit_read(ptr, 8);
- bitlen -= 800;
- }
-
- if (xing->flags & XING_SCALE) {
- if (bitlen < 32)
- return false;
- xing->scale = mad_bit_read(ptr, 32);
- bitlen -= 32;
- }
-
- /* Make sure we consume no less than 120 bytes (960 bits) in hopes that
- * the LAME tag is found there, and not right after the Xing header */
- bitsleft = 960 - ((*oldbitlen) - bitlen);
- if (bitsleft < 0)
- return false;
- else if (bitsleft > 0) {
- mad_bit_read(ptr, bitsleft);
- bitlen -= bitsleft;
- }
-
- *oldbitlen = bitlen;
-
- return true;
-}
-
-static bool
-parse_lame(struct lame *lame, struct mad_bitptr *ptr, int *bitlen)
-{
- int adj = 0;
- int name;
- int orig;
- int sign;
- int gain;
- int i;
-
- /* Unlike the xing header, the lame tag has a fixed length. Fail if
- * not all 36 bytes (288 bits) are there. */
- if (*bitlen < 288)
- return false;
-
- for (i = 0; i < 9; i++)
- lame->encoder[i] = (char)mad_bit_read(ptr, 8);
- lame->encoder[9] = '\0';
-
- *bitlen -= 72;
-
- /* This is technically incorrect, since the encoder might not be lame.
- * But there's no other way to determine if this is a lame tag, and we
- * wouldn't want to go reading a tag that's not there. */
- if (!g_str_has_prefix(lame->encoder, "LAME"))
- return false;
-
- if (sscanf(lame->encoder+4, "%u.%u",
- &lame->version.major, &lame->version.minor) != 2)
- return false;
-
- g_debug("detected LAME version %i.%i (\"%s\")\n",
- lame->version.major, lame->version.minor, lame->encoder);
-
- /* The reference volume was changed from the 83dB used in the
- * ReplayGain spec to 89dB in lame 3.95.1. Bump the gain for older
- * versions, since everyone else uses 89dB instead of 83dB.
- * Unfortunately, lame didn't differentiate between 3.95 and 3.95.1, so
- * it's impossible to make the proper adjustment for 3.95.
- * Fortunately, 3.95 was only out for about a day before 3.95.1 was
- * released. -- tmz */
- if (lame->version.major < 3 ||
- (lame->version.major == 3 && lame->version.minor < 95))
- adj = 6;
-
- mad_bit_read(ptr, 16);
-
- lame->peak = mad_f_todouble(mad_bit_read(ptr, 32) << 5); /* peak */
- g_debug("LAME peak found: %f\n", lame->peak);
-
- lame->track_gain = 0;
- name = mad_bit_read(ptr, 3); /* gain name */
- orig = mad_bit_read(ptr, 3); /* gain originator */
- sign = mad_bit_read(ptr, 1); /* sign bit */
- gain = mad_bit_read(ptr, 9); /* gain*10 */
- if (gain && name == 1 && orig != 0) {
- lame->track_gain = ((sign ? -gain : gain) / 10.0) + adj;
- g_debug("LAME track gain found: %f\n", lame->track_gain);
- }
-
- /* tmz reports that this isn't currently written by any version of lame
- * (as of 3.97). Since we have no way of testing it, don't use it.
- * Wouldn't want to go blowing someone's ears just because we read it
- * wrong. :P -- jat */
- lame->album_gain = 0;
-#if 0
- name = mad_bit_read(ptr, 3); /* gain name */
- orig = mad_bit_read(ptr, 3); /* gain originator */
- sign = mad_bit_read(ptr, 1); /* sign bit */
- gain = mad_bit_read(ptr, 9); /* gain*10 */
- if (gain && name == 2 && orig != 0) {
- lame->album_gain = ((sign ? -gain : gain) / 10.0) + adj;
- g_debug("LAME album gain found: %f\n", lame->track_gain);
- }
-#else
- mad_bit_read(ptr, 16);
-#endif
-
- mad_bit_read(ptr, 16);
-
- lame->encoder_delay = mad_bit_read(ptr, 12);
- lame->encoder_padding = mad_bit_read(ptr, 12);
-
- g_debug("encoder delay is %i, encoder padding is %i\n",
- lame->encoder_delay, lame->encoder_padding);
-
- mad_bit_read(ptr, 80);
-
- lame->crc = mad_bit_read(ptr, 16);
-
- *bitlen -= 216;
-
- return true;
-}
-
-static inline float
-mp3_frame_duration(const struct mad_frame *frame)
-{
- return mad_timer_count(frame->header.duration,
- MAD_UNITS_MILLISECONDS) / 1000.0;
-}
-
-static goffset
-mp3_this_frame_offset(const struct mp3_data *data)
-{
- goffset offset = data->input_stream->offset;
-
- if (data->stream.this_frame != NULL)
- offset -= data->stream.bufend - data->stream.this_frame;
- else
- offset -= data->stream.bufend - data->stream.buffer;
-
- return offset;
-}
-
-static goffset
-mp3_rest_including_this_frame(const struct mp3_data *data)
-{
- return data->input_stream->size - mp3_this_frame_offset(data);
-}
-
-/**
- * Attempt to calulcate the length of the song from filesize
- */
-static void
-mp3_filesize_to_song_length(struct mp3_data *data)
-{
- goffset rest = mp3_rest_including_this_frame(data);
-
- if (rest > 0) {
- float frame_duration = mp3_frame_duration(&data->frame);
-
- data->total_time = (rest * 8.0) / (data->frame).header.bitrate;
- data->max_frames = data->total_time / frame_duration +
- FRAMES_CUSHION;
- } else {
- data->max_frames = FRAMES_CUSHION;
- data->total_time = 0;
- }
-}
-
-static bool
-mp3_decode_first_frame(struct mp3_data *data, struct tag **tag)
-{
- struct xing xing;
- struct lame lame;
- struct mad_bitptr ptr;
- int bitlen;
- enum mp3_action ret;
-
- /* stfu gcc */
- memset(&xing, 0, sizeof(struct xing));
- xing.flags = 0;
-
- while (true) {
- do {
- ret = decode_next_frame_header(data, tag);
- } while (ret == DECODE_CONT);
- if (ret == DECODE_BREAK)
- return false;
- if (ret == DECODE_SKIP) continue;
-
- do {
- ret = decodeNextFrame(data);
- } while (ret == DECODE_CONT);
- if (ret == DECODE_BREAK)
- return false;
- if (ret == DECODE_OK) break;
- }
-
- ptr = data->stream.anc_ptr;
- bitlen = data->stream.anc_bitlen;
-
- mp3_filesize_to_song_length(data);
-
- /*
- * if an xing tag exists, use that!
- */
- if (parse_xing(&xing, &ptr, &bitlen)) {
- data->found_xing = true;
- data->mute_frame = MUTEFRAME_SKIP;
-
- if ((xing.flags & XING_FRAMES) && xing.frames) {
- mad_timer_t duration = data->frame.header.duration;
- mad_timer_multiply(&duration, xing.frames);
- data->total_time = ((float)mad_timer_count(duration, MAD_UNITS_MILLISECONDS)) / 1000;
- data->max_frames = xing.frames;
- }
-
- if (parse_lame(&lame, &ptr, &bitlen)) {
- if (gapless_playback &&
- data->input_stream->seekable) {
- data->drop_start_samples = lame.encoder_delay +
- DECODERDELAY;
- data->drop_end_samples = lame.encoder_padding;
- }
-
- /* Album gain isn't currently used. See comment in
- * parse_lame() for details. -- jat */
- if (data->decoder != NULL &&
- !data->found_replay_gain &&
- lame.track_gain) {
- struct replay_gain_info rgi;
- replay_gain_info_init(&rgi);
- rgi.tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain;
- rgi.tuples[REPLAY_GAIN_TRACK].peak = lame.peak;
- decoder_replay_gain(data->decoder, &rgi);
- }
- }
- }
-
- if (!data->max_frames)
- return false;
-
- if (data->max_frames > 8 * 1024 * 1024) {
- g_warning("mp3 file header indicates too many frames: %lu\n",
- data->max_frames);
- return false;
- }
-
- data->frame_offsets = g_malloc(sizeof(long) * data->max_frames);
- data->times = g_malloc(sizeof(mad_timer_t) * data->max_frames);
-
- return true;
-}
-
-static void mp3_data_finish(struct mp3_data *data)
-{
- mad_synth_finish(&data->synth);
- mad_frame_finish(&data->frame);
- mad_stream_finish(&data->stream);
-
- g_free(data->frame_offsets);
- g_free(data->times);
-}
-
-/* this is primarily used for getting total time for tags */
-static int
-mad_decoder_total_file_time(struct input_stream *is)
-{
- struct mp3_data data;
- int ret;
-
- mp3_data_init(&data, NULL, is);
- if (!mp3_decode_first_frame(&data, NULL))
- ret = -1;
- else
- ret = data.total_time + 0.5;
- mp3_data_finish(&data);
-
- return ret;
-}
-
-static bool
-mp3_open(struct input_stream *is, struct mp3_data *data,
- struct decoder *decoder, struct tag **tag)
-{
- mp3_data_init(data, decoder, is);
- *tag = NULL;
- if (!mp3_decode_first_frame(data, tag)) {
- mp3_data_finish(data);
- if (tag && *tag)
- tag_free(*tag);
- return false;
- }
-
- return true;
-}
-
-static long
-mp3_time_to_frame(const struct mp3_data *data, double t)
-{
- unsigned long i;
-
- for (i = 0; i < data->highest_frame; ++i) {
- double frame_time =
- mad_timer_count(data->times[i],
- MAD_UNITS_MILLISECONDS) / 1000.;
- if (frame_time >= t)
- break;
- }
-
- return i;
-}
-
-static void
-mp3_update_timer_next_frame(struct mp3_data *data)
-{
- if (data->current_frame >= data->highest_frame) {
- /* record this frame's properties in
- data->frame_offsets (for seeking) and
- data->times */
- data->bit_rate = (data->frame).header.bitrate;
-
- if (data->current_frame >= data->max_frames)
- /* cap data->current_frame */
- data->current_frame = data->max_frames - 1;
- else
- data->highest_frame++;
-
- data->frame_offsets[data->current_frame] =
- mp3_this_frame_offset(data);
-
- mad_timer_add(&data->timer, (data->frame).header.duration);
- data->times[data->current_frame] = data->timer;
- } else
- /* get the new timer value from data->times */
- data->timer = data->times[data->current_frame];
-
- data->current_frame++;
- data->elapsed_time =
- mad_timer_count(data->timer, MAD_UNITS_MILLISECONDS) / 1000.0;
-}
-
-/**
- * Sends the synthesized current frame via decoder_data().
- */
-static enum decoder_command
-mp3_send_pcm(struct mp3_data *data, unsigned i, unsigned pcm_length)
-{
- unsigned max_samples;
-
- max_samples = sizeof(data->output_buffer) /
- sizeof(data->output_buffer[0]) /
- MAD_NCHANNELS(&(data->frame).header);
-
- while (i < pcm_length) {
- enum decoder_command cmd;
- unsigned int num_samples = pcm_length - i;
- if (num_samples > max_samples)
- num_samples = max_samples;
-
- i += num_samples;
-
- mad_fixed_to_24_buffer(data->output_buffer,
- &data->synth,
- i - num_samples, i,
- MAD_NCHANNELS(&(data->frame).header));
- num_samples *= MAD_NCHANNELS(&(data->frame).header);
-
- cmd = decoder_data(data->decoder, data->input_stream,
- data->output_buffer,
- sizeof(data->output_buffer[0]) * num_samples,
- data->bit_rate / 1000);
- if (cmd != DECODE_COMMAND_NONE)
- return cmd;
- }
-
- return DECODE_COMMAND_NONE;
-}
-
-/**
- * Synthesize the current frame and send it via decoder_data().
- */
-static enum decoder_command
-mp3_synth_and_send(struct mp3_data *data)
-{
- unsigned i, pcm_length;
- enum decoder_command cmd;
-
- mad_synth_frame(&data->synth, &data->frame);
-
- if (!data->found_first_frame) {
- unsigned int samples_per_frame = data->synth.pcm.length;
- data->drop_start_frames = data->drop_start_samples / samples_per_frame;
- data->drop_end_frames = data->drop_end_samples / samples_per_frame;
- data->drop_start_samples = data->drop_start_samples % samples_per_frame;
- data->drop_end_samples = data->drop_end_samples % samples_per_frame;
- data->found_first_frame = true;
- }
-
- if (data->drop_start_frames > 0) {
- data->drop_start_frames--;
- return DECODE_COMMAND_NONE;
- } else if ((data->drop_end_frames > 0) &&
- (data->current_frame == (data->max_frames + 1 - data->drop_end_frames))) {
- /* stop decoding, effectively dropping all remaining
- frames */
- return DECODE_COMMAND_STOP;
- }
-
- if (!data->decoded_first_frame) {
- i = data->drop_start_samples;
- data->decoded_first_frame = true;
- } else
- i = 0;
-
- pcm_length = data->synth.pcm.length;
- if (data->drop_end_samples &&
- (data->current_frame == data->max_frames - data->drop_end_frames)) {
- if (data->drop_end_samples >= pcm_length)
- pcm_length = 0;
- else
- pcm_length -= data->drop_end_samples;
- }
-
- cmd = mp3_send_pcm(data, i, pcm_length);
- if (cmd != DECODE_COMMAND_NONE)
- return cmd;
-
- if (data->drop_end_samples &&
- (data->current_frame == data->max_frames - data->drop_end_frames))
- /* stop decoding, effectively dropping
- * all remaining samples */
- return DECODE_COMMAND_STOP;
-
- return DECODE_COMMAND_NONE;
-}
-
-static bool
-mp3_read(struct mp3_data *data)
-{
- struct decoder *decoder = data->decoder;
- enum mp3_action ret;
- enum decoder_command cmd;
-
- mp3_update_timer_next_frame(data);
-
- switch (data->mute_frame) {
- case MUTEFRAME_SKIP:
- data->mute_frame = MUTEFRAME_NONE;
- break;
- case MUTEFRAME_SEEK:
- if (data->elapsed_time >= data->seek_where)
- data->mute_frame = MUTEFRAME_NONE;
- break;
- case MUTEFRAME_NONE:
- cmd = mp3_synth_and_send(data);
- if (cmd == DECODE_COMMAND_SEEK) {
- unsigned long j;
-
- assert(data->input_stream->seekable);
-
- j = mp3_time_to_frame(data,
- decoder_seek_where(decoder));
- if (j < data->highest_frame) {
- if (mp3_seek(data, data->frame_offsets[j])) {
- data->current_frame = j;
- decoder_command_finished(decoder);
- } else
- decoder_seek_error(decoder);
- } else {
- data->seek_where = decoder_seek_where(decoder);
- data->mute_frame = MUTEFRAME_SEEK;
- decoder_command_finished(decoder);
- }
- } else if (cmd != DECODE_COMMAND_NONE)
- return false;
- }
-
- while (true) {
- bool skip = false;
-
- do {
- struct tag *tag = NULL;
-
- ret = decode_next_frame_header(data, &tag);
-
- if (tag != NULL) {
- decoder_tag(decoder, data->input_stream, tag);
- tag_free(tag);
- }
- } while (ret == DECODE_CONT);
- if (ret == DECODE_BREAK)
- return false;
- else if (ret == DECODE_SKIP)
- skip = true;
-
- if (data->mute_frame == MUTEFRAME_NONE) {
- do {
- ret = decodeNextFrame(data);
- } while (ret == DECODE_CONT);
- if (ret == DECODE_BREAK)
- return false;
- }
-
- if (!skip && ret == DECODE_OK)
- break;
- }
-
- return ret != DECODE_BREAK;
-}
-
-static void
-mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
-{
- struct mp3_data data;
- GError *error = NULL;
- struct tag *tag = NULL;
- struct audio_format audio_format;
-
- if (!mp3_open(input_stream, &data, decoder, &tag)) {
- if (decoder_get_command(decoder) == DECODE_COMMAND_NONE)
- g_warning
- ("Input does not appear to be a mp3 bit stream.\n");
- return;
- }
-
- if (!audio_format_init_checked(&audio_format,
- data.frame.header.samplerate,
- SAMPLE_FORMAT_S24_P32,
- MAD_NCHANNELS(&data.frame.header),
- &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
-
- if (tag != NULL)
- tag_free(tag);
- mp3_data_finish(&data);
- return;
- }
-
- decoder_initialized(decoder, &audio_format,
- data.input_stream->seekable, data.total_time);
-
- if (tag != NULL) {
- decoder_tag(decoder, input_stream, tag);
- tag_free(tag);
- }
-
- while (mp3_read(&data)) ;
-
- mp3_data_finish(&data);
-}
-
-static bool
-mad_decoder_scan_stream(struct input_stream *is,
- const struct tag_handler *handler, void *handler_ctx)
-{
- int total_time;
-
- total_time = mad_decoder_total_file_time(is);
- if (total_time < 0)
- return false;
-
- tag_handler_invoke_duration(handler, handler_ctx, total_time);
- return true;
-}
-
-static const char *const mp3_suffixes[] = { "mp3", "mp2", NULL };
-static const char *const mp3_mime_types[] = { "audio/mpeg", NULL };
-
-const struct decoder_plugin mad_decoder_plugin = {
- .name = "mad",
- .init = mp3_plugin_init,
- .stream_decode = mp3_decode,
- .scan_stream = mad_decoder_scan_stream,
- .suffixes = mp3_suffixes,
- .mime_types = mp3_mime_types
-};
diff --git a/src/decoder/mikmod_decoder_plugin.c b/src/decoder/mikmod_decoder_plugin.c
deleted file mode 100644
index 5681a7a5..00000000
--- a/src/decoder/mikmod_decoder_plugin.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "mpd_error.h"
-#include "tag_handler.h"
-
-#include <glib.h>
-#include <mikmod.h>
-#include <assert.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "mikmod"
-
-/* this is largely copied from alsaplayer */
-
-#define MIKMOD_FRAME_SIZE 4096
-
-static BOOL
-mikmod_mpd_init(void)
-{
- return VC_Init();
-}
-
-static void
-mikmod_mpd_exit(void)
-{
- VC_Exit();
-}
-
-static void
-mikmod_mpd_update(void)
-{
-}
-
-static BOOL
-mikmod_mpd_is_present(void)
-{
- return true;
-}
-
-static char drv_name[] = PACKAGE_NAME;
-static char drv_version[] = VERSION;
-
-#if (LIBMIKMOD_VERSION > 0x030106)
-static char drv_alias[] = PACKAGE;
-#endif
-
-static MDRIVER drv_mpd = {
- NULL,
- drv_name,
- drv_version,
- 0,
- 255,
-#if (LIBMIKMOD_VERSION > 0x030106)
- drv_alias,
-#if (LIBMIKMOD_VERSION >= 0x030200)
- NULL, /* CmdLineHelp */
-#endif
- NULL, /* CommandLine */
-#endif
- mikmod_mpd_is_present,
- VC_SampleLoad,
- VC_SampleUnload,
- VC_SampleSpace,
- VC_SampleLength,
- mikmod_mpd_init,
- mikmod_mpd_exit,
- NULL,
- VC_SetNumVoices,
- VC_PlayStart,
- VC_PlayStop,
- mikmod_mpd_update,
- NULL,
- VC_VoiceSetVolume,
- VC_VoiceGetVolume,
- VC_VoiceSetFrequency,
- VC_VoiceGetFrequency,
- VC_VoiceSetPanning,
- VC_VoiceGetPanning,
- VC_VoicePlay,
- VC_VoiceStop,
- VC_VoiceStopped,
- VC_VoiceGetPosition,
- VC_VoiceRealVolume
-};
-
-static unsigned mikmod_sample_rate;
-
-static bool
-mikmod_decoder_init(const struct config_param *param)
-{
- static char params[] = "";
-
- mikmod_sample_rate = config_get_block_unsigned(param, "sample_rate",
- 44100);
- if (!audio_valid_sample_rate(mikmod_sample_rate))
- MPD_ERROR("Invalid sample rate in line %d: %u",
- param->line, mikmod_sample_rate);
-
- md_device = 0;
- md_reverb = 0;
-
- MikMod_RegisterDriver(&drv_mpd);
- MikMod_RegisterAllLoaders();
-
- md_pansep = 64;
- md_mixfreq = mikmod_sample_rate;
- md_mode = (DMODE_SOFT_MUSIC | DMODE_INTERP | DMODE_STEREO |
- DMODE_16BITS);
-
- if (MikMod_Init(params)) {
- g_warning("Could not init MikMod: %s\n",
- MikMod_strerror(MikMod_errno));
- return false;
- }
-
- return true;
-}
-
-static void
-mikmod_decoder_finish(void)
-{
- MikMod_Exit();
-}
-
-static void
-mikmod_decoder_file_decode(struct decoder *decoder, const char *path_fs)
-{
- char *path2;
- MODULE *handle;
- struct audio_format audio_format;
- int ret;
- SBYTE buffer[MIKMOD_FRAME_SIZE];
- enum decoder_command cmd = DECODE_COMMAND_NONE;
-
- path2 = g_strdup(path_fs);
- handle = Player_Load(path2, 128, 0);
- g_free(path2);
-
- if (handle == NULL) {
- g_warning("failed to open mod: %s", path_fs);
- return;
- }
-
- /* Prevent module from looping forever */
- handle->loop = 0;
-
- audio_format_init(&audio_format, mikmod_sample_rate, SAMPLE_FORMAT_S16, 2);
- assert(audio_format_valid(&audio_format));
-
- decoder_initialized(decoder, &audio_format, false, 0);
-
- Player_Start(handle);
- while (cmd == DECODE_COMMAND_NONE && Player_Active()) {
- ret = VC_WriteBytes(buffer, sizeof(buffer));
- cmd = decoder_data(decoder, NULL, buffer, ret, 0);
- }
-
- Player_Stop();
- Player_Free(handle);
-}
-
-static bool
-mikmod_decoder_scan_file(const char *path_fs,
- const struct tag_handler *handler, void *handler_ctx)
-{
- char *path2 = g_strdup(path_fs);
- MODULE *handle = Player_Load(path2, 128, 0);
-
- if (handle == NULL) {
- g_free(path2);
- g_debug("Failed to open file: %s", path_fs);
- return false;
-
- }
-
- Player_Free(handle);
-
- char *title = Player_LoadTitle(path2);
- g_free(path2);
-
- if (title != NULL) {
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_TITLE, title);
- free(title);
- }
-
- return true;
-}
-
-static const char *const mikmod_decoder_suffixes[] = {
- "amf",
- "dsm",
- "far",
- "gdm",
- "imf",
- "it",
- "med",
- "mod",
- "mtm",
- "s3m",
- "stm",
- "stx",
- "ult",
- "uni",
- "xm",
- NULL
-};
-
-const struct decoder_plugin mikmod_decoder_plugin = {
- .name = "mikmod",
- .init = mikmod_decoder_init,
- .finish = mikmod_decoder_finish,
- .file_decode = mikmod_decoder_file_decode,
- .scan_file = mikmod_decoder_scan_file,
- .suffixes = mikmod_decoder_suffixes,
-};
diff --git a/src/decoder/modplug_decoder_plugin.c b/src/decoder/modplug_decoder_plugin.c
deleted file mode 100644
index 21ee79e7..00000000
--- a/src/decoder/modplug_decoder_plugin.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "tag_handler.h"
-
-#include <glib.h>
-#include <modplug.h>
-#include <assert.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "modplug"
-
-enum {
- MODPLUG_FRAME_SIZE = 4096,
- MODPLUG_PREALLOC_BLOCK = 256 * 1024,
- MODPLUG_READ_BLOCK = 128 * 1024,
- MODPLUG_FILE_LIMIT = 100 * 1024 * 1024,
-};
-
-static GByteArray *mod_loadfile(struct decoder *decoder, struct input_stream *is)
-{
- unsigned char *data;
- GByteArray *bdatas;
- size_t ret;
-
- if (is->size == 0) {
- g_warning("file is empty");
- return NULL;
- }
-
- if (is->size > MODPLUG_FILE_LIMIT) {
- g_warning("file too large");
- return NULL;
- }
-
- //known/unknown size, preallocate array, lets read in chunks
- if (is->size > 0) {
- bdatas = g_byte_array_sized_new(is->size);
- } else {
- bdatas = g_byte_array_sized_new(MODPLUG_PREALLOC_BLOCK);
- }
-
- data = g_malloc(MODPLUG_READ_BLOCK);
-
- while (true) {
- ret = decoder_read(decoder, is, data, MODPLUG_READ_BLOCK);
- if (ret == 0) {
- if (input_stream_lock_eof(is))
- /* end of file */
- break;
-
- /* I/O error - skip this song */
- g_free(data);
- g_byte_array_free(bdatas, true);
- return NULL;
- }
-
- if (bdatas->len + ret > MODPLUG_FILE_LIMIT) {
- g_warning("stream too large\n");
- g_free(data);
- g_byte_array_free(bdatas, TRUE);
- return NULL;
- }
-
- g_byte_array_append(bdatas, data, ret);
- }
-
- g_free(data);
-
- return bdatas;
-}
-
-static void
-mod_decode(struct decoder *decoder, struct input_stream *is)
-{
- ModPlugFile *f;
- ModPlug_Settings settings;
- GByteArray *bdatas;
- struct audio_format audio_format;
- int ret;
- char audio_buffer[MODPLUG_FRAME_SIZE];
- enum decoder_command cmd = DECODE_COMMAND_NONE;
-
- bdatas = mod_loadfile(decoder, is);
-
- if (!bdatas) {
- g_warning("could not load stream\n");
- return;
- }
-
- ModPlug_GetSettings(&settings);
- /* alter setting */
- settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; /* RESAMP */
- settings.mChannels = 2;
- settings.mBits = 16;
- settings.mFrequency = 44100;
- /* insert more setting changes here */
- ModPlug_SetSettings(&settings);
-
- f = ModPlug_Load(bdatas->data, bdatas->len);
- g_byte_array_free(bdatas, TRUE);
- if (!f) {
- g_warning("could not decode stream\n");
- return;
- }
-
- audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2);
- assert(audio_format_valid(&audio_format));
-
- decoder_initialized(decoder, &audio_format,
- is->seekable, ModPlug_GetLength(f) / 1000.0);
-
- do {
- ret = ModPlug_Read(f, audio_buffer, MODPLUG_FRAME_SIZE);
- if (ret <= 0)
- break;
-
- cmd = decoder_data(decoder, NULL,
- audio_buffer, ret,
- 0);
-
- if (cmd == DECODE_COMMAND_SEEK) {
- float where = decoder_seek_where(decoder);
-
- ModPlug_Seek(f, (int)(where * 1000.0));
-
- decoder_command_finished(decoder);
- }
-
- } while (cmd != DECODE_COMMAND_STOP);
-
- ModPlug_Unload(f);
-}
-
-static bool
-modplug_scan_stream(struct input_stream *is,
- const struct tag_handler *handler, void *handler_ctx)
-{
- ModPlugFile *f;
- GByteArray *bdatas;
-
- bdatas = mod_loadfile(NULL, is);
- if (!bdatas)
- return false;
-
- f = ModPlug_Load(bdatas->data, bdatas->len);
- g_byte_array_free(bdatas, TRUE);
- if (f == NULL)
- return false;
-
- tag_handler_invoke_duration(handler, handler_ctx,
- ModPlug_GetLength(f) / 1000);
-
- const char *title = ModPlug_GetName(f);
- if (title != NULL)
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_TITLE, title);
-
- ModPlug_Unload(f);
-
- return true;
-}
-
-static const char *const mod_suffixes[] = {
- "669", "amf", "ams", "dbm", "dfm", "dsm", "far", "it",
- "med", "mdl", "mod", "mtm", "mt2", "okt", "s3m", "stm",
- "ult", "umx", "xm",
- NULL
-};
-
-const struct decoder_plugin modplug_decoder_plugin = {
- .name = "modplug",
- .stream_decode = mod_decode,
- .scan_stream = modplug_scan_stream,
- .suffixes = mod_suffixes,
-};
diff --git a/src/decoder/mp4ff_decoder_plugin.c b/src/decoder/mp4ff_decoder_plugin.c
deleted file mode 100644
index ca78a22d..00000000
--- a/src/decoder/mp4ff_decoder_plugin.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "audio_check.h"
-#include "tag_table.h"
-#include "tag_handler.h"
-
-#include <glib.h>
-
-#include <mp4ff.h>
-#include <faad.h>
-
-#include <assert.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "mp4ff"
-
-/* all code here is either based on or copied from FAAD2's frontend code */
-
-struct mp4ff_input_stream {
- mp4ff_callback_t callback;
-
- struct decoder *decoder;
- struct input_stream *input_stream;
-};
-
-static int
-mp4_get_aac_track(mp4ff_t * infile, faacDecHandle decoder,
- uint32_t *sample_rate, unsigned char *channels_r)
-{
-#ifdef HAVE_FAAD_LONG
- /* neaacdec.h declares all arguments as "unsigned long", but
- internally expects uint32_t pointers. To avoid gcc
- warnings, use this workaround. */
- unsigned long *sample_rate_r = (unsigned long*)sample_rate;
-#else
- uint32_t *sample_rate_r = sample_rate;
-#endif
- int i, rc;
- int num_tracks = mp4ff_total_tracks(infile);
-
- for (i = 0; i < num_tracks; i++) {
- unsigned char *buff = NULL;
- unsigned int buff_size = 0;
-
- if (mp4ff_get_track_type(infile, i) != 1)
- /* not an audio track */
- continue;
-
- if (decoder == NULL)
- /* have don't have a decoder to initialize -
- we're done now, because we found an audio
- track */
- return i;
-
- mp4ff_get_decoder_config(infile, i, &buff, &buff_size);
- if (buff == NULL)
- continue;
-
- rc = faacDecInit2(decoder, buff, buff_size,
- sample_rate_r, channels_r);
- free(buff);
-
- if (rc >= 0)
- /* found a valid AAC track */
- return i;
- }
-
- /* can't decode this */
- return -1;
-}
-
-static uint32_t
-mp4_read(void *user_data, void *buffer, uint32_t length)
-{
- struct mp4ff_input_stream *mis = user_data;
-
- if (length == 0)
- /* libmp4ff is known to attempt to read 0 bytes - make
- this a special case, because the input_stream API
- would not allow this */
- return 0;
-
- return decoder_read(mis->decoder, mis->input_stream, buffer, length);
-}
-
-static uint32_t
-mp4_seek(void *user_data, uint64_t position)
-{
- struct mp4ff_input_stream *mis = user_data;
-
- return input_stream_lock_seek(mis->input_stream, position, SEEK_SET,
- NULL)
- ? 0 : -1;
-}
-
-static const mp4ff_callback_t mpd_mp4ff_callback = {
- .read = mp4_read,
- .seek = mp4_seek,
-};
-
-static mp4ff_t *
-mp4ff_input_stream_open(struct mp4ff_input_stream *mis,
- struct decoder *decoder,
- struct input_stream *input_stream)
-{
- mis->callback = mpd_mp4ff_callback;
- mis->callback.user_data = mis;
- mis->decoder = decoder;
- mis->input_stream = input_stream;
-
- return mp4ff_open_read(&mis->callback);
-}
-
-static faacDecHandle
-mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format)
-{
- faacDecHandle decoder;
- faacDecConfigurationPtr config;
- int track;
- uint32_t sample_rate;
- unsigned char channels;
- GError *error = NULL;
-
- decoder = faacDecOpen();
-
- config = faacDecGetCurrentConfiguration(decoder);
- config->outputFormat = FAAD_FMT_16BIT;
-#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX
- config->downMatrix = 1;
-#endif
-#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
- config->dontUpSampleImplicitSBR = 0;
-#endif
- faacDecSetConfiguration(decoder, config);
-
- track = mp4_get_aac_track(mp4fh, decoder, &sample_rate, &channels);
- if (track < 0) {
- g_warning("No AAC track found");
- faacDecClose(decoder);
- return NULL;
- }
-
- if (!audio_format_init_checked(audio_format, sample_rate,
- SAMPLE_FORMAT_S16, channels,
- &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- faacDecClose(decoder);
- return NULL;
- }
-
- *track_r = track;
-
- return decoder;
-}
-
-static void
-mp4_decode(struct decoder *mpd_decoder, struct input_stream *input_stream)
-{
- struct mp4ff_input_stream mis;
- mp4ff_t *mp4fh;
- int32_t track;
- float file_time, total_time;
- int32_t scale;
- faacDecHandle decoder;
- struct audio_format audio_format;
- faacDecFrameInfo frame_info;
- unsigned char *mp4_buffer;
- unsigned int mp4_buffer_size;
- long sample_id;
- long num_samples;
- long dur;
- unsigned int sample_count;
- char *sample_buffer;
- size_t sample_buffer_length;
- unsigned int initial = 1;
- float *seek_table;
- long seek_table_end = -1;
- bool seek_position_found = false;
- long offset;
- uint16_t bit_rate = 0;
- bool seeking = false;
- double seek_where = 0;
- enum decoder_command cmd = DECODE_COMMAND_NONE;
-
- mp4fh = mp4ff_input_stream_open(&mis, mpd_decoder, input_stream);
- if (!mp4fh) {
- g_warning("Input does not appear to be a mp4 stream.\n");
- return;
- }
-
- decoder = mp4_faad_new(mp4fh, &track, &audio_format);
- if (decoder == NULL) {
- mp4ff_close(mp4fh);
- return;
- }
-
- file_time = mp4ff_get_track_duration_use_offsets(mp4fh, track);
- scale = mp4ff_time_scale(mp4fh, track);
-
- if (scale < 0) {
- g_warning("Error getting audio format of mp4 AAC track.\n");
- faacDecClose(decoder);
- mp4ff_close(mp4fh);
- return;
- }
- total_time = ((float)file_time) / scale;
-
- num_samples = mp4ff_num_samples(mp4fh, track);
- if (num_samples > (long)(G_MAXINT / sizeof(float))) {
- g_warning("Integer overflow.\n");
- faacDecClose(decoder);
- mp4ff_close(mp4fh);
- return;
- }
-
- file_time = 0.0;
-
- seek_table = input_stream->seekable
- ? g_malloc(sizeof(float) * num_samples)
- : NULL;
-
- decoder_initialized(mpd_decoder, &audio_format,
- input_stream->seekable,
- total_time);
-
- for (sample_id = 0;
- sample_id < num_samples && cmd != DECODE_COMMAND_STOP;
- sample_id++) {
- if (cmd == DECODE_COMMAND_SEEK) {
- assert(seek_table != NULL);
-
- seeking = true;
- seek_where = decoder_seek_where(mpd_decoder);
- }
-
- if (seeking && seek_table_end > 1 &&
- seek_table[seek_table_end] >= seek_where) {
- int i = 2;
-
- assert(seek_table != NULL);
-
- while (seek_table[i] < seek_where)
- i++;
- sample_id = i - 1;
- file_time = seek_table[sample_id];
- }
-
- dur = mp4ff_get_sample_duration(mp4fh, track, sample_id);
- offset = mp4ff_get_sample_offset(mp4fh, track, sample_id);
-
- if (seek_table != NULL && sample_id > seek_table_end) {
- seek_table[sample_id] = file_time;
- seek_table_end = sample_id;
- }
-
- if (sample_id == 0)
- dur = 0;
- if (offset > dur)
- dur = 0;
- else
- dur -= offset;
- file_time += ((float)dur) / scale;
-
- if (seeking && file_time >= seek_where)
- seek_position_found = true;
-
- if (seeking && seek_position_found) {
- seek_position_found = false;
- seeking = 0;
- decoder_command_finished(mpd_decoder);
- }
-
- if (seeking)
- continue;
-
- if (mp4ff_read_sample(mp4fh, track, sample_id, &mp4_buffer,
- &mp4_buffer_size) == 0)
- break;
-
-#ifdef HAVE_FAAD_BUFLEN_FUNCS
- sample_buffer = faacDecDecode(decoder, &frame_info, mp4_buffer,
- mp4_buffer_size);
-#else
- sample_buffer = faacDecDecode(decoder, &frame_info, mp4_buffer);
-#endif
-
- free(mp4_buffer);
-
- if (frame_info.error > 0) {
- g_warning("faad2 error: %s\n",
- faacDecGetErrorMessage(frame_info.error));
- break;
- }
-
- if (frame_info.channels != audio_format.channels) {
- g_warning("channel count changed from %u to %u",
- audio_format.channels, frame_info.channels);
- break;
- }
-
-#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
- if (frame_info.samplerate != audio_format.sample_rate) {
- g_warning("sample rate changed from %u to %lu",
- audio_format.sample_rate,
- (unsigned long)frame_info.samplerate);
- break;
- }
-#endif
-
- if (audio_format.channels * (unsigned long)(dur + offset) > frame_info.samples) {
- dur = frame_info.samples / audio_format.channels;
- offset = 0;
- }
-
- sample_count = (unsigned long)(dur * audio_format.channels);
-
- if (sample_count > 0) {
- initial = 0;
- bit_rate = frame_info.bytesconsumed * 8.0 *
- frame_info.channels * scale /
- frame_info.samples / 1000 + 0.5;
- }
-
- sample_buffer_length = sample_count * 2;
-
- sample_buffer += offset * audio_format.channels * 2;
-
- cmd = decoder_data(mpd_decoder, input_stream,
- sample_buffer, sample_buffer_length,
- bit_rate);
- }
-
- g_free(seek_table);
- faacDecClose(decoder);
- mp4ff_close(mp4fh);
-}
-
-static const struct tag_table mp4ff_tags[] = {
- { "album artist", TAG_ALBUM_ARTIST },
- { "writer", TAG_COMPOSER },
- { "band", TAG_PERFORMER },
- { NULL, TAG_NUM_OF_ITEM_TYPES }
-};
-
-static enum tag_type
-mp4ff_tag_name_parse(const char *name)
-{
- enum tag_type type = tag_table_lookup_i(mp4ff_tags, name);
- if (type == TAG_NUM_OF_ITEM_TYPES)
- type = tag_name_parse_i(name);
-
- if (g_ascii_strcasecmp(name, "albumartist") == 0 ||
- g_ascii_strcasecmp(name, "album_artist") == 0)
- return TAG_ALBUM_ARTIST;
-
- return type;
-}
-
-static bool
-mp4ff_scan_stream(struct input_stream *is,
- const struct tag_handler *handler, void *handler_ctx)
-{
- struct mp4ff_input_stream mis;
- int32_t track;
- int32_t file_time;
- int32_t scale;
- int i;
-
- mp4ff_t *mp4fh = mp4ff_input_stream_open(&mis, NULL, is);
- if (mp4fh == NULL)
- return false;
-
- track = mp4_get_aac_track(mp4fh, NULL, NULL, NULL);
- if (track < 0) {
- mp4ff_close(mp4fh);
- return false;
- }
-
- file_time = mp4ff_get_track_duration_use_offsets(mp4fh, track);
- scale = mp4ff_time_scale(mp4fh, track);
- if (scale < 0) {
- mp4ff_close(mp4fh);
- return false;
- }
-
- tag_handler_invoke_duration(handler, handler_ctx,
- ((float)file_time) / scale + 0.5);
-
- for (i = 0; i < mp4ff_meta_get_num_items(mp4fh); i++) {
- char *item;
- char *value;
-
- mp4ff_meta_get_by_index(mp4fh, i, &item, &value);
-
- tag_handler_invoke_pair(handler, handler_ctx, item, value);
-
- enum tag_type type = mp4ff_tag_name_parse(item);
- if (type != TAG_NUM_OF_ITEM_TYPES)
- tag_handler_invoke_tag(handler, handler_ctx,
- type, value);
-
- free(item);
- free(value);
- }
-
- mp4ff_close(mp4fh);
-
- return true;
-}
-
-static const char *const mp4_suffixes[] = {
- "m4a",
- "m4b",
- "mp4",
- NULL
-};
-
-static const char *const mp4_mime_types[] = { "audio/mp4", "audio/m4a", NULL };
-
-const struct decoder_plugin mp4ff_decoder_plugin = {
- .name = "mp4ff",
- .stream_decode = mp4_decode,
- .scan_stream = mp4ff_scan_stream,
- .suffixes = mp4_suffixes,
- .mime_types = mp4_mime_types,
-};
diff --git a/src/decoder/mpcdec_decoder_plugin.c b/src/decoder/mpcdec_decoder_plugin.c
deleted file mode 100644
index d4768b35..00000000
--- a/src/decoder/mpcdec_decoder_plugin.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "audio_check.h"
-#include "tag_handler.h"
-
-#ifdef MPC_IS_OLD_API
-#include <mpcdec/mpcdec.h>
-#else
-#include <mpc/mpcdec.h>
-#include <math.h>
-#endif
-
-#include <glib.h>
-#include <assert.h>
-#include <unistd.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "mpcdec"
-
-struct mpc_decoder_data {
- struct input_stream *is;
- struct decoder *decoder;
-};
-
-#ifdef MPC_IS_OLD_API
-#define cb_first_arg void *vdata
-#define cb_data vdata
-#else
-#define cb_first_arg mpc_reader *reader
-#define cb_data reader->data
-#endif
-
-static mpc_int32_t
-mpc_read_cb(cb_first_arg, void *ptr, mpc_int32_t size)
-{
- struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data;
-
- return decoder_read(data->decoder, data->is, ptr, size);
-}
-
-static mpc_bool_t
-mpc_seek_cb(cb_first_arg, mpc_int32_t offset)
-{
- struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data;
-
- return input_stream_lock_seek(data->is, offset, SEEK_SET, NULL);
-}
-
-static mpc_int32_t
-mpc_tell_cb(cb_first_arg)
-{
- struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data;
-
- return (long)(data->is->offset);
-}
-
-static mpc_bool_t
-mpc_canseek_cb(cb_first_arg)
-{
- struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data;
-
- return data->is->seekable;
-}
-
-static mpc_int32_t
-mpc_getsize_cb(cb_first_arg)
-{
- struct mpc_decoder_data *data = (struct mpc_decoder_data *) cb_data;
-
- return data->is->size;
-}
-
-/* this _looks_ performance-critical, don't de-inline -- eric */
-static inline int32_t
-mpc_to_mpd_sample(MPC_SAMPLE_FORMAT sample)
-{
- /* only doing 16-bit audio for now */
- int32_t val;
-
- enum {
- bits = 24,
- };
-
- const int clip_min = -1 << (bits - 1);
- const int clip_max = (1 << (bits - 1)) - 1;
-
-#ifdef MPC_FIXED_POINT
- const int shift = bits - MPC_FIXED_POINT_SCALE_SHIFT;
-
- if (shift < 0)
- val = sample >> -shift;
- else
- val = sample << shift;
-#else
- const int float_scale = 1 << (bits - 1);
-
- val = sample * float_scale;
-#endif
-
- if (val < clip_min)
- val = clip_min;
- else if (val > clip_max)
- val = clip_max;
-
- return val;
-}
-
-static void
-mpc_to_mpd_buffer(int32_t *dest, const MPC_SAMPLE_FORMAT *src,
- unsigned num_samples)
-{
- while (num_samples-- > 0)
- *dest++ = mpc_to_mpd_sample(*src++);
-}
-
-static void
-mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
-{
-#ifdef MPC_IS_OLD_API
- mpc_decoder decoder;
-#else
- mpc_demux *demux;
- mpc_frame_info frame;
- mpc_status status;
-#endif
- mpc_reader reader;
- mpc_streaminfo info;
- GError *error = NULL;
- struct audio_format audio_format;
-
- struct mpc_decoder_data data;
-
- MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH];
-
- mpc_uint32_t ret;
- int32_t chunk[G_N_ELEMENTS(sample_buffer)];
- long bit_rate = 0;
- mpc_uint32_t vbr_update_bits;
- enum decoder_command cmd = DECODE_COMMAND_NONE;
-
- data.is = is;
- data.decoder = mpd_decoder;
-
- reader.read = mpc_read_cb;
- reader.seek = mpc_seek_cb;
- reader.tell = mpc_tell_cb;
- reader.get_size = mpc_getsize_cb;
- reader.canseek = mpc_canseek_cb;
- reader.data = &data;
-
-#ifdef MPC_IS_OLD_API
- mpc_streaminfo_init(&info);
-
- if ((ret = mpc_streaminfo_read(&info, &reader)) != ERROR_CODE_OK) {
- if (decoder_get_command(mpd_decoder) != DECODE_COMMAND_STOP)
- g_warning("Not a valid musepack stream\n");
- return;
- }
-
- mpc_decoder_setup(&decoder, &reader);
-
- if (!mpc_decoder_initialize(&decoder, &info)) {
- if (decoder_get_command(mpd_decoder) != DECODE_COMMAND_STOP)
- g_warning("Not a valid musepack stream\n");
- return;
- }
-#else
- demux = mpc_demux_init(&reader);
- if (demux == NULL) {
- if (decoder_get_command(mpd_decoder) != DECODE_COMMAND_STOP)
- g_warning("Not a valid musepack stream");
- return;
- }
-
- mpc_demux_get_info(demux, &info);
-#endif
-
- if (!audio_format_init_checked(&audio_format, info.sample_freq,
- SAMPLE_FORMAT_S24_P32,
- info.channels, &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
-#ifndef MPC_IS_OLD_API
- mpc_demux_exit(demux);
-#endif
- return;
- }
-
- struct replay_gain_info replay_gain_info;
- replay_gain_info_init(&replay_gain_info);
-#ifdef MPC_IS_OLD_API
- replay_gain_info.tuples[REPLAY_GAIN_ALBUM].gain = info.gain_album * 0.01;
- replay_gain_info.tuples[REPLAY_GAIN_ALBUM].peak = info.peak_album / 32767.0;
- replay_gain_info.tuples[REPLAY_GAIN_TRACK].gain = info.gain_title * 0.01;
- replay_gain_info.tuples[REPLAY_GAIN_TRACK].peak = info.peak_title / 32767.0;
-#else
- replay_gain_info.tuples[REPLAY_GAIN_ALBUM].gain = MPC_OLD_GAIN_REF - (info.gain_album / 256.);
- replay_gain_info.tuples[REPLAY_GAIN_ALBUM].peak = pow(10, info.peak_album / 256. / 20) / 32767;
- replay_gain_info.tuples[REPLAY_GAIN_TRACK].gain = MPC_OLD_GAIN_REF - (info.gain_title / 256.);
- replay_gain_info.tuples[REPLAY_GAIN_TRACK].peak = pow(10, info.peak_title / 256. / 20) / 32767;
-#endif
-
- decoder_replay_gain(mpd_decoder, &replay_gain_info);
-
- decoder_initialized(mpd_decoder, &audio_format,
- is->seekable,
- mpc_streaminfo_get_length(&info));
-
- do {
- if (cmd == DECODE_COMMAND_SEEK) {
- mpc_int64_t where = decoder_seek_where(mpd_decoder) *
- audio_format.sample_rate;
- bool success;
-
-#ifdef MPC_IS_OLD_API
- success = mpc_decoder_seek_sample(&decoder, where);
-#else
- success = mpc_demux_seek_sample(demux, where)
- == MPC_STATUS_OK;
-#endif
- if (success)
- decoder_command_finished(mpd_decoder);
- else
- decoder_seek_error(mpd_decoder);
- }
-
- vbr_update_bits = 0;
-
-#ifdef MPC_IS_OLD_API
- mpc_uint32_t vbr_update_acc = 0;
-
- ret = mpc_decoder_decode(&decoder, sample_buffer,
- &vbr_update_acc, &vbr_update_bits);
- if (ret == 0 || ret == (mpc_uint32_t)-1)
- break;
-#else
- frame.buffer = (MPC_SAMPLE_FORMAT *)sample_buffer;
- status = mpc_demux_decode(demux, &frame);
- if (status != MPC_STATUS_OK) {
- g_warning("Failed to decode sample");
- break;
- }
-
- if (frame.bits == -1)
- break;
-
- ret = frame.samples;
-#endif
-
- ret *= info.channels;
-
- mpc_to_mpd_buffer(chunk, sample_buffer, ret);
-
- bit_rate = vbr_update_bits * audio_format.sample_rate
- / 1152 / 1000;
-
- cmd = decoder_data(mpd_decoder, is,
- chunk, ret * sizeof(chunk[0]),
- bit_rate);
- } while (cmd != DECODE_COMMAND_STOP);
-
-#ifndef MPC_IS_OLD_API
- mpc_demux_exit(demux);
-#endif
-}
-
-static float
-mpcdec_get_file_duration(struct input_stream *is)
-{
- float total_time = -1;
-
- mpc_reader reader;
-#ifndef MPC_IS_OLD_API
- mpc_demux *demux;
-#endif
- mpc_streaminfo info;
- struct mpc_decoder_data data;
-
- data.is = is;
- data.decoder = NULL;
-
- reader.read = mpc_read_cb;
- reader.seek = mpc_seek_cb;
- reader.tell = mpc_tell_cb;
- reader.get_size = mpc_getsize_cb;
- reader.canseek = mpc_canseek_cb;
- reader.data = &data;
-
-#ifdef MPC_IS_OLD_API
- mpc_streaminfo_init(&info);
-
- if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK)
- return -1;
-#else
- demux = mpc_demux_init(&reader);
- if (demux == NULL)
- return -1;
-
- mpc_demux_get_info(demux, &info);
- mpc_demux_exit(demux);
-#endif
-
- total_time = mpc_streaminfo_get_length(&info);
-
- return total_time;
-}
-
-static bool
-mpcdec_scan_stream(struct input_stream *is,
- const struct tag_handler *handler, void *handler_ctx)
-{
- float total_time = mpcdec_get_file_duration(is);
-
- if (total_time < 0)
- return false;
-
- tag_handler_invoke_duration(handler, handler_ctx, total_time);
- return true;
-}
-
-static const char *const mpcdec_suffixes[] = { "mpc", NULL };
-
-const struct decoder_plugin mpcdec_decoder_plugin = {
- .name = "mpcdec",
- .stream_decode = mpcdec_decode,
- .scan_stream = mpcdec_scan_stream,
- .suffixes = mpcdec_suffixes,
-};
diff --git a/src/decoder/mpg123_decoder_plugin.c b/src/decoder/mpg123_decoder_plugin.c
deleted file mode 100644
index 657a9c88..00000000
--- a/src/decoder/mpg123_decoder_plugin.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h" /* must be first for large file support */
-#include "decoder_api.h"
-#include "audio_check.h"
-#include "tag_handler.h"
-
-#include <glib.h>
-
-#include <mpg123.h>
-#include <stdio.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)
-{
- GError *gerror = NULL;
- 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;
- }
-
- if (!audio_format_init_checked(audio_format, rate, SAMPLE_FORMAT_S16,
- channels, &gerror)) {
- g_warning("%s", gerror->message);
- g_error_free(gerror);
- 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;
- enum decoder_command cmd;
- struct mpg123_frameinfo info;
-
- /* 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, true,
- (float)num_samples /
- (float)audio_format.sample_rate);
-
- if (mpg123_info(handle, &info) != MPG123_OK) {
- info.vbr = MPG123_CBR;
- info.bitrate = 0;
- }
-
- switch (info.vbr) {
- case MPG123_ABR:
- info.bitrate = info.abr_rate;
- break;
- case MPG123_CBR:
- break;
- default:
- info.bitrate = 0;
- }
-
- /* the decoder main loop */
-
- do {
- unsigned char buffer[8192];
- size_t nbytes;
-
- /* 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;
- }
-
- /* update bitrate for ABR/VBR */
- if (info.vbr != MPG123_CBR) {
- /* FIXME: maybe skip, as too expensive? */
- /* FIXME: maybe, (info.vbr == MPG123_VBR) ? */
- if (mpg123_info (handle, &info) != MPG123_OK)
- info.bitrate = 0;
- }
-
- /* send to MPD */
-
- cmd = decoder_data(decoder, NULL, buffer, nbytes, info.bitrate);
-
- if (cmd == DECODE_COMMAND_SEEK) {
- off_t c = decoder_seek_where(decoder)*audio_format.sample_rate;
- c = mpg123_seek(handle, c, SEEK_SET);
- if (c < 0)
- decoder_seek_error(decoder);
- else {
- decoder_command_finished(decoder);
- decoder_timestamp(decoder, c/(double)audio_format.sample_rate);
- }
-
- cmd = DECODE_COMMAND_NONE;
- }
- } while (cmd == DECODE_COMMAND_NONE);
-
- /* cleanup */
-
- mpg123_delete(handle);
-}
-
-static bool
-mpd_mpg123_scan_file(const char *path_fs,
- const struct tag_handler *handler, void *handler_ctx)
-{
- struct audio_format audio_format;
- mpg123_handle *handle;
- int error;
- off_t num_samples;
-
- handle = mpg123_new(NULL, &error);
- if (handle == NULL) {
- g_warning("mpg123_new() failed: %s",
- mpg123_plain_strerror(error));
- return false;
- }
-
- if (!mpd_mpg123_open(handle, path_fs, &audio_format)) {
- mpg123_delete(handle);
- return false;
- }
-
- num_samples = mpg123_length(handle);
- if (num_samples <= 0) {
- mpg123_delete(handle);
- return false;
- }
-
- /* ID3 tag support not yet implemented */
-
- mpg123_delete(handle);
-
- tag_handler_invoke_duration(handler, handler_ctx,
- num_samples / audio_format.sample_rate);
- return true;
-}
-
-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 */
- .scan_file = mpd_mpg123_scan_file,
- .suffixes = mpg123_suffixes,
-};
diff --git a/src/decoder/pcm_decoder_plugin.c b/src/decoder/pcm_decoder_plugin.c
deleted file mode 100644
index fc7dffc0..00000000
--- a/src/decoder/pcm_decoder_plugin.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder/pcm_decoder_plugin.h"
-#include "decoder_api.h"
-#include "util/byte_reverse.h"
-
-#include <glib.h>
-#include <unistd.h>
-#include <stdio.h> /* for SEEK_SET */
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "pcm"
-
-static void
-pcm_stream_decode(struct decoder *decoder, struct input_stream *is)
-{
- static const struct audio_format audio_format = {
- .sample_rate = 44100,
- .format = SAMPLE_FORMAT_S16,
- .channels = 2,
- };
-
- const bool reverse_endian = is->mime != NULL &&
- strcmp(is->mime, "audio/x-mpd-cdda-pcm-reverse") == 0;
-
- GError *error = NULL;
- enum decoder_command cmd;
-
- double time_to_size = audio_format_time_to_size(&audio_format);
-
- float total_time = -1;
- if (is->size >= 0)
- total_time = is->size / time_to_size;
-
- decoder_initialized(decoder, &audio_format, is->seekable, total_time);
-
- do {
- char buffer[4096];
-
- size_t nbytes = decoder_read(decoder, is,
- buffer, sizeof(buffer));
-
- if (nbytes == 0 && input_stream_lock_eof(is))
- break;
-
- if (reverse_endian)
- /* make sure we deliver samples in host byte order */
- reverse_bytes_16((uint16_t *)buffer,
- (uint16_t *)buffer,
- (uint16_t *)(buffer + nbytes));
-
- cmd = nbytes > 0
- ? decoder_data(decoder, is,
- buffer, nbytes, 0)
- : decoder_get_command(decoder);
- if (cmd == DECODE_COMMAND_SEEK) {
- goffset offset = (goffset)(time_to_size *
- decoder_seek_where(decoder));
- if (input_stream_lock_seek(is, offset, SEEK_SET,
- &error)) {
- decoder_command_finished(decoder);
- } else {
- g_warning("seeking failed: %s", error->message);
- g_error_free(error);
- decoder_seek_error(decoder);
- }
-
- cmd = DECODE_COMMAND_NONE;
- }
- } while (cmd == DECODE_COMMAND_NONE);
-}
-
-static const char *const pcm_mime_types[] = {
- /* for streams obtained by the cdio_paranoia input plugin */
- "audio/x-mpd-cdda-pcm",
-
- /* same as above, but with reverse byte order */
- "audio/x-mpd-cdda-pcm-reverse",
-
- NULL
-};
-
-const struct decoder_plugin pcm_decoder_plugin = {
- .name = "pcm",
- .stream_decode = pcm_stream_decode,
- .mime_types = pcm_mime_types,
-};
diff --git a/src/decoder/pcm_decoder_plugin.h b/src/decoder/pcm_decoder_plugin.h
deleted file mode 100644
index 11df8015..00000000
--- a/src/decoder/pcm_decoder_plugin.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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.
- */
-
-/** \file
- *
- * Not really a decoder; this plugin forwards its input data "as-is".
- *
- * It was written only to support the "cdio_paranoia" input plugin,
- * which does not need a decoder.
- */
-
-#ifndef MPD_DECODER_PCM_H
-#define MPD_DECODER_PCM_H
-
-extern const struct decoder_plugin pcm_decoder_plugin;
-
-#endif
diff --git a/src/decoder/sidplay_decoder_plugin.cxx b/src/decoder/sidplay_decoder_plugin.cxx
deleted file mode 100644
index 5d162f17..00000000
--- a/src/decoder/sidplay_decoder_plugin.cxx
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-
-extern "C" {
-#include "../decoder_api.h"
-#include "tag_handler.h"
-}
-
-#include <errno.h>
-#include <stdlib.h>
-#include <glib.h>
-
-#include <sidplay/sidplay2.h>
-#include <sidplay/builders/resid.h>
-#include <sidplay/utils/SidTuneMod.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "sidplay"
-
-#define SUBTUNE_PREFIX "tune_"
-
-static GPatternSpec *path_with_subtune;
-static const char *songlength_file;
-static GKeyFile *songlength_database;
-
-static bool all_files_are_containers;
-static unsigned default_songlength;
-
-static bool filter_setting;
-
-static GKeyFile *
-sidplay_load_songlength_db(const char *path)
-{
- GError *error = NULL;
- gchar *data;
- gsize size;
-
- if (!g_file_get_contents(path, &data, &size, &error)) {
- g_warning("unable to read songlengths file %s: %s",
- path, error->message);
- g_error_free(error);
- return NULL;
- }
-
- /* replace any ; comment characters with # */
- for (gsize i = 0; i < size; i++)
- if (data[i] == ';')
- data[i] = '#';
-
- GKeyFile *db = g_key_file_new();
- bool success = g_key_file_load_from_data(db, data, size,
- G_KEY_FILE_NONE, &error);
- g_free(data);
- if (!success) {
- g_warning("unable to parse songlengths file %s: %s",
- path, error->message);
- g_error_free(error);
- g_key_file_free(db);
- return NULL;
- }
-
- g_key_file_set_list_separator(db, ' ');
- return db;
-}
-
-static bool
-sidplay_init(const struct config_param *param)
-{
- /* read the songlengths database file */
- songlength_file=config_get_block_string(param,
- "songlength_database", NULL);
- if (songlength_file != NULL)
- songlength_database = sidplay_load_songlength_db(songlength_file);
-
- default_songlength=config_get_block_unsigned(param,
- "default_songlength", 0);
-
- all_files_are_containers=config_get_block_bool(param,
- "all_files_are_containers", true);
-
- path_with_subtune=g_pattern_spec_new(
- "*/" SUBTUNE_PREFIX "???.sid");
-
- filter_setting=config_get_block_bool(param, "filter", true);
-
- return true;
-}
-
-void
-sidplay_finish()
-{
- g_pattern_spec_free(path_with_subtune);
-
- if(songlength_database)
- g_key_file_free(songlength_database);
-}
-
-/**
- * returns the file path stripped of any /tune_xxx.sid subtune
- * suffix
- */
-static char *
-get_container_name(const char *path_fs)
-{
- char *path_container=g_strdup(path_fs);
-
- if(!g_pattern_match(path_with_subtune,
- strlen(path_container), path_container, NULL))
- return path_container;
-
- char *ptr=g_strrstr(path_container, "/" SUBTUNE_PREFIX);
- if(ptr) *ptr='\0';
-
- return path_container;
-}
-
-/**
- * returns tune number from file.sid/tune_xxx.sid style path or 1 if
- * no subtune is appended
- */
-static int
-get_song_num(const char *path_fs)
-{
- if(g_pattern_match(path_with_subtune,
- strlen(path_fs), path_fs, NULL)) {
- char *sub=g_strrstr(path_fs, "/" SUBTUNE_PREFIX);
- if(!sub) return 1;
-
- sub+=strlen("/" SUBTUNE_PREFIX);
- int song_num=strtol(sub, NULL, 10);
-
- if (errno == EINVAL)
- return 1;
- else
- return song_num;
- } else
- return 1;
-}
-
-/* get the song length in seconds */
-static int
-get_song_length(const char *path_fs)
-{
- if (songlength_database == NULL)
- return -1;
-
- gchar *sid_file=get_container_name(path_fs);
- SidTuneMod tune(sid_file);
- g_free(sid_file);
- if(!tune) {
- g_warning("failed to load file for calculating md5 sum");
- return -1;
- }
- char md5sum[SIDTUNE_MD5_LENGTH+1];
- tune.createMD5(md5sum);
-
- int song_num=get_song_num(path_fs);
-
- gsize num_items;
- gchar **values=g_key_file_get_string_list(songlength_database,
- "Database", md5sum, &num_items, NULL);
- if(!values || song_num>num_items) {
- g_strfreev(values);
- return -1;
- }
-
- int minutes=strtol(values[song_num-1], NULL, 10);
- if(errno==EINVAL) minutes=0;
-
- int seconds;
- char *ptr=strchr(values[song_num-1], ':');
- if(ptr) {
- seconds=strtol(ptr+1, NULL, 10);
- if(errno==EINVAL) seconds=0;
- } else
- seconds=0;
-
- g_strfreev(values);
-
- return (minutes*60)+seconds;
-}
-
-static void
-sidplay_file_decode(struct decoder *decoder, const char *path_fs)
-{
- int channels;
-
- /* load the tune */
-
- char *path_container=get_container_name(path_fs);
- SidTune tune(path_container, NULL, true);
- g_free(path_container);
- if (!tune) {
- g_warning("failed to load file");
- return;
- }
-
- int song_num=get_song_num(path_fs);
- tune.selectSong(song_num);
-
- int song_len=get_song_length(path_fs);
- if(song_len==-1) song_len=default_songlength;
-
- /* initialize the player */
-
- sidplay2 player;
- int iret = player.load(&tune);
- if (iret != 0) {
- g_warning("sidplay2.load() failed: %s", player.error());
- return;
- }
-
- /* initialize the builder */
-
- ReSIDBuilder builder("ReSID");
- if (!builder) {
- g_warning("failed to initialize ReSIDBuilder");
- return;
- }
-
- builder.create(player.info().maxsids);
- if (!builder) {
- g_warning("ReSIDBuilder.create() failed");
- return;
- }
-
- builder.filter(filter_setting);
- if (!builder) {
- g_warning("ReSIDBuilder.filter() failed");
- return;
- }
-
- /* configure the player */
-
- sid2_config_t config = player.config();
-
- config.clockDefault = SID2_CLOCK_PAL;
- config.clockForced = true;
- config.clockSpeed = SID2_CLOCK_CORRECT;
- config.frequency = 48000;
- config.optimisation = SID2_DEFAULT_OPTIMISATION;
-
- config.precision = 16;
- config.sidDefault = SID2_MOS6581;
- config.sidEmulation = &builder;
- config.sidModel = SID2_MODEL_CORRECT;
- config.sidSamples = true;
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- config.sampleFormat = SID2_LITTLE_SIGNED;
-#else
- config.sampleFormat = SID2_BIG_SIGNED;
-#endif
- if (tune.isStereo()) {
- config.playback = sid2_stereo;
- channels = 2;
- } else {
- config.playback = sid2_mono;
- channels = 1;
- }
-
- iret = player.config(config);
- if (iret != 0) {
- g_warning("sidplay2.config() failed: %s", player.error());
- return;
- }
-
- /* initialize the MPD decoder */
-
- struct audio_format audio_format;
- audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, channels);
- assert(audio_format_valid(&audio_format));
-
- decoder_initialized(decoder, &audio_format, true, (float)song_len);
-
- /* .. and play */
-
- const unsigned timebase = player.timebase();
- song_len *= timebase;
-
- enum decoder_command cmd;
- do {
- char buffer[4096];
- size_t nbytes;
-
- nbytes = player.play(buffer, sizeof(buffer));
- if (nbytes == 0)
- break;
-
- decoder_timestamp(decoder, (double)player.time() / timebase);
-
- cmd = decoder_data(decoder, NULL, buffer, nbytes, 0);
-
- if(cmd==DECODE_COMMAND_SEEK) {
- unsigned data_time = player.time();
- unsigned target_time = (unsigned)
- (decoder_seek_where(decoder) * timebase);
-
- /* can't rewind so return to zero and seek forward */
- if(target_time<data_time) {
- player.stop();
- data_time=0;
- }
-
- /* ignore data until target time is reached */
- while(data_time<target_time) {
- nbytes=player.play(buffer, sizeof(buffer));
- if(nbytes==0)
- break;
- data_time = player.time();
- }
-
- decoder_command_finished(decoder);
- }
-
- if (song_len > 0 && player.time() >= song_len)
- break;
-
- } while (cmd != DECODE_COMMAND_STOP);
-}
-
-static bool
-sidplay_scan_file(const char *path_fs,
- const struct tag_handler *handler, void *handler_ctx)
-{
- int song_num=get_song_num(path_fs);
- char *path_container=get_container_name(path_fs);
-
- SidTune tune(path_container, NULL, true);
- g_free(path_container);
- if (!tune)
- return false;
-
- const SidTuneInfo &info = tune.getInfo();
-
- /* title */
- const char *title;
- if (info.numberOfInfoStrings > 0 && info.infoString[0] != NULL)
- title=info.infoString[0];
- else
- title="";
-
- if(info.songs>1) {
- char *tag_title=g_strdup_printf("%s (%d/%d)",
- title, song_num, info.songs);
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_TITLE, tag_title);
- g_free(tag_title);
- } else
- tag_handler_invoke_tag(handler, handler_ctx, TAG_TITLE, title);
-
- /* artist */
- if (info.numberOfInfoStrings > 1 && info.infoString[1] != NULL)
- tag_handler_invoke_tag(handler, handler_ctx, TAG_ARTIST,
- info.infoString[1]);
-
- /* track */
- char *track=g_strdup_printf("%d", song_num);
- tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track);
- g_free(track);
-
- /* time */
- int song_len=get_song_length(path_fs);
- if (song_len >= 0)
- tag_handler_invoke_duration(handler, handler_ctx, song_len);
-
- return true;
-}
-
-static char *
-sidplay_container_scan(const char *path_fs, const unsigned int tnum)
-{
- SidTune tune(path_fs, NULL, true);
- if (!tune)
- return NULL;
-
- const SidTuneInfo &info=tune.getInfo();
-
- /* Don't treat sids containing a single tune
- as containers */
- if(!all_files_are_containers && info.songs<2)
- return NULL;
-
- /* Construct container/tune path names, eg.
- Delta.sid/tune_001.sid */
- if(tnum<=info.songs) {
- char *subtune= g_strdup_printf(
- SUBTUNE_PREFIX "%03u.sid", tnum);
- return subtune;
- } else
- return NULL;
-}
-
-static const char *const sidplay_suffixes[] = {
- "sid",
- "mus",
- "str",
- "prg",
- "P00",
- NULL
-};
-
-extern const struct decoder_plugin sidplay_decoder_plugin;
-const struct decoder_plugin sidplay_decoder_plugin = {
- "sidplay",
- sidplay_init,
- sidplay_finish,
- NULL, /* stream_decode() */
- sidplay_file_decode,
- sidplay_scan_file,
- NULL, /* stream_tag() */
- sidplay_container_scan,
- sidplay_suffixes,
- NULL, /* mime_types */
-};
diff --git a/src/decoder/sndfile_decoder_plugin.c b/src/decoder/sndfile_decoder_plugin.c
deleted file mode 100644
index 8dd98236..00000000
--- a/src/decoder/sndfile_decoder_plugin.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "audio_check.h"
-#include "tag_handler.h"
-
-#include <sndfile.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "sndfile"
-
-static sf_count_t
-sndfile_vio_get_filelen(void *user_data)
-{
- const struct input_stream *is = user_data;
-
- return is->size;
-}
-
-static sf_count_t
-sndfile_vio_seek(sf_count_t offset, int whence, void *user_data)
-{
- struct input_stream *is = user_data;
- bool success;
-
- success = input_stream_lock_seek(is, offset, whence, NULL);
- if (!success)
- return -1;
-
- return is->offset;
-}
-
-static sf_count_t
-sndfile_vio_read(void *ptr, sf_count_t count, void *user_data)
-{
- struct input_stream *is = user_data;
- GError *error = NULL;
- size_t nbytes;
-
- nbytes = input_stream_lock_read(is, ptr, count, &error);
- if (nbytes == 0 && error != NULL) {
- g_warning("%s", error->message);
- g_error_free(error);
- return -1;
- }
-
- return nbytes;
-}
-
-static sf_count_t
-sndfile_vio_write(G_GNUC_UNUSED const void *ptr,
- G_GNUC_UNUSED sf_count_t count,
- G_GNUC_UNUSED void *user_data)
-{
- /* no writing! */
- return -1;
-}
-
-static sf_count_t
-sndfile_vio_tell(void *user_data)
-{
- const struct input_stream *is = user_data;
-
- return is->offset;
-}
-
-/**
- * This SF_VIRTUAL_IO implementation wraps MPD's #input_stream to a
- * libsndfile stream.
- */
-static SF_VIRTUAL_IO vio = {
- .get_filelen = sndfile_vio_get_filelen,
- .seek = sndfile_vio_seek,
- .read = sndfile_vio_read,
- .write = sndfile_vio_write,
- .tell = sndfile_vio_tell,
-};
-
-/**
- * Converts a frame number to a timestamp (in seconds).
- */
-static float
-frame_to_time(sf_count_t frame, const struct audio_format *audio_format)
-{
- return (float)frame / (float)audio_format->sample_rate;
-}
-
-/**
- * Converts a timestamp (in seconds) to a frame number.
- */
-static sf_count_t
-time_to_frame(float t, const struct audio_format *audio_format)
-{
- return (sf_count_t)(t * audio_format->sample_rate);
-}
-
-static void
-sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
-{
- GError *error = NULL;
- SNDFILE *sf;
- SF_INFO info;
- struct audio_format audio_format;
- size_t frame_size;
- sf_count_t read_frames, num_frames;
- int buffer[4096];
- enum decoder_command cmd;
-
- info.format = 0;
-
- sf = sf_open_virtual(&vio, SFM_READ, &info, is);
- if (sf == NULL) {
- g_warning("sf_open_virtual() failed");
- return;
- }
-
- /* for now, always read 32 bit samples. Later, we could lower
- MPD's CPU usage by reading 16 bit samples with
- sf_readf_short() on low-quality source files. */
- if (!audio_format_init_checked(&audio_format, info.samplerate,
- SAMPLE_FORMAT_S32,
- info.channels, &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- return;
- }
-
- decoder_initialized(decoder, &audio_format, info.seekable,
- frame_to_time(info.frames, &audio_format));
-
- frame_size = audio_format_frame_size(&audio_format);
- read_frames = sizeof(buffer) / frame_size;
-
- do {
- num_frames = sf_readf_int(sf, buffer, read_frames);
- if (num_frames <= 0)
- break;
-
- cmd = decoder_data(decoder, is,
- buffer, num_frames * frame_size,
- 0);
- if (cmd == DECODE_COMMAND_SEEK) {
- sf_count_t c =
- time_to_frame(decoder_seek_where(decoder),
- &audio_format);
- c = sf_seek(sf, c, SEEK_SET);
- if (c < 0)
- decoder_seek_error(decoder);
- else
- decoder_command_finished(decoder);
- cmd = DECODE_COMMAND_NONE;
- }
- } while (cmd == DECODE_COMMAND_NONE);
-
- sf_close(sf);
-}
-
-static bool
-sndfile_scan_file(const char *path_fs,
- const struct tag_handler *handler, void *handler_ctx)
-{
- SNDFILE *sf;
- SF_INFO info;
- const char *p;
-
- info.format = 0;
-
- sf = sf_open(path_fs, SFM_READ, &info);
- if (sf == NULL)
- return false;
-
- if (!audio_valid_sample_rate(info.samplerate)) {
- sf_close(sf);
- g_warning("Invalid sample rate in %s\n", path_fs);
- return false;
- }
-
- tag_handler_invoke_duration(handler, handler_ctx,
- info.frames / info.samplerate);
-
- p = sf_get_string(sf, SF_STR_TITLE);
- if (p != NULL)
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_TITLE, p);
-
- p = sf_get_string(sf, SF_STR_ARTIST);
- if (p != NULL)
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_ARTIST, p);
-
- p = sf_get_string(sf, SF_STR_DATE);
- if (p != NULL)
- tag_handler_invoke_tag(handler, handler_ctx,
- TAG_DATE, p);
-
- sf_close(sf);
-
- return true;
-}
-
-static const char *const sndfile_suffixes[] = {
- "wav", "aiff", "aif", /* Microsoft / SGI / Apple */
- "au", "snd", /* Sun / DEC / NeXT */
- "paf", /* Paris Audio File */
- "iff", "svx", /* Commodore Amiga IFF / SVX */
- "sf", /* IRCAM */
- "voc", /* Creative */
- "w64", /* Soundforge */
- "pvf", /* Portable Voice Format */
- "xi", /* Fasttracker */
- "htk", /* HMM Tool Kit */
- "caf", /* Apple */
- "sd2", /* Sound Designer II */
-
- /* libsndfile also supports FLAC and Ogg Vorbis, but only by
- linking with libFLAC and libvorbis - we can do better, we
- have native plugins for these libraries */
-
- NULL
-};
-
-static const char *const sndfile_mime_types[] = {
- "audio/x-wav",
- "audio/x-aiff",
-
- /* what are the MIME types of the other supported formats? */
-
- NULL
-};
-
-const struct decoder_plugin sndfile_decoder_plugin = {
- .name = "sndfile",
- .stream_decode = sndfile_stream_decode,
- .scan_file = sndfile_scan_file,
- .suffixes = sndfile_suffixes,
- .mime_types = sndfile_mime_types,
-};
diff --git a/src/decoder/vorbis_comments.c b/src/decoder/vorbis_comments.c
deleted file mode 100644
index 6c2d57b7..00000000
--- a/src/decoder/vorbis_comments.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2003-2012 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 "config.h"
-#include "vorbis_comments.h"
-#include "tag.h"
-#include "tag_table.h"
-#include "tag_handler.h"
-#include "replay_gain_info.h"
-
-#include <glib.h>
-#include <assert.h>
-#include <stddef.h>
-#include <string.h>
-#include <stdlib.h>
-
-static const char *
-vorbis_comment_value(const char *comment, const char *needle)
-{
- size_t len = strlen(needle);
-
- if (g_ascii_strncasecmp(comment, needle, len) == 0 &&
- comment[len] == '=')
- return comment + len + 1;
-
- return NULL;
-}
-
-bool
-vorbis_comments_to_replay_gain(struct replay_gain_info *rgi, char **comments)
-{
- const char *temp;
- bool found = false;
-
- replay_gain_info_init(rgi);
-
- while (*comments) {
- if ((temp =
- vorbis_comment_value(*comments, "replaygain_track_gain"))) {
- rgi->tuples[REPLAY_GAIN_TRACK].gain = atof(temp);
- found = true;
- } else if ((temp = vorbis_comment_value(*comments,
- "replaygain_album_gain"))) {
- rgi->tuples[REPLAY_GAIN_ALBUM].gain = atof(temp);
- found = true;
- } else if ((temp = vorbis_comment_value(*comments,
- "replaygain_track_peak"))) {
- rgi->tuples[REPLAY_GAIN_TRACK].peak = atof(temp);
- found = true;
- } else if ((temp = vorbis_comment_value(*comments,
- "replaygain_album_peak"))) {
- rgi->tuples[REPLAY_GAIN_ALBUM].peak = atof(temp);
- found = true;
- }
-
- comments++;
- }
-
- return found;
-}
-
-/**
- * Check if the comment's name equals the passed name, and if so, copy
- * the comment value into the tag.
- */
-static bool
-vorbis_copy_comment(const char *comment,
- const char *name, enum tag_type tag_type,
- const struct tag_handler *handler, void *handler_ctx)
-{
- const char *value;
-
- value = vorbis_comment_value(comment, name);
- if (value != NULL) {
- tag_handler_invoke_tag(handler, handler_ctx, tag_type, value);
- return true;
- }
-
- return false;
-}
-
-static const struct tag_table vorbis_tags[] = {
- { "tracknumber", TAG_TRACK },
- { "discnumber", TAG_DISC },
- { "album artist", TAG_ALBUM_ARTIST },
- { NULL, TAG_NUM_OF_ITEM_TYPES }
-};
-
-static void
-vorbis_scan_comment(const char *comment,
- const struct tag_handler *handler, void *handler_ctx)
-{
- if (handler->pair != NULL) {
- char *name = g_strdup((const char*)comment);
- char *value = strchr(name, '=');
-
- if (value != NULL && value > name) {
- *value++ = 0;
- tag_handler_invoke_pair(handler, handler_ctx,
- name, value);
- }
-
- g_free(name);
- }
-
- for (const struct tag_table *i = vorbis_tags; i->name != NULL; ++i)
- if (vorbis_copy_comment(comment, i->name, i->type,
- handler, handler_ctx))
- return;
-
- for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
- if (vorbis_copy_comment(comment,
- tag_item_names[i], i,
- handler, handler_ctx))
- return;
-}
-
-void
-vorbis_comments_scan(char **comments,
- const struct tag_handler *handler, void *handler_ctx)
-{
- while (*comments)
- vorbis_scan_comment(*comments++,
- handler, handler_ctx);
-
-}
-
-struct tag *
-vorbis_comments_to_tag(char **comments)
-{
- struct tag *tag = tag_new();
- vorbis_comments_scan(comments, &add_tag_handler, tag);
-
- if (tag_is_empty(tag)) {
- tag_free(tag);
- tag = NULL;
- }
-
- return tag;
-}
diff --git a/src/decoder/vorbis_comments.h b/src/decoder/vorbis_comments.h
deleted file mode 100644
index c1509693..00000000
--- a/src/decoder/vorbis_comments.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2003-2012 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.
- */
-
-#ifndef MPD_VORBIS_COMMENTS_H
-#define MPD_VORBIS_COMMENTS_H
-
-#include "check.h"
-
-#include <stdbool.h>
-
-struct replay_gain_info;
-struct tag_handler;
-
-bool
-vorbis_comments_to_replay_gain(struct replay_gain_info *rgi, char **comments);
-
-void
-vorbis_comments_scan(char **comments,
- const struct tag_handler *handler, void *handler_ctx);
-
-struct tag *
-vorbis_comments_to_tag(char **comments);
-
-#endif
diff --git a/src/decoder/vorbis_decoder_plugin.c b/src/decoder/vorbis_decoder_plugin.c
deleted file mode 100644
index 15cdc0ca..00000000
--- a/src/decoder/vorbis_decoder_plugin.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "vorbis_comments.h"
-#include "_ogg_common.h"
-#include "audio_check.h"
-#include "uri.h"
-#include "tag_handler.h"
-
-#ifndef HAVE_TREMOR
-#define OV_EXCLUDE_STATIC_CALLBACKS
-#include <vorbis/vorbisfile.h>
-#else
-#include <tremor/ivorbisfile.h>
-/* Macros to make Tremor's API look like libogg. Tremor always
- returns host-byte-order 16-bit signed data, and uses integer
- milliseconds where libogg uses double seconds.
-*/
-#define ov_read(VF, BUFFER, LENGTH, BIGENDIANP, WORD, SGNED, BITSTREAM) \
- ov_read(VF, BUFFER, LENGTH, BITSTREAM)
-#define ov_time_total(VF, I) ((double)ov_time_total(VF, I)/1000)
-#define ov_time_tell(VF) ((double)ov_time_tell(VF)/1000)
-#define ov_time_seek_page(VF, S) (ov_time_seek_page(VF, (S)*1000))
-#endif /* HAVE_TREMOR */
-
-#include <glib.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <unistd.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "vorbis"
-#define OGG_CHUNK_SIZE 4096
-
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-#define OGG_DECODE_USE_BIGENDIAN 1
-#else
-#define OGG_DECODE_USE_BIGENDIAN 0
-#endif
-
-struct vorbis_input_stream {
- struct decoder *decoder;
-
- struct input_stream *input_stream;
- bool seekable;
-};
-
-static size_t ogg_read_cb(void *ptr, size_t size, size_t nmemb, void *data)
-{
- struct vorbis_input_stream *vis = data;
- size_t ret;
-
- ret = decoder_read(vis->decoder, vis->input_stream, ptr, size * nmemb);
-
- errno = 0;
-
- return ret / size;
-}
-
-static int ogg_seek_cb(void *data, ogg_int64_t offset, int whence)
-{
- struct vorbis_input_stream *vis = data;
-
- return vis->seekable &&
- (!vis->decoder || decoder_get_command(vis->decoder) != DECODE_COMMAND_STOP) &&
- input_stream_lock_seek(vis->input_stream, offset, whence, NULL)
- ? 0 : -1;
-}
-
-/* TODO: check Ogg libraries API and see if we can just not have this func */
-static int ogg_close_cb(G_GNUC_UNUSED void *data)
-{
- return 0;
-}
-
-static long ogg_tell_cb(void *data)
-{
- const struct vorbis_input_stream *vis = data;
-
- return (long)vis->input_stream->offset;
-}
-
-static const ov_callbacks vorbis_is_callbacks = {
- .read_func = ogg_read_cb,
- .seek_func = ogg_seek_cb,
- .close_func = ogg_close_cb,
- .tell_func = ogg_tell_cb,
-};
-
-static const char *
-vorbis_strerror(int code)
-{
- switch (code) {
- case OV_EREAD:
- return "read error";
-
- case OV_ENOTVORBIS:
- return "not vorbis stream";
-
- case OV_EVERSION:
- return "vorbis version mismatch";
-
- case OV_EBADHEADER:
- return "invalid vorbis header";
-
- case OV_EFAULT:
- return "internal logic error";
-
- default:
- return "unknown error";
- }
-}
-
-static bool
-vorbis_is_open(struct vorbis_input_stream *vis, OggVorbis_File *vf,
- struct decoder *decoder, struct input_stream *input_stream)
-{
- vis->decoder = decoder;
- vis->input_stream = input_stream;
- vis->seekable = input_stream->seekable &&
- (input_stream->uri == NULL ||
- !uri_has_scheme(input_stream->uri));
-
- int ret = ov_open_callbacks(vis, vf, NULL, 0, vorbis_is_callbacks);
- if (ret < 0) {
- if (decoder == NULL ||
- decoder_get_command(decoder) == DECODE_COMMAND_NONE)
- g_warning("Failed to open Ogg Vorbis stream: %s",
- vorbis_strerror(ret));
- return false;
- }
-
- return true;
-}
-
-static void
-vorbis_send_comments(struct decoder *decoder, struct input_stream *is,
- char **comments)
-{
- struct tag *tag;
-
- tag = vorbis_comments_to_tag(comments);
- if (!tag)
- return;
-
- decoder_tag(decoder, is, tag);
- tag_free(tag);
-}
-
-/* public */
-static void
-vorbis_stream_decode(struct decoder *decoder,
- struct input_stream *input_stream)
-{
- GError *error = NULL;
- OggVorbis_File vf;
- struct vorbis_input_stream vis;
- struct audio_format audio_format;
- float total_time;
- int current_section;
- int prev_section = -1;
- long ret;
- char chunk[OGG_CHUNK_SIZE];
- long bitRate = 0;
- long test;
- const vorbis_info *vi;
- enum decoder_command cmd = DECODE_COMMAND_NONE;
-
- if (ogg_stream_type_detect(input_stream) != VORBIS)
- return;
-
- /* rewind the stream, because ogg_stream_type_detect() has
- moved it */
- input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL);
-
- if (!vorbis_is_open(&vis, &vf, decoder, input_stream))
- return;
-
- vi = ov_info(&vf, -1);
- if (vi == NULL) {
- g_warning("ov_info() has failed");
- return;
- }
-
- if (!audio_format_init_checked(&audio_format, vi->rate,
- SAMPLE_FORMAT_S16,
- vi->channels, &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- return;
- }
-
- total_time = ov_time_total(&vf, -1);
- if (total_time < 0)
- total_time = 0;
-
- decoder_initialized(decoder, &audio_format, vis.seekable, total_time);
-
- do {
- if (cmd == DECODE_COMMAND_SEEK) {
- double seek_where = decoder_seek_where(decoder);
- if (0 == ov_time_seek_page(&vf, seek_where)) {
- decoder_command_finished(decoder);
- } else
- decoder_seek_error(decoder);
- }
-
- ret = ov_read(&vf, chunk, sizeof(chunk),
- OGG_DECODE_USE_BIGENDIAN, 2, 1, &current_section);
- if (ret == OV_HOLE) /* bad packet */
- ret = 0;
- else if (ret <= 0)
- /* break on EOF or other error */
- break;
-
- if (current_section != prev_section) {
- char **comments;
-
- vi = ov_info(&vf, -1);
- if (vi == NULL) {
- g_warning("ov_info() has failed");
- break;
- }
-
- if (vi->rate != (long)audio_format.sample_rate ||
- vi->channels != (int)audio_format.channels) {
- /* we don't support audio format
- change yet */
- g_warning("audio format change, stopping here");
- break;
- }
-
- comments = ov_comment(&vf, -1)->user_comments;
- vorbis_send_comments(decoder, input_stream, comments);
-
- struct replay_gain_info rgi;
- if (vorbis_comments_to_replay_gain(&rgi, comments))
- decoder_replay_gain(decoder, &rgi);
-
- prev_section = current_section;
- }
-
- if ((test = ov_bitrate_instant(&vf)) > 0)
- bitRate = test / 1000;
-
- cmd = decoder_data(decoder, input_stream,
- chunk, ret,
- bitRate);
- } while (cmd != DECODE_COMMAND_STOP);
-
- ov_clear(&vf);
-}
-
-static bool
-vorbis_scan_stream(struct input_stream *is,
- const struct tag_handler *handler, void *handler_ctx)
-{
- struct vorbis_input_stream vis;
- OggVorbis_File vf;
-
- if (!vorbis_is_open(&vis, &vf, NULL, is))
- return false;
-
- tag_handler_invoke_duration(handler, handler_ctx,
- (int)(ov_time_total(&vf, -1) + 0.5));
-
- vorbis_comments_scan(ov_comment(&vf, -1)->user_comments,
- handler, handler_ctx);
-
- ov_clear(&vf);
- return true;
-}
-
-static const char *const vorbis_suffixes[] = {
- "ogg", "oga", NULL
-};
-
-static const char *const vorbis_mime_types[] = {
- "application/ogg",
- "application/x-ogg",
- "audio/ogg",
- "audio/vorbis",
- "audio/vorbis+ogg",
- "audio/x-ogg",
- "audio/x-vorbis",
- "audio/x-vorbis+ogg",
- NULL
-};
-
-const struct decoder_plugin vorbis_decoder_plugin = {
- .name = "vorbis",
- .stream_decode = vorbis_stream_decode,
- .scan_stream = vorbis_scan_stream,
- .suffixes = vorbis_suffixes,
- .mime_types = vorbis_mime_types
-};
diff --git a/src/decoder/wavpack_decoder_plugin.c b/src/decoder/wavpack_decoder_plugin.c
deleted file mode 100644
index ae85b0e2..00000000
--- a/src/decoder/wavpack_decoder_plugin.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "audio_check.h"
-#include "path.h"
-#include "utils.h"
-#include "tag_table.h"
-#include "tag_handler.h"
-
-#include <wavpack/wavpack.h>
-#include <glib.h>
-
-#include <assert.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "wavpack"
-
-#define ERRORLEN 80
-
-static const struct tag_table wavpack_tags[] = {
- { "artist", TAG_ARTIST },
- { "album", TAG_ALBUM },
- { "title", TAG_TITLE },
- { "track", TAG_TRACK },
- { "name", TAG_NAME },
- { "genre", TAG_GENRE },
- { "date", TAG_DATE },
- { "composer", TAG_COMPOSER },
- { "performer", TAG_PERFORMER },
- { "comment", TAG_COMMENT },
- { "disc", TAG_DISC },
- { NULL, TAG_NUM_OF_ITEM_TYPES }
-};
-
-/** A pointer type for format converter function. */
-typedef void (*format_samples_t)(
- int bytes_per_sample,
- void *buffer, uint32_t count
-);
-
-/*
- * This function has been borrowed from the tiny player found on
- * wavpack.com. Modifications were required because mpd only handles
- * max 24-bit samples.
- */
-static void
-format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
-{
- int32_t *src = buffer;
-
- switch (bytes_per_sample) {
- case 1: {
- int8_t *dst = buffer;
- /*
- * The asserts like the following one are because we do the
- * formatting of samples within a single buffer. The size
- * of the output samples never can be greater than the size
- * of the input ones. Otherwise we would have an overflow.
- */
- assert_static(sizeof(*dst) <= sizeof(*src));
-
- /* pass through and align 8-bit samples */
- while (count--) {
- *dst++ = *src++;
- }
- break;
- }
- case 2: {
- uint16_t *dst = buffer;
- assert_static(sizeof(*dst) <= sizeof(*src));
-
- /* pass through and align 16-bit samples */
- while (count--) {
- *dst++ = *src++;
- }
- break;
- }
-
- case 3:
- case 4:
- /* do nothing */
- break;
- }
-}
-
-/*
- * This function converts floating point sample data to 24-bit integer.
- */
-static void
-format_samples_float(G_GNUC_UNUSED int bytes_per_sample, void *buffer,
- uint32_t count)
-{
- float *p = buffer;
-
- while (count--) {
- *p /= (1 << 23);
- ++p;
- }
-}
-
-/**
- * Choose a MPD sample format from libwavpacks' number of bits.
- */
-static enum sample_format
-wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample)
-{
- if (is_float)
- return SAMPLE_FORMAT_FLOAT;
-
- switch (bytes_per_sample) {
- case 1:
- return SAMPLE_FORMAT_S8;
-
- case 2:
- return SAMPLE_FORMAT_S16;
-
- case 3:
- return SAMPLE_FORMAT_S24_P32;
-
- case 4:
- return SAMPLE_FORMAT_S32;
-
- default:
- return SAMPLE_FORMAT_UNDEFINED;
- }
-}
-
-/*
- * This does the main decoding thing.
- * Requires an already opened WavpackContext.
- */
-static void
-wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
-{
- GError *error = NULL;
- bool is_float;
- enum sample_format sample_format;
- struct audio_format audio_format;
- format_samples_t format_samples;
- float total_time;
- int bytes_per_sample, output_sample_size;
-
- is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0;
- sample_format =
- wavpack_bits_to_sample_format(is_float,
- WavpackGetBytesPerSample(wpc));
-
- if (!audio_format_init_checked(&audio_format,
- WavpackGetSampleRate(wpc),
- sample_format,
- WavpackGetNumChannels(wpc), &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- return;
- }
-
- if (is_float) {
- format_samples = format_samples_float;
- } else {
- format_samples = format_samples_int;
- }
-
- total_time = WavpackGetNumSamples(wpc);
- total_time /= audio_format.sample_rate;
- bytes_per_sample = WavpackGetBytesPerSample(wpc);
- output_sample_size = audio_format_frame_size(&audio_format);
-
- /* wavpack gives us all kind of samples in a 32-bit space */
- int32_t chunk[1024];
- const uint32_t samples_requested = G_N_ELEMENTS(chunk) /
- audio_format.channels;
-
- decoder_initialized(decoder, &audio_format, can_seek, total_time);
-
- enum decoder_command cmd = decoder_get_command(decoder);
- while (cmd != DECODE_COMMAND_STOP) {
- if (cmd == DECODE_COMMAND_SEEK) {
- if (can_seek) {
- unsigned where = decoder_seek_where(decoder) *
- audio_format.sample_rate;
-
- if (WavpackSeekSample(wpc, where)) {
- decoder_command_finished(decoder);
- } else {
- decoder_seek_error(decoder);
- }
- } else {
- decoder_seek_error(decoder);
- }
- }
-
- uint32_t samples_got = WavpackUnpackSamples(wpc, chunk,
- samples_requested);
- if (samples_got == 0)
- break;
-
- int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 +
- 0.5);
- format_samples(bytes_per_sample, chunk,
- samples_got * audio_format.channels);
-
- cmd = decoder_data(decoder, NULL, chunk,
- samples_got * output_sample_size,
- bitrate);
- }
-}
-
-/**
- * Locate and parse a floating point tag. Returns true if it was
- * found.
- */
-static bool
-wavpack_tag_float(WavpackContext *wpc, const char *key, float *value_r)
-{
- char buffer[64];
- int ret;
-
- ret = WavpackGetTagItem(wpc, key, buffer, sizeof(buffer));
- if (ret <= 0)
- return false;
-
- *value_r = atof(buffer);
- return true;
-}
-
-static bool
-wavpack_replaygain(struct replay_gain_info *replay_gain_info,
- WavpackContext *wpc)
-{
- bool found = false;
-
- replay_gain_info_init(replay_gain_info);
-
- found |= wavpack_tag_float(
- wpc, "replaygain_track_gain",
- &replay_gain_info->tuples[REPLAY_GAIN_TRACK].gain
- );
- found |= wavpack_tag_float(
- wpc, "replaygain_track_peak",
- &replay_gain_info->tuples[REPLAY_GAIN_TRACK].peak
- );
- found |= wavpack_tag_float(
- wpc, "replaygain_album_gain",
- &replay_gain_info->tuples[REPLAY_GAIN_ALBUM].gain
- );
- found |= wavpack_tag_float(
- wpc, "replaygain_album_peak",
- &replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak
- );
-
- return found;
-}
-
-static void
-wavpack_scan_tag_item(WavpackContext *wpc, const char *name,
- enum tag_type type,
- const struct tag_handler *handler, void *handler_ctx)
-{
- char buffer[1024];
- int len = WavpackGetTagItem(wpc, name, buffer, sizeof(buffer));
- if (len <= 0 || (unsigned)len >= sizeof(buffer))
- return;
-
- tag_handler_invoke_tag(handler, handler_ctx, type, buffer);
-
-}
-
-static void
-wavpack_scan_pair(WavpackContext *wpc, const char *name,
- const struct tag_handler *handler, void *handler_ctx)
-{
- char buffer[8192];
- int len = WavpackGetTagItem(wpc, name, buffer, sizeof(buffer));
- if (len <= 0 || (unsigned)len >= sizeof(buffer))
- return;
-
- tag_handler_invoke_pair(handler, handler_ctx, name, buffer);
-}
-
-/*
- * Reads metainfo from the specified file.
- */
-static bool
-wavpack_scan_file(const char *fname,
- const struct tag_handler *handler, void *handler_ctx)
-{
- WavpackContext *wpc;
- char error[ERRORLEN];
-
- wpc = WavpackOpenFileInput(fname, error, OPEN_TAGS, 0);
- if (wpc == NULL) {
- g_warning(
- "failed to open WavPack file \"%s\": %s\n",
- fname, error
- );
- return false;
- }
-
- tag_handler_invoke_duration(handler, handler_ctx,
- WavpackGetNumSamples(wpc) /
- WavpackGetSampleRate(wpc));
-
- for (const struct tag_table *i = wavpack_tags; i->name != NULL; ++i)
- wavpack_scan_tag_item(wpc, i->name, i->type,
- handler, handler_ctx);
-
- if (handler->pair != NULL) {
- char name[64];
-
- for (int i = 0, n = WavpackGetNumTagItems(wpc);
- i < n; ++i) {
- int len = WavpackGetTagItemIndexed(wpc, i, name,
- sizeof(name));
- if (len <= 0 || (unsigned)len >= sizeof(name))
- continue;
-
- wavpack_scan_pair(wpc, name, handler, handler_ctx);
- }
- }
-
- WavpackCloseFile(wpc);
-
- return true;
-}
-
-/*
- * mpd input_stream <=> WavpackStreamReader wrapper callbacks
- */
-
-/* This struct is needed for per-stream last_byte storage. */
-struct wavpack_input {
- struct decoder *decoder;
- struct input_stream *is;
- /* Needed for push_back_byte() */
- int last_byte;
-};
-
-/**
- * Little wrapper for struct wavpack_input to cast from void *.
- */
-static struct wavpack_input *
-wpin(void *id)
-{
- assert(id);
- return id;
-}
-
-static int32_t
-wavpack_input_read_bytes(void *id, void *data, int32_t bcount)
-{
- uint8_t *buf = (uint8_t *)data;
- int32_t i = 0;
-
- if (wpin(id)->last_byte != EOF) {
- *buf++ = wpin(id)->last_byte;
- wpin(id)->last_byte = EOF;
- --bcount;
- ++i;
- }
-
- /* wavpack fails if we return a partial read, so we just wait
- until the buffer is full */
- while (bcount > 0) {
- size_t nbytes = decoder_read(
- wpin(id)->decoder, wpin(id)->is, buf, bcount
- );
- if (nbytes == 0) {
- /* EOF, error or a decoder command */
- break;
- }
-
- i += nbytes;
- bcount -= nbytes;
- buf += nbytes;
- }
-
- return i;
-}
-
-static uint32_t
-wavpack_input_get_pos(void *id)
-{
- return wpin(id)->is->offset;
-}
-
-static int
-wavpack_input_set_pos_abs(void *id, uint32_t pos)
-{
- return input_stream_lock_seek(wpin(id)->is, pos, SEEK_SET, NULL)
- ? 0 : -1;
-}
-
-static int
-wavpack_input_set_pos_rel(void *id, int32_t delta, int mode)
-{
- return input_stream_lock_seek(wpin(id)->is, delta, mode, NULL)
- ? 0 : -1;
-}
-
-static int
-wavpack_input_push_back_byte(void *id, int c)
-{
- if (wpin(id)->last_byte == EOF) {
- wpin(id)->last_byte = c;
- return c;
- } else {
- return EOF;
- }
-}
-
-static uint32_t
-wavpack_input_get_length(void *id)
-{
- if (wpin(id)->is->size < 0)
- return 0;
-
- return wpin(id)->is->size;
-}
-
-static int
-wavpack_input_can_seek(void *id)
-{
- return wpin(id)->is->seekable;
-}
-
-static WavpackStreamReader mpd_is_reader = {
- .read_bytes = wavpack_input_read_bytes,
- .get_pos = wavpack_input_get_pos,
- .set_pos_abs = wavpack_input_set_pos_abs,
- .set_pos_rel = wavpack_input_set_pos_rel,
- .push_back_byte = wavpack_input_push_back_byte,
- .get_length = wavpack_input_get_length,
- .can_seek = wavpack_input_can_seek,
- .write_bytes = NULL /* no need to write edited tags */
-};
-
-static void
-wavpack_input_init(struct wavpack_input *isp, struct decoder *decoder,
- struct input_stream *is)
-{
- isp->decoder = decoder;
- isp->is = is;
- isp->last_byte = EOF;
-}
-
-static struct input_stream *
-wavpack_open_wvc(struct decoder *decoder, const char *uri,
- GMutex *mutex, GCond *cond,
- struct wavpack_input *wpi)
-{
- struct input_stream *is_wvc;
- char *wvc_url = NULL;
- char first_byte;
- size_t nbytes;
-
- /*
- * As we use dc->utf8url, this function will be bad for
- * single files. utf8url is not absolute file path :/
- */
- if (uri == NULL)
- return false;
-
- wvc_url = g_strconcat(uri, "c", NULL);
- is_wvc = input_stream_open(wvc_url, mutex, cond, NULL);
- g_free(wvc_url);
-
- if (is_wvc == NULL)
- return NULL;
-
- /*
- * And we try to buffer in order to get know
- * about a possible 404 error.
- */
- nbytes = decoder_read(
- decoder, is_wvc, &first_byte, sizeof(first_byte)
- );
- if (nbytes == 0) {
- input_stream_close(is_wvc);
- return NULL;
- }
-
- /* push it back */
- wavpack_input_init(wpi, decoder, is_wvc);
- wpi->last_byte = first_byte;
- return is_wvc;
-}
-
-/*
- * Decodes a stream.
- */
-static void
-wavpack_streamdecode(struct decoder * decoder, struct input_stream *is)
-{
- char error[ERRORLEN];
- WavpackContext *wpc;
- struct input_stream *is_wvc;
- int open_flags = OPEN_NORMALIZE;
- struct wavpack_input isp, isp_wvc;
- bool can_seek = is->seekable;
-
- is_wvc = wavpack_open_wvc(decoder, is->uri, is->mutex, is->cond,
- &isp_wvc);
- if (is_wvc != NULL) {
- open_flags |= OPEN_WVC;
- can_seek &= is_wvc->seekable;
- }
-
- if (!can_seek) {
- open_flags |= OPEN_STREAMING;
- }
-
- wavpack_input_init(&isp, decoder, is);
- wpc = WavpackOpenFileInputEx(
- &mpd_is_reader, &isp,
- open_flags & OPEN_WVC ? &isp_wvc : NULL,
- error, open_flags, 23
- );
-
- if (wpc == NULL) {
- g_warning("failed to open WavPack stream: %s\n", error);
- return;
- }
-
- wavpack_decode(decoder, wpc, can_seek);
-
- WavpackCloseFile(wpc);
- if (open_flags & OPEN_WVC) {
- input_stream_close(is_wvc);
- }
-}
-
-/*
- * Decodes a file.
- */
-static void
-wavpack_filedecode(struct decoder *decoder, const char *fname)
-{
- char error[ERRORLEN];
- WavpackContext *wpc;
-
- wpc = WavpackOpenFileInput(
- fname, error,
- OPEN_TAGS | OPEN_WVC | OPEN_NORMALIZE, 23
- );
- if (wpc == NULL) {
- g_warning(
- "failed to open WavPack file \"%s\": %s\n",
- fname, error
- );
- return;
- }
-
- struct replay_gain_info replay_gain_info;
- if (wavpack_replaygain(&replay_gain_info, wpc))
- decoder_replay_gain(decoder, &replay_gain_info);
-
- wavpack_decode(decoder, wpc, true);
-
- WavpackCloseFile(wpc);
-}
-
-static char const *const wavpack_suffixes[] = {
- "wv",
- NULL
-};
-
-static char const *const wavpack_mime_types[] = {
- "audio/x-wavpack",
- NULL
-};
-
-const struct decoder_plugin wavpack_decoder_plugin = {
- .name = "wavpack",
- .stream_decode = wavpack_streamdecode,
- .file_decode = wavpack_filedecode,
- .scan_file = wavpack_scan_file,
- .suffixes = wavpack_suffixes,
- .mime_types = wavpack_mime_types
-};
diff --git a/src/decoder/wildmidi_decoder_plugin.c b/src/decoder/wildmidi_decoder_plugin.c
deleted file mode 100644
index 2cdb30a9..00000000
--- a/src/decoder/wildmidi_decoder_plugin.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2003-2011 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 "config.h"
-#include "decoder_api.h"
-#include "tag_handler.h"
-#include "glib_compat.h"
-
-#include <glib.h>
-
-#include <wildmidi_lib.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "wildmidi"
-
-enum {
- WILDMIDI_SAMPLE_RATE = 48000,
-};
-
-static bool
-wildmidi_init(const struct config_param *param)
-{
- const char *config_file;
- int ret;
-
- config_file = config_get_block_string(param, "config_file",
- "/etc/timidity/timidity.cfg");
- if (!g_file_test(config_file, G_FILE_TEST_IS_REGULAR)) {
- g_debug("configuration file does not exist: %s", config_file);
- return false;
- }
-
- ret = WildMidi_Init(config_file, WILDMIDI_SAMPLE_RATE, 0);
- return ret == 0;
-}
-
-static void
-wildmidi_finish(void)
-{
- WildMidi_Shutdown();
-}
-
-static void
-wildmidi_file_decode(struct decoder *decoder, const char *path_fs)
-{
- static const struct audio_format audio_format = {
- .sample_rate = WILDMIDI_SAMPLE_RATE,
- .format = SAMPLE_FORMAT_S16,
- .channels = 2,
- };
- midi *wm;
- const struct _WM_Info *info;
- enum decoder_command cmd;
-
- wm = WildMidi_Open(path_fs);
- if (wm == NULL)
- return;
-
- info = WildMidi_GetInfo(wm);
- if (info == NULL) {
- WildMidi_Close(wm);
- return;
- }
-
- decoder_initialized(decoder, &audio_format, true,
- info->approx_total_samples / WILDMIDI_SAMPLE_RATE);
-
- do {
- char buffer[4096];
- int len;
-
- info = WildMidi_GetInfo(wm);
- if (info == NULL)
- break;
-
- len = WildMidi_GetOutput(wm, buffer, sizeof(buffer));
- if (len <= 0)
- break;
-
- cmd = decoder_data(decoder, NULL, buffer, len, 0);
-
- if (cmd == DECODE_COMMAND_SEEK) {
- unsigned long seek_where = WILDMIDI_SAMPLE_RATE *
- decoder_seek_where(decoder);
-
-#ifdef HAVE_WILDMIDI_SAMPLED_SEEK
- WildMidi_SampledSeek(wm, &seek_where);
-#else
- WildMidi_FastSeek(wm, &seek_where);
-#endif
- decoder_command_finished(decoder);
- cmd = DECODE_COMMAND_NONE;
- }
-
- } while (cmd == DECODE_COMMAND_NONE);
-
- WildMidi_Close(wm);
-}
-
-static bool
-wildmidi_scan_file(const char *path_fs,
- const struct tag_handler *handler, void *handler_ctx)
-{
- midi *wm = WildMidi_Open(path_fs);
- if (wm == NULL)
- return false;
-
- const struct _WM_Info *info = WildMidi_GetInfo(wm);
- if (info == NULL) {
- WildMidi_Close(wm);
- return false;
- }
-
- int duration = info->approx_total_samples / WILDMIDI_SAMPLE_RATE;
- tag_handler_invoke_duration(handler, handler_ctx, duration);
-
- WildMidi_Close(wm);
-
- return true;
-}
-
-static const char *const wildmidi_suffixes[] = {
- "mid",
- NULL
-};
-
-const struct decoder_plugin wildmidi_decoder_plugin = {
- .name = "wildmidi",
- .init = wildmidi_init,
- .finish = wildmidi_finish,
- .file_decode = wildmidi_file_decode,
- .scan_file = wildmidi_scan_file,
- .suffixes = wildmidi_suffixes,
-};
diff --git a/src/decoder_list.c b/src/decoder_list.c
index 177b632a..7dc4c3be 100644
--- a/src/decoder_list.c
+++ b/src/decoder_list.c
@@ -23,91 +23,15 @@
#include "utils.h"
#include "conf.h"
#include "mpd_error.h"
-#include "decoder/pcm_decoder_plugin.h"
-#include "decoder/dsdiff_decoder_plugin.h"
-#include "decoder/dsf_decoder_plugin.h"
#include <glib.h>
#include <string.h>
-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 flac_decoder_plugin;
-extern const struct decoder_plugin oggflac_decoder_plugin;
-extern const struct decoder_plugin sndfile_decoder_plugin;
-extern const struct decoder_plugin audiofile_decoder_plugin;
-extern const struct decoder_plugin mp4ff_decoder_plugin;
-extern const struct decoder_plugin faad_decoder_plugin;
-extern const struct decoder_plugin mpcdec_decoder_plugin;
-extern const struct decoder_plugin wavpack_decoder_plugin;
-extern const struct decoder_plugin modplug_decoder_plugin;
-extern const struct decoder_plugin mikmod_decoder_plugin;
-extern const struct decoder_plugin sidplay_decoder_plugin;
-extern const struct decoder_plugin wildmidi_decoder_plugin;
-extern const struct decoder_plugin fluidsynth_decoder_plugin;
extern const struct decoder_plugin ffmpeg_decoder_plugin;
-extern const struct decoder_plugin gme_decoder_plugin;
const struct decoder_plugin *const decoder_plugins[] = {
-#ifdef HAVE_MAD
- &mad_decoder_plugin,
-#endif
-#ifdef HAVE_MPG123
- &mpg123_decoder_plugin,
-#endif
-#ifdef ENABLE_VORBIS_DECODER
- &vorbis_decoder_plugin,
-#endif
-#if defined(HAVE_FLAC)
- &oggflac_decoder_plugin,
-#endif
-#ifdef HAVE_FLAC
- &flac_decoder_plugin,
-#endif
-#ifdef ENABLE_SNDFILE
- &sndfile_decoder_plugin,
-#endif
-#ifdef HAVE_AUDIOFILE
- &audiofile_decoder_plugin,
-#endif
- &dsdiff_decoder_plugin,
- &dsf_decoder_plugin,
-#ifdef HAVE_FAAD
- &faad_decoder_plugin,
-#endif
-#ifdef HAVE_MP4
- &mp4ff_decoder_plugin,
-#endif
-#ifdef HAVE_MPCDEC
- &mpcdec_decoder_plugin,
-#endif
-#ifdef HAVE_WAVPACK
- &wavpack_decoder_plugin,
-#endif
-#ifdef HAVE_MODPLUG
- &modplug_decoder_plugin,
-#endif
-#ifdef ENABLE_MIKMOD_DECODER
- &mikmod_decoder_plugin,
-#endif
-#ifdef ENABLE_SIDPLAY
- &sidplay_decoder_plugin,
-#endif
-#ifdef ENABLE_WILDMIDI
- &wildmidi_decoder_plugin,
-#endif
-#ifdef ENABLE_FLUIDSYNTH
- &fluidsynth_decoder_plugin,
-#endif
-#ifdef HAVE_FFMPEG
&ffmpeg_decoder_plugin,
-#endif
-#ifdef HAVE_GME
- &gme_decoder_plugin,
-#endif
- &pcm_decoder_plugin,
NULL
};