From 3a2254c91f19364d41aacea442c43b00aa1175e2 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 17 Apr 2013 01:12:05 +0200 Subject: output: convert to C++ --- Makefile.am | 4 +- src/CommandLine.cxx | 2 +- src/MixerAll.cxx | 5 +- src/OutputAll.cxx | 6 +- src/OutputCommand.cxx | 7 +- src/OutputControl.cxx | 8 +- src/OutputFinish.cxx | 8 +- src/OutputInit.cxx | 6 +- src/OutputInternal.hxx | 277 ++++++++++++++++++++++++++++++++++++++++ src/OutputPlugin.cxx | 8 +- src/OutputPlugin.hxx | 211 +++++++++++++++++++++++++++++++ src/OutputPrint.cxx | 2 +- src/OutputState.cxx | 2 +- src/OutputThread.cxx | 6 +- src/output/HttpdInternal.hxx | 2 +- src/output_api.h | 4 +- src/output_internal.h | 294 ------------------------------------------- src/output_plugin.h | 219 -------------------------------- test/run_output.cxx | 8 +- 19 files changed, 510 insertions(+), 569 deletions(-) create mode 100644 src/OutputInternal.hxx create mode 100644 src/OutputPlugin.hxx delete mode 100644 src/output_internal.h delete mode 100644 src/output_plugin.h diff --git a/Makefile.am b/Makefile.am index 7429ea8fa..766506f94 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,7 +54,6 @@ mpd_headers = \ src/ape.h \ src/audio_format.h \ src/audio_check.h \ - src/output_internal.h \ src/output_api.h \ src/filter_internal.h \ src/command.h \ @@ -768,6 +767,7 @@ OUTPUT_LIBS = \ $(SHOUT_LIBS) OUTPUT_API_SRC = \ + src/OutputInternal.hxx \ src/OutputList.cxx src/OutputList.hxx \ src/OutputAll.cxx src/OutputAll.hxx \ src/OutputThread.cxx src/OutputThread.hxx \ @@ -776,7 +776,7 @@ OUTPUT_API_SRC = \ src/OutputState.cxx src/OutputState.hxx \ src/OutputPrint.cxx src/OutputPrint.hxx \ src/OutputCommand.cxx src/OutputCommand.hxx \ - src/OutputPlugin.cxx src/output_plugin.h \ + src/OutputPlugin.cxx src/OutputPlugin.hxx \ src/OutputFinish.cxx \ src/OutputInit.cxx diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx index 0de211fd7..ec6d8c7b1 100644 --- a/src/CommandLine.cxx +++ b/src/CommandLine.cxx @@ -25,7 +25,7 @@ #include "DecoderList.hxx" #include "decoder_plugin.h" #include "OutputList.hxx" -#include "output_plugin.h" +#include "OutputPlugin.hxx" #include "InputRegistry.hxx" #include "InputPlugin.hxx" #include "PlaylistRegistry.hxx" diff --git a/src/MixerAll.cxx b/src/MixerAll.cxx index 3069f60d7..5a6235de4 100644 --- a/src/MixerAll.cxx +++ b/src/MixerAll.cxx @@ -24,10 +24,7 @@ #include "MixerList.hxx" #include "OutputAll.hxx" #include "pcm/PcmVolume.hxx" - -extern "C" { -#include "output_internal.h" -} +#include "OutputInternal.hxx" #include diff --git a/src/OutputAll.cxx b/src/OutputAll.cxx index 4cdcc84e7..c125a9730 100644 --- a/src/OutputAll.cxx +++ b/src/OutputAll.cxx @@ -19,12 +19,8 @@ #include "config.h" #include "OutputAll.hxx" - -extern "C" { -#include "output_internal.h" -} - #include "PlayerControl.hxx" +#include "OutputInternal.hxx" #include "OutputControl.hxx" #include "OutputError.hxx" #include "MusicBuffer.hxx" diff --git a/src/OutputCommand.cxx b/src/OutputCommand.cxx index 3921a9634..bf051babf 100644 --- a/src/OutputCommand.cxx +++ b/src/OutputCommand.cxx @@ -27,15 +27,12 @@ #include "config.h" #include "OutputCommand.hxx" #include "OutputAll.hxx" +#include "OutputInternal.hxx" +#include "OutputPlugin.hxx" #include "PlayerControl.hxx" #include "MixerControl.hxx" #include "Idle.hxx" -extern "C" { -#include "output_internal.h" -#include "output_plugin.h" -} - extern unsigned audio_output_state_version; bool diff --git a/src/OutputControl.cxx b/src/OutputControl.cxx index c451938f7..3fe4b1e79 100644 --- a/src/OutputControl.cxx +++ b/src/OutputControl.cxx @@ -20,12 +20,8 @@ #include "config.h" #include "OutputControl.hxx" #include "OutputThread.hxx" -#include "output_api.h" - -extern "C" { -#include "output_internal.h" -} - +#include "OutputInternal.hxx" +#include "OutputPlugin.hxx" #include "MixerPlugin.hxx" #include "MixerControl.hxx" #include "notify.hxx" diff --git a/src/OutputFinish.cxx b/src/OutputFinish.cxx index 559a5cf25..a64c02d58 100644 --- a/src/OutputFinish.cxx +++ b/src/OutputFinish.cxx @@ -18,12 +18,8 @@ */ #include "config.h" - -extern "C" { -#include "output_internal.h" -#include "output_plugin.h" -} - +#include "OutputInternal.hxx" +#include "OutputPlugin.hxx" #include "MixerControl.hxx" #include "FilterInternal.hxx" diff --git a/src/OutputInit.cxx b/src/OutputInit.cxx index c3a71c129..793f68dc2 100644 --- a/src/OutputInit.cxx +++ b/src/OutputInit.cxx @@ -18,17 +18,13 @@ */ #include "config.h" +#include "OutputInternal.hxx" #include "OutputControl.hxx" #include "OutputList.hxx" #include "OutputError.hxx" #include "FilterConfig.hxx" #include "output_api.h" #include "AudioParser.hxx" - -extern "C" { -#include "output_internal.h" -} - #include "MixerList.hxx" #include "MixerType.hxx" #include "MixerControl.hxx" diff --git a/src/OutputInternal.hxx b/src/OutputInternal.hxx new file mode 100644 index 000000000..dd7e5bc1d --- /dev/null +++ b/src/OutputInternal.hxx @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OUTPUT_INTERNAL_HXX +#define MPD_OUTPUT_INTERNAL_HXX + +#include "audio_format.h" +#include "pcm/pcm_buffer.h" + +#include + +#include + +class Filter; +struct config_param; + +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 audio_output { + /** + * The device's configured display name. + */ + const char *name; + + /** + * The plugin which implements this output device. + */ + const struct audio_output_plugin *plugin; + + /** + * The #mixer object associated with this audio output device. + * May be NULL 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; + + /** + * If not NULL, the device has failed, and this timer is used + * to estimate how long it should stay disabled (unless + * explicitly reopened with "play"). + */ + GTimer *fail_timer; + + /** + * The configured audio format. + */ + struct audio_format config_audio_format; + + /** + * The audio_format in which audio data is received from the + * player thread (which in turn receives it from the decoder). + */ + struct audio_format 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(). + */ + struct audio_format out_audio_format; + + /** + * The buffer used to allocate the cross-fading result. + */ + struct pcm_buffer cross_fade_buffer; + + /** + * 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 NULL if the output thread isn't + * running. + */ + GThread *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 struct music_pipe *pipe; + + /** + * This mutex protects #open, #fail_timer, #chunk and + * #chunk_finished. + */ + GMutex *mutex; + + /** + * This condition object wakes up the output thread after + * #command has been set. + */ + GCond *cond; + + /** + * The player_control object which "owns" this output. This + * object is needed to signal command completion. + */ + struct player_control *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 struct audio_output *ao) +{ + return ao->open; +} + +static inline bool +audio_output_command_is_finished(const struct audio_output *ao) +{ + return ao->command == AO_COMMAND_NONE; +} + +struct audio_output * +audio_output_new(const struct config_param *param, + struct player_control *pc, + GError **error_r); + +bool +ao_base_init(struct audio_output *ao, + const struct audio_output_plugin *plugin, + const struct config_param *param, GError **error_r); + +void +ao_base_finish(struct audio_output *ao); + +void +audio_output_free(struct audio_output *ao); + +#endif diff --git a/src/OutputPlugin.cxx b/src/OutputPlugin.cxx index 9aa0f7792..8482a1d4f 100644 --- a/src/OutputPlugin.cxx +++ b/src/OutputPlugin.cxx @@ -18,12 +18,8 @@ */ #include "config.h" - -extern "C" { -#include "output_plugin.h" -} - -#include "output_internal.h" +#include "OutputPlugin.hxx" +#include "OutputInternal.hxx" struct audio_output * ao_plugin_init(const struct audio_output_plugin *plugin, diff --git a/src/OutputPlugin.hxx b/src/OutputPlugin.hxx new file mode 100644 index 000000000..3839cd5b3 --- /dev/null +++ b/src/OutputPlugin.hxx @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_OUTPUT_PLUGIN_HXX +#define MPD_OUTPUT_PLUGIN_HXX + +#include "gcc.h" +#include "gerror.h" + +#include +#include + +struct config_param; +struct audio_format; +struct tag; + +/** + * A plugin which controls an audio output device. + */ +struct audio_output_plugin { + /** + * the plugin's name + */ + const char *name; + + /** + * Test if this plugin can provide a default output, in case + * none has been configured. This method is optional. + */ + bool (*test_default_device)(void); + + /** + * Configure and initialize the device, but do not open it + * yet. + * + * @param param the configuration section, or NULL if there is + * no configuration + * @param error location to store the error occurring, or NULL + * to ignore errors + * @return NULL on error, or an opaque pointer to the plugin's + * data + */ + struct audio_output *(*init)(const struct config_param *param, + GError **error); + + /** + * Free resources allocated by this device. + */ + void (*finish)(struct audio_output *data); + + /** + * Enable the device. This may allocate resources, preparing + * for the device to be opened. Enabling a device cannot + * fail: if an error occurs during that, it should be reported + * by the open() method. + * + * @param error_r location to store the error occurring, or + * NULL to ignore errors + * @return true on success, false on error + */ + bool (*enable)(struct audio_output *data, GError **error_r); + + /** + * Disables the device. It is closed before this method is + * called. + */ + void (*disable)(struct audio_output *data); + + /** + * Really open the device. + * + * @param audio_format the audio format in which data is going + * to be delivered; may be modified by the plugin + * @param error location to store the error occurring, or NULL + * to ignore errors + */ + bool (*open)(struct audio_output *data, struct audio_format *audio_format, + GError **error); + + /** + * Close the device. + */ + void (*close)(struct audio_output *data); + + /** + * Returns a positive number if the output thread shall delay + * the next call to play() or pause(). This should be + * implemented instead of doing a sleep inside the plugin, + * because this allows MPD to listen to commands meanwhile. + * + * @return the number of milliseconds to wait + */ + unsigned (*delay)(struct audio_output *data); + + /** + * Display metadata for the next chunk. Optional method, + * because not all devices can display metadata. + */ + void (*send_tag)(struct audio_output *data, const struct tag *tag); + + /** + * Play a chunk of audio data. + * + * @param error location to store the error occurring, or NULL + * to ignore errors + * @return the number of bytes played, or 0 on error + */ + size_t (*play)(struct audio_output *data, + const void *chunk, size_t size, + GError **error); + + /** + * Wait until the device has finished playing. + */ + void (*drain)(struct audio_output *data); + + /** + * Try to cancel data which may still be in the device's + * buffers. + */ + void (*cancel)(struct audio_output *data); + + /** + * Pause the device. If supported, it may perform a special + * action, which keeps the device open, but does not play + * anything. Output plugins like "shout" might want to play + * silence during pause, so their clients won't be + * disconnected. Plugins which do not support pausing will + * simply be closed, and have to be reopened when unpaused. + * + * @return false on error (output will be closed then), true + * for continue to pause + */ + bool (*pause)(struct audio_output *data); + + /** + * The mixer plugin associated with this output plugin. This + * may be NULL if no mixer plugin is implemented. When + * created, this mixer plugin gets the same #config_param as + * this audio output device. + */ + const struct mixer_plugin *mixer_plugin; +}; + +static inline bool +ao_plugin_test_default_device(const struct audio_output_plugin *plugin) +{ + return plugin->test_default_device != NULL + ? plugin->test_default_device() + : false; +} + +gcc_malloc +struct audio_output * +ao_plugin_init(const struct audio_output_plugin *plugin, + const struct config_param *param, + GError **error); + +void +ao_plugin_finish(struct audio_output *ao); + +bool +ao_plugin_enable(struct audio_output *ao, GError **error_r); + +void +ao_plugin_disable(struct audio_output *ao); + +bool +ao_plugin_open(struct audio_output *ao, struct audio_format *audio_format, + GError **error); + +void +ao_plugin_close(struct audio_output *ao); + +gcc_pure +unsigned +ao_plugin_delay(struct audio_output *ao); + +void +ao_plugin_send_tag(struct audio_output *ao, const struct tag *tag); + +size_t +ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size, + GError **error); + +void +ao_plugin_drain(struct audio_output *ao); + +void +ao_plugin_cancel(struct audio_output *ao); + +bool +ao_plugin_pause(struct audio_output *ao); + +#endif diff --git a/src/OutputPrint.cxx b/src/OutputPrint.cxx index 240ea967b..4e1cf9ced 100644 --- a/src/OutputPrint.cxx +++ b/src/OutputPrint.cxx @@ -25,7 +25,7 @@ #include "config.h" #include "OutputPrint.hxx" #include "OutputAll.hxx" -#include "output_internal.h" +#include "OutputInternal.hxx" #include "Client.hxx" void diff --git a/src/OutputState.cxx b/src/OutputState.cxx index 27fa34f8f..776cac8f4 100644 --- a/src/OutputState.cxx +++ b/src/OutputState.cxx @@ -25,7 +25,7 @@ #include "config.h" #include "OutputState.hxx" #include "OutputAll.hxx" -#include "output_internal.h" +#include "OutputInternal.hxx" #include diff --git a/src/OutputThread.cxx b/src/OutputThread.cxx index 34b3f50ba..7f2732fd8 100644 --- a/src/OutputThread.cxx +++ b/src/OutputThread.cxx @@ -19,13 +19,9 @@ #include "config.h" #include "OutputThread.hxx" +#include "OutputInternal.hxx" #include "output_api.h" #include "pcm/PcmMix.hxx" - -extern "C" { -#include "output_internal.h" -} - #include "notify.hxx" #include "FilterInternal.hxx" #include "filter/ConvertFilterPlugin.hxx" diff --git a/src/output/HttpdInternal.hxx b/src/output/HttpdInternal.hxx index 4b526bcde..e79b9a224 100644 --- a/src/output/HttpdInternal.hxx +++ b/src/output/HttpdInternal.hxx @@ -25,7 +25,7 @@ #ifndef MPD_OUTPUT_HTTPD_INTERNAL_H #define MPD_OUTPUT_HTTPD_INTERNAL_H -#include "output_internal.h" +#include "OutputInternal.hxx" #include "timer.h" #include "thread/Mutex.hxx" #include "event/ServerSocket.hxx" diff --git a/src/output_api.h b/src/output_api.h index dfeef3518..dee72d8db 100644 --- a/src/output_api.h +++ b/src/output_api.h @@ -20,8 +20,8 @@ #ifndef MPD_OUTPUT_API_H #define MPD_OUTPUT_API_H -#include "output_plugin.h" -#include "output_internal.h" +#include "OutputPlugin.hxx" +#include "OutputInternal.hxx" #include "audio_format.h" #include "tag.h" #include "conf.h" diff --git a/src/output_internal.h b/src/output_internal.h deleted file mode 100644 index ed4188af0..000000000 --- a/src/output_internal.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_OUTPUT_INTERNAL_H -#define MPD_OUTPUT_INTERNAL_H - -#include "audio_format.h" -#include "pcm/pcm_buffer.h" - -#include - -#include - -#ifdef __cplusplus -class Filter; -#else -typedef void *Filter; -#endif - -struct config_param; - -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 audio_output { - /** - * The device's configured display name. - */ - const char *name; - - /** - * The plugin which implements this output device. - */ - const struct audio_output_plugin *plugin; - - /** - * The #mixer object associated with this audio output device. - * May be NULL if none is available, or if software volume is - * configured. - */ -#ifdef __cplusplus - class Mixer *mixer; -#else - struct mixer *mixer; -#endif - - /** - * 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; - - /** - * If not NULL, the device has failed, and this timer is used - * to estimate how long it should stay disabled (unless - * explicitly reopened with "play"). - */ - GTimer *fail_timer; - - /** - * The configured audio format. - */ - struct audio_format config_audio_format; - - /** - * The audio_format in which audio data is received from the - * player thread (which in turn receives it from the decoder). - */ - struct audio_format 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(). - */ - struct audio_format out_audio_format; - - /** - * The buffer used to allocate the cross-fading result. - */ - struct pcm_buffer cross_fade_buffer; - - /** - * 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 NULL if the output thread isn't - * running. - */ - GThread *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 struct music_pipe *pipe; - - /** - * This mutex protects #open, #fail_timer, #chunk and - * #chunk_finished. - */ - GMutex *mutex; - - /** - * This condition object wakes up the output thread after - * #command has been set. - */ - GCond *cond; - - /** - * The player_control object which "owns" this output. This - * object is needed to signal command completion. - */ - struct player_control *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 struct audio_output *ao) -{ - return ao->open; -} - -static inline bool -audio_output_command_is_finished(const struct audio_output *ao) -{ - return ao->command == AO_COMMAND_NONE; -} - -#ifdef __cplusplus -extern "C" { -#endif - -struct audio_output * -audio_output_new(const struct config_param *param, - struct player_control *pc, - GError **error_r); - -bool -ao_base_init(struct audio_output *ao, - const struct audio_output_plugin *plugin, - const struct config_param *param, GError **error_r); - -void -ao_base_finish(struct audio_output *ao); - -void -audio_output_free(struct audio_output *ao); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/output_plugin.h b/src/output_plugin.h deleted file mode 100644 index 2b71ba6a6..000000000 --- a/src/output_plugin.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_OUTPUT_PLUGIN_H -#define MPD_OUTPUT_PLUGIN_H - -#include "gcc.h" -#include "gerror.h" - -#include -#include - -struct config_param; -struct audio_format; -struct tag; - -/** - * A plugin which controls an audio output device. - */ -struct audio_output_plugin { - /** - * the plugin's name - */ - const char *name; - - /** - * Test if this plugin can provide a default output, in case - * none has been configured. This method is optional. - */ - bool (*test_default_device)(void); - - /** - * Configure and initialize the device, but do not open it - * yet. - * - * @param param the configuration section, or NULL if there is - * no configuration - * @param error location to store the error occurring, or NULL - * to ignore errors - * @return NULL on error, or an opaque pointer to the plugin's - * data - */ - struct audio_output *(*init)(const struct config_param *param, - GError **error); - - /** - * Free resources allocated by this device. - */ - void (*finish)(struct audio_output *data); - - /** - * Enable the device. This may allocate resources, preparing - * for the device to be opened. Enabling a device cannot - * fail: if an error occurs during that, it should be reported - * by the open() method. - * - * @param error_r location to store the error occurring, or - * NULL to ignore errors - * @return true on success, false on error - */ - bool (*enable)(struct audio_output *data, GError **error_r); - - /** - * Disables the device. It is closed before this method is - * called. - */ - void (*disable)(struct audio_output *data); - - /** - * Really open the device. - * - * @param audio_format the audio format in which data is going - * to be delivered; may be modified by the plugin - * @param error location to store the error occurring, or NULL - * to ignore errors - */ - bool (*open)(struct audio_output *data, struct audio_format *audio_format, - GError **error); - - /** - * Close the device. - */ - void (*close)(struct audio_output *data); - - /** - * Returns a positive number if the output thread shall delay - * the next call to play() or pause(). This should be - * implemented instead of doing a sleep inside the plugin, - * because this allows MPD to listen to commands meanwhile. - * - * @return the number of milliseconds to wait - */ - unsigned (*delay)(struct audio_output *data); - - /** - * Display metadata for the next chunk. Optional method, - * because not all devices can display metadata. - */ - void (*send_tag)(struct audio_output *data, const struct tag *tag); - - /** - * Play a chunk of audio data. - * - * @param error location to store the error occurring, or NULL - * to ignore errors - * @return the number of bytes played, or 0 on error - */ - size_t (*play)(struct audio_output *data, - const void *chunk, size_t size, - GError **error); - - /** - * Wait until the device has finished playing. - */ - void (*drain)(struct audio_output *data); - - /** - * Try to cancel data which may still be in the device's - * buffers. - */ - void (*cancel)(struct audio_output *data); - - /** - * Pause the device. If supported, it may perform a special - * action, which keeps the device open, but does not play - * anything. Output plugins like "shout" might want to play - * silence during pause, so their clients won't be - * disconnected. Plugins which do not support pausing will - * simply be closed, and have to be reopened when unpaused. - * - * @return false on error (output will be closed then), true - * for continue to pause - */ - bool (*pause)(struct audio_output *data); - - /** - * The mixer plugin associated with this output plugin. This - * may be NULL if no mixer plugin is implemented. When - * created, this mixer plugin gets the same #config_param as - * this audio output device. - */ - const struct mixer_plugin *mixer_plugin; -}; - -static inline bool -ao_plugin_test_default_device(const struct audio_output_plugin *plugin) -{ - return plugin->test_default_device != NULL - ? plugin->test_default_device() - : false; -} - -#ifdef __cplusplus -extern "C" { -#endif - -gcc_malloc -struct audio_output * -ao_plugin_init(const struct audio_output_plugin *plugin, - const struct config_param *param, - GError **error); - -void -ao_plugin_finish(struct audio_output *ao); - -bool -ao_plugin_enable(struct audio_output *ao, GError **error_r); - -void -ao_plugin_disable(struct audio_output *ao); - -bool -ao_plugin_open(struct audio_output *ao, struct audio_format *audio_format, - GError **error); - -void -ao_plugin_close(struct audio_output *ao); - -gcc_pure -unsigned -ao_plugin_delay(struct audio_output *ao); - -void -ao_plugin_send_tag(struct audio_output *ao, const struct tag *tag); - -size_t -ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error); - -void -ao_plugin_drain(struct audio_output *ao); - -void -ao_plugin_cancel(struct audio_output *ao); - -bool -ao_plugin_pause(struct audio_output *ao); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/test/run_output.cxx b/test/run_output.cxx index e41fe1cad..8c5007a9e 100644 --- a/test/run_output.cxx +++ b/test/run_output.cxx @@ -19,6 +19,8 @@ #include "config.h" #include "OutputControl.hxx" +#include "OutputInternal.hxx" +#include "OutputPlugin.hxx" #include "conf.h" #include "Idle.hxx" #include "Main.hxx" @@ -28,12 +30,6 @@ #include "fs/Path.hxx" #include "AudioParser.hxx" #include "pcm/PcmConvert.hxx" - -extern "C" { -#include "output_plugin.h" -#include "output_internal.h" -} - #include "FilterRegistry.hxx" #include "PlayerControl.hxx" #include "stdbin.h" -- cgit v1.2.3