summaryrefslogtreecommitdiff
path: root/src/output/Interface.hxx
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2017-08-09 16:58:44 +0200
committerMax Kellermann <max@musicpd.org>2017-08-10 09:01:41 +0200
commit31bad5f7af6cb59a276319a9fc1bb9ceebdc79ff (patch)
treee703f0d6be9351b0c35f91c154dcf5b84248180c /src/output/Interface.hxx
parent1cf7f3d87c6b2668afc28caedd9efe0a242e98f4 (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.hxx110
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