output/Wrapper: new helper class
This commit is contained in:
		| @@ -1236,6 +1236,7 @@ OUTPUT_LIBS = \ | |||||||
| OUTPUT_API_SRC = \ | OUTPUT_API_SRC = \ | ||||||
| 	src/output/OutputAPI.hxx \ | 	src/output/OutputAPI.hxx \ | ||||||
| 	src/output/Internal.hxx \ | 	src/output/Internal.hxx \ | ||||||
|  | 	src/output/Wrapper.hxx \ | ||||||
| 	src/output/Registry.cxx src/output/Registry.hxx \ | 	src/output/Registry.cxx src/output/Registry.hxx \ | ||||||
| 	src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx \ | 	src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx \ | ||||||
| 	src/output/OutputThread.cxx \ | 	src/output/OutputThread.cxx \ | ||||||
|   | |||||||
							
								
								
									
										93
									
								
								src/output/Wrapper.hxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/output/Wrapper.hxx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | |||||||
|  | /* | ||||||
|  |  * 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_WRAPPER_HXX | ||||||
|  | #define MPD_OUTPUT_WRAPPER_HXX | ||||||
|  |  | ||||||
|  | #include "util/Cast.hxx" | ||||||
|  |  | ||||||
|  | template<class T> | ||||||
|  | struct AudioOutputWrapper { | ||||||
|  | 	static T &Cast(AudioOutput &ao) { | ||||||
|  | 		return ContainerCast(ao, &T::base); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static AudioOutput *Init(const config_param ¶m, Error &error) { | ||||||
|  | 		T *t = T::Create(param, error); | ||||||
|  | 		return t != nullptr | ||||||
|  | 			? &t->base | ||||||
|  | 			: nullptr; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static void Finish(AudioOutput *ao) { | ||||||
|  | 		T *t = &Cast(*ao); | ||||||
|  | 		delete t; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static bool Enable(AudioOutput *ao, Error &error) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		return t.Enable(error); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static void Disable(AudioOutput *ao) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		t.Disable(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static bool Open(AudioOutput *ao, AudioFormat &audio_format, | ||||||
|  | 			 Error &error) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		return t.Open(audio_format, error); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static void Close(AudioOutput *ao) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		t.Close(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	gcc_pure | ||||||
|  | 	static unsigned Delay(AudioOutput *ao) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		return t.Delay(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static size_t Play(AudioOutput *ao, const void *chunk, size_t size, | ||||||
|  | 			   Error &error) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		return t.Play(chunk, size, error); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static void Drain(AudioOutput *ao) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		t.Drain(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static void Cancel(AudioOutput *ao) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		t.Cancel(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	gcc_pure | ||||||
|  | 	static bool Pause(AudioOutput *ao) { | ||||||
|  | 		T &t = Cast(*ao); | ||||||
|  | 		return t.Pause(); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -20,6 +20,7 @@ | |||||||
| #include "config.h" | #include "config.h" | ||||||
| #include "JackOutputPlugin.hxx" | #include "JackOutputPlugin.hxx" | ||||||
| #include "../OutputAPI.hxx" | #include "../OutputAPI.hxx" | ||||||
|  | #include "../Wrapper.hxx" | ||||||
| #include "config/ConfigError.hxx" | #include "config/ConfigError.hxx" | ||||||
| #include "util/ConstBuffer.hxx" | #include "util/ConstBuffer.hxx" | ||||||
| #include "util/SplitString.hxx" | #include "util/SplitString.hxx" | ||||||
| @@ -100,6 +101,10 @@ struct JackOutput { | |||||||
|  |  | ||||||
| 	bool Open(AudioFormat &new_audio_format, Error &error); | 	bool Open(AudioFormat &new_audio_format, Error &error); | ||||||
|  |  | ||||||
|  | 	void Close() { | ||||||
|  | 		Stop(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	bool Start(Error &error); | 	bool Start(Error &error); | ||||||
| 	void Stop(); | 	void Stop(); | ||||||
|  |  | ||||||
| @@ -117,7 +122,15 @@ struct JackOutput { | |||||||
| 	 */ | 	 */ | ||||||
| 	size_t WriteSamples(const float *src, size_t n_frames); | 	size_t WriteSamples(const float *src, size_t n_frames); | ||||||
|  |  | ||||||
|  | 	unsigned Delay() const { | ||||||
|  | 		return base.pause && pause && !shutdown | ||||||
|  | 			? 1000 | ||||||
|  | 			: 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	size_t Play(const void *chunk, size_t size, Error &error); | 	size_t Play(const void *chunk, size_t size, Error &error); | ||||||
|  |  | ||||||
|  | 	bool Pause(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static constexpr Domain jack_output_domain("jack_output"); | static constexpr Domain jack_output_domain("jack_output"); | ||||||
| @@ -468,30 +481,6 @@ mpd_jack_init(const config_param ¶m, Error &error) | |||||||
| 	return &jd->base; | 	return &jd->base; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void |  | ||||||
| mpd_jack_finish(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	JackOutput *jd = (JackOutput *)ao; |  | ||||||
|  |  | ||||||
| 	delete jd; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static bool |  | ||||||
| mpd_jack_enable(AudioOutput *ao, Error &error) |  | ||||||
| { |  | ||||||
| 	JackOutput &jo = *(JackOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return jo.Enable(error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| mpd_jack_disable(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	JackOutput &jo = *(JackOutput *)ao; |  | ||||||
|  |  | ||||||
| 	jo.Disable(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Stops the playback on the JACK connection. |  * Stops the playback on the JACK connection. | ||||||
|  */ |  */ | ||||||
| @@ -648,33 +637,6 @@ JackOutput::Open(AudioFormat &new_audio_format, Error &error) | |||||||
| 	return Start(error); | 	return Start(error); | ||||||
| } | } | ||||||
|  |  | ||||||
| static bool |  | ||||||
| mpd_jack_open(AudioOutput *ao, AudioFormat &audio_format, |  | ||||||
| 	      Error &error) |  | ||||||
| { |  | ||||||
| 	JackOutput &jo = *(JackOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return jo.Open(audio_format, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| mpd_jack_close(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	JackOutput &jo = *(JackOutput *)ao; |  | ||||||
|  |  | ||||||
| 	jo.Stop(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static unsigned |  | ||||||
| mpd_jack_delay(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	JackOutput *jd = (JackOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return jd->base.pause && jd->pause && !jd->shutdown |  | ||||||
| 		? 1000 |  | ||||||
| 		: 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t | inline size_t | ||||||
| JackOutput::WriteSamples(const float *src, size_t n_frames) | JackOutput::WriteSamples(const float *src, size_t n_frames) | ||||||
| { | { | ||||||
| @@ -744,42 +706,33 @@ JackOutput::Play(const void *chunk, size_t size, Error &error) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static size_t | inline bool | ||||||
| mpd_jack_play(AudioOutput *ao, const void *chunk, size_t size, | JackOutput::Pause() | ||||||
| 	      Error &error) |  | ||||||
| { | { | ||||||
| 	JackOutput &jo = *(JackOutput *)ao; | 	if (shutdown) | ||||||
|  |  | ||||||
| 	return jo.Play(chunk, size, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static bool |  | ||||||
| mpd_jack_pause(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	JackOutput *jd = (JackOutput *)ao; |  | ||||||
|  |  | ||||||
| 	if (jd->shutdown) |  | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 	jd->pause = true; | 	pause = true; | ||||||
|  |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | typedef AudioOutputWrapper<JackOutput> Wrapper; | ||||||
|  |  | ||||||
| const struct AudioOutputPlugin jack_output_plugin = { | const struct AudioOutputPlugin jack_output_plugin = { | ||||||
| 	"jack", | 	"jack", | ||||||
| 	mpd_jack_test_default_device, | 	mpd_jack_test_default_device, | ||||||
| 	mpd_jack_init, | 	mpd_jack_init, | ||||||
| 	mpd_jack_finish, | 	&Wrapper::Finish, | ||||||
| 	mpd_jack_enable, | 	&Wrapper::Enable, | ||||||
| 	mpd_jack_disable, | 	&Wrapper::Disable, | ||||||
| 	mpd_jack_open, | 	&Wrapper::Open, | ||||||
| 	mpd_jack_close, | 	&Wrapper::Close, | ||||||
| 	mpd_jack_delay, | 	&Wrapper::Delay, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	mpd_jack_play, | 	&Wrapper::Play, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	mpd_jack_pause, | 	&Wrapper::Pause, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ | |||||||
| #include "config.h" | #include "config.h" | ||||||
| #include "PipeOutputPlugin.hxx" | #include "PipeOutputPlugin.hxx" | ||||||
| #include "../OutputAPI.hxx" | #include "../OutputAPI.hxx" | ||||||
|  | #include "../Wrapper.hxx" | ||||||
| #include "config/ConfigError.hxx" | #include "config/ConfigError.hxx" | ||||||
| #include "util/Error.hxx" | #include "util/Error.hxx" | ||||||
| #include "util/Domain.hxx" | #include "util/Domain.hxx" | ||||||
| @@ -29,6 +30,8 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  |  | ||||||
| class PipeOutput { | class PipeOutput { | ||||||
|  | 	friend AudioOutputWrapper<PipeOutput>; | ||||||
|  |  | ||||||
| 	AudioOutput base; | 	AudioOutput base; | ||||||
|  |  | ||||||
| 	std::string cmd; | 	std::string cmd; | ||||||
| @@ -40,7 +43,7 @@ class PipeOutput { | |||||||
| 	bool Configure(const config_param ¶m, Error &error); | 	bool Configure(const config_param ¶m, Error &error); | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	static AudioOutput *Create(const config_param ¶m, Error &error); | 	static PipeOutput *Create(const config_param ¶m, Error &error); | ||||||
|  |  | ||||||
| 	bool Open(AudioFormat &audio_format, Error &error); | 	bool Open(AudioFormat &audio_format, Error &error); | ||||||
|  |  | ||||||
| @@ -70,7 +73,7 @@ PipeOutput::Configure(const config_param ¶m, Error &error) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline AudioOutput * | inline PipeOutput * | ||||||
| PipeOutput::Create(const config_param ¶m, Error &error) | PipeOutput::Create(const config_param ¶m, Error &error) | ||||||
| { | { | ||||||
| 	PipeOutput *po = new PipeOutput(); | 	PipeOutput *po = new PipeOutput(); | ||||||
| @@ -80,21 +83,7 @@ PipeOutput::Create(const config_param ¶m, Error &error) | |||||||
| 		return nullptr; | 		return nullptr; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &po->base; | 	return po; | ||||||
| } |  | ||||||
|  |  | ||||||
| static AudioOutput * |  | ||||||
| pipe_output_init(const config_param ¶m, Error &error) |  | ||||||
| { |  | ||||||
| 	return PipeOutput::Create(param, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| pipe_output_finish(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	PipeOutput *pd = (PipeOutput *)ao; |  | ||||||
|  |  | ||||||
| 	delete pd; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool | inline bool | ||||||
| @@ -110,22 +99,6 @@ PipeOutput::Open(gcc_unused AudioFormat &audio_format, Error &error) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| static bool |  | ||||||
| pipe_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) |  | ||||||
| { |  | ||||||
| 	PipeOutput &po = *(PipeOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return po.Open(audio_format, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| pipe_output_close(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	PipeOutput &po = *(PipeOutput *)ao; |  | ||||||
|  |  | ||||||
| 	po.Close(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t | inline size_t | ||||||
| PipeOutput::Play(const void *chunk, size_t size, Error &error) | PipeOutput::Play(const void *chunk, size_t size, Error &error) | ||||||
| { | { | ||||||
| @@ -136,27 +109,20 @@ PipeOutput::Play(const void *chunk, size_t size, Error &error) | |||||||
| 	return nbytes; | 	return nbytes; | ||||||
| } | } | ||||||
|  |  | ||||||
| static size_t | typedef AudioOutputWrapper<PipeOutput> Wrapper; | ||||||
| pipe_output_play(AudioOutput *ao, const void *chunk, size_t size, |  | ||||||
| 		 Error &error) |  | ||||||
| { |  | ||||||
| 	PipeOutput &po = *(PipeOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return po.Play(chunk, size, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const struct AudioOutputPlugin pipe_output_plugin = { | const struct AudioOutputPlugin pipe_output_plugin = { | ||||||
| 	"pipe", | 	"pipe", | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	pipe_output_init, | 	&Wrapper::Init, | ||||||
| 	pipe_output_finish, | 	&Wrapper::Finish, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	pipe_output_open, | 	&Wrapper::Open, | ||||||
| 	pipe_output_close, | 	&Wrapper::Close, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	pipe_output_play, | 	&Wrapper::Play, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	nullptr, | 	nullptr, | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ | |||||||
| #include "config.h" | #include "config.h" | ||||||
| #include "RecorderOutputPlugin.hxx" | #include "RecorderOutputPlugin.hxx" | ||||||
| #include "../OutputAPI.hxx" | #include "../OutputAPI.hxx" | ||||||
|  | #include "../Wrapper.hxx" | ||||||
| #include "encoder/EncoderPlugin.hxx" | #include "encoder/EncoderPlugin.hxx" | ||||||
| #include "encoder/EncoderList.hxx" | #include "encoder/EncoderList.hxx" | ||||||
| #include "config/ConfigError.hxx" | #include "config/ConfigError.hxx" | ||||||
| @@ -213,16 +214,6 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &error) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| static bool |  | ||||||
| recorder_output_open(AudioOutput *ao, |  | ||||||
| 		     AudioFormat &audio_format, |  | ||||||
| 		     Error &error) |  | ||||||
| { |  | ||||||
| 	RecorderOutput &recorder = *(RecorderOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return recorder.Open(audio_format, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void | inline void | ||||||
| RecorderOutput::Close() | RecorderOutput::Close() | ||||||
| { | { | ||||||
| @@ -238,14 +229,6 @@ RecorderOutput::Close() | |||||||
| 	close(fd); | 	close(fd); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void |  | ||||||
| recorder_output_close(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	RecorderOutput &recorder = *(RecorderOutput *)ao; |  | ||||||
|  |  | ||||||
| 	recorder.Close(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void | inline void | ||||||
| RecorderOutput::SendTag(const Tag &tag) | RecorderOutput::SendTag(const Tag &tag) | ||||||
| { | { | ||||||
| @@ -275,6 +258,8 @@ recorder_output_play(AudioOutput *ao, const void *chunk, size_t size, | |||||||
| 		? size : 0; | 		? size : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | typedef AudioOutputWrapper<RecorderOutput> Wrapper; | ||||||
|  |  | ||||||
| const struct AudioOutputPlugin recorder_output_plugin = { | const struct AudioOutputPlugin recorder_output_plugin = { | ||||||
| 	"recorder", | 	"recorder", | ||||||
| 	nullptr, | 	nullptr, | ||||||
| @@ -282,8 +267,8 @@ const struct AudioOutputPlugin recorder_output_plugin = { | |||||||
| 	recorder_output_finish, | 	recorder_output_finish, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	recorder_output_open, | 	&Wrapper::Open, | ||||||
| 	recorder_output_close, | 	&Wrapper::Close, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	recorder_output_send_tag, | 	recorder_output_send_tag, | ||||||
| 	recorder_output_play, | 	recorder_output_play, | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ | |||||||
| #include "config.h" | #include "config.h" | ||||||
| #include "RoarOutputPlugin.hxx" | #include "RoarOutputPlugin.hxx" | ||||||
| #include "../OutputAPI.hxx" | #include "../OutputAPI.hxx" | ||||||
|  | #include "../Wrapper.hxx" | ||||||
| #include "mixer/MixerList.hxx" | #include "mixer/MixerList.hxx" | ||||||
| #include "thread/Mutex.hxx" | #include "thread/Mutex.hxx" | ||||||
| #include "util/Error.hxx" | #include "util/Error.hxx" | ||||||
| @@ -36,6 +37,8 @@ | |||||||
| #undef new | #undef new | ||||||
|  |  | ||||||
| class RoarOutput { | class RoarOutput { | ||||||
|  | 	friend struct AudioOutputWrapper<RoarOutput>; | ||||||
|  |  | ||||||
| 	AudioOutput base; | 	AudioOutput base; | ||||||
|  |  | ||||||
| 	std::string host, name; | 	std::string host, name; | ||||||
| @@ -146,14 +149,6 @@ roar_init(const config_param ¶m, Error &error) | |||||||
| 	return *self; | 	return *self; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void |  | ||||||
| roar_finish(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	RoarOutput *self = (RoarOutput *)ao; |  | ||||||
|  |  | ||||||
| 	delete self; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void | static void | ||||||
| roar_use_audio_format(struct roar_audio_info *info, | roar_use_audio_format(struct roar_audio_info *info, | ||||||
| 		      AudioFormat &audio_format) | 		      AudioFormat &audio_format) | ||||||
| @@ -221,14 +216,6 @@ RoarOutput::Open(AudioFormat &audio_format, Error &error) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| static bool |  | ||||||
| roar_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) |  | ||||||
| { |  | ||||||
| 	RoarOutput *self = (RoarOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return self->Open(audio_format, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void | inline void | ||||||
| RoarOutput::Close() | RoarOutput::Close() | ||||||
| { | { | ||||||
| @@ -242,13 +229,6 @@ RoarOutput::Close() | |||||||
| 	roar_disconnect(&con); | 	roar_disconnect(&con); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void |  | ||||||
| roar_close(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	RoarOutput *self = (RoarOutput *)ao; |  | ||||||
| 	self->Close(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void | inline void | ||||||
| RoarOutput::Cancel() | RoarOutput::Cancel() | ||||||
| { | { | ||||||
| @@ -277,14 +257,6 @@ RoarOutput::Cancel() | |||||||
| 	alive = true; | 	alive = true; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void |  | ||||||
| roar_cancel(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	RoarOutput *self = (RoarOutput *)ao; |  | ||||||
|  |  | ||||||
| 	self->Cancel(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t | inline size_t | ||||||
| RoarOutput::Play(const void *chunk, size_t size, Error &error) | RoarOutput::Play(const void *chunk, size_t size, Error &error) | ||||||
| { | { | ||||||
| @@ -302,14 +274,6 @@ RoarOutput::Play(const void *chunk, size_t size, Error &error) | |||||||
| 	return nbytes; | 	return nbytes; | ||||||
| } | } | ||||||
|  |  | ||||||
| static size_t |  | ||||||
| roar_play(AudioOutput *ao, const void *chunk, size_t size, |  | ||||||
| 	  Error &error) |  | ||||||
| { |  | ||||||
| 	RoarOutput *self = (RoarOutput *)ao; |  | ||||||
| 	return self->Play(chunk, size, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static const char* | static const char* | ||||||
| roar_tag_convert(TagType type, bool *is_uuid) | roar_tag_convert(TagType type, bool *is_uuid) | ||||||
| { | { | ||||||
| @@ -413,20 +377,22 @@ roar_send_tag(AudioOutput *ao, const Tag &meta) | |||||||
| 	self->SendTag(meta); | 	self->SendTag(meta); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | typedef AudioOutputWrapper<RoarOutput> Wrapper; | ||||||
|  |  | ||||||
| const struct AudioOutputPlugin roar_output_plugin = { | const struct AudioOutputPlugin roar_output_plugin = { | ||||||
| 	"roar", | 	"roar", | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	roar_init, | 	roar_init, | ||||||
| 	roar_finish, | 	&Wrapper::Finish, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	roar_open, | 	&Wrapper::Open, | ||||||
| 	roar_close, | 	&Wrapper::Close, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	roar_send_tag, | 	roar_send_tag, | ||||||
| 	roar_play, | 	&Wrapper::Play, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	roar_cancel, | 	&Wrapper::Cancel, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	&roar_mixer_plugin, | 	&roar_mixer_plugin, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ | |||||||
| #include "Play.hxx" | #include "Play.hxx" | ||||||
| #include "AndroidSimpleBufferQueue.hxx" | #include "AndroidSimpleBufferQueue.hxx" | ||||||
| #include "../../OutputAPI.hxx" | #include "../../OutputAPI.hxx" | ||||||
|  | #include "../../Wrapper.hxx" | ||||||
| #include "util/Macros.hxx" | #include "util/Macros.hxx" | ||||||
| #include "util/Error.hxx" | #include "util/Error.hxx" | ||||||
| #include "util/Domain.hxx" | #include "util/Domain.hxx" | ||||||
| @@ -34,6 +35,8 @@ | |||||||
| #include <SLES/OpenSLES_Android.h> | #include <SLES/OpenSLES_Android.h> | ||||||
|  |  | ||||||
| class SlesOutput { | class SlesOutput { | ||||||
|  | 	friend AudioOutputWrapper<SlesOutput>; | ||||||
|  |  | ||||||
| 	static constexpr unsigned N_BUFFERS = 3; | 	static constexpr unsigned N_BUFFERS = 3; | ||||||
| 	static constexpr size_t BUFFER_SIZE = 65536; | 	static constexpr size_t BUFFER_SIZE = 65536; | ||||||
|  |  | ||||||
| @@ -455,85 +458,22 @@ sles_output_init(const config_param ¶m, Error &error) | |||||||
| 	return *sles; | 	return *sles; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void | typedef AudioOutputWrapper<SlesOutput> Wrapper; | ||||||
| sles_output_finish(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	SlesOutput *sles = (SlesOutput *)ao; |  | ||||||
|  |  | ||||||
| 	delete sles; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static bool |  | ||||||
| sles_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &error) |  | ||||||
| { |  | ||||||
| 	SlesOutput &sles = *(SlesOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return sles.Open(audio_format, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| sles_output_close(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	SlesOutput &sles = *(SlesOutput *)ao; |  | ||||||
|  |  | ||||||
| 	sles.Close(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static unsigned |  | ||||||
| sles_output_delay(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	SlesOutput &sles = *(SlesOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return sles.Delay(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static size_t |  | ||||||
| sles_output_play(AudioOutput *ao, const void *chunk, size_t size, |  | ||||||
| 		 Error &error) |  | ||||||
| { |  | ||||||
| 	SlesOutput &sles = *(SlesOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return sles.Play(chunk, size, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| sles_output_drain(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	SlesOutput &sles = *(SlesOutput *)ao; |  | ||||||
|  |  | ||||||
| 	sles.Drain(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| sles_output_cancel(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	SlesOutput &sles = *(SlesOutput *)ao; |  | ||||||
|  |  | ||||||
| 	sles.Cancel(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static bool |  | ||||||
| sles_output_pause(AudioOutput *ao) |  | ||||||
| { |  | ||||||
| 	SlesOutput &sles = *(SlesOutput *)ao; |  | ||||||
|  |  | ||||||
| 	return sles.Pause(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const struct AudioOutputPlugin sles_output_plugin = { | const struct AudioOutputPlugin sles_output_plugin = { | ||||||
| 	"sles", | 	"sles", | ||||||
| 	sles_test_default_device, | 	sles_test_default_device, | ||||||
| 	sles_output_init, | 	sles_output_init, | ||||||
| 	sles_output_finish, | 	&Wrapper::Finish, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	sles_output_open, | 	&Wrapper::Open, | ||||||
| 	sles_output_close, | 	&Wrapper::Close, | ||||||
| 	sles_output_delay, | 	&Wrapper::Delay, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| 	sles_output_play, | 	&Wrapper::Play, | ||||||
| 	sles_output_drain, | 	&Wrapper::Drain, | ||||||
| 	sles_output_cancel, | 	&Wrapper::Cancel, | ||||||
| 	sles_output_pause, | 	&Wrapper::Pause, | ||||||
| 	nullptr, | 	nullptr, | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann