diff options
author | Max Kellermann <max@musicpd.org> | 2017-08-07 21:55:29 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2017-08-08 18:58:40 +0200 |
commit | bea5681fd8adbc3536ee82b031970e7861ab90f9 (patch) | |
tree | 108e44153acd32466331b68eccb973b0bc745af5 | |
parent | e11229494ed03e48af20ef9bdffcd0e8798a689a (diff) |
output/Interface: define a new struct AudioOutput
Hide struct FilteredAudioOutput from the plugins, preparing for hiding
MPD's core internals.
31 files changed, 228 insertions, 178 deletions
diff --git a/Makefile.am b/Makefile.am index b6fa7de37..35fdbe6cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1373,6 +1373,7 @@ OUTPUT_LIBS = \ OUTPUT_API_SRC = \ src/output/Client.hxx \ src/output/OutputAPI.hxx \ + src/output/Interface.hxx \ src/output/Filtered.cxx src/output/Filtered.hxx \ src/output/Wrapper.hxx \ src/output/Registry.cxx src/output/Registry.hxx \ @@ -2105,11 +2106,10 @@ test_run_convert_LDADD = \ libutil.a test_run_output_LDADD = $(MPD_LIBS) \ - $(PCM_LIBS) \ $(OUTPUT_LIBS) \ $(ENCODER_LIBS) \ libmixer_plugins.a \ - $(FILTER_LIBS) \ + $(PCM_LIBS) \ $(TAG_LIBS) \ libconf.a \ libbasic.a \ @@ -2123,13 +2123,10 @@ test_run_output_LDADD = $(MPD_LIBS) \ test_run_output_SOURCES = test/run_output.cxx \ src/Log.cxx src/LogBackend.cxx \ src/output/Domain.cxx \ - src/output/Init.cxx src/output/Finish.cxx src/output/Registry.cxx \ + src/output/Registry.cxx \ src/output/OutputPlugin.cxx \ src/mixer/MixerControl.cxx \ - src/mixer/MixerType.cxx \ - src/filter/FilterPlugin.cxx \ - src/filter/FilterConfig.cxx \ - src/filter/Observer.cxx + src/mixer/MixerType.cxx test_read_mixer_LDADD = \ libpcm.a \ diff --git a/src/output/Filtered.cxx b/src/output/Filtered.cxx index a2ff17261..13056bc9c 100644 --- a/src/output/Filtered.cxx +++ b/src/output/Filtered.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "Filtered.hxx" +#include "Interface.hxx" #include "OutputPlugin.hxx" #include "Domain.hxx" #include "Log.hxx" @@ -31,22 +32,22 @@ bool FilteredAudioOutput::SupportsEnableDisable() const noexcept { - assert((plugin.enable == nullptr) == (plugin.disable == nullptr)); + assert((output->plugin.enable == nullptr) == (output->plugin.disable == nullptr)); - return plugin.enable != nullptr; + return output->plugin.enable != nullptr; } bool FilteredAudioOutput::SupportsPause() const noexcept { - return plugin.pause != nullptr; + return output->plugin.pause != nullptr; } void FilteredAudioOutput::Enable() { try { - ao_plugin_enable(*this); + ao_plugin_enable(*output); } catch (const std::runtime_error &e) { std::throw_with_nested(FormatRuntimeError("Failed to enable output %s", GetLogName())); @@ -56,7 +57,7 @@ FilteredAudioOutput::Enable() void FilteredAudioOutput::Disable() noexcept { - ao_plugin_disable(*this); + ao_plugin_disable(*output); } void @@ -76,7 +77,7 @@ FilteredAudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format) out_audio_format = desired_audio_format; try { - ao_plugin_open(*this, out_audio_format); + ao_plugin_open(*output, out_audio_format); } catch (const std::runtime_error &e) { std::throw_with_nested(FormatRuntimeError("Failed to open %s", GetLogName())); @@ -90,7 +91,7 @@ FilteredAudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format) try { ConfigureConvertFilter(); } catch (const std::runtime_error &e) { - ao_plugin_close(*this); + ao_plugin_close(*output); if (out_audio_format.format == SampleFormat::DSD) { /* if the audio output supports DSD, but not @@ -119,7 +120,7 @@ FilteredAudioOutput::CloseOutput(bool drain) noexcept else Cancel(); - ao_plugin_close(*this); + ao_plugin_close(*output); } void @@ -148,31 +149,31 @@ FilteredAudioOutput::Close(bool drain) noexcept std::chrono::steady_clock::duration FilteredAudioOutput::Delay() noexcept { - return ao_plugin_delay(*this); + return ao_plugin_delay(*output); } void FilteredAudioOutput::SendTag(const Tag &tag) { - ao_plugin_send_tag(*this, tag); + ao_plugin_send_tag(*output, tag); } size_t FilteredAudioOutput::Play(const void *data, size_t size) { - return ao_plugin_play(*this, data, size); + return ao_plugin_play(*output, data, size); } void FilteredAudioOutput::Drain() { - ao_plugin_drain(*this); + ao_plugin_drain(*output); } void FilteredAudioOutput::Cancel() noexcept { - ao_plugin_cancel(*this); + ao_plugin_cancel(*output); } void @@ -185,7 +186,7 @@ bool FilteredAudioOutput::IteratePause() noexcept { try { - return ao_plugin_pause(*this); + return ao_plugin_pause(*output); } catch (const std::runtime_error &e) { FormatError(e, "Failed to pause %s", GetLogName()); diff --git a/src/output/Filtered.hxx b/src/output/Filtered.hxx index ed1f6ccb7..937ad9c75 100644 --- a/src/output/Filtered.hxx +++ b/src/output/Filtered.hxx @@ -33,7 +33,7 @@ class Mixer; class MixerListener; struct MusicChunk; struct ConfigBlock; -struct AudioOutputPlugin; +struct AudioOutput; struct ReplayGainConfig; struct Tag; @@ -54,7 +54,7 @@ public: /** * The plugin which implements this output device. */ - const AudioOutputPlugin &plugin; + AudioOutput *const output; /** * The #mixer object associated with this audio output device. @@ -120,18 +120,11 @@ public: /** * Throws #std::runtime_error on error. */ - FilteredAudioOutput(const AudioOutputPlugin &_plugin, + FilteredAudioOutput(AudioOutput &_output, const ConfigBlock &block); ~FilteredAudioOutput(); - /** - * Plugins shall call this method if they require an - * "audio_format" setting which evaluates - * AudioFormat::IsFullyDefined(). - */ - void NeedFullyDefinedAudioFormat(); - private: void Configure(const ConfigBlock &block); diff --git a/src/output/Finish.cxx b/src/output/Finish.cxx index b5729fd29..9db4d50fe 100644 --- a/src/output/Finish.cxx +++ b/src/output/Finish.cxx @@ -31,6 +31,8 @@ FilteredAudioOutput::~FilteredAudioOutput() delete prepared_replay_gain_filter; delete prepared_other_replay_gain_filter; delete prepared_filter; + + ao_plugin_finish(output); } void @@ -43,5 +45,5 @@ FilteredAudioOutput::BeginDestroy() noexcept void FilteredAudioOutput::FinishDestroy() noexcept { - ao_plugin_finish(this); + ao_plugin_finish(output); } diff --git a/src/output/Init.cxx b/src/output/Init.cxx index 3d042ae9c..5d1b58574 100644 --- a/src/output/Init.cxx +++ b/src/output/Init.cxx @@ -50,25 +50,21 @@ #define AUDIO_OUTPUT_FORMAT "format" #define AUDIO_FILTERS "filters" -FilteredAudioOutput::FilteredAudioOutput(const AudioOutputPlugin &_plugin, +FilteredAudioOutput::FilteredAudioOutput(AudioOutput &_output, const ConfigBlock &block) - :plugin(_plugin) + :output(&_output) { +#ifndef NDEBUG + const auto &plugin = output->plugin; assert(plugin.finish != nullptr); assert(plugin.open != nullptr); assert(plugin.close != nullptr); assert(plugin.play != nullptr); +#endif Configure(block); } -void -FilteredAudioOutput::NeedFullyDefinedAudioFormat() -{ - if (!config_audio_format.IsFullyDefined()) - throw std::runtime_error("Need full audio format specification"); -} - static const AudioOutputPlugin * audio_output_detect() { @@ -176,7 +172,7 @@ FilteredAudioOutput::Configure(const ConfigBlock &block) { char buffer[64]; snprintf(buffer, sizeof(buffer), "\"%s\" (%s)", - name, plugin.name); + name, output->plugin.name); log_name = buffer; } @@ -211,6 +207,9 @@ FilteredAudioOutput::Setup(EventLoop &event_loop, MixerListener &mixer_listener, const ConfigBlock &block) { + if (output->need_fully_defined_audio_format && + !config_audio_format.IsFullyDefined()) + throw std::runtime_error("Need full audio format specification"); /* create the replay_gain filter */ @@ -234,7 +233,7 @@ FilteredAudioOutput::Setup(EventLoop &event_loop, try { mixer = audio_output_load_mixer(event_loop, *this, block, - plugin.mixer_plugin, + output->plugin.mixer_plugin, *prepared_filter, mixer_listener); } catch (const std::runtime_error &e) { @@ -295,13 +294,22 @@ audio_output_new(EventLoop &event_loop, auto *ao = ao_plugin_init(event_loop, *plugin, block); assert(ao != nullptr); + FilteredAudioOutput *f; + try { - ao->Setup(event_loop, replay_gain_config, - mixer_listener, block); + f = new FilteredAudioOutput(*ao, block); } catch (...) { ao_plugin_finish(ao); throw; } - return ao; + try { + f->Setup(event_loop, replay_gain_config, + mixer_listener, block); + } catch (...) { + delete f; + throw; + } + + return f; } diff --git a/src/output/Interface.hxx b/src/output/Interface.hxx new file mode 100644 index 000000000..f6b939178 --- /dev/null +++ b/src/output/Interface.hxx @@ -0,0 +1,49 @@ +/* + * Copyright 2003-2017 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_AUDIO_OUTPUT_INTERFACE_HXX +#define MPD_AUDIO_OUTPUT_INTERFACE_HXX + +struct AudioOutputPlugin; +struct FilteredAudioOutput; + +struct AudioOutput { + /** + * The plugin which implements this output device. + */ + const AudioOutputPlugin &plugin; + + FilteredAudioOutput *parent; + + bool need_fully_defined_audio_format = false; + + AudioOutput(const AudioOutputPlugin &_plugin) + :plugin(_plugin) {} + + /** + * Plugins shall call this method if they require an + * "audio_format" setting which evaluates + * AudioFormat::IsFullyDefined(). + */ + void NeedFullyDefinedAudioFormat() { + need_fully_defined_audio_format = true; + } +}; + +#endif diff --git a/src/output/OutputAPI.hxx b/src/output/OutputAPI.hxx index beef09d08..fd6913e0a 100644 --- a/src/output/OutputAPI.hxx +++ b/src/output/OutputAPI.hxx @@ -23,7 +23,7 @@ // IWYU pragma: begin_exports #include "OutputPlugin.hxx" -#include "Filtered.hxx" +#include "Interface.hxx" #include "AudioFormat.hxx" #include "tag/Tag.hxx" #include "config/Block.hxx" diff --git a/src/output/OutputPlugin.cxx b/src/output/OutputPlugin.cxx index f69c52d23..52ce3c3d2 100644 --- a/src/output/OutputPlugin.cxx +++ b/src/output/OutputPlugin.cxx @@ -19,9 +19,11 @@ #include "config.h" #include "OutputPlugin.hxx" -#include "Filtered.hxx" +#include "Interface.hxx" -FilteredAudioOutput * +#include <assert.h> + +AudioOutput * ao_plugin_init(EventLoop &event_loop, const AudioOutputPlugin &plugin, const ConfigBlock &block) @@ -32,39 +34,39 @@ ao_plugin_init(EventLoop &event_loop, } void -ao_plugin_finish(FilteredAudioOutput *ao) noexcept +ao_plugin_finish(AudioOutput *ao) noexcept { ao->plugin.finish(ao); } void -ao_plugin_enable(FilteredAudioOutput &ao) +ao_plugin_enable(AudioOutput &ao) { if (ao.plugin.enable != nullptr) ao.plugin.enable(&ao); } void -ao_plugin_disable(FilteredAudioOutput &ao) noexcept +ao_plugin_disable(AudioOutput &ao) noexcept { if (ao.plugin.disable != nullptr) ao.plugin.disable(&ao); } void -ao_plugin_open(FilteredAudioOutput &ao, AudioFormat &audio_format) +ao_plugin_open(AudioOutput &ao, AudioFormat &audio_format) { ao.plugin.open(&ao, audio_format); } void -ao_plugin_close(FilteredAudioOutput &ao) noexcept +ao_plugin_close(AudioOutput &ao) noexcept { ao.plugin.close(&ao); } std::chrono::steady_clock::duration -ao_plugin_delay(FilteredAudioOutput &ao) noexcept +ao_plugin_delay(AudioOutput &ao) noexcept { return ao.plugin.delay != nullptr ? ao.plugin.delay(&ao) @@ -72,34 +74,34 @@ ao_plugin_delay(FilteredAudioOutput &ao) noexcept } void -ao_plugin_send_tag(FilteredAudioOutput &ao, const Tag &tag) +ao_plugin_send_tag(AudioOutput &ao, const Tag &tag) { if (ao.plugin.send_tag != nullptr) ao.plugin.send_tag(&ao, tag); } size_t -ao_plugin_play(FilteredAudioOutput &ao, const void *chunk, size_t size) +ao_plugin_play(AudioOutput &ao, const void *chunk, size_t size) { return ao.plugin.play(&ao, chunk, size); } void -ao_plugin_drain(FilteredAudioOutput &ao) +ao_plugin_drain(AudioOutput &ao) { if (ao.plugin.drain != nullptr) ao.plugin.drain(&ao); } void -ao_plugin_cancel(FilteredAudioOutput &ao) noexcept +ao_plugin_cancel(AudioOutput &ao) noexcept { if (ao.plugin.cancel != nullptr) ao.plugin.cancel(&ao); } bool -ao_plugin_pause(FilteredAudioOutput &ao) +ao_plugin_pause(AudioOutput &ao) { return ao.plugin.pause != nullptr && ao.plugin.pause(&ao); } diff --git a/src/output/OutputPlugin.hxx b/src/output/OutputPlugin.hxx index bea770b94..5ce52e15c 100644 --- a/src/output/OutputPlugin.hxx +++ b/src/output/OutputPlugin.hxx @@ -29,7 +29,7 @@ struct ConfigBlock; struct AudioFormat; struct Tag; -struct FilteredAudioOutput; +struct AudioOutput; struct MixerPlugin; class EventLoop; @@ -57,12 +57,12 @@ struct AudioOutputPlugin { * @param param the configuration section, or nullptr if there is * no configuration */ - FilteredAudioOutput *(*init)(EventLoop &event_loop, const ConfigBlock &block); + AudioOutput *(*init)(EventLoop &event_loop, const ConfigBlock &block); /** * Free resources allocated by this device. */ - void (*finish)(FilteredAudioOutput *data); + void (*finish)(AudioOutput *data); /** * Enable the device. This may allocate resources, preparing @@ -70,13 +70,13 @@ struct AudioOutputPlugin { * * Throws #std::runtime_error on error. */ - void (*enable)(FilteredAudioOutput *data); + void (*enable)(AudioOutput *data); /** * Disables the device. It is closed before this method is * called. */ - void (*disable)(FilteredAudioOutput *data); + void (*disable)(AudioOutput *data); /** * Really open the device. @@ -86,12 +86,12 @@ struct AudioOutputPlugin { * @param audio_format the audio format in which data is going * to be delivered; may be modified by the plugin */ - void (*open)(FilteredAudioOutput *data, AudioFormat &audio_format); + void (*open)(AudioOutput *data, AudioFormat &audio_format); /** * Close the device. */ - void (*close)(FilteredAudioOutput *data); + void (*close)(AudioOutput *data); /** * Returns a positive number if the output thread shall further @@ -102,13 +102,13 @@ struct AudioOutputPlugin { * * @return the duration to wait */ - std::chrono::steady_clock::duration (*delay)(FilteredAudioOutput *data) noexcept; + std::chrono::steady_clock::duration (*delay)(AudioOutput *data) noexcept; /** * Display metadata for the next chunk. Optional method, * because not all devices can display metadata. */ - void (*send_tag)(FilteredAudioOutput *data, const Tag &tag); + void (*send_tag)(AudioOutput *data, const Tag &tag); /** * Play a chunk of audio data. @@ -117,19 +117,19 @@ struct AudioOutputPlugin { * * @return the number of bytes played */ - size_t (*play)(FilteredAudioOutput *data, + size_t (*play)(AudioOutput *data, const void *chunk, size_t size); /** * Wait until the device has finished playing. */ - void (*drain)(FilteredAudioOutput *data); + void (*drain)(AudioOutput *data); /** * Try to cancel data which may still be in the device's * buffers. */ - void (*cancel)(FilteredAudioOutput *data); + void (*cancel)(AudioOutput *data); /** * Pause the device. If supported, it may perform a special @@ -142,7 +142,7 @@ struct AudioOutputPlugin { * @return false on error (output will be closed by caller), * true for continue to pause */ - bool (*pause)(FilteredAudioOutput *data); + bool (*pause)(AudioOutput *data); /** * The mixer plugin associated with this output plugin. This @@ -162,43 +162,43 @@ ao_plugin_test_default_device(const AudioOutputPlugin *plugin) } gcc_malloc -FilteredAudioOutput * +AudioOutput * ao_plugin_init(EventLoop &event_loop, const AudioOutputPlugin &plugin, const ConfigBlock &block); void -ao_plugin_finish(FilteredAudioOutput *ao) noexcept; +ao_plugin_finish(AudioOutput *ao) noexcept; void -ao_plugin_enable(FilteredAudioOutput &ao); +ao_plugin_enable(AudioOutput &ao); void -ao_plugin_disable(FilteredAudioOutput &ao) noexcept; +ao_plugin_disable(AudioOutput &ao) noexcept; void -ao_plugin_open(FilteredAudioOutput &ao, AudioFormat &audio_format); +ao_plugin_open(AudioOutput &ao, AudioFormat &audio_format); void -ao_plugin_close(FilteredAudioOutput &ao) noexcept; +ao_plugin_close(AudioOutput &ao) noexcept; gcc_pure std::chrono::steady_clock::duration -ao_plugin_delay(FilteredAudioOutput &ao) noexcept; +ao_plugin_delay(AudioOutput &ao) noexcept; void -ao_plugin_send_tag(FilteredAudioOutput &ao, const Tag &tag); +ao_plugin_send_tag(AudioOutput &ao, const Tag &tag); size_t -ao_plugin_play(FilteredAudioOutput &ao, const void *chunk, size_t size); +ao_plugin_play(AudioOutput &ao, const void *chunk, size_t size); void -ao_plugin_drain(FilteredAudioOutput &ao); +ao_plugin_drain(AudioOutput &ao); void -ao_plugin_cancel(FilteredAudioOutput &ao) noexcept; +ao_plugin_cancel(AudioOutput &ao) noexcept; bool -ao_plugin_pause(FilteredAudioOutput &ao); +ao_plugin_pause(AudioOutput &ao); #endif diff --git a/src/output/Wrapper.hxx b/src/output/Wrapper.hxx index 96882ad81..ac3e9f168 100644 --- a/src/output/Wrapper.hxx +++ b/src/output/Wrapper.hxx @@ -20,78 +20,79 @@ #ifndef MPD_OUTPUT_WRAPPER_HXX #define MPD_OUTPUT_WRAPPER_HXX -#include "Filtered.hxx" +#include "Interface.hxx" #include "util/Cast.hxx" #include <chrono> struct ConfigBlock; +struct AudioFormat; struct Tag; template<class T> struct AudioOutputWrapper { - static T &Cast(FilteredAudioOutput &ao) { + static T &Cast(AudioOutput &ao) { return ContainerCast(ao, &T::base); } - static FilteredAudioOutput *Init(EventLoop &event_loop, + static AudioOutput *Init(EventLoop &event_loop, const ConfigBlock &block) { T *t = T::Create(event_loop, block); return &t->base; } - static void Finish(FilteredAudioOutput *ao) { + static void Finish(AudioOutput *ao) { T *t = &Cast(*ao); delete t; } - static void Enable(FilteredAudioOutput *ao) { + static void Enable(AudioOutput *ao) { T &t = Cast(*ao); t.Enable(); } - static void Disable(FilteredAudioOutput *ao) { + static void Disable(AudioOutput *ao) { T &t = Cast(*ao); t.Disable(); } - static void Open(FilteredAudioOutput *ao, AudioFormat &audio_format) { + static void Open(AudioOutput *ao, AudioFormat &audio_format) { T &t = Cast(*ao); t.Open(audio_format); } - static void Close(FilteredAudioOutput *ao) { + static void Close(AudioOutput *ao) { T &t = Cast(*ao); t.Close(); } gcc_pure - static std::chrono::steady_clock::duration Delay(FilteredAudioOutput *ao) noexcept { + static std::chrono::steady_clock::duration Delay(AudioOutput *ao) noexcept { T &t = Cast(*ao); return t.Delay(); } - static void SendTag(FilteredAudioOutput *ao, const Tag &tag) { + static void SendTag(AudioOutput *ao, const Tag &tag) { T &t = Cast(*ao); t.SendTag(tag); } - static size_t Play(FilteredAudioOutput *ao, const void *chunk, size_t size) { + static size_t Play(AudioOutput *ao, const void *chunk, size_t size) { T &t = Cast(*ao); return t.Play(chunk, size); } - static void Drain(FilteredAudioOutput *ao) { + static void Drain(AudioOutput *ao) { T &t = Cast(*ao); t.Drain(); } - static void Cancel(FilteredAudioOutput *ao) { + static void Cancel(AudioOutput *ao) { T &t = Cast(*ao); t.Cancel(); } - static bool Pause(FilteredAudioOutput *ao) { + static bool Pause(AudioOutput *ao) { T &t = Cast(*ao); return t.Pause(); } diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index 1d3d24869..b1b44b8bc 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -64,7 +64,7 @@ class AlsaOutput final friend struct AudioOutputWrapper<AlsaOutput>; - FilteredAudioOutput base; + AudioOutput base; Manual<PcmExport> pcm_export; @@ -414,7 +414,7 @@ static constexpr Domain alsa_output_domain("alsa_output"); AlsaOutput::AlsaOutput(EventLoop &loop, const ConfigBlock &block) :MultiSocketMonitor(loop), DeferredMonitor(loop), - base(alsa_output_plugin, block), + base(alsa_output_plugin), device(block.GetBlockValue("device", "")), #ifdef ENABLE_DSD dop(block.GetBlockValue("dop", false) || diff --git a/src/output/plugins/AoOutputPlugin.cxx b/src/output/plugins/AoOutputPlugin.cxx index 0be06acd0..ed8b359aa 100644 --- a/src/output/plugins/AoOutputPlugin.cxx +++ b/src/output/plugins/AoOutputPlugin.cxx @@ -40,7 +40,7 @@ static unsigned ao_output_ref; class AoOutput { friend struct AudioOutputWrapper<AoOutput>; - FilteredAudioOutput base; + AudioOutput base; const size_t write_size; int driver; @@ -95,7 +95,7 @@ MakeAoError() } AoOutput::AoOutput(const ConfigBlock &block) - :base(ao_output_plugin, block), + :base(ao_output_plugin), write_size(block.GetBlockValue("write_size", 1024u)) { if (ao_output_ref == 0) { diff --git a/src/output/plugins/FifoOutputPlugin.cxx b/src/output/plugins/FifoOutputPlugin.cxx index c001e2195..788ad85e6 100644 --- a/src/output/plugins/FifoOutputPlugin.cxx +++ b/src/output/plugins/FifoOutputPlugin.cxx @@ -37,7 +37,7 @@ class FifoOutput { friend struct AudioOutputWrapper<FifoOutput>; - FilteredAudioOutput base; + AudioOutput base; const AllocatedPath path; std::string path_utf8; @@ -75,7 +75,7 @@ public: static constexpr Domain fifo_output_domain("fifo_output"); FifoOutput::FifoOutput(const ConfigBlock &block) - :base(fifo_output_plugin, block), + :base(fifo_output_plugin), path(block.GetPath("path")) { if (path.IsNull()) diff --git a/src/output/plugins/HaikuOutputPlugin.cxx b/src/output/plugins/HaikuOutputPlugin.cxx index d6b8c5b2e..bb8d9a378 100644 --- a/src/output/plugins/HaikuOutputPlugin.cxx +++ b/src/output/plugins/HaikuOutputPlugin.cxx @@ -48,7 +48,7 @@ class HaikuOutput { friend int haiku_output_get_volume(HaikuOutput &haiku); friend bool haiku_output_set_volume(HaikuOutput &haiku, unsigned volume); - FilteredAudioOutput base; + AudioOutput base; size_t write_size; @@ -66,7 +66,7 @@ class HaikuOutput { public: HaikuOutput(const ConfigBlock &block) - :base(haiku_output_plugin, block), + :base(haiku_output_plugin), /* XXX: by default we should let the MediaKit propose the buffer size */ write_size(block.GetBlockValue("write_size", 4096u)) {} diff --git a/src/output/plugins/JackOutputPlugin.cxx b/src/output/plugins/JackOutputPlugin.cxx index 770de3fdb..e1884a95c 100644 --- a/src/output/plugins/JackOutputPlugin.cxx +++ b/src/output/plugins/JackOutputPlugin.cxx @@ -43,7 +43,7 @@ static constexpr unsigned MAX_PORTS = 16; static constexpr size_t jack_sample_size = sizeof(jack_default_audio_sample_t); struct JackOutput { - FilteredAudioOutput base; + AudioOutput base; /** * libjack options passed to jack_client_open(). @@ -162,7 +162,7 @@ parse_port_list(const char *source, std::string dest[]) } JackOutput::JackOutput(const ConfigBlock &block) - :base(jack_output_plugin, block), + :base(jack_output_plugin), name(block.GetBlockValue("client_name", nullptr)), server_name(block.GetBlockValue("server_name", nullptr)) { @@ -443,7 +443,7 @@ JackOutput::Disable() } } -static FilteredAudioOutput * +static AudioOutput * mpd_jack_init(EventLoop &, const ConfigBlock &block) { jack_set_error_function(mpd_jack_error); diff --git a/src/output/plugins/NullOutputPlugin.cxx b/src/output/plugins/NullOutputPlugin.cxx index 4603e16df..4b28751d5 100644 --- a/src/output/plugins/NullOutputPlugin.cxx +++ b/src/output/plugins/NullOutputPlugin.cxx @@ -26,7 +26,7 @@ class NullOutput { friend struct AudioOutputWrapper<NullOutput>; - FilteredAudioOutput base; + AudioOutput base; const bool sync; @@ -34,7 +34,7 @@ class NullOutput { public: NullOutput(const ConfigBlock &block) - :base(null_output_plugin, block), + :base(null_output_plugin), sync(block.GetBlockValue("sync", true)) {} static NullOutput *Create(EventLoop &event_loop, diff --git a/src/output/plugins/OSXOutputPlugin.cxx b/src/output/plugins/OSXOutputPlugin.cxx index c619d2ec5..03c1bc6f1 100644 --- a/src/output/plugins/OSXOutputPlugin.cxx +++ b/src/output/plugins/OSXOutputPlugin.cxx @@ -36,7 +36,7 @@ #include <memory> struct OSXOutput { - FilteredAudioOutput base; + AudioOutput base; /* configuration settings */ OSType component_subtype; @@ -80,7 +80,7 @@ osx_output_test_default_device(void) } OSXOutput::OSXOutput(const ConfigBlock &block) - :base(osx_output_plugin, block) + :base(osx_output_plugin) { const char *device = block.GetBlockValue("device"); @@ -103,7 +103,7 @@ OSXOutput::OSXOutput(const ConfigBlock &block) sync_sample_rate = block.GetBlockValue("sync_sample_rate", false); } -static FilteredAudioOutput * +static AudioOutput * osx_output_init(EventLoop &, const ConfigBlock &block) { OSXOutput *oo = new OSXOutput(block); @@ -128,7 +128,7 @@ osx_output_init(EventLoop &, const ConfigBlock &block) } static void -osx_output_finish(FilteredAudioOutput *ao) +osx_output_finish(AudioOutput *ao) { OSXOutput *oo = (OSXOutput *)ao; @@ -514,7 +514,7 @@ osx_render(void *vdata, } static void -osx_output_enable(FilteredAudioOutput *ao) +osx_output_enable(AudioOutput *ao) { char errormsg[1024]; OSXOutput *oo = (OSXOutput *)ao; @@ -550,7 +550,7 @@ osx_output_enable(FilteredAudioOutput *ao) } static void -osx_output_disable(FilteredAudioOutput *ao) +osx_output_disable(AudioOutput *ao) { OSXOutput *oo = (OSXOutput *)ao; @@ -562,7 +562,7 @@ osx_output_disable(FilteredAudioOutput *ao) } static void -osx_output_close(FilteredAudioOutput *ao) +osx_output_close(AudioOutput *ao) { OSXOutput *od = (OSXOutput *)ao; @@ -573,7 +573,7 @@ osx_output_close(FilteredAudioOutput *ao) } static void -osx_output_open(FilteredAudioOutput *ao, AudioFormat &audio_format) +osx_output_open(AudioOutput *ao, AudioFormat &audio_format) { char errormsg[1024]; OSXOutput *od = (OSXOutput *)ao; @@ -663,14 +663,14 @@ osx_output_open(FilteredAudioOutput *ao, AudioFormat &audio_format) } static size_t -osx_output_play(FilteredAudioOutput *ao, const void *chunk, size_t size) +osx_output_play(AudioOutput *ao, const void *chunk, size_t size) { OSXOutput *od = (OSXOutput *)ao; return od->ring_buffer->push((uint8_t *)chunk, size); } static std::chrono::steady_clock::duration -osx_output_delay(FilteredAudioOutput *ao) noexcept +osx_output_delay(AudioOutput *ao) noexcept { OSXOutput *od = (OSXOutput *)ao; return od->ring_buffer->write_available() diff --git a/src/output/plugins/OpenALOutputPlugin.cxx b/src/output/plugins/OpenALOutputPlugin.cxx index 79d7c165e..0bdd98038 100644 --- a/src/output/plugins/OpenALOutputPlugin.cxx +++ b/src/output/plugins/OpenALOutputPlugin.cxx @@ -39,7 +39,7 @@ class OpenALOutput { /* should be enough for buffer size = 2048 */ static constexpr unsigned NUM_BUFFERS = 16; - FilteredAudioOutput base; + AudioOutput base; const char *device_name; ALCdevice *device; @@ -138,7 +138,7 @@ OpenALOutput::SetupContext() } OpenALOutput::OpenALOutput(const ConfigBlock &block) - :base(openal_output_plugin, block), + :base(openal_output_plugin), device_name(block.GetBlockValue("device")) { if (device_name == nullptr) diff --git a/src/output/plugins/OssOutputPlugin.cxx b/src/output/plugins/OssOutputPlugin.cxx index b5fe87461..6581237fa 100644 --- a/src/output/plugins/OssOutputPlugin.cxx +++ b/src/output/plugins/OssOutputPlugin.cxx @@ -63,7 +63,7 @@ class OssOutput { friend struct AudioOutputWrapper<OssOutput>; - FilteredAudioOutput base; + AudioOutput base; #ifdef AFMT_S24_PACKED Manual<PcmExport> pcm_export; @@ -85,8 +85,8 @@ class OssOutput { int oss_format; public: - OssOutput(const ConfigBlock &block, const char *_device=nullptr) - :base(oss_output_plugin, block), + explicit OssOutput(const char *_device=nullptr) + :base(oss_output_plugin), fd(-1), device(_device) {} static OssOutput *Create(EventLoop &event_loop, @@ -192,11 +192,10 @@ oss_open_default() int err[ARRAY_SIZE(default_devices)]; enum oss_stat ret[ARRAY_SIZE(default_devices)]; - const ConfigBlock empty; for (int i = ARRAY_SIZE(default_devices); --i >= 0; ) { ret[i] = oss_stat_device(default_devices[i], &err[i]); if (ret[i] == OSS_STAT_NO_ERROR) - return new OssOutput(empty, default_devices[i]); + return new OssOutput(default_devices[i]); } for (int i = ARRAY_SIZE(default_devices); --i >= 0; ) { @@ -231,7 +230,7 @@ OssOutput::Create(EventLoop &, const ConfigBlock &block) { const char *device = block.GetBlockValue("device"); if (device != nullptr) - return new OssOutput(block, device); + return new OssOutput(device); return oss_open_default(); } diff --git a/src/output/plugins/PipeOutputPlugin.cxx b/src/output/plugins/PipeOutputPlugin.cxx index 455b16fab..b0f7f6492 100644 --- a/src/output/plugins/PipeOutputPlugin.cxx +++ b/src/output/plugins/PipeOutputPlugin.cxx @@ -31,7 +31,7 @@ class PipeOutput { friend struct AudioOutputWrapper<PipeOutput>; - FilteredAudioOutput base; + AudioOutput base; const std::string cmd; FILE *fh; @@ -52,7 +52,7 @@ public: }; PipeOutput::PipeOutput(const ConfigBlock &block) - :base(pipe_output_plugin, block), + :base(pipe_output_plugin), cmd(block.GetBlockValue("command", "")) { if (cmd.empty()) diff --git a/src/output/plugins/PulseOutputPlugin.cxx b/src/output/plugins/PulseOutputPlugin.cxx index cd1f4c97b..da18bfc4b 100644 --- a/src/output/plugins/PulseOutputPlugin.cxx +++ b/src/output/plugins/PulseOutputPlugin.cxx @@ -47,7 +47,7 @@ class PulseOutput { friend struct AudioOutputWrapper<PulseOutput>; - FilteredAudioOutput base; + AudioOutput base; const char *name; const char *server; @@ -179,7 +179,7 @@ private: }; PulseOutput::PulseOutput(const ConfigBlock &block) - :base(pulse_output_plugin, block), + :base(pulse_output_plugin), name(block.GetBlockValue("name", "mpd_pulse")), server(block.GetBlockValue("server")), sink(block.GetBlockValue("sink")) diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx index 075abf472..a57a54773 100644 --- a/src/output/plugins/RecorderOutputPlugin.cxx +++ b/src/output/plugins/RecorderOutputPlugin.cxx @@ -45,7 +45,7 @@ static constexpr Domain recorder_domain("recorder"); class RecorderOutput { friend struct AudioOutputWrapper<RecorderOutput>; - FilteredAudioOutput base; + AudioOutput base; /** * The configured encoder plugin. @@ -114,7 +114,7 @@ private: }; RecorderOutput::RecorderOutput(const ConfigBlock &block) - :base(recorder_output_plugin, block) + :base(recorder_output_plugin) { /* read configuration */ diff --git a/src/output/plugins/RoarOutputPlugin.cxx b/src/output/plugins/RoarOutputPlugin.cxx index 4963cf9f7..6f0a31d22 100644 --- a/src/output/plugins/RoarOutputPlugin.cxx +++ b/src/output/plugins/RoarOutputPlugin.cxx @@ -39,7 +39,7 @@ class RoarOutput { friend struct AudioOutputWrapper<RoarOutput>; - FilteredAudioOutput base; + AudioOutput base; const std::string host, name; @@ -54,7 +54,7 @@ class RoarOutput { public: RoarOutput(const ConfigBlock &block); - operator FilteredAudioOutput *() { + operator AudioOutput *() { return &base; } @@ -86,7 +86,7 @@ GetConfiguredRole(const ConfigBlock &block) noexcept } RoarOutput::RoarOutput(const ConfigBlock &block) - :base(roar_output_plugin, block), + :base(roar_output_plugin), host(block.GetBlockValue("server", "")), name(block.GetBlockValue("name", "MPD")), role(GetConfiguredRole(block)) diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx index de8722982..ecde49c81 100644 --- a/src/output/plugins/ShoutOutputPlugin.cxx +++ b/src/output/plugins/ShoutOutputPlugin.cxx @@ -40,7 +40,7 @@ static constexpr unsigned DEFAULT_CONN_TIMEOUT = 2; struct ShoutOutput final { - FilteredAudioOutput base; + AudioOutput base; shout_t *shout_conn; shout_metadata_t *shout_meta; @@ -113,7 +113,7 @@ ShoutSetAudioInfo(shout_t *shout_conn, const AudioFormat &audio_format) } ShoutOutput::ShoutOutput(const ConfigBlock &block) - :base(shout_output_plugin, block), + :base(shout_output_plugin), shout_conn(shout_new()), shout_meta(shout_metadata_new()) { diff --git a/src/output/plugins/SndioOutputPlugin.cxx b/src/output/plugins/SndioOutputPlugin.cxx index a0d7a3e48..7fa48fc1a 100644 --- a/src/output/plugins/SndioOutputPlugin.cxx +++ b/src/output/plugins/SndioOutputPlugin.cxx @@ -47,7 +47,7 @@ static constexpr Domain sndio_output_domain("sndio_output"); class SndioOutput { friend struct AudioOutputWrapper<SndioOutput>; - FilteredAudioOutput base; + AudioOutput base; const char *const device; const unsigned buffer_time; /* in ms */ struct sio_hdl *sio_hdl; @@ -65,7 +65,7 @@ public: }; SndioOutput::SndioOutput(const ConfigBlock &block) - :base(sndio_output_plugin, block), + :base(sndio_output_plugin), device(block.GetBlockValue("device", SIO_DEVANY)), buffer_time(block.GetBlockValue("buffer_time", MPD_SNDIO_BUFFER_TIME_MS)) diff --git a/src/output/plugins/SolarisOutputPlugin.cxx b/src/output/plugins/SolarisOutputPlugin.cxx index ae4e71ff8..438ebd765 100644 --- a/src/output/plugins/SolarisOutputPlugin.cxx +++ b/src/output/plugins/SolarisOutputPlugin.cxx @@ -53,7 +53,7 @@ struct audio_info { class SolarisOutput { friend struct AudioOutputWrapper<SolarisOutput>; - FilteredAudioOutput base; + AudioOutput base; /* configuration */ const char *const device; @@ -61,7 +61,7 @@ class SolarisOutput { int fd; explicit SolarisOutput(const ConfigBlock &block) - :base(solaris_output_plugin, block), + :base(solaris_output_plugin), device(block.GetBlockValue("device", "/dev/audio")) {} public: diff --git a/src/output/plugins/WinmmOutputPlugin.cxx b/src/output/plugins/WinmmOutputPlugin.cxx index 0a335eeaf..25372edf7 100644 --- a/src/output/plugins/WinmmOutputPlugin.cxx +++ b/src/output/plugins/WinmmOutputPlugin.cxx @@ -42,7 +42,7 @@ struct WinmmBuffer { class WinmmOutput { friend struct AudioOutputWrapper<WinmmOutput>; - FilteredAudioOutput base; + AudioOutput base; const UINT device_id; HWAVEOUT handle; @@ -148,7 +148,7 @@ get_device_id(const char *device_name) } WinmmOutput::WinmmOutput(const ConfigBlock &block) - :base(winmm_output_plugin, block), + :base(winmm_output_plugin), device_id(get_device_id(block.GetBlockValue("device"))) { } diff --git a/src/output/plugins/httpd/HttpdInternal.hxx b/src/output/plugins/httpd/HttpdInternal.hxx index 7ad0a1325..45b6edde6 100644 --- a/src/output/plugins/httpd/HttpdInternal.hxx +++ b/src/output/plugins/httpd/HttpdInternal.hxx @@ -52,7 +52,7 @@ struct Tag; class HttpdOutput final : ServerSocket, DeferredMonitor { friend struct AudioOutputWrapper<HttpdOutput>; - FilteredAudioOutput base; + AudioOutput base; /** * True if the audio output is open and accepts client @@ -160,7 +160,7 @@ public: static HttpdOutput *Create(EventLoop &event_loop, const ConfigBlock &block); - static constexpr HttpdOutput *Cast(FilteredAudioOutput *ao) { + static constexpr HttpdOutput *Cast(AudioOutput *ao) { return &ContainerCast(*ao, &HttpdOutput::base); } diff --git a/src/output/plugins/httpd/HttpdOutputPlugin.cxx b/src/output/plugins/httpd/HttpdOutputPlugin.cxx index 6836dc09a..e65a6982d 100644 --- a/src/output/plugins/httpd/HttpdOutputPlugin.cxx +++ b/src/output/plugins/httpd/HttpdOutputPlugin.cxx @@ -51,7 +51,7 @@ const Domain httpd_output_domain("httpd_output"); inline HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block) :ServerSocket(_loop), DeferredMonitor(_loop), - base(httpd_output_plugin, block), + base(httpd_output_plugin), encoder(nullptr), unflushed_input(0), metadata(nullptr) { diff --git a/src/output/plugins/sles/SlesOutputPlugin.cxx b/src/output/plugins/sles/SlesOutputPlugin.cxx index ca47f99a4..279d29c4d 100644 --- a/src/output/plugins/sles/SlesOutputPlugin.cxx +++ b/src/output/plugins/sles/SlesOutputPlugin.cxx @@ -43,7 +43,7 @@ class SlesOutput { static constexpr unsigned N_BUFFERS = 3; static constexpr size_t BUFFER_SIZE = 65536; - FilteredAudioOutput base; + AudioOutput base; SLES::Object engine_object, mix_object, play_object; SLES::Play play; @@ -87,9 +87,9 @@ class SlesOutput { uint8_t buffers[N_BUFFERS][BUFFER_SIZE]; public: - SlesOutput(const ConfigBlock &block); + SlesOutput(); - operator FilteredAudioOutput *() { + operator AudioOutput *() { return &base; } @@ -129,8 +129,8 @@ private: static constexpr Domain sles_domain("sles"); -SlesOutput::SlesOutput(const ConfigBlock &block) - :base(sles_output_plugin, block) +SlesOutput::SlesOutput() + :base(sles_output_plugin) { } @@ -416,9 +416,9 @@ sles_test_default_device() } inline SlesOutput * -SlesOutput::Create(EventLoop &, const ConfigBlock &block) +SlesOutput::Create(EventLoop &, const ConfigBlock &) { - return new SlesOutput(block); + return new SlesOutput(); } typedef AudioOutputWrapper<SlesOutput> Wrapper; diff --git a/test/run_output.cxx b/test/run_output.cxx index a374c4007..2f7f75774 100644 --- a/test/run_output.cxx +++ b/test/run_output.cxx @@ -18,19 +18,17 @@ */ #include "config.h" -#include "output/Filtered.hxx" +#include "output/Interface.hxx" +#include "output/Registry.hxx" #include "output/OutputPlugin.hxx" #include "config/Param.hxx" #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" -#include "Idle.hxx" -#include "Main.hxx" +#include "config/Block.hxx" #include "event/Thread.hxx" #include "fs/Path.hxx" #include "AudioParser.hxx" -#include "ReplayGainConfig.hxx" #include "pcm/PcmConvert.hxx" -#include "filter/FilterRegistry.hxx" #include "util/StringBuffer.hxx" #include "util/RuntimeError.hxx" #include "util/ScopeExit.hxx" @@ -42,28 +40,29 @@ #include <stdlib.h> #include <stdio.h> -const FilterPlugin * -filter_plugin_by_name(gcc_unused const char *name) noexcept -{ - assert(false); - return NULL; -} - -static FilteredAudioOutput * +static AudioOutput * load_audio_output(EventLoop &event_loop, const char *name) { - const auto *param = config_find_block(ConfigBlockOption::AUDIO_OUTPUT, + const auto *block = config_find_block(ConfigBlockOption::AUDIO_OUTPUT, "name", name); - if (param == NULL) - throw FormatRuntimeError("No such configured audio output: %s\n", + if (block == nullptr) + throw FormatRuntimeError("No such configured audio output: %s", name); - return audio_output_new(event_loop, ReplayGainConfig(), *param, - *(MixerListener *)nullptr); + const char *plugin_name = block->GetBlockValue("type"); + if (plugin_name == nullptr) + throw std::runtime_error("Missing \"type\" configuration"); + + const auto *plugin = AudioOutputPlugin_get(plugin_name); + if (plugin == nullptr) + throw FormatRuntimeError("No such audio output plugin: %s", + plugin_name); + + return ao_plugin_init(event_loop, *plugin, *block); } static void -run_output(FilteredAudioOutput &ao, AudioFormat audio_format) +run_output(AudioOutput &ao, AudioFormat audio_format) { /* open the audio output */ @@ -140,8 +139,7 @@ try { /* cleanup and exit */ - ao->BeginDestroy(); - ao->FinishDestroy(); + ao_plugin_finish(ao); config_global_finish(); |