diff -Naur audacious-plugins-3.10.1-orig/src/openmpt/Makefile audacious-plugins-3.10.1/src/openmpt/Makefile --- audacious-plugins-3.10.1-orig/src/openmpt/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ audacious-plugins-3.10.1/src/openmpt/Makefile 2019-12-26 11:31:08.234961926 +0100 @@ -0,0 +1,15 @@ +PLUGIN = openmpt${PLUGIN_SUFFIX} + +SRCS = mpt.cc \ + mptwrap.cc + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${INPUT_PLUGIN_DIR} + +LD = ${CXX} +CFLAGS += ${PLUGIN_CFLAGS} +CXXFLAGS += ${PLUGIN_CFLAGS} +CPPFLAGS += ${PLUGIN_CPPFLAGS} `pkg-config --cflags libopenmpt` -I../.. +LIBS += `pkg-config --libs libopenmpt` diff -Naur audacious-plugins-3.10.1-orig/src/openmpt/mpt.cc audacious-plugins-3.10.1/src/openmpt/mpt.cc --- audacious-plugins-3.10.1-orig/src/openmpt/mpt.cc 1970-01-01 01:00:00.000000000 +0100 +++ audacious-plugins-3.10.1/src/openmpt/mpt.cc 2019-10-29 03:24:11.000000000 +0100 @@ -0,0 +1,167 @@ +/*- + * Copyright (c) 2015-2019 Chris Spiegel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "mptwrap.h" + +static bool force_apply = false; + +static constexpr const char *CFG_SECTION = "openmpt"; +static constexpr const char *SETTING_STEREO_SEPARATION = "stereo_separation"; +static constexpr const char *SETTING_INTERPOLATOR = "interpolator"; + +class MPTPlugin : public InputPlugin +{ +public: + static const char about[]; + static const char *const exts[]; + static const PreferencesWidget widgets[]; + static const PluginPreferences prefs; + + static constexpr PluginInfo info = + { + N_("OpenMPT (Module Player)"), + PACKAGE, + about, + &prefs, + }; + + static constexpr auto iinfo = InputInfo(0) + /* For continuity, be at a lower priority than modplug for the time being */ + .with_priority(1) + .with_exts(exts); + + constexpr MPTPlugin() : InputPlugin(info, iinfo) { } + + bool init() + { + static constexpr const char * defaults[] = + { + SETTING_STEREO_SEPARATION, aud::numeric_string::str, + SETTING_INTERPOLATOR, aud::numeric_string::str, + nullptr, + }; + + aud_config_set_defaults(CFG_SECTION, defaults); + + return true; + } + + bool is_our_file(const char *filename, VFSFile &file) + { + MPTWrap mpt; + return mpt.open(file); + } + + bool read_tag(const char *filename, VFSFile &file, Tuple &tuple, Index *) + { + MPTWrap mpt; + if (!mpt.open(file)) + return false; + + tuple.set_filename(filename); + tuple.set_format(mpt.format(), mpt.channels(), mpt.rate(), 0); + + tuple.set_int(Tuple::Length, mpt.duration()); + tuple.set_str(Tuple::Title, mpt.title()); + + return true; + } + + bool play(const char *filename, VFSFile &file) + { + MPTWrap mpt; + if (!mpt.open(file)) + return false; + + force_apply = true; + + open_audio(FMT_FLOAT, mpt.rate(), mpt.channels()); + + while (!check_stop()) + { + float buffer[16384]; + int seek_value = check_seek(); + + if (seek_value >= 0) + mpt.seek(seek_value); + + if (force_apply) + { + mpt.set_interpolator(aud_get_int(CFG_SECTION, SETTING_INTERPOLATOR)); + mpt.set_stereo_separation(aud_get_int(CFG_SECTION, SETTING_STEREO_SEPARATION)); + force_apply = false; + } + + auto n = mpt.read(buffer, aud::n_elems(buffer)); + if (n == 0) + break; + + write_audio(buffer, n * sizeof buffer[0]); + } + + return true; + } +}; + +const char MPTPlugin::about[] = N_("Module player based on libopenmpt\n\nWritten by: Chris Spiegel "); + +const char *const MPTPlugin::exts[] = +{ + "669", "amf", "ams", "dbm", "digi", "dmf", "dsm", "far", "gdm", "ice", "imf", + "it", "j2b", "m15", "mdl", "med", "mmcmp", "mms", "mo3", "mod", "mptm", "mt2", + "mtm", "nst", "okt", "plm", "ppm", "psm", "pt36", "ptm", "s3m", "sfx", "sfx2", + "st26", "stk", "stm", "ult", "umx", "wow", "xm", "xpk", + nullptr +}; + +static void values_changed() +{ + force_apply = true; +} + +const PreferencesWidget MPTPlugin::widgets[] = +{ + WidgetSpin( + N_("Stereo separation:"), + WidgetInt(CFG_SECTION, SETTING_STEREO_SEPARATION, values_changed), + { 0.0, 100.0, 1.0, N_("%") } + ), + + WidgetCombo( + N_("Interpolation:"), + WidgetInt(CFG_SECTION, SETTING_INTERPOLATOR, values_changed), + { MPTWrap::interpolators } + ) +}; + +const PluginPreferences MPTPlugin::prefs = {{ widgets }}; + +EXPORT MPTPlugin aud_plugin_instance; diff -Naur audacious-plugins-3.10.1-orig/src/openmpt/mptwrap.cc audacious-plugins-3.10.1/src/openmpt/mptwrap.cc --- audacious-plugins-3.10.1-orig/src/openmpt/mptwrap.cc 1970-01-01 01:00:00.000000000 +0100 +++ audacious-plugins-3.10.1/src/openmpt/mptwrap.cc 2019-10-29 03:24:11.000000000 +0100 @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2015-2019 Chris Spiegel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#define WANT_VFS_STDIO_COMPAT +#include +#include "mptwrap.h" + +constexpr ComboItem MPTWrap::interpolators[]; +constexpr openmpt_stream_callbacks MPTWrap::callbacks; + +static String to_aud_str(const char * str) +{ + String aud_str(str); + openmpt_free_string(str); + return aud_str; +} + +bool MPTWrap::open(VFSFile &file) +{ +#if OPENMPT_API_VERSION_MAJOR <= 0 && OPENMPT_API_VERSION_MINOR < 3 + auto m = openmpt_module_create(callbacks, &file, openmpt_log_func_silent, + nullptr, nullptr); +#else + auto m = openmpt_module_create2(callbacks, &file, openmpt_log_func_silent, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); +#endif + + if (m == nullptr) + return false; + + mod.capture(m); + + openmpt_module_select_subsong(mod.get(), -1); + + m_duration = openmpt_module_get_duration_seconds(mod.get()) * 1000; + m_title = to_aud_str(openmpt_module_get_metadata(mod.get(), "title")); + m_format = to_aud_str(openmpt_module_get_metadata(mod.get(), "type_long")); + + return true; +} + +size_t MPTWrap::stream_read(void *instance, void *buf, size_t n) +{ + return VFS(instance)->fread(buf, 1, n); +} + +int MPTWrap::stream_seek(void *instance, int64_t offset, int whence) +{ + VFSSeekType w = to_vfs_seek_type(whence); + return VFS(instance)->fseek(offset, w) >= 0 ? 0 : -1; +} + +int64_t MPTWrap::stream_tell(void *instance) +{ + return VFS(instance)->ftell(); +} + +bool MPTWrap::is_valid_interpolator(int interpolator_value) +{ + return std::any_of(std::begin(interpolators), std::end(interpolators), + [interpolator_value](const ComboItem &ci) { return ci.num == interpolator_value; }); +} + +void MPTWrap::set_interpolator(int interpolator_value) +{ + if (is_valid_interpolator(interpolator_value)) + openmpt_module_set_render_param(mod.get(), + OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, interpolator_value); +} + +bool MPTWrap::is_valid_stereo_separation(int separation) +{ + return separation >= 0 && separation <= 100; +} + +void MPTWrap::set_stereo_separation(int separation) +{ + if (is_valid_stereo_separation(separation)) + openmpt_module_set_render_param(mod.get(), + OPENMPT_MODULE_RENDER_STEREOSEPARATION_PERCENT, separation); +} + +int64_t MPTWrap::read(float *buf, int64_t bufcnt) +{ + auto n = openmpt_module_read_interleaved_float_stereo(mod.get(), rate(), + bufcnt / channels(), buf); + + return n * channels(); +} + +void MPTWrap::seek(int pos) +{ + openmpt_module_set_position_seconds(mod.get(), pos / 1000.0); +} diff -Naur audacious-plugins-3.10.1-orig/src/openmpt/mptwrap.h audacious-plugins-3.10.1/src/openmpt/mptwrap.h --- audacious-plugins-3.10.1-orig/src/openmpt/mptwrap.h 1970-01-01 01:00:00.000000000 +0100 +++ audacious-plugins-3.10.1/src/openmpt/mptwrap.h 2019-10-29 03:24:11.000000000 +0100 @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2015-2019 Chris Spiegel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef AUDACIOUS_MPT_MPTWRAP_H +#define AUDACIOUS_MPT_MPTWRAP_H + +#include +#include +#include + +#include +#include + +class MPTWrap +{ +public: + static constexpr int interp_none = 1; + static constexpr int interp_linear = 2; + static constexpr int interp_cubic = 4; + static constexpr int interp_windowed = 8; + + static constexpr int default_interpolator = interp_windowed; + static constexpr int default_stereo_separation = 70; + + static constexpr ComboItem interpolators[] = + { + {N_("None"), interp_none}, + {N_("Linear"), interp_linear}, + {N_("Cubic"), interp_cubic}, + {N_("Windowed sinc"), interp_windowed} + }; + + static bool is_valid_interpolator(int); + void set_interpolator(int); + + static bool is_valid_stereo_separation(int); + void set_stereo_separation(int); + + bool open(VFSFile &); + int64_t read(float *, int64_t); + void seek(int pos); + + static constexpr int rate() { return 48000; } + static constexpr int channels() { return 2; } + + int duration() const { return m_duration; } + const String & title() const { return m_title; } + const String & format() const { return m_format; } + +private: + static size_t stream_read(void *, void *, size_t); + static int stream_seek(void *, int64_t, int); + static int64_t stream_tell(void *); + static VFSFile *VFS(void *instance) { return reinterpret_cast(instance); } + + static constexpr openmpt_stream_callbacks callbacks = { stream_read, stream_seek, stream_tell }; + + SmartPtr mod; + + int m_duration = 0; + String m_title; + String m_format; +}; + +#endif