aboutsummaryrefslogtreecommitdiff
path: root/src/filter
diff options
context:
space:
mode:
Diffstat (limited to 'src/filter')
-rw-r--r--src/filter/AutoConvertFilterPlugin.cxx132
-rw-r--r--src/filter/AutoConvertFilterPlugin.hxx (renamed from src/filter/autoconvert_filter_plugin.h)12
-rw-r--r--src/filter/ChainFilterPlugin.cxx184
-rw-r--r--src/filter/ChainFilterPlugin.hxx (renamed from src/filter/chain_filter_plugin.h)12
-rw-r--r--src/filter/ConvertFilterPlugin.cxx119
-rw-r--r--src/filter/ConvertFilterPlugin.hxx (renamed from src/filter/convert_filter_plugin.h)11
-rw-r--r--src/filter/NormalizeFilterPlugin.cxx84
-rw-r--r--src/filter/NullFilterPlugin.cxx60
-rw-r--r--src/filter/ReplayGainFilterPlugin.cxx242
-rw-r--r--src/filter/ReplayGainFilterPlugin.hxx (renamed from src/filter/replay_gain_filter_plugin.h)16
-rw-r--r--src/filter/RouteFilterPlugin.cxx (renamed from src/filter/route_filter_plugin.c)177
-rw-r--r--src/filter/VolumeFilterPlugin.cxx148
-rw-r--r--src/filter/VolumeFilterPlugin.hxx (renamed from src/filter/volume_filter_plugin.h)12
-rw-r--r--src/filter/autoconvert_filter_plugin.c169
-rw-r--r--src/filter/chain_filter_plugin.c213
-rw-r--r--src/filter/convert_filter_plugin.c146
-rw-r--r--src/filter/normalize_filter_plugin.c112
-rw-r--r--src/filter/null_filter_plugin.c93
-rw-r--r--src/filter/replay_gain_filter_plugin.c245
-rw-r--r--src/filter/volume_filter_plugin.c158
20 files changed, 1080 insertions, 1265 deletions
diff --git a/src/filter/AutoConvertFilterPlugin.cxx b/src/filter/AutoConvertFilterPlugin.cxx
new file mode 100644
index 00000000..55ee4694
--- /dev/null
+++ b/src/filter/AutoConvertFilterPlugin.cxx
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2003-2013 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 "AutoConvertFilterPlugin.hxx"
+#include "ConvertFilterPlugin.hxx"
+#include "FilterPlugin.hxx"
+#include "FilterInternal.hxx"
+#include "FilterRegistry.hxx"
+#include "audio_format.h"
+
+#include <assert.h>
+
+class AutoConvertFilter final : public Filter {
+ /**
+ * The audio format being fed to the underlying filter. This
+ * plugin actually doesn't need this variable, we have it here
+ * just so our open() method doesn't return a stack pointer.
+ */
+ audio_format child_audio_format;
+
+ /**
+ * The underlying filter.
+ */
+ Filter *filter;
+
+ /**
+ * A convert_filter, just in case conversion is needed. nullptr
+ * if unused.
+ */
+ Filter *convert;
+
+public:
+ AutoConvertFilter(Filter *_filter):filter(_filter) {}
+ ~AutoConvertFilter() {
+ delete filter;
+ }
+
+ virtual const audio_format *Open(audio_format &af, GError **error_r);
+ virtual void Close();
+ virtual const void *FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r);
+};
+
+const struct audio_format *
+AutoConvertFilter::Open(audio_format &in_audio_format, GError **error_r)
+{
+ assert(audio_format_valid(&in_audio_format));
+
+ /* open the "real" filter */
+
+ child_audio_format = in_audio_format;
+ const audio_format *out_audio_format =
+ filter->Open(child_audio_format, error_r);
+ if (out_audio_format == nullptr)
+ return nullptr;
+
+ /* need to convert? */
+
+ if (!audio_format_equals(&child_audio_format, &in_audio_format)) {
+ /* yes - create a convert_filter */
+
+ convert = filter_new(&convert_filter_plugin, nullptr, error_r);
+ if (convert == nullptr) {
+ filter->Close();
+ return nullptr;
+ }
+
+ audio_format audio_format2 = in_audio_format;
+ const audio_format *audio_format3 =
+ convert->Open(audio_format2, error_r);
+ if (audio_format3 == nullptr) {
+ delete convert;
+ filter->Close();
+ return nullptr;
+ }
+
+ assert(audio_format_equals(&audio_format2, &in_audio_format));
+
+ convert_filter_set(convert, child_audio_format);
+ } else
+ /* no */
+ convert = nullptr;
+
+ return out_audio_format;
+}
+
+void
+AutoConvertFilter::Close()
+{
+ if (convert != nullptr) {
+ convert->Close();
+ delete convert;
+ }
+
+ filter->Close();
+}
+
+const void *
+AutoConvertFilter::FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r)
+{
+ if (convert != nullptr) {
+ src = convert->FilterPCM(src, src_size, &src_size, error_r);
+ if (src == nullptr)
+ return nullptr;
+ }
+
+ return filter->FilterPCM(src, src_size, dest_size_r, error_r);
+}
+
+Filter *
+autoconvert_filter_new(Filter *filter)
+{
+ return new AutoConvertFilter(filter);
+}
diff --git a/src/filter/autoconvert_filter_plugin.h b/src/filter/AutoConvertFilterPlugin.hxx
index def08ab7..7db72a34 100644
--- a/src/filter/autoconvert_filter_plugin.h
+++ b/src/filter/AutoConvertFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,10 +17,10 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef AUTOCONVERT_FILTER_PLUGIN_H
-#define AUTOCONVERT_FILTER_PLUGIN_H
+#ifndef MPD_AUTOCONVERT_FILTER_PLUGIN_HXX
+#define MPD_AUTOCONVERT_FILTER_PLUGIN_HXX
-struct filter;
+class Filter;
/**
* Creates a new "autoconvert" filter. When opened, it ensures that
@@ -28,7 +28,7 @@ struct filter;
* requests a different format, it automatically creates a
* convert_filter.
*/
-struct filter *
-autoconvert_filter_new(struct filter *filter);
+Filter *
+autoconvert_filter_new(Filter *filter);
#endif
diff --git a/src/filter/ChainFilterPlugin.cxx b/src/filter/ChainFilterPlugin.cxx
new file mode 100644
index 00000000..c8666615
--- /dev/null
+++ b/src/filter/ChainFilterPlugin.cxx
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2003-2013 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 "ChainFilterPlugin.hxx"
+#include "conf.h"
+#include "FilterPlugin.hxx"
+#include "FilterInternal.hxx"
+#include "FilterRegistry.hxx"
+#include "audio_format.h"
+
+#include <glib.h>
+
+#include <list>
+
+#include <assert.h>
+
+class ChainFilter final : public Filter {
+ struct Child {
+ const char *name;
+ Filter *filter;
+
+ Child(const char *_name, Filter *_filter)
+ :name(_name), filter(_filter) {}
+ ~Child() {
+ delete filter;
+ }
+
+ Child(const Child &) = delete;
+ Child &operator=(const Child &) = delete;
+ };
+
+ std::list<Child> children;
+
+public:
+ void Append(const char *name, Filter *filter) {
+ children.emplace_back(name, filter);
+ }
+
+ virtual const audio_format *Open(audio_format &af, GError **error_r);
+ virtual void Close();
+ virtual const void *FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r);
+
+private:
+ /**
+ * Close all filters in the chain until #until is reached.
+ * #until itself is not closed.
+ */
+ void CloseUntil(const Filter *until);
+};
+
+static inline GQuark
+filter_quark(void)
+{
+ return g_quark_from_static_string("filter");
+}
+
+static Filter *
+chain_filter_init(gcc_unused const struct config_param *param,
+ gcc_unused GError **error_r)
+{
+ return new ChainFilter();
+}
+
+void
+ChainFilter::CloseUntil(const Filter *until)
+{
+ for (auto &child : children) {
+ if (child.filter == until)
+ /* don't close this filter */
+ return;
+
+ /* close this filter */
+ child.filter->Close();
+ }
+
+ /* this assertion fails if #until does not exist (anymore) */
+ assert(false);
+}
+
+static const struct audio_format *
+chain_open_child(const char *name, Filter *filter,
+ const audio_format &prev_audio_format,
+ GError **error_r)
+{
+ audio_format conv_audio_format = prev_audio_format;
+ const audio_format *next_audio_format =
+ filter->Open(conv_audio_format, error_r);
+ if (next_audio_format == NULL)
+ return NULL;
+
+ if (!audio_format_equals(&conv_audio_format, &prev_audio_format)) {
+ struct audio_format_string s;
+
+ filter->Close();
+ g_set_error(error_r, filter_quark(), 0,
+ "Audio format not supported by filter '%s': %s",
+ name,
+ audio_format_to_string(&prev_audio_format, &s));
+ return NULL;
+ }
+
+ return next_audio_format;
+}
+
+const audio_format *
+ChainFilter::Open(audio_format &in_audio_format, GError **error_r)
+{
+ const audio_format *audio_format = &in_audio_format;
+
+ for (auto &child : children) {
+ audio_format = chain_open_child(child.name, child.filter,
+ *audio_format, error_r);
+ if (audio_format == NULL) {
+ /* rollback, close all children */
+ CloseUntil(child.filter);
+ return NULL;
+ }
+ }
+
+ /* return the output format of the last filter */
+ return audio_format;
+}
+
+void
+ChainFilter::Close()
+{
+ for (auto &child : children)
+ child.filter->Close();
+}
+
+const void *
+ChainFilter::FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r)
+{
+ for (auto &child : children) {
+ /* feed the output of the previous filter as input
+ into the current one */
+ src = child.filter->FilterPCM(src, src_size, &src_size,
+ error_r);
+ if (src == NULL)
+ return NULL;
+ }
+
+ /* return the output of the last filter */
+ *dest_size_r = src_size;
+ return src;
+}
+
+const struct filter_plugin chain_filter_plugin = {
+ "chain",
+ chain_filter_init,
+};
+
+Filter *
+filter_chain_new(void)
+{
+ return new ChainFilter();
+}
+
+void
+filter_chain_append(Filter &_chain, const char *name, Filter *filter)
+{
+ ChainFilter &chain = (ChainFilter &)_chain;
+
+ chain.Append(name, filter);
+}
diff --git a/src/filter/chain_filter_plugin.h b/src/filter/ChainFilterPlugin.hxx
index 1dba4666..884c7ca1 100644
--- a/src/filter/chain_filter_plugin.h
+++ b/src/filter/ChainFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,15 +24,15 @@
* output to the next one.
*/
-#ifndef MPD_FILTER_CHAIN_H
-#define MPD_FILTER_CHAIN_H
+#ifndef MPD_FILTER_CHAIN_HXX
+#define MPD_FILTER_CHAIN_HXX
-struct filter;
+class Filter;
/**
* Creates a new filter chain.
*/
-struct filter *
+Filter *
filter_chain_new(void);
/**
@@ -43,6 +43,6 @@ filter_chain_new(void);
* @param filter the filter to be appended to #chain
*/
void
-filter_chain_append(struct filter *chain, struct filter *filter);
+filter_chain_append(Filter &chain, const char *name, Filter *filter);
#endif
diff --git a/src/filter/ConvertFilterPlugin.cxx b/src/filter/ConvertFilterPlugin.cxx
new file mode 100644
index 00000000..2c690765
--- /dev/null
+++ b/src/filter/ConvertFilterPlugin.cxx
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2003-2013 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 "ConvertFilterPlugin.hxx"
+#include "FilterPlugin.hxx"
+#include "FilterInternal.hxx"
+#include "FilterRegistry.hxx"
+#include "conf.h"
+#include "PcmConvert.hxx"
+#include "util/Manual.hxx"
+#include "audio_format.h"
+#include "poison.h"
+
+#include <assert.h>
+#include <string.h>
+
+class ConvertFilter final : public Filter {
+ /**
+ * The input audio format; PCM data is passed to the filter()
+ * method in this format.
+ */
+ audio_format in_audio_format;
+
+ /**
+ * The output audio format; the consumer of this plugin
+ * expects PCM data in this format. This defaults to
+ * #in_audio_format, and can be set with convert_filter_set().
+ */
+ audio_format out_audio_format;
+
+ Manual<PcmConvert> state;
+
+public:
+ void Set(const audio_format &_out_audio_format) {
+ assert(audio_format_valid(&in_audio_format));
+ assert(audio_format_valid(&out_audio_format));
+ assert(audio_format_valid(&_out_audio_format));
+
+ out_audio_format = _out_audio_format;
+ }
+
+ virtual const audio_format *Open(audio_format &af, GError **error_r);
+ virtual void Close();
+ virtual const void *FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r);
+};
+
+static Filter *
+convert_filter_init(gcc_unused const struct config_param *param,
+ gcc_unused GError **error_r)
+{
+ return new ConvertFilter();
+}
+
+const struct audio_format *
+ConvertFilter::Open(audio_format &audio_format, gcc_unused GError **error_r)
+{
+ assert(audio_format_valid(&audio_format));
+
+ in_audio_format = out_audio_format = audio_format;
+ state.Construct();
+
+ return &in_audio_format;
+}
+
+void
+ConvertFilter::Close()
+{
+ state.Destruct();
+
+ poison_undefined(&in_audio_format, sizeof(in_audio_format));
+ poison_undefined(&out_audio_format, sizeof(out_audio_format));
+}
+
+const void *
+ConvertFilter::FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r)
+{
+ if (audio_format_equals(&in_audio_format, &out_audio_format)) {
+ /* optimized special case: no-op */
+ *dest_size_r = src_size;
+ return src;
+ }
+
+ return state->Convert(&in_audio_format,
+ src, src_size,
+ &out_audio_format, dest_size_r,
+ error_r);
+}
+
+const struct filter_plugin convert_filter_plugin = {
+ "convert",
+ convert_filter_init,
+};
+
+void
+convert_filter_set(Filter *_filter, const audio_format &out_audio_format)
+{
+ ConvertFilter *filter = (ConvertFilter *)_filter;
+
+ filter->Set(out_audio_format);
+}
diff --git a/src/filter/convert_filter_plugin.h b/src/filter/ConvertFilterPlugin.hxx
index 156adf8e..840bf496 100644
--- a/src/filter/convert_filter_plugin.h
+++ b/src/filter/ConvertFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,10 +17,10 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef CONVERT_FILTER_PLUGIN_H
-#define CONVERT_FILTER_PLUGIN_H
+#ifndef MPD_CONVERT_FILTER_PLUGIN_HXX
+#define MPD_CONVERT_FILTER_PLUGIN_HXX
-struct filter;
+class Filter;
struct audio_format;
/**
@@ -30,7 +30,6 @@ struct audio_format;
* the last in a chain.
*/
void
-convert_filter_set(struct filter *filter,
- const struct audio_format *out_audio_format);
+convert_filter_set(Filter *filter, const audio_format &out_audio_format);
#endif
diff --git a/src/filter/NormalizeFilterPlugin.cxx b/src/filter/NormalizeFilterPlugin.cxx
new file mode 100644
index 00000000..e18c5cdf
--- /dev/null
+++ b/src/filter/NormalizeFilterPlugin.cxx
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2003-2013 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 "FilterPlugin.hxx"
+#include "FilterInternal.hxx"
+#include "FilterRegistry.hxx"
+#include "pcm_buffer.h"
+#include "audio_format.h"
+#include "AudioCompress/compress.h"
+
+#include <assert.h>
+#include <string.h>
+
+class NormalizeFilter final : public Filter {
+ struct Compressor *compressor;
+
+ struct pcm_buffer buffer;
+
+public:
+ virtual const audio_format *Open(audio_format &af, GError **error_r);
+ virtual void Close();
+ virtual const void *FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r);
+};
+
+static Filter *
+normalize_filter_init(gcc_unused const struct config_param *param,
+ gcc_unused GError **error_r)
+{
+ return new NormalizeFilter();
+}
+
+const struct audio_format *
+NormalizeFilter::Open(audio_format &audio_format, gcc_unused GError **error_r)
+{
+ audio_format.format = SAMPLE_FORMAT_S16;
+
+ compressor = Compressor_new(0);
+ pcm_buffer_init(&buffer);
+
+ return &audio_format;
+}
+
+void
+NormalizeFilter::Close()
+{
+ pcm_buffer_deinit(&buffer);
+ Compressor_delete(compressor);
+}
+
+const void *
+NormalizeFilter::FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, gcc_unused GError **error_r)
+{
+ int16_t *dest = (int16_t *)pcm_buffer_get(&buffer, src_size);
+ memcpy(dest, src, src_size);
+
+ Compressor_Process_int16(compressor, dest, src_size / 2);
+
+ *dest_size_r = src_size;
+ return dest;
+}
+
+const struct filter_plugin normalize_filter_plugin = {
+ "normalize",
+ normalize_filter_init,
+};
diff --git a/src/filter/NullFilterPlugin.cxx b/src/filter/NullFilterPlugin.cxx
new file mode 100644
index 00000000..d68065a3
--- /dev/null
+++ b/src/filter/NullFilterPlugin.cxx
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2003-2013 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 filter plugin does nothing. That is not quite useful, except
+ * for testing the filter core, or as a template for new filter
+ * plugins.
+ */
+
+#include "config.h"
+#include "FilterPlugin.hxx"
+#include "FilterInternal.hxx"
+#include "FilterRegistry.hxx"
+#include "gcc.h"
+
+class NullFilter final : public Filter {
+public:
+ virtual const audio_format *Open(audio_format &af,
+ gcc_unused GError **error_r) {
+ return &af;
+ }
+
+ virtual void Close() {}
+
+ virtual const void *FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r,
+ gcc_unused GError **error_r) {
+ *dest_size_r = src_size;
+ return src;
+ }
+};
+
+static Filter *
+null_filter_init(gcc_unused const struct config_param *param,
+ gcc_unused GError **error_r)
+{
+ return new NullFilter();
+}
+
+const struct filter_plugin null_filter_plugin = {
+ "null",
+ null_filter_init,
+};
diff --git a/src/filter/ReplayGainFilterPlugin.cxx b/src/filter/ReplayGainFilterPlugin.cxx
new file mode 100644
index 00000000..1fa2269b
--- /dev/null
+++ b/src/filter/ReplayGainFilterPlugin.cxx
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2003-2013 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 "ReplayGainFilterPlugin.hxx"
+#include "FilterPlugin.hxx"
+#include "FilterInternal.hxx"
+#include "FilterRegistry.hxx"
+#include "audio_format.h"
+#include "replay_gain_info.h"
+#include "replay_gain_config.h"
+#include "MixerControl.hxx"
+#include "PcmVolume.hxx"
+
+extern "C" {
+#include "pcm_buffer.h"
+}
+
+#include <assert.h>
+#include <string.h>
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "replay_gain"
+
+class ReplayGainFilter final : public Filter {
+ /**
+ * If set, then this hardware mixer is used for applying
+ * replay gain, instead of the software volume library.
+ */
+ struct mixer *mixer;
+
+ /**
+ * The base volume level for scale=1.0, between 1 and 100
+ * (including).
+ */
+ unsigned base;
+
+ enum replay_gain_mode mode;
+
+ struct replay_gain_info info;
+
+ /**
+ * The current volume, between 0 and a value that may or may not exceed
+ * #PCM_VOLUME_1.
+ *
+ * If the default value of true is used for replaygain_limit, the
+ * application of the volume to the signal will never cause clipping.
+ *
+ * On the other hand, if the user has set replaygain_limit to false,
+ * the chance of clipping is explicitly preferred if that's required to
+ * maintain a consistent audio level. Whether clipping will actually
+ * occur depends on what value the user is using for replaygain_preamp.
+ */
+ unsigned volume;
+
+ struct audio_format format;
+
+ struct pcm_buffer buffer;
+
+public:
+ ReplayGainFilter()
+ :mixer(nullptr), mode(REPLAY_GAIN_OFF),
+ volume(PCM_VOLUME_1) {
+ replay_gain_info_init(&info);
+ }
+
+ void SetMixer(struct mixer *_mixer, unsigned _base) {
+ assert(_mixer == NULL || (_base > 0 && _base <= 100));
+
+ mixer = _mixer;
+ base = _base;
+
+ Update();
+ }
+
+ void SetInfo(const struct replay_gain_info *_info) {
+ if (_info != NULL) {
+ info = *_info;
+ replay_gain_info_complete(&info);
+ } else
+ replay_gain_info_init(&info);
+
+ Update();
+ }
+
+ void SetMode(enum replay_gain_mode _mode) {
+ if (_mode == mode)
+ /* no change */
+ return;
+
+ g_debug("replay gain mode has changed %d->%d\n", mode, _mode);
+
+ mode = _mode;
+ Update();
+ }
+
+ /**
+ * Recalculates the new volume after a property was changed.
+ */
+ void Update();
+
+ virtual const audio_format *Open(audio_format &af, GError **error_r);
+ virtual void Close();
+ virtual const void *FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r);
+};
+
+static inline GQuark
+replay_gain_quark(void)
+{
+ return g_quark_from_static_string("replay_gain");
+}
+
+void
+ReplayGainFilter::Update()
+{
+ if (mode != REPLAY_GAIN_OFF) {
+ float scale = replay_gain_tuple_scale(&info.tuples[mode],
+ replay_gain_preamp, replay_gain_missing_preamp, replay_gain_limit);
+ g_debug("scale=%f\n", (double)scale);
+
+ volume = pcm_float_to_volume(scale);
+ } else
+ volume = PCM_VOLUME_1;
+
+ if (mixer != NULL) {
+ /* update the hardware mixer volume */
+
+ unsigned _volume = (volume * base) / PCM_VOLUME_1;
+ if (_volume > 100)
+ _volume = 100;
+
+ GError *error = NULL;
+ if (!mixer_set_volume(mixer, _volume, &error)) {
+ g_warning("Failed to update hardware mixer: %s",
+ error->message);
+ g_error_free(error);
+ }
+ }
+}
+
+static Filter *
+replay_gain_filter_init(gcc_unused const struct config_param *param,
+ gcc_unused GError **error_r)
+{
+ return new ReplayGainFilter();
+}
+
+const audio_format *
+ReplayGainFilter::Open(audio_format &af, gcc_unused GError **error_r)
+{
+ format = af;
+ pcm_buffer_init(&buffer);
+
+ return &format;
+}
+
+void
+ReplayGainFilter::Close()
+{
+ pcm_buffer_deinit(&buffer);
+}
+
+const void *
+ReplayGainFilter::FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r)
+{
+
+ *dest_size_r = src_size;
+
+ if (volume == PCM_VOLUME_1)
+ /* optimized special case: 100% volume = no-op */
+ return src;
+
+ void *dest = pcm_buffer_get(&buffer, src_size);
+ if (volume <= 0) {
+ /* optimized special case: 0% volume = memset(0) */
+ /* XXX is this valid for all sample formats? What
+ about floating point? */
+ memset(dest, 0, src_size);
+ return dest;
+ }
+
+ memcpy(dest, src, src_size);
+
+ bool success = pcm_volume(dest, src_size,
+ sample_format(format.format),
+ volume);
+ if (!success) {
+ g_set_error(error_r, replay_gain_quark(), 0,
+ "pcm_volume() has failed");
+ return NULL;
+ }
+
+ return dest;
+}
+
+const struct filter_plugin replay_gain_filter_plugin = {
+ "replay_gain",
+ replay_gain_filter_init,
+};
+
+void
+replay_gain_filter_set_mixer(Filter *_filter, struct mixer *mixer,
+ unsigned base)
+{
+ ReplayGainFilter *filter = (ReplayGainFilter *)_filter;
+
+ filter->SetMixer(mixer, base);
+}
+
+void
+replay_gain_filter_set_info(Filter *_filter, const replay_gain_info *info)
+{
+ ReplayGainFilter *filter = (ReplayGainFilter *)_filter;
+
+ filter->SetInfo(info);
+}
+
+void
+replay_gain_filter_set_mode(Filter *_filter, enum replay_gain_mode mode)
+{
+ ReplayGainFilter *filter = (ReplayGainFilter *)_filter;
+
+ filter->SetMode(mode);
+}
diff --git a/src/filter/replay_gain_filter_plugin.h b/src/filter/ReplayGainFilterPlugin.hxx
index 45b738e4..dd8ceb95 100644
--- a/src/filter/replay_gain_filter_plugin.h
+++ b/src/filter/ReplayGainFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,12 +17,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef REPLAY_GAIN_FILTER_PLUGIN_H
-#define REPLAY_GAIN_FILTER_PLUGIN_H
+#ifndef MPD_REPLAY_GAIN_FILTER_PLUGIN_HXX
+#define MPD_REPLAY_GAIN_FILTER_PLUGIN_HXX
#include "replay_gain_info.h"
-struct filter;
+class Filter;
struct mixer;
/**
@@ -34,7 +34,7 @@ struct mixer;
* (including).
*/
void
-replay_gain_filter_set_mixer(struct filter *_filter, struct mixer *mixer,
+replay_gain_filter_set_mixer(Filter *_filter, struct mixer *mixer,
unsigned base);
/**
@@ -44,7 +44,9 @@ replay_gain_filter_set_mixer(struct filter *_filter, struct mixer *mixer,
* gain data is available for the current song
*/
void
-replay_gain_filter_set_info(struct filter *filter,
- const struct replay_gain_info *info);
+replay_gain_filter_set_info(Filter *filter, const replay_gain_info *info);
+
+void
+replay_gain_filter_set_mode(Filter *filter, enum replay_gain_mode mode);
#endif
diff --git a/src/filter/route_filter_plugin.c b/src/filter/RouteFilterPlugin.cxx
index 3bf8677e..55957893 100644
--- a/src/filter/route_filter_plugin.c
+++ b/src/filter/RouteFilterPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -41,25 +41,19 @@
#include "config.h"
#include "conf.h"
+#include "ConfigQuark.hxx"
#include "audio_format.h"
#include "audio_check.h"
-#include "filter_plugin.h"
-#include "filter_internal.h"
-#include "filter_registry.h"
+#include "FilterPlugin.hxx"
+#include "FilterInternal.hxx"
+#include "FilterRegistry.hxx"
#include "pcm_buffer.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
-
-struct route_filter {
-
- /**
- * Inherit (and support cast to/from) filter
- */
- struct filter base;
-
+class RouteFilter final : public Filter {
/**
* The minimum number of channels we need for output
* to be able to perform all the copies the user has specified
@@ -109,21 +103,31 @@ struct route_filter {
*/
struct pcm_buffer output_buffer;
+public:
+ RouteFilter():sources(nullptr) {}
+ ~RouteFilter() {
+ g_free(sources);
+ }
+
+ /**
+ * Parse the "routes" section, a string on the form
+ * a>b, c>d, e>f, ...
+ * where a... are non-unique, non-negative integers
+ * and input channel a gets copied to output channel b, etc.
+ * @param param the configuration block to read
+ * @param filter a route_filter whose min_channels and sources[] to set
+ * @return true on success, false on error
+ */
+ bool Configure(const config_param *param, GError **error_r);
+
+ virtual const audio_format *Open(audio_format &af, GError **error_r);
+ virtual void Close();
+ virtual const void *FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r);
};
-/**
- * Parse the "routes" section, a string on the form
- * a>b, c>d, e>f, ...
- * where a... are non-unique, non-negative integers
- * and input channel a gets copied to output channel b, etc.
- * @param param the configuration block to read
- * @param filter a route_filter whose min_channels and sources[] to set
- * @return true on success, false on error
- */
-static bool
-route_filter_parse(const struct config_param *param,
- struct route_filter *filter,
- GError **error_r) {
+bool
+RouteFilter::Configure(const config_param *param, GError **error_r) {
/* TODO:
* With a more clever way of marking "don't copy to output N",
@@ -138,8 +142,8 @@ route_filter_parse(const struct config_param *param,
const char *routes =
config_get_block_string(param, "routes", "0>0, 1>1");
- filter->min_input_channels = 0;
- filter->min_output_channels = 0;
+ min_input_channels = 0;
+ min_output_channels = 0;
tokens = g_strsplit(routes, ",", 255);
number_of_copies = g_strv_length(tokens);
@@ -170,28 +174,28 @@ route_filter_parse(const struct config_param *param,
// Keep track of the highest channel numbers seen
// as either in- or outputs
- if (source >= filter->min_input_channels)
- filter->min_input_channels = source + 1;
- if (dest >= filter->min_output_channels)
- filter->min_output_channels = dest + 1;
+ if (source >= min_input_channels)
+ min_input_channels = source + 1;
+ if (dest >= min_output_channels)
+ min_output_channels = dest + 1;
g_strfreev(sd);
}
- if (!audio_valid_channel_count(filter->min_output_channels)) {
+ if (!audio_valid_channel_count(min_output_channels)) {
g_strfreev(tokens);
g_set_error(error_r, audio_format_quark(), 0,
"Invalid number of output channels requested: %d",
- filter->min_output_channels);
+ min_output_channels);
return false;
}
// Allocate a map of "copy nothing to me"
- filter->sources =
- g_malloc(filter->min_output_channels * sizeof(signed char));
+ sources = (signed char *)
+ g_malloc(min_output_channels * sizeof(signed char));
- for (int i=0; i<filter->min_output_channels; ++i)
- filter->sources[i] = -1;
+ for (int i=0; i<min_output_channels; ++i)
+ sources[i] = -1;
// Run through the spec again, and save the
// actual mapping output <- input
@@ -215,7 +219,7 @@ route_filter_parse(const struct config_param *param,
source = strtol(sd[0], NULL, 10);
dest = strtol(sd[1], NULL, 10);
- filter->sources[dest] = source;
+ sources[dest] = source;
g_strfreev(sd);
}
@@ -225,92 +229,73 @@ route_filter_parse(const struct config_param *param,
return true;
}
-static struct filter *
-route_filter_init(const struct config_param *param,
- G_GNUC_UNUSED GError **error_r)
-{
- struct route_filter *filter = g_new(struct route_filter, 1);
- filter_init(&filter->base, &route_filter_plugin);
-
- // Allocate and set the filter->sources[] array
- route_filter_parse(param, filter, error_r);
-
- return &filter->base;
-}
-
-static void
-route_filter_finish(struct filter *_filter)
+static Filter *
+route_filter_init(const config_param *param, GError **error_r)
{
- struct route_filter *filter = (struct route_filter *)_filter;
+ RouteFilter *filter = new RouteFilter();
+ if (!filter->Configure(param, error_r)) {
+ delete filter;
+ return nullptr;
+ }
- g_free(filter->sources);
- g_free(filter);
+ return filter;
}
-static const struct audio_format *
-route_filter_open(struct filter *_filter, struct audio_format *audio_format,
- G_GNUC_UNUSED GError **error_r)
+const struct audio_format *
+RouteFilter::Open(audio_format &audio_format, gcc_unused GError **error_r)
{
- struct route_filter *filter = (struct route_filter *)_filter;
-
// Copy the input format for later reference
- filter->input_format = *audio_format;
- filter->input_frame_size =
- audio_format_frame_size(&filter->input_format);
+ input_format = audio_format;
+ input_frame_size = audio_format_frame_size(&input_format);
// Decide on an output format which has enough channels,
// and is otherwise identical
- filter->output_format = *audio_format;
- filter->output_format.channels = filter->min_output_channels;
+ output_format = audio_format;
+ output_format.channels = min_output_channels;
// Precalculate this simple value, to speed up allocation later
- filter->output_frame_size =
- audio_format_frame_size(&filter->output_format);
+ output_frame_size = audio_format_frame_size(&output_format);
// This buffer grows as needed
- pcm_buffer_init(&filter->output_buffer);
+ pcm_buffer_init(&output_buffer);
- return &filter->output_format;
+ return &output_format;
}
-static void
-route_filter_close(struct filter *_filter)
+void
+RouteFilter::Close()
{
- struct route_filter *filter = (struct route_filter *)_filter;
-
- pcm_buffer_deinit(&filter->output_buffer);
+ pcm_buffer_deinit(&output_buffer);
}
-static const void *
-route_filter_filter(struct filter *_filter,
- const void *src, size_t src_size,
- size_t *dest_size_r, G_GNUC_UNUSED GError **error_r)
+const void *
+RouteFilter::FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, gcc_unused GError **error_r)
{
- struct route_filter *filter = (struct route_filter *)_filter;
-
- size_t number_of_frames = src_size / filter->input_frame_size;
+ size_t number_of_frames = src_size / input_frame_size;
size_t bytes_per_frame_per_channel =
- audio_format_sample_size(&filter->input_format);
+ audio_format_sample_size(&input_format);
// A moving pointer that always refers to channel 0 in the input, at the currently handled frame
- const uint8_t *base_source = src;
+ const uint8_t *base_source = (const uint8_t *)src;
// A moving pointer that always refers to the currently filled channel of the currently handled frame, in the output
uint8_t *chan_destination;
// Grow our reusable buffer, if needed, and set the moving pointer
- *dest_size_r = number_of_frames * filter->output_frame_size;
- chan_destination = pcm_buffer_get(&filter->output_buffer, *dest_size_r);
+ *dest_size_r = number_of_frames * output_frame_size;
+ chan_destination = (uint8_t *)
+ pcm_buffer_get(&output_buffer, *dest_size_r);
// Perform our copy operations, with N input channels and M output channels
for (unsigned int s=0; s<number_of_frames; ++s) {
// Need to perform one copy per output channel
- for (unsigned int c=0; c<filter->min_output_channels; ++c) {
- if (filter->sources[c] == -1 ||
- (unsigned)filter->sources[c] >= filter->input_format.channels) {
+ for (unsigned int c=0; c<min_output_channels; ++c) {
+ if (sources[c] == -1 ||
+ (unsigned)sources[c] >= input_format.channels) {
// No source for this destination output,
// give it zeroes as input
memset(chan_destination,
@@ -320,7 +305,7 @@ route_filter_filter(struct filter *_filter,
// Get the data from channel sources[c]
// and copy it to the output
const uint8_t *data = base_source +
- (filter->sources[c] * bytes_per_frame_per_channel);
+ (sources[c] * bytes_per_frame_per_channel);
memcpy(chan_destination,
data,
bytes_per_frame_per_channel);
@@ -331,18 +316,14 @@ route_filter_filter(struct filter *_filter,
// Go on to the next N input samples
- base_source += filter->input_frame_size;
+ base_source += input_frame_size;
}
// Here it is, ladies and gentlemen! Rerouted data!
- return (void *) filter->output_buffer.buffer;
+ return (void *) output_buffer.buffer;
}
const struct filter_plugin route_filter_plugin = {
- .name = "route",
- .init = route_filter_init,
- .finish = route_filter_finish,
- .open = route_filter_open,
- .close = route_filter_close,
- .filter = route_filter_filter,
+ "route",
+ route_filter_init,
};
diff --git a/src/filter/VolumeFilterPlugin.cxx b/src/filter/VolumeFilterPlugin.cxx
new file mode 100644
index 00000000..0689f5da
--- /dev/null
+++ b/src/filter/VolumeFilterPlugin.cxx
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2003-2013 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 "VolumeFilterPlugin.hxx"
+#include "FilterPlugin.hxx"
+#include "FilterInternal.hxx"
+#include "FilterRegistry.hxx"
+#include "conf.h"
+#include "pcm_buffer.h"
+#include "PcmVolume.hxx"
+#include "audio_format.h"
+
+#include <assert.h>
+#include <string.h>
+
+class VolumeFilter final : public Filter {
+ /**
+ * The current volume, from 0 to #PCM_VOLUME_1.
+ */
+ unsigned volume;
+
+ struct audio_format format;
+
+ struct pcm_buffer buffer;
+
+public:
+ VolumeFilter()
+ :volume(PCM_VOLUME_1) {}
+
+ unsigned GetVolume() const {
+ assert(volume <= PCM_VOLUME_1);
+
+ return volume;
+ }
+
+ void SetVolume(unsigned _volume) {
+ assert(_volume <= PCM_VOLUME_1);
+
+ volume = _volume;
+ }
+
+ virtual const audio_format *Open(audio_format &af, GError **error_r);
+ virtual void Close();
+ virtual const void *FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r);
+};
+
+static inline GQuark
+volume_quark(void)
+{
+ return g_quark_from_static_string("pcm_volume");
+}
+
+static Filter *
+volume_filter_init(gcc_unused const struct config_param *param,
+ gcc_unused GError **error_r)
+{
+ return new VolumeFilter();
+}
+
+const struct audio_format *
+VolumeFilter::Open(audio_format &audio_format, gcc_unused GError **error_r)
+{
+ format = audio_format;
+ pcm_buffer_init(&buffer);
+
+ return &format;
+}
+
+void
+VolumeFilter::Close()
+{
+ pcm_buffer_deinit(&buffer);
+}
+
+const void *
+VolumeFilter::FilterPCM(const void *src, size_t src_size,
+ size_t *dest_size_r, GError **error_r)
+{
+ *dest_size_r = src_size;
+
+ if (volume >= PCM_VOLUME_1)
+ /* optimized special case: 100% volume = no-op */
+ return src;
+
+ void *dest = pcm_buffer_get(&buffer, src_size);
+
+ if (volume <= 0) {
+ /* optimized special case: 0% volume = memset(0) */
+ /* XXX is this valid for all sample formats? What
+ about floating point? */
+ memset(dest, 0, src_size);
+ return dest;
+ }
+
+ memcpy(dest, src, src_size);
+
+ bool success = pcm_volume(dest, src_size,
+ sample_format(format.format),
+ volume);
+ if (!success) {
+ g_set_error(error_r, volume_quark(), 0,
+ "pcm_volume() has failed");
+ return NULL;
+ }
+
+ return dest;
+}
+
+const struct filter_plugin volume_filter_plugin = {
+ "volume",
+ volume_filter_init,
+};
+
+unsigned
+volume_filter_get(const Filter *_filter)
+{
+ const VolumeFilter *filter =
+ (const VolumeFilter *)_filter;
+
+ return filter->GetVolume();
+}
+
+void
+volume_filter_set(Filter *_filter, unsigned volume)
+{
+ VolumeFilter *filter = (VolumeFilter *)_filter;
+
+ filter->SetVolume(volume);
+}
+
diff --git a/src/filter/volume_filter_plugin.h b/src/filter/VolumeFilterPlugin.hxx
index 5b16f7e5..822b7e93 100644
--- a/src/filter/volume_filter_plugin.h
+++ b/src/filter/VolumeFilterPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,15 +17,15 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef VOLUME_FILTER_PLUGIN_H
-#define VOLUME_FILTER_PLUGIN_H
+#ifndef MPD_VOLUME_FILTER_PLUGIN_HXX
+#define MPD_VOLUME_FILTER_PLUGIN_HXX
-struct filter;
+class Filter;
unsigned
-volume_filter_get(const struct filter *filter);
+volume_filter_get(const Filter *filter);
void
-volume_filter_set(struct filter *filter, unsigned volume);
+volume_filter_set(Filter *filter, unsigned volume);
#endif
diff --git a/src/filter/autoconvert_filter_plugin.c b/src/filter/autoconvert_filter_plugin.c
deleted file mode 100644
index 3826a0fb..00000000
--- a/src/filter/autoconvert_filter_plugin.c
+++ /dev/null
@@ -1,169 +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 "filter/autoconvert_filter_plugin.h"
-#include "filter/convert_filter_plugin.h"
-#include "filter_plugin.h"
-#include "filter_internal.h"
-#include "filter_registry.h"
-#include "conf.h"
-#include "pcm_convert.h"
-#include "audio_format.h"
-#include "poison.h"
-
-#include <assert.h>
-#include <string.h>
-
-struct autoconvert_filter {
- struct filter base;
-
- /**
- * The audio format being fed to the underlying filter. This
- * plugin actually doesn't need this variable, we have it here
- * just so our open() method doesn't return a stack pointer.
- */
- struct audio_format in_audio_format;
-
- /**
- * The underlying filter.
- */
- struct filter *filter;
-
- /**
- * A convert_filter, just in case conversion is needed. NULL
- * if unused.
- */
- struct filter *convert;
-};
-
-static void
-autoconvert_filter_finish(struct filter *_filter)
-{
- struct autoconvert_filter *filter =
- (struct autoconvert_filter *)_filter;
-
- filter_free(filter->filter);
- g_free(filter);
-}
-
-static const struct audio_format *
-autoconvert_filter_open(struct filter *_filter,
- struct audio_format *in_audio_format,
- GError **error_r)
-{
- struct autoconvert_filter *filter =
- (struct autoconvert_filter *)_filter;
- const struct audio_format *out_audio_format;
-
- assert(audio_format_valid(in_audio_format));
-
- /* open the "real" filter */
-
- filter->in_audio_format = *in_audio_format;
-
- out_audio_format = filter_open(filter->filter,
- &filter->in_audio_format, error_r);
- if (out_audio_format == NULL)
- return NULL;
-
- /* need to convert? */
-
- if (!audio_format_equals(&filter->in_audio_format, in_audio_format)) {
- /* yes - create a convert_filter */
- struct audio_format audio_format2 = *in_audio_format;
- const struct audio_format *audio_format3;
-
- filter->convert = filter_new(&convert_filter_plugin, NULL,
- error_r);
- if (filter->convert == NULL) {
- filter_close(filter->filter);
- return NULL;
- }
-
- audio_format3 = filter_open(filter->convert, &audio_format2,
- error_r);
- if (audio_format3 == NULL) {
- filter_free(filter->convert);
- filter_close(filter->filter);
- return NULL;
- }
-
- assert(audio_format_equals(&audio_format2, in_audio_format));
-
- convert_filter_set(filter->convert, &filter->in_audio_format);
- } else
- /* no */
- filter->convert = NULL;
-
- return out_audio_format;
-}
-
-static void
-autoconvert_filter_close(struct filter *_filter)
-{
- struct autoconvert_filter *filter =
- (struct autoconvert_filter *)_filter;
-
- if (filter->convert != NULL) {
- filter_close(filter->convert);
- filter_free(filter->convert);
- }
-
- filter_close(filter->filter);
-}
-
-static const void *
-autoconvert_filter_filter(struct filter *_filter, const void *src,
- size_t src_size, size_t *dest_size_r,
- GError **error_r)
-{
- struct autoconvert_filter *filter =
- (struct autoconvert_filter *)_filter;
-
- if (filter->convert != NULL) {
- src = filter_filter(filter->convert, src, src_size, &src_size,
- error_r);
- if (src == NULL)
- return NULL;
- }
-
- return filter_filter(filter->filter, src, src_size, dest_size_r,
- error_r);
-}
-
-static const struct filter_plugin autoconvert_filter_plugin = {
- .name = "convert",
- .finish = autoconvert_filter_finish,
- .open = autoconvert_filter_open,
- .close = autoconvert_filter_close,
- .filter = autoconvert_filter_filter,
-};
-
-struct filter *
-autoconvert_filter_new(struct filter *_filter)
-{
- struct autoconvert_filter *filter =
- g_new(struct autoconvert_filter, 1);
-
- filter_init(&filter->base, &autoconvert_filter_plugin);
- filter->filter = _filter;
-
- return &filter->base;
-}
diff --git a/src/filter/chain_filter_plugin.c b/src/filter/chain_filter_plugin.c
deleted file mode 100644
index 2c785a36..00000000
--- a/src/filter/chain_filter_plugin.c
+++ /dev/null
@@ -1,213 +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 "conf.h"
-#include "filter/chain_filter_plugin.h"
-#include "filter_plugin.h"
-#include "filter_internal.h"
-#include "filter_registry.h"
-#include "audio_format.h"
-
-#include <assert.h>
-
-struct filter_chain {
- /** the base class */
- struct filter base;
-
- GSList *children;
-};
-
-static inline GQuark
-filter_quark(void)
-{
- return g_quark_from_static_string("filter");
-}
-
-static struct filter *
-chain_filter_init(G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error_r)
-{
- struct filter_chain *chain = g_new(struct filter_chain, 1);
-
- filter_init(&chain->base, &chain_filter_plugin);
- chain->children = NULL;
-
- return &chain->base;
-}
-
-static void
-chain_free_child(gpointer data, G_GNUC_UNUSED gpointer user_data)
-{
- struct filter *filter = data;
-
- filter_free(filter);
-}
-
-static void
-chain_filter_finish(struct filter *_filter)
-{
- struct filter_chain *chain = (struct filter_chain *)_filter;
-
- g_slist_foreach(chain->children, chain_free_child, NULL);
- g_slist_free(chain->children);
-
- g_free(chain);
-}
-
-/**
- * Close all filters in the chain until #until is reached. #until
- * itself is not closed.
- */
-static void
-chain_close_until(struct filter_chain *chain, const struct filter *until)
-{
- GSList *i = chain->children;
- struct filter *filter;
-
- while (true) {
- /* this assertion fails if #until does not exist
- (anymore) */
- assert(i != NULL);
-
- if (i->data == until)
- /* don't close this filter */
- break;
-
- /* close this filter */
- filter = i->data;
- filter_close(filter);
-
- i = g_slist_next(i);
- }
-}
-
-static const struct audio_format *
-chain_open_child(struct filter *filter,
- const struct audio_format *prev_audio_format,
- GError **error_r)
-{
- struct audio_format conv_audio_format = *prev_audio_format;
- const struct audio_format *next_audio_format;
-
- next_audio_format = filter_open(filter, &conv_audio_format, error_r);
- if (next_audio_format == NULL)
- return NULL;
-
- if (!audio_format_equals(&conv_audio_format, prev_audio_format)) {
- struct audio_format_string s;
-
- filter_close(filter);
- g_set_error(error_r, filter_quark(), 0,
- "Audio format not supported by filter '%s': %s",
- filter->plugin->name,
- audio_format_to_string(prev_audio_format, &s));
- return NULL;
- }
-
- return next_audio_format;
-}
-
-static const struct audio_format *
-chain_filter_open(struct filter *_filter, struct audio_format *in_audio_format,
- GError **error_r)
-{
- struct filter_chain *chain = (struct filter_chain *)_filter;
- const struct audio_format *audio_format = in_audio_format;
-
- for (GSList *i = chain->children; i != NULL; i = g_slist_next(i)) {
- struct filter *filter = i->data;
-
- audio_format = chain_open_child(filter, audio_format, error_r);
- if (audio_format == NULL) {
- /* rollback, close all children */
- chain_close_until(chain, filter);
- return NULL;
- }
- }
-
- /* return the output format of the last filter */
- return audio_format;
-}
-
-static void
-chain_close_child(gpointer data, G_GNUC_UNUSED gpointer user_data)
-{
- struct filter *filter = data;
-
- filter_close(filter);
-}
-
-static void
-chain_filter_close(struct filter *_filter)
-{
- struct filter_chain *chain = (struct filter_chain *)_filter;
-
- g_slist_foreach(chain->children, chain_close_child, NULL);
-}
-
-static const void *
-chain_filter_filter(struct filter *_filter,
- const void *src, size_t src_size,
- size_t *dest_size_r, GError **error_r)
-{
- struct filter_chain *chain = (struct filter_chain *)_filter;
-
- for (GSList *i = chain->children; i != NULL; i = g_slist_next(i)) {
- struct filter *filter = i->data;
-
- /* feed the output of the previous filter as input
- into the current one */
- src = filter_filter(filter, src, src_size, &src_size, error_r);
- if (src == NULL)
- return NULL;
- }
-
- /* return the output of the last filter */
- *dest_size_r = src_size;
- return src;
-}
-
-const struct filter_plugin chain_filter_plugin = {
- .name = "chain",
- .init = chain_filter_init,
- .finish = chain_filter_finish,
- .open = chain_filter_open,
- .close = chain_filter_close,
- .filter = chain_filter_filter,
-};
-
-struct filter *
-filter_chain_new(void)
-{
- struct filter *filter = filter_new(&chain_filter_plugin, NULL, NULL);
- /* chain_filter_init() never fails */
- assert(filter != NULL);
-
- return filter;
-}
-
-void
-filter_chain_append(struct filter *_chain, struct filter *filter)
-{
- struct filter_chain *chain = (struct filter_chain *)_chain;
-
- chain->children = g_slist_append(chain->children, filter);
-}
-
diff --git a/src/filter/convert_filter_plugin.c b/src/filter/convert_filter_plugin.c
deleted file mode 100644
index c55b69af..00000000
--- a/src/filter/convert_filter_plugin.c
+++ /dev/null
@@ -1,146 +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 "filter/convert_filter_plugin.h"
-#include "filter_plugin.h"
-#include "filter_internal.h"
-#include "filter_registry.h"
-#include "conf.h"
-#include "pcm_convert.h"
-#include "audio_format.h"
-#include "poison.h"
-
-#include <assert.h>
-#include <string.h>
-
-struct convert_filter {
- struct filter base;
-
- /**
- * The current convert, from 0 to #PCM_CONVERT_1.
- */
- unsigned convert;
-
- /**
- * The input audio format; PCM data is passed to the filter()
- * method in this format.
- */
- struct audio_format in_audio_format;
-
- /**
- * The output audio format; the consumer of this plugin
- * expects PCM data in this format. This defaults to
- * #in_audio_format, and can be set with convert_filter_set().
- */
- struct audio_format out_audio_format;
-
- struct pcm_convert_state state;
-};
-
-static struct filter *
-convert_filter_init(G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error_r)
-{
- struct convert_filter *filter = g_new(struct convert_filter, 1);
-
- filter_init(&filter->base, &convert_filter_plugin);
- return &filter->base;
-}
-
-static void
-convert_filter_finish(struct filter *filter)
-{
- g_free(filter);
-}
-
-static const struct audio_format *
-convert_filter_open(struct filter *_filter, struct audio_format *audio_format,
- G_GNUC_UNUSED GError **error_r)
-{
- struct convert_filter *filter = (struct convert_filter *)_filter;
-
- assert(audio_format_valid(audio_format));
-
- filter->in_audio_format = filter->out_audio_format = *audio_format;
- pcm_convert_init(&filter->state);
-
- return &filter->in_audio_format;
-}
-
-static void
-convert_filter_close(struct filter *_filter)
-{
- struct convert_filter *filter = (struct convert_filter *)_filter;
-
- pcm_convert_deinit(&filter->state);
-
- poison_undefined(&filter->in_audio_format,
- sizeof(filter->in_audio_format));
- poison_undefined(&filter->out_audio_format,
- sizeof(filter->out_audio_format));
-}
-
-static const void *
-convert_filter_filter(struct filter *_filter, const void *src, size_t src_size,
- size_t *dest_size_r, GError **error_r)
-{
- struct convert_filter *filter = (struct convert_filter *)_filter;
- const void *dest;
-
- if (audio_format_equals(&filter->in_audio_format,
- &filter->out_audio_format)) {
- /* optimized special case: no-op */
- *dest_size_r = src_size;
- return src;
- }
-
- dest = pcm_convert(&filter->state, &filter->in_audio_format,
- src, src_size,
- &filter->out_audio_format, dest_size_r,
- error_r);
- if (dest == NULL)
- return NULL;
-
- return dest;
-}
-
-const struct filter_plugin convert_filter_plugin = {
- .name = "convert",
- .init = convert_filter_init,
- .finish = convert_filter_finish,
- .open = convert_filter_open,
- .close = convert_filter_close,
- .filter = convert_filter_filter,
-};
-
-void
-convert_filter_set(struct filter *_filter,
- const struct audio_format *out_audio_format)
-{
- struct convert_filter *filter = (struct convert_filter *)_filter;
-
- assert(filter != NULL);
- assert(audio_format_valid(&filter->in_audio_format));
- assert(audio_format_valid(&filter->out_audio_format));
- assert(out_audio_format != NULL);
- assert(audio_format_valid(out_audio_format));
-
- filter->out_audio_format = *out_audio_format;
-}
diff --git a/src/filter/normalize_filter_plugin.c b/src/filter/normalize_filter_plugin.c
deleted file mode 100644
index 2151482e..00000000
--- a/src/filter/normalize_filter_plugin.c
+++ /dev/null
@@ -1,112 +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 "filter_plugin.h"
-#include "filter_internal.h"
-#include "filter_registry.h"
-#include "pcm_buffer.h"
-#include "audio_format.h"
-#include "AudioCompress/compress.h"
-
-#include <assert.h>
-#include <string.h>
-
-struct normalize_filter {
- struct filter filter;
-
- struct Compressor *compressor;
-
- struct pcm_buffer buffer;
-};
-
-static inline GQuark
-normalize_quark(void)
-{
- return g_quark_from_static_string("normalize");
-}
-
-static struct filter *
-normalize_filter_init(G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error_r)
-{
- struct normalize_filter *filter = g_new(struct normalize_filter, 1);
-
- filter_init(&filter->filter, &normalize_filter_plugin);
-
- return &filter->filter;
-}
-
-static void
-normalize_filter_finish(struct filter *filter)
-{
- g_free(filter);
-}
-
-static const struct audio_format *
-normalize_filter_open(struct filter *_filter,
- struct audio_format *audio_format,
- G_GNUC_UNUSED GError **error_r)
-{
- struct normalize_filter *filter = (struct normalize_filter *)_filter;
-
- audio_format->format = SAMPLE_FORMAT_S16;
-
- filter->compressor = Compressor_new(0);
-
- pcm_buffer_init(&filter->buffer);
-
- return audio_format;
-}
-
-static void
-normalize_filter_close(struct filter *_filter)
-{
- struct normalize_filter *filter = (struct normalize_filter *)_filter;
-
- pcm_buffer_deinit(&filter->buffer);
- Compressor_delete(filter->compressor);
-}
-
-static const void *
-normalize_filter_filter(struct filter *_filter,
- const void *src, size_t src_size, size_t *dest_size_r,
- G_GNUC_UNUSED GError **error_r)
-{
- struct normalize_filter *filter = (struct normalize_filter *)_filter;
- void *dest;
-
- dest = pcm_buffer_get(&filter->buffer, src_size);
-
- memcpy(dest, src, src_size);
-
- Compressor_Process_int16(filter->compressor, dest, src_size / 2);
-
- *dest_size_r = src_size;
- return dest;
-}
-
-const struct filter_plugin normalize_filter_plugin = {
- .name = "normalize",
- .init = normalize_filter_init,
- .finish = normalize_filter_finish,
- .open = normalize_filter_open,
- .close = normalize_filter_close,
- .filter = normalize_filter_filter,
-};
diff --git a/src/filter/null_filter_plugin.c b/src/filter/null_filter_plugin.c
deleted file mode 100644
index e7c99882..00000000
--- a/src/filter/null_filter_plugin.c
+++ /dev/null
@@ -1,93 +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
- *
- * This filter plugin does nothing. That is not quite useful, except
- * for testing the filter core, or as a template for new filter
- * plugins.
- */
-
-#include "config.h"
-#include "filter_plugin.h"
-#include "filter_internal.h"
-#include "filter_registry.h"
-
-#include <assert.h>
-
-struct null_filter {
- struct filter filter;
-};
-
-static struct filter *
-null_filter_init(G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error_r)
-{
- struct null_filter *filter = g_new(struct null_filter, 1);
-
- filter_init(&filter->filter, &null_filter_plugin);
- return &filter->filter;
-}
-
-static void
-null_filter_finish(struct filter *_filter)
-{
- struct null_filter *filter = (struct null_filter *)_filter;
-
- g_free(filter);
-}
-
-static const struct audio_format *
-null_filter_open(struct filter *_filter, struct audio_format *audio_format,
- G_GNUC_UNUSED GError **error_r)
-{
- struct null_filter *filter = (struct null_filter *)_filter;
- (void)filter;
-
- return audio_format;
-}
-
-static void
-null_filter_close(struct filter *_filter)
-{
- struct null_filter *filter = (struct null_filter *)_filter;
- (void)filter;
-}
-
-static const void *
-null_filter_filter(struct filter *_filter,
- const void *src, size_t src_size,
- size_t *dest_size_r, G_GNUC_UNUSED GError **error_r)
-{
- struct null_filter *filter = (struct null_filter *)_filter;
- (void)filter;
-
- /* return the unmodified source buffer */
- *dest_size_r = src_size;
- return src;
-}
-
-const struct filter_plugin null_filter_plugin = {
- .name = "null",
- .init = null_filter_init,
- .finish = null_filter_finish,
- .open = null_filter_open,
- .close = null_filter_close,
- .filter = null_filter_filter,
-};
diff --git a/src/filter/replay_gain_filter_plugin.c b/src/filter/replay_gain_filter_plugin.c
deleted file mode 100644
index 583a09f9..00000000
--- a/src/filter/replay_gain_filter_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"
-#include "filter/replay_gain_filter_plugin.h"
-#include "filter_plugin.h"
-#include "filter_internal.h"
-#include "filter_registry.h"
-#include "audio_format.h"
-#include "pcm_buffer.h"
-#include "pcm_volume.h"
-#include "replay_gain_info.h"
-#include "replay_gain_config.h"
-#include "mixer_control.h"
-
-#include <assert.h>
-#include <string.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "replay_gain"
-
-struct replay_gain_filter {
- struct filter filter;
-
- /**
- * If set, then this hardware mixer is used for applying
- * replay gain, instead of the software volume library.
- */
- struct mixer *mixer;
-
- /**
- * The base volume level for scale=1.0, between 1 and 100
- * (including).
- */
- unsigned base;
-
- enum replay_gain_mode mode;
-
- struct replay_gain_info info;
-
- /**
- * The current volume, between 0 and a value that may or may not exceed
- * #PCM_VOLUME_1.
- *
- * If the default value of true is used for replaygain_limit, the
- * application of the volume to the signal will never cause clipping.
- *
- * On the other hand, if the user has set replaygain_limit to false,
- * the chance of clipping is explicitly preferred if that's required to
- * maintain a consistent audio level. Whether clipping will actually
- * occur depends on what value the user is using for replaygain_preamp.
- */
- unsigned volume;
-
- struct audio_format audio_format;
-
- struct pcm_buffer buffer;
-};
-
-static inline GQuark
-replay_gain_quark(void)
-{
- return g_quark_from_static_string("replay_gain");
-}
-
-/**
- * Recalculates the new volume after a property was changed.
- */
-static void
-replay_gain_filter_update(struct replay_gain_filter *filter)
-{
- if (filter->mode != REPLAY_GAIN_OFF) {
- float scale = replay_gain_tuple_scale(&filter->info.tuples[filter->mode],
- replay_gain_preamp, replay_gain_missing_preamp, replay_gain_limit);
- g_debug("scale=%f\n", (double)scale);
-
- filter->volume = pcm_float_to_volume(scale);
- } else
- filter->volume = PCM_VOLUME_1;
-
- if (filter->mixer != NULL) {
- /* update the hardware mixer volume */
-
- unsigned volume = (filter->volume * filter->base) / PCM_VOLUME_1;
- if (volume > 100)
- volume = 100;
-
- GError *error = NULL;
- if (!mixer_set_volume(filter->mixer, volume, &error)) {
- g_warning("Failed to update hardware mixer: %s",
- error->message);
- g_error_free(error);
- }
- }
-}
-
-static struct filter *
-replay_gain_filter_init(G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error_r)
-{
- struct replay_gain_filter *filter = g_new(struct replay_gain_filter, 1);
-
- filter_init(&filter->filter, &replay_gain_filter_plugin);
- filter->mixer = NULL;
-
- filter->mode = replay_gain_get_real_mode();
- replay_gain_info_init(&filter->info);
- filter->volume = PCM_VOLUME_1;
-
- return &filter->filter;
-}
-
-static void
-replay_gain_filter_finish(struct filter *filter)
-{
- g_free(filter);
-}
-
-static const struct audio_format *
-replay_gain_filter_open(struct filter *_filter,
- struct audio_format *audio_format,
- G_GNUC_UNUSED GError **error_r)
-{
- struct replay_gain_filter *filter =
- (struct replay_gain_filter *)_filter;
-
- filter->audio_format = *audio_format;
- pcm_buffer_init(&filter->buffer);
-
- return &filter->audio_format;
-}
-
-static void
-replay_gain_filter_close(struct filter *_filter)
-{
- struct replay_gain_filter *filter =
- (struct replay_gain_filter *)_filter;
-
- pcm_buffer_deinit(&filter->buffer);
-}
-
-static const void *
-replay_gain_filter_filter(struct filter *_filter,
- const void *src, size_t src_size,
- size_t *dest_size_r, GError **error_r)
-{
- struct replay_gain_filter *filter =
- (struct replay_gain_filter *)_filter;
- bool success;
- void *dest;
- enum replay_gain_mode rg_mode;
-
- /* check if the mode has been changed since the last call */
- rg_mode = replay_gain_get_real_mode();
-
- if (filter->mode != rg_mode) {
- g_debug("replay gain mode has changed %d->%d\n", filter->mode, rg_mode);
- filter->mode = rg_mode;
- replay_gain_filter_update(filter);
- }
-
- *dest_size_r = src_size;
-
- if (filter->volume == PCM_VOLUME_1)
- /* optimized special case: 100% volume = no-op */
- return src;
-
- dest = pcm_buffer_get(&filter->buffer, src_size);
-
- if (filter->volume <= 0) {
- /* optimized special case: 0% volume = memset(0) */
- /* XXX is this valid for all sample formats? What
- about floating point? */
- memset(dest, 0, src_size);
- return dest;
- }
-
- memcpy(dest, src, src_size);
-
- success = pcm_volume(dest, src_size, filter->audio_format.format,
- filter->volume);
- if (!success) {
- g_set_error(error_r, replay_gain_quark(), 0,
- "pcm_volume() has failed");
- return NULL;
- }
-
- return dest;
-}
-
-const struct filter_plugin replay_gain_filter_plugin = {
- .name = "replay_gain",
- .init = replay_gain_filter_init,
- .finish = replay_gain_filter_finish,
- .open = replay_gain_filter_open,
- .close = replay_gain_filter_close,
- .filter = replay_gain_filter_filter,
-};
-
-void
-replay_gain_filter_set_mixer(struct filter *_filter, struct mixer *mixer,
- unsigned base)
-{
- struct replay_gain_filter *filter =
- (struct replay_gain_filter *)_filter;
-
- assert(mixer == NULL || (base > 0 && base <= 100));
-
- filter->mixer = mixer;
- filter->base = base;
-
- replay_gain_filter_update(filter);
-}
-
-void
-replay_gain_filter_set_info(struct filter *_filter,
- const struct replay_gain_info *info)
-{
- struct replay_gain_filter *filter =
- (struct replay_gain_filter *)_filter;
-
- if (info != NULL) {
- filter->info = *info;
- replay_gain_info_complete(&filter->info);
- } else
- replay_gain_info_init(&filter->info);
-
- replay_gain_filter_update(filter);
-}
diff --git a/src/filter/volume_filter_plugin.c b/src/filter/volume_filter_plugin.c
deleted file mode 100644
index 3260e898..00000000
--- a/src/filter/volume_filter_plugin.c
+++ /dev/null
@@ -1,158 +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 "filter/volume_filter_plugin.h"
-#include "filter_plugin.h"
-#include "filter_internal.h"
-#include "filter_registry.h"
-#include "conf.h"
-#include "pcm_buffer.h"
-#include "pcm_volume.h"
-#include "audio_format.h"
-
-#include <assert.h>
-#include <string.h>
-
-struct volume_filter {
- struct filter filter;
-
- /**
- * The current volume, from 0 to #PCM_VOLUME_1.
- */
- unsigned volume;
-
- struct audio_format audio_format;
-
- struct pcm_buffer buffer;
-};
-
-static inline GQuark
-volume_quark(void)
-{
- return g_quark_from_static_string("pcm_volume");
-}
-
-static struct filter *
-volume_filter_init(G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error_r)
-{
- struct volume_filter *filter = g_new(struct volume_filter, 1);
-
- filter_init(&filter->filter, &volume_filter_plugin);
- filter->volume = PCM_VOLUME_1;
-
- return &filter->filter;
-}
-
-static void
-volume_filter_finish(struct filter *filter)
-{
- g_free(filter);
-}
-
-static const struct audio_format *
-volume_filter_open(struct filter *_filter, struct audio_format *audio_format,
- G_GNUC_UNUSED GError **error_r)
-{
- struct volume_filter *filter = (struct volume_filter *)_filter;
-
- filter->audio_format = *audio_format;
- pcm_buffer_init(&filter->buffer);
-
- return &filter->audio_format;
-}
-
-static void
-volume_filter_close(struct filter *_filter)
-{
- struct volume_filter *filter = (struct volume_filter *)_filter;
-
- pcm_buffer_deinit(&filter->buffer);
-}
-
-static const void *
-volume_filter_filter(struct filter *_filter, const void *src, size_t src_size,
- size_t *dest_size_r, GError **error_r)
-{
- struct volume_filter *filter = (struct volume_filter *)_filter;
- bool success;
- void *dest;
-
- *dest_size_r = src_size;
-
- if (filter->volume >= PCM_VOLUME_1)
- /* optimized special case: 100% volume = no-op */
- return src;
-
- dest = pcm_buffer_get(&filter->buffer, src_size);
-
- if (filter->volume <= 0) {
- /* optimized special case: 0% volume = memset(0) */
- /* XXX is this valid for all sample formats? What
- about floating point? */
- memset(dest, 0, src_size);
- return dest;
- }
-
- memcpy(dest, src, src_size);
-
- success = pcm_volume(dest, src_size, filter->audio_format.format,
- filter->volume);
- if (!success) {
- g_set_error(error_r, volume_quark(), 0,
- "pcm_volume() has failed");
- return NULL;
- }
-
- return dest;
-}
-
-const struct filter_plugin volume_filter_plugin = {
- .name = "volume",
- .init = volume_filter_init,
- .finish = volume_filter_finish,
- .open = volume_filter_open,
- .close = volume_filter_close,
- .filter = volume_filter_filter,
-};
-
-unsigned
-volume_filter_get(const struct filter *_filter)
-{
- const struct volume_filter *filter =
- (const struct volume_filter *)_filter;
-
- assert(filter->filter.plugin == &volume_filter_plugin);
- assert(filter->volume <= PCM_VOLUME_1);
-
- return filter->volume;
-}
-
-void
-volume_filter_set(struct filter *_filter, unsigned volume)
-{
- struct volume_filter *filter = (struct volume_filter *)_filter;
-
- assert(filter->filter.plugin == &volume_filter_plugin);
- assert(volume <= PCM_VOLUME_1);
-
- filter->volume = volume;
-}
-