Interface.hxx 3.88 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Copyright 2003-2017 The Music Player Daemon Project
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef MPD_AUDIO_OUTPUT_INTERFACE_HXX
#define MPD_AUDIO_OUTPUT_INTERFACE_HXX

23 24 25 26
#include <chrono>

struct AudioFormat;
struct Tag;
27

28
class AudioOutput {
29
	const unsigned flags;
30 31 32

	bool need_fully_defined_audio_format = false;

33 34 35 36
protected:
	static constexpr unsigned FLAG_ENABLE_DISABLE = 0x1;
	static constexpr unsigned FLAG_PAUSE = 0x2;

37
public:
38 39 40 41 42
	explicit AudioOutput(unsigned _flags):flags(_flags) {}
	virtual ~AudioOutput() = default;

	AudioOutput(const AudioOutput &) = delete;
	AudioOutput &operator=(const AudioOutput &) = delete;
43

44 45 46 47 48 49
	bool SupportsEnableDisable() const {
		return flags & FLAG_ENABLE_DISABLE;
	}

	bool SupportsPause() const {
		return flags & FLAG_PAUSE;
50 51 52 53 54 55
	}

	bool GetNeedFullyDefinedAudioFormat() const {
		return need_fully_defined_audio_format;
	}

56 57 58 59 60 61 62 63
	/**
	 * Plugins shall call this method if they require an
	 * "audio_format" setting which evaluates
	 * AudioFormat::IsFullyDefined().
	 */
	void NeedFullyDefinedAudioFormat() {
		need_fully_defined_audio_format = true;
	}
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

	/**
	 * 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; }
145 146 147
};

#endif