diff options
author | Max Kellermann <max@musicpd.org> | 2017-08-09 16:58:44 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2017-08-10 09:01:41 +0200 |
commit | 31bad5f7af6cb59a276319a9fc1bb9ceebdc79ff (patch) | |
tree | e703f0d6be9351b0c35f91c154dcf5b84248180c /src/output/Interface.hxx | |
parent | 1cf7f3d87c6b2668afc28caedd9efe0a242e98f4 (diff) |
output/Interface: convert to abstract class
Yet another C-style vtable replaced with C++.
Diffstat (limited to 'src/output/Interface.hxx')
-rw-r--r-- | src/output/Interface.hxx | 110 |
1 files changed, 101 insertions, 9 deletions
diff --git a/src/output/Interface.hxx b/src/output/Interface.hxx index 645a94b2e..83737df5b 100644 --- a/src/output/Interface.hxx +++ b/src/output/Interface.hxx @@ -20,22 +20,33 @@ #ifndef MPD_AUDIO_OUTPUT_INTERFACE_HXX #define MPD_AUDIO_OUTPUT_INTERFACE_HXX -struct AudioOutputPlugin; +#include <chrono> + +struct AudioFormat; +struct Tag; class AudioOutput { - /** - * The plugin which implements this output device. - */ - const AudioOutputPlugin &plugin; + const unsigned flags; bool need_fully_defined_audio_format = false; +protected: + static constexpr unsigned FLAG_ENABLE_DISABLE = 0x1; + static constexpr unsigned FLAG_PAUSE = 0x2; + public: - AudioOutput(const AudioOutputPlugin &_plugin) - :plugin(_plugin) {} + explicit AudioOutput(unsigned _flags):flags(_flags) {} + virtual ~AudioOutput() = default; + + AudioOutput(const AudioOutput &) = delete; + AudioOutput &operator=(const AudioOutput &) = delete; - const AudioOutputPlugin &GetPlugin() const { - return plugin; + bool SupportsEnableDisable() const { + return flags & FLAG_ENABLE_DISABLE; + } + + bool SupportsPause() const { + return flags & FLAG_PAUSE; } bool GetNeedFullyDefinedAudioFormat() const { @@ -50,6 +61,87 @@ public: void NeedFullyDefinedAudioFormat() { need_fully_defined_audio_format = true; } + + /** + * Enable the device. This may allocate resources, preparing + * for the device to be opened. + * + * Throws #std::runtime_error on error. + */ + virtual void Enable() {} + + /** + * Disables the device. It is closed before this method is + * called. + */ + virtual void Disable() noexcept {} + + /** + * Really open the device. + * + * Throws #std::runtime_error on error. + * + * @param audio_format the audio format in which data is going + * to be delivered; may be modified by the plugin + */ + virtual void Open(AudioFormat &audio_format) = 0; + + /** + * Close the device. + */ + virtual void Close() noexcept = 0; + + /** + * Returns a positive number if the output thread shall further + * delay the next call to Play() or Pause(), which will happen + * until this function returns 0. This should be implemented + * instead of doing a sleep inside the plugin, because this + * allows MPD to listen to commands meanwhile. + * + * @return the duration to wait + */ + virtual std::chrono::steady_clock::duration Delay() const noexcept { + return std::chrono::steady_clock::duration::zero(); + } + + /** + * Display metadata for the next chunk. Optional method, + * because not all devices can display metadata. + */ + virtual void SendTag(const Tag &) {} + + /** + * Play a chunk of audio data. + * + * Throws #std::runtime_error on error. + * + * @return the number of bytes played + */ + virtual size_t Play(const void *chunk, size_t size) = 0; + + /** + * Wait until the device has finished playing. + */ + virtual void Drain() {} + + /** + * Try to cancel data which may still be in the device's + * buffers. + */ + virtual void Cancel() noexcept {} + + /** + * 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 by caller), + * true for continue to pause + */ + virtual bool Pause() noexcept { return true; } }; #endif |