From 68b79f97f331588f29fbf956d53a2e99f70e8b7f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 28 Jan 2014 11:42:54 +0100 Subject: output: rename source files --- Makefile.am | 14 +- src/CommandLine.cxx | 2 +- src/mixer/MixerAll.cxx | 2 +- src/output/Domain.cxx | 23 +++ src/output/Domain.hxx | 25 +++ src/output/Finish.cxx | 51 ++++++ src/output/Init.cxx | 329 +++++++++++++++++++++++++++++++++++ src/output/Internal.hxx | 302 ++++++++++++++++++++++++++++++++ src/output/MultipleOutputs.cxx | 4 +- src/output/OutputAPI.hxx | 2 +- src/output/OutputCommand.cxx | 2 +- src/output/OutputControl.cxx | 4 +- src/output/OutputError.cxx | 23 --- src/output/OutputError.hxx | 25 --- src/output/OutputFinish.cxx | 51 ------ src/output/OutputInit.cxx | 329 ----------------------------------- src/output/OutputInternal.hxx | 302 -------------------------------- src/output/OutputList.cxx | 100 ----------- src/output/OutputList.hxx | 35 ---- src/output/OutputPlugin.cxx | 2 +- src/output/OutputPrint.cxx | 2 +- src/output/OutputState.cxx | 4 +- src/output/OutputThread.cxx | 4 +- src/output/Registry.cxx | 100 +++++++++++ src/output/Registry.hxx | 35 ++++ src/output/plugins/HttpdInternal.hxx | 2 +- test/run_output.cxx | 2 +- 27 files changed, 888 insertions(+), 888 deletions(-) create mode 100644 src/output/Domain.cxx create mode 100644 src/output/Domain.hxx create mode 100644 src/output/Finish.cxx create mode 100644 src/output/Init.cxx create mode 100644 src/output/Internal.hxx delete mode 100644 src/output/OutputError.cxx delete mode 100644 src/output/OutputError.hxx delete mode 100644 src/output/OutputFinish.cxx delete mode 100644 src/output/OutputInit.cxx delete mode 100644 src/output/OutputInternal.hxx delete mode 100644 src/output/OutputList.cxx delete mode 100644 src/output/OutputList.hxx create mode 100644 src/output/Registry.cxx create mode 100644 src/output/Registry.hxx diff --git a/Makefile.am b/Makefile.am index 536bf4105..d50a17264 100644 --- a/Makefile.am +++ b/Makefile.am @@ -960,18 +960,18 @@ OUTPUT_LIBS = \ OUTPUT_API_SRC = \ src/output/OutputAPI.hxx \ - src/output/OutputInternal.hxx \ - src/output/OutputList.cxx src/output/OutputList.hxx \ + src/output/Internal.hxx \ + src/output/Registry.cxx src/output/Registry.hxx \ src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx \ src/output/OutputThread.cxx src/output/OutputThread.hxx \ - src/output/OutputError.cxx src/output/OutputError.hxx \ + src/output/Domain.cxx src/output/Domain.hxx \ src/output/OutputControl.cxx src/output/OutputControl.hxx \ src/output/OutputState.cxx src/output/OutputState.hxx \ src/output/OutputPrint.cxx src/output/OutputPrint.hxx \ src/output/OutputCommand.cxx src/output/OutputCommand.hxx \ src/output/OutputPlugin.cxx src/output/OutputPlugin.hxx \ - src/output/OutputFinish.cxx \ - src/output/OutputInit.cxx + src/output/Finish.cxx \ + src/output/Init.cxx liboutput_plugins_a_SOURCES = \ src/output/plugins/NullOutputPlugin.cxx \ @@ -1590,8 +1590,8 @@ test_run_output_SOURCES = test/run_output.cxx \ src/AudioParser.cxx \ src/Timer.cxx \ src/Page.cxx \ - src/output/OutputError.cxx \ - src/output/OutputInit.cxx src/output/OutputFinish.cxx src/output/OutputList.cxx \ + src/output/Domain.cxx \ + src/output/Init.cxx src/output/Finish.cxx src/output/Registry.cxx \ src/output/OutputPlugin.cxx \ src/mixer/MixerControl.cxx \ src/mixer/MixerType.cxx \ diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx index 19bc9d4bb..5500d43ba 100644 --- a/src/CommandLine.cxx +++ b/src/CommandLine.cxx @@ -27,7 +27,7 @@ #include "db/DatabasePlugin.hxx" #include "decoder/DecoderList.hxx" #include "decoder/DecoderPlugin.hxx" -#include "output/OutputList.hxx" +#include "output/Registry.hxx" #include "output/OutputPlugin.hxx" #include "input/Registry.hxx" #include "input/InputPlugin.hxx" diff --git a/src/mixer/MixerAll.cxx b/src/mixer/MixerAll.cxx index c2fa903f2..ac40bc496 100644 --- a/src/mixer/MixerAll.cxx +++ b/src/mixer/MixerAll.cxx @@ -22,7 +22,7 @@ #include "MixerControl.hxx" #include "MixerInternal.hxx" #include "MixerList.hxx" -#include "output/OutputInternal.hxx" +#include "output/Internal.hxx" #include "pcm/Volume.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" diff --git a/src/output/Domain.cxx b/src/output/Domain.cxx new file mode 100644 index 000000000..878e5f3c5 --- /dev/null +++ b/src/output/Domain.cxx @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003-2014 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 "Domain.hxx" +#include "util/Domain.hxx" + +const Domain output_domain("output"); diff --git a/src/output/Domain.hxx b/src/output/Domain.hxx new file mode 100644 index 000000000..e3a20142f --- /dev/null +++ b/src/output/Domain.hxx @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2014 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_OUTPUT_ERROR_HXX +#define MPD_OUTPUT_ERROR_HXX + +extern const class Domain output_domain; + +#endif diff --git a/src/output/Finish.cxx b/src/output/Finish.cxx new file mode 100644 index 000000000..b3f94fe31 --- /dev/null +++ b/src/output/Finish.cxx @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2003-2014 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 "Internal.hxx" +#include "OutputPlugin.hxx" +#include "mixer/MixerControl.hxx" +#include "filter/FilterInternal.hxx" + +#include + +void +ao_base_finish(AudioOutput *ao) +{ + assert(!ao->open); + assert(!ao->fail_timer.IsDefined()); + assert(!ao->thread.IsDefined()); + + if (ao->mixer != nullptr) + mixer_free(ao->mixer); + + delete ao->replay_gain_filter; + delete ao->other_replay_gain_filter; + delete ao->filter; +} + +void +audio_output_free(AudioOutput *ao) +{ + assert(!ao->open); + assert(!ao->fail_timer.IsDefined()); + assert(!ao->thread.IsDefined()); + + ao_plugin_finish(ao); +} diff --git a/src/output/Init.cxx b/src/output/Init.cxx new file mode 100644 index 000000000..29c7137d9 --- /dev/null +++ b/src/output/Init.cxx @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2003-2014 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 "Internal.hxx" +#include "Registry.hxx" +#include "Domain.hxx" +#include "OutputAPI.hxx" +#include "filter/FilterConfig.hxx" +#include "AudioParser.hxx" +#include "mixer/MixerList.hxx" +#include "mixer/MixerType.hxx" +#include "mixer/MixerControl.hxx" +#include "mixer/plugins/SoftwareMixerPlugin.hxx" +#include "filter/FilterPlugin.hxx" +#include "filter/FilterRegistry.hxx" +#include "filter/plugins/AutoConvertFilterPlugin.hxx" +#include "filter/plugins/ReplayGainFilterPlugin.hxx" +#include "filter/plugins/ChainFilterPlugin.hxx" +#include "config/ConfigError.hxx" +#include "config/ConfigGlobal.hxx" +#include "util/Error.hxx" +#include "Log.hxx" + +#include +#include + +#define AUDIO_OUTPUT_TYPE "type" +#define AUDIO_OUTPUT_NAME "name" +#define AUDIO_OUTPUT_FORMAT "format" +#define AUDIO_FILTERS "filters" + +static const AudioOutputPlugin * +audio_output_detect(Error &error) +{ + LogDefault(output_domain, "Attempt to detect audio output device"); + + audio_output_plugins_for_each(plugin) { + if (plugin->test_default_device == nullptr) + continue; + + FormatDefault(output_domain, + "Attempting to detect a %s audio device", + plugin->name); + if (ao_plugin_test_default_device(plugin)) + return plugin; + } + + error.Set(output_domain, "Unable to detect an audio device"); + return nullptr; +} + +/** + * Determines the mixer type which should be used for the specified + * configuration block. + * + * This handles the deprecated options mixer_type (global) and + * mixer_enabled, if the mixer_type setting is not configured. + */ +gcc_pure +static enum mixer_type +audio_output_mixer_type(const config_param ¶m) +{ + /* read the local "mixer_type" setting */ + const char *p = param.GetBlockValue("mixer_type"); + if (p != nullptr) + return mixer_type_parse(p); + + /* try the local "mixer_enabled" setting next (deprecated) */ + if (!param.GetBlockValue("mixer_enabled", true)) + return MIXER_TYPE_NONE; + + /* fall back to the global "mixer_type" setting (also + deprecated) */ + return mixer_type_parse(config_get_string(CONF_MIXER_TYPE, + "hardware")); +} + +static Mixer * +audio_output_load_mixer(AudioOutput *ao, + const config_param ¶m, + const struct mixer_plugin *plugin, + Filter &filter_chain, + Error &error) +{ + Mixer *mixer; + + switch (audio_output_mixer_type(param)) { + case MIXER_TYPE_NONE: + case MIXER_TYPE_UNKNOWN: + return nullptr; + + case MIXER_TYPE_HARDWARE: + if (plugin == nullptr) + return nullptr; + + return mixer_new(plugin, ao, param, error); + + case MIXER_TYPE_SOFTWARE: + mixer = mixer_new(&software_mixer_plugin, nullptr, + config_param(), + IgnoreError()); + assert(mixer != nullptr); + + filter_chain_append(filter_chain, "software_mixer", + software_mixer_get_filter(mixer)); + return mixer; + } + + assert(false); + gcc_unreachable(); +} + +bool +ao_base_init(AudioOutput *ao, + const AudioOutputPlugin *plugin, + const config_param ¶m, Error &error) +{ + assert(ao != nullptr); + assert(plugin != nullptr); + assert(plugin->finish != nullptr); + assert(plugin->open != nullptr); + assert(plugin->close != nullptr); + assert(plugin->play != nullptr); + + if (!param.IsNull()) { + ao->name = param.GetBlockValue(AUDIO_OUTPUT_NAME); + if (ao->name == nullptr) { + error.Set(config_domain, + "Missing \"name\" configuration"); + return false; + } + + const char *p = param.GetBlockValue(AUDIO_OUTPUT_FORMAT); + if (p != nullptr) { + bool success = + audio_format_parse(ao->config_audio_format, + p, true, error); + if (!success) + return false; + } else + ao->config_audio_format.Clear(); + } else { + ao->name = "default detected output"; + + ao->config_audio_format.Clear(); + } + + ao->plugin = plugin; + ao->tags = param.GetBlockValue("tags", true); + ao->always_on = param.GetBlockValue("always_on", false); + ao->enabled = param.GetBlockValue("enabled", true); + ao->really_enabled = false; + ao->open = false; + ao->pause = false; + ao->allow_play = true; + ao->in_playback_loop = false; + ao->woken_for_play = false; + + /* set up the filter chain */ + + ao->filter = filter_chain_new(); + assert(ao->filter != nullptr); + + /* create the normalization filter (if configured) */ + + if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) { + Filter *normalize_filter = + filter_new(&normalize_filter_plugin, config_param(), + IgnoreError()); + assert(normalize_filter != nullptr); + + filter_chain_append(*ao->filter, "normalize", + autoconvert_filter_new(normalize_filter)); + } + + Error filter_error; + filter_chain_parse(*ao->filter, + param.GetBlockValue(AUDIO_FILTERS, ""), + filter_error); + + // It's not really fatal - Part of the filter chain has been set up already + // and even an empty one will work (if only with unexpected behaviour) + if (filter_error.IsDefined()) + FormatError(filter_error, + "Failed to initialize filter chain for '%s'", + ao->name); + + ao->command = AO_COMMAND_NONE; + + ao->mixer = nullptr; + ao->replay_gain_filter = nullptr; + ao->other_replay_gain_filter = nullptr; + + /* done */ + + return true; +} + +static bool +audio_output_setup(AudioOutput *ao, const config_param ¶m, + Error &error) +{ + + /* create the replay_gain filter */ + + const char *replay_gain_handler = + param.GetBlockValue("replay_gain_handler", "software"); + + if (strcmp(replay_gain_handler, "none") != 0) { + ao->replay_gain_filter = filter_new(&replay_gain_filter_plugin, + param, IgnoreError()); + assert(ao->replay_gain_filter != nullptr); + + ao->replay_gain_serial = 0; + + ao->other_replay_gain_filter = filter_new(&replay_gain_filter_plugin, + param, + IgnoreError()); + assert(ao->other_replay_gain_filter != nullptr); + + ao->other_replay_gain_serial = 0; + } else { + ao->replay_gain_filter = nullptr; + ao->other_replay_gain_filter = nullptr; + } + + /* set up the mixer */ + + Error mixer_error; + ao->mixer = audio_output_load_mixer(ao, param, + ao->plugin->mixer_plugin, + *ao->filter, mixer_error); + if (ao->mixer == nullptr && mixer_error.IsDefined()) + FormatError(mixer_error, + "Failed to initialize hardware mixer for '%s'", + ao->name); + + /* use the hardware mixer for replay gain? */ + + if (strcmp(replay_gain_handler, "mixer") == 0) { + if (ao->mixer != nullptr) + replay_gain_filter_set_mixer(ao->replay_gain_filter, + ao->mixer, 100); + else + FormatError(output_domain, + "No such mixer for output '%s'", ao->name); + } else if (strcmp(replay_gain_handler, "software") != 0 && + ao->replay_gain_filter != nullptr) { + error.Set(config_domain, + "Invalid \"replay_gain_handler\" value"); + return false; + } + + /* the "convert" filter must be the last one in the chain */ + + ao->convert_filter = filter_new(&convert_filter_plugin, config_param(), + IgnoreError()); + assert(ao->convert_filter != nullptr); + + filter_chain_append(*ao->filter, "convert", ao->convert_filter); + + return true; +} + +AudioOutput * +audio_output_new(const config_param ¶m, + PlayerControl &pc, + Error &error) +{ + const AudioOutputPlugin *plugin; + + if (!param.IsNull()) { + const char *p; + + p = param.GetBlockValue(AUDIO_OUTPUT_TYPE); + if (p == nullptr) { + error.Set(config_domain, + "Missing \"type\" configuration"); + return nullptr; + } + + plugin = AudioOutputPlugin_get(p); + if (plugin == nullptr) { + error.Format(config_domain, + "No such audio output plugin: %s", p); + return nullptr; + } + } else { + LogWarning(output_domain, + "No 'AudioOutput' defined in config file"); + + plugin = audio_output_detect(error); + if (plugin == nullptr) + return nullptr; + + FormatDefault(output_domain, + "Successfully detected a %s audio device", + plugin->name); + } + + AudioOutput *ao = ao_plugin_init(plugin, param, error); + if (ao == nullptr) + return nullptr; + + if (!audio_output_setup(ao, param, error)) { + ao_plugin_finish(ao); + return nullptr; + } + + ao->player_control = &pc; + return ao; +} diff --git a/src/output/Internal.hxx b/src/output/Internal.hxx new file mode 100644 index 000000000..31b6fd7c7 --- /dev/null +++ b/src/output/Internal.hxx @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2003-2014 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_OUTPUT_INTERNAL_HXX +#define MPD_OUTPUT_INTERNAL_HXX + +#include "AudioFormat.hxx" +#include "pcm/PcmBuffer.hxx" +#include "pcm/PcmDither.hxx" +#include "thread/Mutex.hxx" +#include "thread/Cond.hxx" +#include "thread/Thread.hxx" +#include "system/PeriodClock.hxx" + +class Error; +class Filter; +class MusicPipe; +struct config_param; +struct PlayerControl; +struct AudioOutputPlugin; + +enum audio_output_command { + AO_COMMAND_NONE = 0, + AO_COMMAND_ENABLE, + AO_COMMAND_DISABLE, + AO_COMMAND_OPEN, + + /** + * This command is invoked when the input audio format + * changes. + */ + AO_COMMAND_REOPEN, + + AO_COMMAND_CLOSE, + AO_COMMAND_PAUSE, + + /** + * Drains the internal (hardware) buffers of the device. This + * operation may take a while to complete. + */ + AO_COMMAND_DRAIN, + + AO_COMMAND_CANCEL, + AO_COMMAND_KILL +}; + +struct AudioOutput { + /** + * The device's configured display name. + */ + const char *name; + + /** + * The plugin which implements this output device. + */ + const AudioOutputPlugin *plugin; + + /** + * The #mixer object associated with this audio output device. + * May be nullptr if none is available, or if software volume is + * configured. + */ + class Mixer *mixer; + + /** + * Will this output receive tags from the decoder? The + * default is true, but it may be configured to false to + * suppress sending tags to the output. + */ + bool tags; + + /** + * Shall this output always play something (i.e. silence), + * even when playback is stopped? + */ + bool always_on; + + /** + * Has the user enabled this device? + */ + bool enabled; + + /** + * Is this device actually enabled, i.e. the "enable" method + * has succeeded? + */ + bool really_enabled; + + /** + * Is the device (already) open and functional? + * + * This attribute may only be modified by the output thread. + * It is protected with #mutex: write accesses inside the + * output thread and read accesses outside of it may only be + * performed while the lock is held. + */ + bool open; + + /** + * Is the device paused? i.e. the output thread is in the + * ao_pause() loop. + */ + bool pause; + + /** + * When this flag is set, the output thread will not do any + * playback. It will wait until the flag is cleared. + * + * This is used to synchronize the "clear" operation on the + * shared music pipe during the CANCEL command. + */ + bool allow_play; + + /** + * True while the OutputThread is inside ao_play(). This + * means the PlayerThread does not need to wake up the + * OutputThread when new chunks are added to the MusicPipe, + * because the OutputThread is already watching that. + */ + bool in_playback_loop; + + /** + * Has the OutputThread been woken up to play more chunks? + * This is set by audio_output_play() and reset by ao_play() + * to reduce the number of duplicate wakeups. + */ + bool woken_for_play; + + /** + * If not nullptr, the device has failed, and this timer is used + * to estimate how long it should stay disabled (unless + * explicitly reopened with "play"). + */ + PeriodClock fail_timer; + + /** + * The configured audio format. + */ + AudioFormat config_audio_format; + + /** + * The audio_format in which audio data is received from the + * player thread (which in turn receives it from the decoder). + */ + AudioFormat in_audio_format; + + /** + * The audio_format which is really sent to the device. This + * is basically config_audio_format (if configured) or + * in_audio_format, but may have been modified by + * plugin->open(). + */ + AudioFormat out_audio_format; + + /** + * The buffer used to allocate the cross-fading result. + */ + PcmBuffer cross_fade_buffer; + + /** + * The dithering state for cross-fading two streams. + */ + PcmDither cross_fade_dither; + + /** + * The filter object of this audio output. This is an + * instance of chain_filter_plugin. + */ + Filter *filter; + + /** + * The replay_gain_filter_plugin instance of this audio + * output. + */ + Filter *replay_gain_filter; + + /** + * The serial number of the last replay gain info. 0 means no + * replay gain info was available. + */ + unsigned replay_gain_serial; + + /** + * The replay_gain_filter_plugin instance of this audio + * output, to be applied to the second chunk during + * cross-fading. + */ + Filter *other_replay_gain_filter; + + /** + * The serial number of the last replay gain info by the + * "other" chunk during cross-fading. + */ + unsigned other_replay_gain_serial; + + /** + * The convert_filter_plugin instance of this audio output. + * It is the last item in the filter chain, and is responsible + * for converting the input data into the appropriate format + * for this audio output. + */ + Filter *convert_filter; + + /** + * The thread handle, or nullptr if the output thread isn't + * running. + */ + Thread thread; + + /** + * The next command to be performed by the output thread. + */ + enum audio_output_command command; + + /** + * The music pipe which provides music chunks to be played. + */ + const MusicPipe *pipe; + + /** + * This mutex protects #open, #fail_timer, #chunk and + * #chunk_finished. + */ + Mutex mutex; + + /** + * This condition object wakes up the output thread after + * #command has been set. + */ + Cond cond; + + /** + * The PlayerControl object which "owns" this output. This + * object is needed to signal command completion. + */ + PlayerControl *player_control; + + /** + * The #music_chunk which is currently being played. All + * chunks before this one may be returned to the + * #music_buffer, because they are not going to be used by + * this output anymore. + */ + const struct music_chunk *chunk; + + /** + * Has the output finished playing #chunk? + */ + bool chunk_finished; +}; + +/** + * Notify object used by the thread's client, i.e. we will send a + * notify signal to this object, expecting the caller to wait on it. + */ +extern struct notify audio_output_client_notify; + +static inline bool +audio_output_is_open(const AudioOutput *ao) +{ + return ao->open; +} + +static inline bool +audio_output_command_is_finished(const AudioOutput *ao) +{ + return ao->command == AO_COMMAND_NONE; +} + +AudioOutput * +audio_output_new(const config_param ¶m, + PlayerControl &pc, + Error &error); + +bool +ao_base_init(AudioOutput *ao, + const AudioOutputPlugin *plugin, + const config_param ¶m, Error &error); + +void +ao_base_finish(AudioOutput *ao); + +void +audio_output_free(AudioOutput *ao); + +#endif diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx index 7df89cc55..c83d8f02d 100644 --- a/src/output/MultipleOutputs.cxx +++ b/src/output/MultipleOutputs.cxx @@ -20,9 +20,9 @@ #include "config.h" #include "MultipleOutputs.hxx" #include "PlayerControl.hxx" -#include "OutputInternal.hxx" +#include "Internal.hxx" #include "OutputControl.hxx" -#include "OutputError.hxx" +#include "Domain.hxx" #include "MusicBuffer.hxx" #include "MusicPipe.hxx" #include "MusicChunk.hxx" diff --git a/src/output/OutputAPI.hxx b/src/output/OutputAPI.hxx index cfbc43196..e0fd6eec8 100644 --- a/src/output/OutputAPI.hxx +++ b/src/output/OutputAPI.hxx @@ -23,7 +23,7 @@ // IWYU pragma: begin_exports #include "OutputPlugin.hxx" -#include "OutputInternal.hxx" +#include "Internal.hxx" #include "AudioFormat.hxx" #include "tag/Tag.hxx" #include "config/ConfigData.hxx" diff --git a/src/output/OutputCommand.cxx b/src/output/OutputCommand.cxx index 6d5690575..6afb70cf1 100644 --- a/src/output/OutputCommand.cxx +++ b/src/output/OutputCommand.cxx @@ -27,7 +27,7 @@ #include "config.h" #include "OutputCommand.hxx" #include "MultipleOutputs.hxx" -#include "OutputInternal.hxx" +#include "Internal.hxx" #include "PlayerControl.hxx" #include "mixer/MixerControl.hxx" #include "Idle.hxx" diff --git a/src/output/OutputControl.cxx b/src/output/OutputControl.cxx index f6844911f..5b4c4f487 100644 --- a/src/output/OutputControl.cxx +++ b/src/output/OutputControl.cxx @@ -21,9 +21,9 @@ #include "config.h" #include "OutputControl.hxx" #include "OutputThread.hxx" -#include "OutputInternal.hxx" +#include "Internal.hxx" #include "OutputPlugin.hxx" -#include "OutputError.hxx" +#include "Domain.hxx" #include "mixer/MixerControl.hxx" #include "notify.hxx" #include "filter/plugins/ReplayGainFilterPlugin.hxx" diff --git a/src/output/OutputError.cxx b/src/output/OutputError.cxx deleted file mode 100644 index 9d4128912..000000000 --- a/src/output/OutputError.cxx +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2003-2014 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 "OutputError.hxx" -#include "util/Domain.hxx" - -const Domain output_domain("output"); diff --git a/src/output/OutputError.hxx b/src/output/OutputError.hxx deleted file mode 100644 index e3a20142f..000000000 --- a/src/output/OutputError.hxx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2003-2014 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_OUTPUT_ERROR_HXX -#define MPD_OUTPUT_ERROR_HXX - -extern const class Domain output_domain; - -#endif diff --git a/src/output/OutputFinish.cxx b/src/output/OutputFinish.cxx deleted file mode 100644 index 1f405aaf9..000000000 --- a/src/output/OutputFinish.cxx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2003-2014 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 "OutputInternal.hxx" -#include "OutputPlugin.hxx" -#include "mixer/MixerControl.hxx" -#include "filter/FilterInternal.hxx" - -#include - -void -ao_base_finish(AudioOutput *ao) -{ - assert(!ao->open); - assert(!ao->fail_timer.IsDefined()); - assert(!ao->thread.IsDefined()); - - if (ao->mixer != nullptr) - mixer_free(ao->mixer); - - delete ao->replay_gain_filter; - delete ao->other_replay_gain_filter; - delete ao->filter; -} - -void -audio_output_free(AudioOutput *ao) -{ - assert(!ao->open); - assert(!ao->fail_timer.IsDefined()); - assert(!ao->thread.IsDefined()); - - ao_plugin_finish(ao); -} diff --git a/src/output/OutputInit.cxx b/src/output/OutputInit.cxx deleted file mode 100644 index f91e5b5e3..000000000 --- a/src/output/OutputInit.cxx +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2003-2014 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 "OutputInternal.hxx" -#include "OutputList.hxx" -#include "OutputError.hxx" -#include "OutputAPI.hxx" -#include "filter/FilterConfig.hxx" -#include "AudioParser.hxx" -#include "mixer/MixerList.hxx" -#include "mixer/MixerType.hxx" -#include "mixer/MixerControl.hxx" -#include "mixer/plugins/SoftwareMixerPlugin.hxx" -#include "filter/FilterPlugin.hxx" -#include "filter/FilterRegistry.hxx" -#include "filter/plugins/AutoConvertFilterPlugin.hxx" -#include "filter/plugins/ReplayGainFilterPlugin.hxx" -#include "filter/plugins/ChainFilterPlugin.hxx" -#include "config/ConfigError.hxx" -#include "config/ConfigGlobal.hxx" -#include "util/Error.hxx" -#include "Log.hxx" - -#include -#include - -#define AUDIO_OUTPUT_TYPE "type" -#define AUDIO_OUTPUT_NAME "name" -#define AUDIO_OUTPUT_FORMAT "format" -#define AUDIO_FILTERS "filters" - -static const AudioOutputPlugin * -audio_output_detect(Error &error) -{ - LogDefault(output_domain, "Attempt to detect audio output device"); - - audio_output_plugins_for_each(plugin) { - if (plugin->test_default_device == nullptr) - continue; - - FormatDefault(output_domain, - "Attempting to detect a %s audio device", - plugin->name); - if (ao_plugin_test_default_device(plugin)) - return plugin; - } - - error.Set(output_domain, "Unable to detect an audio device"); - return nullptr; -} - -/** - * Determines the mixer type which should be used for the specified - * configuration block. - * - * This handles the deprecated options mixer_type (global) and - * mixer_enabled, if the mixer_type setting is not configured. - */ -gcc_pure -static enum mixer_type -audio_output_mixer_type(const config_param ¶m) -{ - /* read the local "mixer_type" setting */ - const char *p = param.GetBlockValue("mixer_type"); - if (p != nullptr) - return mixer_type_parse(p); - - /* try the local "mixer_enabled" setting next (deprecated) */ - if (!param.GetBlockValue("mixer_enabled", true)) - return MIXER_TYPE_NONE; - - /* fall back to the global "mixer_type" setting (also - deprecated) */ - return mixer_type_parse(config_get_string(CONF_MIXER_TYPE, - "hardware")); -} - -static Mixer * -audio_output_load_mixer(AudioOutput *ao, - const config_param ¶m, - const struct mixer_plugin *plugin, - Filter &filter_chain, - Error &error) -{ - Mixer *mixer; - - switch (audio_output_mixer_type(param)) { - case MIXER_TYPE_NONE: - case MIXER_TYPE_UNKNOWN: - return nullptr; - - case MIXER_TYPE_HARDWARE: - if (plugin == nullptr) - return nullptr; - - return mixer_new(plugin, ao, param, error); - - case MIXER_TYPE_SOFTWARE: - mixer = mixer_new(&software_mixer_plugin, nullptr, - config_param(), - IgnoreError()); - assert(mixer != nullptr); - - filter_chain_append(filter_chain, "software_mixer", - software_mixer_get_filter(mixer)); - return mixer; - } - - assert(false); - gcc_unreachable(); -} - -bool -ao_base_init(AudioOutput *ao, - const AudioOutputPlugin *plugin, - const config_param ¶m, Error &error) -{ - assert(ao != nullptr); - assert(plugin != nullptr); - assert(plugin->finish != nullptr); - assert(plugin->open != nullptr); - assert(plugin->close != nullptr); - assert(plugin->play != nullptr); - - if (!param.IsNull()) { - ao->name = param.GetBlockValue(AUDIO_OUTPUT_NAME); - if (ao->name == nullptr) { - error.Set(config_domain, - "Missing \"name\" configuration"); - return false; - } - - const char *p = param.GetBlockValue(AUDIO_OUTPUT_FORMAT); - if (p != nullptr) { - bool success = - audio_format_parse(ao->config_audio_format, - p, true, error); - if (!success) - return false; - } else - ao->config_audio_format.Clear(); - } else { - ao->name = "default detected output"; - - ao->config_audio_format.Clear(); - } - - ao->plugin = plugin; - ao->tags = param.GetBlockValue("tags", true); - ao->always_on = param.GetBlockValue("always_on", false); - ao->enabled = param.GetBlockValue("enabled", true); - ao->really_enabled = false; - ao->open = false; - ao->pause = false; - ao->allow_play = true; - ao->in_playback_loop = false; - ao->woken_for_play = false; - - /* set up the filter chain */ - - ao->filter = filter_chain_new(); - assert(ao->filter != nullptr); - - /* create the normalization filter (if configured) */ - - if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) { - Filter *normalize_filter = - filter_new(&normalize_filter_plugin, config_param(), - IgnoreError()); - assert(normalize_filter != nullptr); - - filter_chain_append(*ao->filter, "normalize", - autoconvert_filter_new(normalize_filter)); - } - - Error filter_error; - filter_chain_parse(*ao->filter, - param.GetBlockValue(AUDIO_FILTERS, ""), - filter_error); - - // It's not really fatal - Part of the filter chain has been set up already - // and even an empty one will work (if only with unexpected behaviour) - if (filter_error.IsDefined()) - FormatError(filter_error, - "Failed to initialize filter chain for '%s'", - ao->name); - - ao->command = AO_COMMAND_NONE; - - ao->mixer = nullptr; - ao->replay_gain_filter = nullptr; - ao->other_replay_gain_filter = nullptr; - - /* done */ - - return true; -} - -static bool -audio_output_setup(AudioOutput *ao, const config_param ¶m, - Error &error) -{ - - /* create the replay_gain filter */ - - const char *replay_gain_handler = - param.GetBlockValue("replay_gain_handler", "software"); - - if (strcmp(replay_gain_handler, "none") != 0) { - ao->replay_gain_filter = filter_new(&replay_gain_filter_plugin, - param, IgnoreError()); - assert(ao->replay_gain_filter != nullptr); - - ao->replay_gain_serial = 0; - - ao->other_replay_gain_filter = filter_new(&replay_gain_filter_plugin, - param, - IgnoreError()); - assert(ao->other_replay_gain_filter != nullptr); - - ao->other_replay_gain_serial = 0; - } else { - ao->replay_gain_filter = nullptr; - ao->other_replay_gain_filter = nullptr; - } - - /* set up the mixer */ - - Error mixer_error; - ao->mixer = audio_output_load_mixer(ao, param, - ao->plugin->mixer_plugin, - *ao->filter, mixer_error); - if (ao->mixer == nullptr && mixer_error.IsDefined()) - FormatError(mixer_error, - "Failed to initialize hardware mixer for '%s'", - ao->name); - - /* use the hardware mixer for replay gain? */ - - if (strcmp(replay_gain_handler, "mixer") == 0) { - if (ao->mixer != nullptr) - replay_gain_filter_set_mixer(ao->replay_gain_filter, - ao->mixer, 100); - else - FormatError(output_domain, - "No such mixer for output '%s'", ao->name); - } else if (strcmp(replay_gain_handler, "software") != 0 && - ao->replay_gain_filter != nullptr) { - error.Set(config_domain, - "Invalid \"replay_gain_handler\" value"); - return false; - } - - /* the "convert" filter must be the last one in the chain */ - - ao->convert_filter = filter_new(&convert_filter_plugin, config_param(), - IgnoreError()); - assert(ao->convert_filter != nullptr); - - filter_chain_append(*ao->filter, "convert", ao->convert_filter); - - return true; -} - -AudioOutput * -audio_output_new(const config_param ¶m, - PlayerControl &pc, - Error &error) -{ - const AudioOutputPlugin *plugin; - - if (!param.IsNull()) { - const char *p; - - p = param.GetBlockValue(AUDIO_OUTPUT_TYPE); - if (p == nullptr) { - error.Set(config_domain, - "Missing \"type\" configuration"); - return nullptr; - } - - plugin = AudioOutputPlugin_get(p); - if (plugin == nullptr) { - error.Format(config_domain, - "No such audio output plugin: %s", p); - return nullptr; - } - } else { - LogWarning(output_domain, - "No 'AudioOutput' defined in config file"); - - plugin = audio_output_detect(error); - if (plugin == nullptr) - return nullptr; - - FormatDefault(output_domain, - "Successfully detected a %s audio device", - plugin->name); - } - - AudioOutput *ao = ao_plugin_init(plugin, param, error); - if (ao == nullptr) - return nullptr; - - if (!audio_output_setup(ao, param, error)) { - ao_plugin_finish(ao); - return nullptr; - } - - ao->player_control = &pc; - return ao; -} diff --git a/src/output/OutputInternal.hxx b/src/output/OutputInternal.hxx deleted file mode 100644 index 31b6fd7c7..000000000 --- a/src/output/OutputInternal.hxx +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2003-2014 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_OUTPUT_INTERNAL_HXX -#define MPD_OUTPUT_INTERNAL_HXX - -#include "AudioFormat.hxx" -#include "pcm/PcmBuffer.hxx" -#include "pcm/PcmDither.hxx" -#include "thread/Mutex.hxx" -#include "thread/Cond.hxx" -#include "thread/Thread.hxx" -#include "system/PeriodClock.hxx" - -class Error; -class Filter; -class MusicPipe; -struct config_param; -struct PlayerControl; -struct AudioOutputPlugin; - -enum audio_output_command { - AO_COMMAND_NONE = 0, - AO_COMMAND_ENABLE, - AO_COMMAND_DISABLE, - AO_COMMAND_OPEN, - - /** - * This command is invoked when the input audio format - * changes. - */ - AO_COMMAND_REOPEN, - - AO_COMMAND_CLOSE, - AO_COMMAND_PAUSE, - - /** - * Drains the internal (hardware) buffers of the device. This - * operation may take a while to complete. - */ - AO_COMMAND_DRAIN, - - AO_COMMAND_CANCEL, - AO_COMMAND_KILL -}; - -struct AudioOutput { - /** - * The device's configured display name. - */ - const char *name; - - /** - * The plugin which implements this output device. - */ - const AudioOutputPlugin *plugin; - - /** - * The #mixer object associated with this audio output device. - * May be nullptr if none is available, or if software volume is - * configured. - */ - class Mixer *mixer; - - /** - * Will this output receive tags from the decoder? The - * default is true, but it may be configured to false to - * suppress sending tags to the output. - */ - bool tags; - - /** - * Shall this output always play something (i.e. silence), - * even when playback is stopped? - */ - bool always_on; - - /** - * Has the user enabled this device? - */ - bool enabled; - - /** - * Is this device actually enabled, i.e. the "enable" method - * has succeeded? - */ - bool really_enabled; - - /** - * Is the device (already) open and functional? - * - * This attribute may only be modified by the output thread. - * It is protected with #mutex: write accesses inside the - * output thread and read accesses outside of it may only be - * performed while the lock is held. - */ - bool open; - - /** - * Is the device paused? i.e. the output thread is in the - * ao_pause() loop. - */ - bool pause; - - /** - * When this flag is set, the output thread will not do any - * playback. It will wait until the flag is cleared. - * - * This is used to synchronize the "clear" operation on the - * shared music pipe during the CANCEL command. - */ - bool allow_play; - - /** - * True while the OutputThread is inside ao_play(). This - * means the PlayerThread does not need to wake up the - * OutputThread when new chunks are added to the MusicPipe, - * because the OutputThread is already watching that. - */ - bool in_playback_loop; - - /** - * Has the OutputThread been woken up to play more chunks? - * This is set by audio_output_play() and reset by ao_play() - * to reduce the number of duplicate wakeups. - */ - bool woken_for_play; - - /** - * If not nullptr, the device has failed, and this timer is used - * to estimate how long it should stay disabled (unless - * explicitly reopened with "play"). - */ - PeriodClock fail_timer; - - /** - * The configured audio format. - */ - AudioFormat config_audio_format; - - /** - * The audio_format in which audio data is received from the - * player thread (which in turn receives it from the decoder). - */ - AudioFormat in_audio_format; - - /** - * The audio_format which is really sent to the device. This - * is basically config_audio_format (if configured) or - * in_audio_format, but may have been modified by - * plugin->open(). - */ - AudioFormat out_audio_format; - - /** - * The buffer used to allocate the cross-fading result. - */ - PcmBuffer cross_fade_buffer; - - /** - * The dithering state for cross-fading two streams. - */ - PcmDither cross_fade_dither; - - /** - * The filter object of this audio output. This is an - * instance of chain_filter_plugin. - */ - Filter *filter; - - /** - * The replay_gain_filter_plugin instance of this audio - * output. - */ - Filter *replay_gain_filter; - - /** - * The serial number of the last replay gain info. 0 means no - * replay gain info was available. - */ - unsigned replay_gain_serial; - - /** - * The replay_gain_filter_plugin instance of this audio - * output, to be applied to the second chunk during - * cross-fading. - */ - Filter *other_replay_gain_filter; - - /** - * The serial number of the last replay gain info by the - * "other" chunk during cross-fading. - */ - unsigned other_replay_gain_serial; - - /** - * The convert_filter_plugin instance of this audio output. - * It is the last item in the filter chain, and is responsible - * for converting the input data into the appropriate format - * for this audio output. - */ - Filter *convert_filter; - - /** - * The thread handle, or nullptr if the output thread isn't - * running. - */ - Thread thread; - - /** - * The next command to be performed by the output thread. - */ - enum audio_output_command command; - - /** - * The music pipe which provides music chunks to be played. - */ - const MusicPipe *pipe; - - /** - * This mutex protects #open, #fail_timer, #chunk and - * #chunk_finished. - */ - Mutex mutex; - - /** - * This condition object wakes up the output thread after - * #command has been set. - */ - Cond cond; - - /** - * The PlayerControl object which "owns" this output. This - * object is needed to signal command completion. - */ - PlayerControl *player_control; - - /** - * The #music_chunk which is currently being played. All - * chunks before this one may be returned to the - * #music_buffer, because they are not going to be used by - * this output anymore. - */ - const struct music_chunk *chunk; - - /** - * Has the output finished playing #chunk? - */ - bool chunk_finished; -}; - -/** - * Notify object used by the thread's client, i.e. we will send a - * notify signal to this object, expecting the caller to wait on it. - */ -extern struct notify audio_output_client_notify; - -static inline bool -audio_output_is_open(const AudioOutput *ao) -{ - return ao->open; -} - -static inline bool -audio_output_command_is_finished(const AudioOutput *ao) -{ - return ao->command == AO_COMMAND_NONE; -} - -AudioOutput * -audio_output_new(const config_param ¶m, - PlayerControl &pc, - Error &error); - -bool -ao_base_init(AudioOutput *ao, - const AudioOutputPlugin *plugin, - const config_param ¶m, Error &error); - -void -ao_base_finish(AudioOutput *ao); - -void -audio_output_free(AudioOutput *ao); - -#endif diff --git a/src/output/OutputList.cxx b/src/output/OutputList.cxx deleted file mode 100644 index c523d4cbc..000000000 --- a/src/output/OutputList.cxx +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2003-2014 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 "OutputList.hxx" -#include "OutputAPI.hxx" -#include "plugins/AlsaOutputPlugin.hxx" -#include "plugins/AoOutputPlugin.hxx" -#include "plugins/FifoOutputPlugin.hxx" -#include "plugins/HttpdOutputPlugin.hxx" -#include "plugins/JackOutputPlugin.hxx" -#include "plugins/NullOutputPlugin.hxx" -#include "plugins/OpenALOutputPlugin.hxx" -#include "plugins/OssOutputPlugin.hxx" -#include "plugins/OSXOutputPlugin.hxx" -#include "plugins/PipeOutputPlugin.hxx" -#include "plugins/PulseOutputPlugin.hxx" -#include "plugins/RecorderOutputPlugin.hxx" -#include "plugins/RoarOutputPlugin.hxx" -#include "plugins/ShoutOutputPlugin.hxx" -#include "plugins/SolarisOutputPlugin.hxx" -#include "plugins/WinmmOutputPlugin.hxx" - -#include - -const AudioOutputPlugin *const audio_output_plugins[] = { -#ifdef HAVE_SHOUT - &shout_output_plugin, -#endif - &null_output_plugin, -#ifdef HAVE_FIFO - &fifo_output_plugin, -#endif -#ifdef ENABLE_PIPE_OUTPUT - &pipe_output_plugin, -#endif -#ifdef HAVE_ALSA - &alsa_output_plugin, -#endif -#ifdef HAVE_ROAR - &roar_output_plugin, -#endif -#ifdef HAVE_AO - &ao_output_plugin, -#endif -#ifdef HAVE_OSS - &oss_output_plugin, -#endif -#ifdef HAVE_OPENAL - &openal_output_plugin, -#endif -#ifdef HAVE_OSX - &osx_output_plugin, -#endif -#ifdef ENABLE_SOLARIS_OUTPUT - &solaris_output_plugin, -#endif -#ifdef HAVE_PULSE - &pulse_output_plugin, -#endif -#ifdef HAVE_JACK - &jack_output_plugin, -#endif -#ifdef ENABLE_HTTPD_OUTPUT - &httpd_output_plugin, -#endif -#ifdef ENABLE_RECORDER_OUTPUT - &recorder_output_plugin, -#endif -#ifdef ENABLE_WINMM_OUTPUT - &winmm_output_plugin, -#endif - nullptr -}; - -const AudioOutputPlugin * -AudioOutputPlugin_get(const char *name) -{ - audio_output_plugins_for_each(plugin) - if (strcmp(plugin->name, name) == 0) - return plugin; - - return nullptr; -} diff --git a/src/output/OutputList.hxx b/src/output/OutputList.hxx deleted file mode 100644 index bc9c1ae2b..000000000 --- a/src/output/OutputList.hxx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2003-2014 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_OUTPUT_LIST_HXX -#define MPD_OUTPUT_LIST_HXX - -struct AudioOutputPlugin; - -extern const AudioOutputPlugin *const audio_output_plugins[]; - -const AudioOutputPlugin * -AudioOutputPlugin_get(const char *name); - -#define audio_output_plugins_for_each(plugin) \ - for (const AudioOutputPlugin *plugin, \ - *const*output_plugin_iterator = &audio_output_plugins[0]; \ - (plugin = *output_plugin_iterator) != nullptr; ++output_plugin_iterator) - -#endif diff --git a/src/output/OutputPlugin.cxx b/src/output/OutputPlugin.cxx index 1c8d3bb48..45b979d3c 100644 --- a/src/output/OutputPlugin.cxx +++ b/src/output/OutputPlugin.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "OutputPlugin.hxx" -#include "OutputInternal.hxx" +#include "Internal.hxx" AudioOutput * ao_plugin_init(const AudioOutputPlugin *plugin, diff --git a/src/output/OutputPrint.cxx b/src/output/OutputPrint.cxx index b9fb79607..414a86e32 100644 --- a/src/output/OutputPrint.cxx +++ b/src/output/OutputPrint.cxx @@ -25,7 +25,7 @@ #include "config.h" #include "OutputPrint.hxx" #include "MultipleOutputs.hxx" -#include "OutputInternal.hxx" +#include "Internal.hxx" #include "client/Client.hxx" void diff --git a/src/output/OutputState.cxx b/src/output/OutputState.cxx index f717e3cbb..7f3a8da7b 100644 --- a/src/output/OutputState.cxx +++ b/src/output/OutputState.cxx @@ -25,8 +25,8 @@ #include "config.h" #include "OutputState.hxx" #include "MultipleOutputs.hxx" -#include "OutputInternal.hxx" -#include "OutputError.hxx" +#include "Internal.hxx" +#include "Domain.hxx" #include "Log.hxx" #include "util/StringUtil.hxx" diff --git a/src/output/OutputThread.cxx b/src/output/OutputThread.cxx index f2ea048df..449198c8b 100644 --- a/src/output/OutputThread.cxx +++ b/src/output/OutputThread.cxx @@ -19,9 +19,9 @@ #include "config.h" #include "OutputThread.hxx" -#include "OutputInternal.hxx" +#include "Internal.hxx" #include "OutputAPI.hxx" -#include "OutputError.hxx" +#include "Domain.hxx" #include "pcm/PcmMix.hxx" #include "notify.hxx" #include "filter/FilterInternal.hxx" diff --git a/src/output/Registry.cxx b/src/output/Registry.cxx new file mode 100644 index 000000000..6ce96fe57 --- /dev/null +++ b/src/output/Registry.cxx @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2003-2014 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 "Registry.hxx" +#include "OutputAPI.hxx" +#include "plugins/AlsaOutputPlugin.hxx" +#include "plugins/AoOutputPlugin.hxx" +#include "plugins/FifoOutputPlugin.hxx" +#include "plugins/HttpdOutputPlugin.hxx" +#include "plugins/JackOutputPlugin.hxx" +#include "plugins/NullOutputPlugin.hxx" +#include "plugins/OpenALOutputPlugin.hxx" +#include "plugins/OssOutputPlugin.hxx" +#include "plugins/OSXOutputPlugin.hxx" +#include "plugins/PipeOutputPlugin.hxx" +#include "plugins/PulseOutputPlugin.hxx" +#include "plugins/RecorderOutputPlugin.hxx" +#include "plugins/RoarOutputPlugin.hxx" +#include "plugins/ShoutOutputPlugin.hxx" +#include "plugins/SolarisOutputPlugin.hxx" +#include "plugins/WinmmOutputPlugin.hxx" + +#include + +const AudioOutputPlugin *const audio_output_plugins[] = { +#ifdef HAVE_SHOUT + &shout_output_plugin, +#endif + &null_output_plugin, +#ifdef HAVE_FIFO + &fifo_output_plugin, +#endif +#ifdef ENABLE_PIPE_OUTPUT + &pipe_output_plugin, +#endif +#ifdef HAVE_ALSA + &alsa_output_plugin, +#endif +#ifdef HAVE_ROAR + &roar_output_plugin, +#endif +#ifdef HAVE_AO + &ao_output_plugin, +#endif +#ifdef HAVE_OSS + &oss_output_plugin, +#endif +#ifdef HAVE_OPENAL + &openal_output_plugin, +#endif +#ifdef HAVE_OSX + &osx_output_plugin, +#endif +#ifdef ENABLE_SOLARIS_OUTPUT + &solaris_output_plugin, +#endif +#ifdef HAVE_PULSE + &pulse_output_plugin, +#endif +#ifdef HAVE_JACK + &jack_output_plugin, +#endif +#ifdef ENABLE_HTTPD_OUTPUT + &httpd_output_plugin, +#endif +#ifdef ENABLE_RECORDER_OUTPUT + &recorder_output_plugin, +#endif +#ifdef ENABLE_WINMM_OUTPUT + &winmm_output_plugin, +#endif + nullptr +}; + +const AudioOutputPlugin * +AudioOutputPlugin_get(const char *name) +{ + audio_output_plugins_for_each(plugin) + if (strcmp(plugin->name, name) == 0) + return plugin; + + return nullptr; +} diff --git a/src/output/Registry.hxx b/src/output/Registry.hxx new file mode 100644 index 000000000..bc9c1ae2b --- /dev/null +++ b/src/output/Registry.hxx @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2003-2014 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_OUTPUT_LIST_HXX +#define MPD_OUTPUT_LIST_HXX + +struct AudioOutputPlugin; + +extern const AudioOutputPlugin *const audio_output_plugins[]; + +const AudioOutputPlugin * +AudioOutputPlugin_get(const char *name); + +#define audio_output_plugins_for_each(plugin) \ + for (const AudioOutputPlugin *plugin, \ + *const*output_plugin_iterator = &audio_output_plugins[0]; \ + (plugin = *output_plugin_iterator) != nullptr; ++output_plugin_iterator) + +#endif diff --git a/src/output/plugins/HttpdInternal.hxx b/src/output/plugins/HttpdInternal.hxx index 1d48c3ad5..ad728949f 100644 --- a/src/output/plugins/HttpdInternal.hxx +++ b/src/output/plugins/HttpdInternal.hxx @@ -25,7 +25,7 @@ #ifndef MPD_OUTPUT_HTTPD_INTERNAL_H #define MPD_OUTPUT_HTTPD_INTERNAL_H -#include "../OutputInternal.hxx" +#include "../Internal.hxx" #include "Timer.hxx" #include "thread/Mutex.hxx" #include "event/ServerSocket.hxx" diff --git a/test/run_output.cxx b/test/run_output.cxx index 04f9b9d63..2664b7150 100644 --- a/test/run_output.cxx +++ b/test/run_output.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "output/OutputControl.hxx" -#include "output/OutputInternal.hxx" +#include "output/Internal.hxx" #include "output/OutputPlugin.hxx" #include "config/ConfigData.hxx" #include "config/ConfigGlobal.hxx" -- cgit v1.2.3