From 33364edfb3ed349c0a05d55e0449bfc0a9a701be Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Sep 2012 22:03:44 +0200 Subject: decoder/adplug: new decoder plugin --- INSTALL | 3 + Makefile.am | 8 ++ configure.ac | 13 ++++ src/decoder/AdPlugDecoderPlugin.cxx | 148 ++++++++++++++++++++++++++++++++++++ src/decoder/AdPlugDecoderPlugin.h | 25 ++++++ src/decoder_list.c | 4 + 6 files changed, 201 insertions(+) create mode 100644 src/decoder/AdPlugDecoderPlugin.cxx create mode 100644 src/decoder/AdPlugDecoderPlugin.h diff --git a/INSTALL b/INSTALL index b0ad34b0..7c565f3d 100644 --- a/INSTALL +++ b/INSTALL @@ -117,6 +117,9 @@ WAVE, AIFF, and many others. libwavpack - http://www.wavpack.com/ For WavPack playback. +libadplug - http://adplug.sourceforge.net/ +For AdLib playback. + despotify - https://github.com/SimonKagstrom/despotify For Spotify playback. diff --git a/Makefile.am b/Makefile.am index 8cdc72c7..ff575456 100644 --- a/Makefile.am +++ b/Makefile.am @@ -542,6 +542,7 @@ libdecoder_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \ $(OPUS_CFLAGS) \ $(FFMPEG_CFLAGS) \ $(MPCDEC_CFLAGS) \ + $(ADPLUG_CFLAGS) \ $(FAAD_CFLAGS) DECODER_LIBS = \ @@ -561,6 +562,7 @@ DECODER_LIBS = \ $(MP4FF_LIBS) \ $(FFMPEG_LIBS) \ $(MPCDEC_LIBS) \ + $(ADPLUG_LIBS) \ $(FAAD_LIBS) DECODER_SRC = @@ -594,6 +596,12 @@ if HAVE_WAVPACK libdecoder_plugins_a_SOURCES += src/decoder/wavpack_decoder_plugin.c endif +if HAVE_ADPLUG +libdecoder_plugins_a_SOURCES += \ + src/decoder/AdPlugDecoderPlugin.cxx \ + src/decoder/AdPlugDecoderPlugin.h +endif + if HAVE_FAAD libdecoder_plugins_a_SOURCES += src/decoder/faad_decoder_plugin.c endif diff --git a/configure.ac b/configure.ac index 702980a2..80cd64fd 100644 --- a/configure.ac +++ b/configure.ac @@ -150,6 +150,11 @@ AC_ARG_ENABLE(mpdclient, [enable support for the MPD client]),, enable_libmpdclient=auto) +AC_ARG_ENABLE(adplug, + AS_HELP_STRING([--enable-adplug], + [enable the AdPlug decoder plugin (default: auto)]),, + enable_adplug=auto) + AC_ARG_ENABLE(alsa, AS_HELP_STRING([--enable-alsa], [enable ALSA support]),, [enable_alsa=auto]) @@ -823,6 +828,14 @@ dnl --------------------------------------------------------------------------- dnl Decoder Plugins dnl --------------------------------------------------------------------------- +dnl -------------------------------- libadplug -------------------------------- +MPD_AUTO_PKG(adplug, ADPLUG, [adplug], + [AdPlug decoder plugin], [libadplug not found]) +if test x$enable_adplug = xyes; then + AC_DEFINE(HAVE_ADPLUG, 1, [Define to use libadplug]) +fi +AM_CONDITIONAL(HAVE_ADPLUG, test x$enable_adplug = xyes) + dnl -------------------------------- audiofile -------------------------------- MPD_AUTO_PKG(audiofile, AUDIOFILE, [audiofile >= 0.1.7], [audiofile decoder plugin], [libaudiofile not found]) diff --git a/src/decoder/AdPlugDecoderPlugin.cxx b/src/decoder/AdPlugDecoderPlugin.cxx new file mode 100644 index 00000000..b3b7f1d7 --- /dev/null +++ b/src/decoder/AdPlugDecoderPlugin.cxx @@ -0,0 +1,148 @@ +/* + * 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 "AdPlugDecoderPlugin.h" +#include "tag_handler.h" + +extern "C" { +#include "decoder_api.h" +#include "audio_check.h" +} + +#include +#include + +#include + +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "adplug" + +static unsigned sample_rate; + +static bool +adplug_init(const struct config_param *param) +{ + GError *error = NULL; + + sample_rate = config_get_block_unsigned(param, "sample_rate", 48000); + if (!audio_check_sample_rate(sample_rate, &error)) { + g_warning("%s\n", error->message); + g_error_free(error); + return false; + } + + return true; +} + +static void +adplug_file_decode(struct decoder *decoder, const char *path_fs) +{ + CEmuopl opl(sample_rate, true, true); + opl.init(); + + CPlayer *player = CAdPlug::factory(path_fs, &opl); + if (player == nullptr) + return; + + struct audio_format audio_format; + audio_format_init(&audio_format, sample_rate, SAMPLE_FORMAT_S16, 2); + assert(audio_format_valid(&audio_format)); + + decoder_initialized(decoder, &audio_format, false, + player->songlength() / 1000.); + + int16_t buffer[2048]; + const unsigned frames_per_buffer = G_N_ELEMENTS(buffer) / 2; + enum decoder_command cmd; + + do { + if (!player->update()) + break; + + opl.update(buffer, frames_per_buffer); + cmd = decoder_data(decoder, NULL, + buffer, sizeof(buffer), + 0); + } while (cmd == DECODE_COMMAND_NONE); + + delete player; +} + +static void +adplug_scan_tag(enum tag_type type, const std::string &value, + const struct tag_handler *handler, void *handler_ctx) +{ + if (!value.empty()) + tag_handler_invoke_tag(handler, handler_ctx, + type, value.c_str()); +} + +static bool +adplug_scan_file(const char *path_fs, + const struct tag_handler *handler, void *handler_ctx) +{ + CEmuopl opl(sample_rate, true, true); + opl.init(); + + CPlayer *player = CAdPlug::factory(path_fs, &opl); + if (player == nullptr) + return false; + + tag_handler_invoke_duration(handler, handler_ctx, + player->songlength() / 1000); + + if (handler->tag != nullptr) { + adplug_scan_tag(TAG_TITLE, player->gettitle(), + handler, handler_ctx); + adplug_scan_tag(TAG_ARTIST, player->getauthor(), + handler, handler_ctx); + adplug_scan_tag(TAG_COMMENT, player->getdesc(), + handler, handler_ctx); + } + + delete player; + return true; +} + +static const char *const adplug_suffixes[] = { + "amd", + "d00", + "hsc", + "laa", + "rad", + "raw", + "sa2", + nullptr +}; + +const struct decoder_plugin adplug_decoder_plugin = { + "adplug", + adplug_init, + nullptr, + nullptr, + adplug_file_decode, + adplug_scan_file, + nullptr, + nullptr, + adplug_suffixes, + nullptr, +}; diff --git a/src/decoder/AdPlugDecoderPlugin.h b/src/decoder/AdPlugDecoderPlugin.h new file mode 100644 index 00000000..9fdf438a --- /dev/null +++ b/src/decoder/AdPlugDecoderPlugin.h @@ -0,0 +1,25 @@ +/* + * 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_ADPLUG_H +#define MPD_DECODER_ADPLUG_H + +extern const struct decoder_plugin adplug_decoder_plugin; + +#endif diff --git a/src/decoder_list.c b/src/decoder_list.c index 3ea704e9..81098e39 100644 --- a/src/decoder_list.c +++ b/src/decoder_list.c @@ -27,6 +27,7 @@ #include "decoder/dsdiff_decoder_plugin.h" #include "decoder/dsf_decoder_plugin.h" #include "decoder/OpusDecoderPlugin.h" +#include "decoder/AdPlugDecoderPlugin.h" #include @@ -105,6 +106,9 @@ const struct decoder_plugin *const decoder_plugins[] = { #ifdef ENABLE_FLUIDSYNTH &fluidsynth_decoder_plugin, #endif +#ifdef HAVE_ADPLUG + &adplug_decoder_plugin, +#endif #ifdef HAVE_FFMPEG &ffmpeg_decoder_plugin, #endif -- cgit v1.2.3