output/sles: migrate from class Error to C++ exceptions

This commit is contained in:
Max Kellermann 2016-11-09 08:35:35 +01:00
parent b4e5fa5c1b
commit dce211dbba

View File

@ -26,7 +26,6 @@
#include "../../OutputAPI.hxx" #include "../../OutputAPI.hxx"
#include "../../Wrapper.hxx" #include "../../Wrapper.hxx"
#include "util/Macros.hxx" #include "util/Macros.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "system/ByteOrder.hxx" #include "system/ByteOrder.hxx"
#include "Log.hxx" #include "Log.hxx"
@ -34,6 +33,8 @@
#include <SLES/OpenSLES.h> #include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h> #include <SLES/OpenSLES_Android.h>
#include <stdexcept>
class SlesOutput { class SlesOutput {
friend struct AudioOutputWrapper<SlesOutput>; friend struct AudioOutputWrapper<SlesOutput>;
@ -84,19 +85,12 @@ class SlesOutput {
uint8_t buffers[N_BUFFERS][BUFFER_SIZE]; uint8_t buffers[N_BUFFERS][BUFFER_SIZE];
public: public:
SlesOutput() SlesOutput(const ConfigBlock &block);
:base(sles_output_plugin) {}
operator AudioOutput *() { operator AudioOutput *() {
return &base; return &base;
} }
bool Initialize(const ConfigBlock &block, Error &error) {
return base.Configure(block, error);
}
bool Configure(const ConfigBlock &block, Error &error);
static SlesOutput *Create(const ConfigBlock &block, Error &error); static SlesOutput *Create(const ConfigBlock &block, Error &error);
bool Open(AudioFormat &audio_format, Error &error); bool Open(AudioFormat &audio_format, Error &error);
@ -130,62 +124,53 @@ private:
static constexpr Domain sles_domain("sles"); static constexpr Domain sles_domain("sles");
inline bool SlesOutput::SlesOutput(const ConfigBlock &block)
SlesOutput::Configure(const ConfigBlock &, Error &) :base(sles_output_plugin, block)
{ {
return true;
} }
inline bool inline bool
SlesOutput::Open(AudioFormat &audio_format, Error &error) SlesOutput::Open(AudioFormat &audio_format, Error &)
{ {
SLresult result; SLresult result;
SLObjectItf _object; SLObjectItf _object;
result = slCreateEngine(&_object, 0, nullptr, 0, result = slCreateEngine(&_object, 0, nullptr, 0,
nullptr, nullptr); nullptr, nullptr);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS)
error.Set(sles_domain, int(result), "slCreateEngine() failed"); throw std::runtime_error("slCreateEngine() failed");
return false;
}
engine_object = SLES::Object(_object); engine_object = SLES::Object(_object);
result = engine_object.Realize(false); result = engine_object.Realize(false);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result), "Engine.Realize() failed");
engine_object.Destroy(); engine_object.Destroy();
throw std::runtime_error("Engine.Realize() failed");
return false; return false;
} }
SLEngineItf _engine; SLEngineItf _engine;
result = engine_object.GetInterface(SL_IID_ENGINE, &_engine); result = engine_object.GetInterface(SL_IID_ENGINE, &_engine);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Engine.GetInterface(IID_ENGINE) failed");
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Engine.GetInterface(IID_ENGINE) failed");
} }
SLES::Engine engine(_engine); SLES::Engine engine(_engine);
result = engine.CreateOutputMix(&_object, 0, nullptr, nullptr); result = engine.CreateOutputMix(&_object, 0, nullptr, nullptr);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Engine.CreateOutputMix() failed");
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Engine.CreateOutputMix() failed");
} }
mix_object = SLES::Object(_object); mix_object = SLES::Object(_object);
result = mix_object.Realize(false); result = mix_object.Realize(false);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Mix.Realize() failed");
mix_object.Destroy(); mix_object.Destroy();
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Mix.Realize() failed");
} }
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
@ -238,11 +223,9 @@ SlesOutput::Open(AudioFormat &audio_format, Error &error)
result = engine.CreateAudioPlayer(&_object, &audioSrc, &audioSnk, result = engine.CreateAudioPlayer(&_object, &audioSrc, &audioSnk,
ARRAY_SIZE(ids2), ids2, req2); ARRAY_SIZE(ids2), ids2, req2);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Engine.CreateAudioPlayer() failed");
mix_object.Destroy(); mix_object.Destroy();
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Engine.CreateAudioPlayer() failed");
} }
play_object = SLES::Object(_object); play_object = SLES::Object(_object);
@ -260,23 +243,19 @@ SlesOutput::Open(AudioFormat &audio_format, Error &error)
result = play_object.Realize(false); result = play_object.Realize(false);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Play.Realize() failed");
play_object.Destroy(); play_object.Destroy();
mix_object.Destroy(); mix_object.Destroy();
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Play.Realize() failed");
} }
SLPlayItf _play; SLPlayItf _play;
result = play_object.GetInterface(SL_IID_PLAY, &_play); result = play_object.GetInterface(SL_IID_PLAY, &_play);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Play.GetInterface(IID_PLAY) failed");
play_object.Destroy(); play_object.Destroy();
mix_object.Destroy(); mix_object.Destroy();
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Play.GetInterface(IID_PLAY) failed");
} }
play = SLES::Play(_play); play = SLES::Play(_play);
@ -285,33 +264,27 @@ SlesOutput::Open(AudioFormat &audio_format, Error &error)
result = play_object.GetInterface(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, result = play_object.GetInterface(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
&_queue); &_queue);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Play.GetInterface(IID_ANDROIDSIMPLEBUFFERQUEUE) failed");
play_object.Destroy(); play_object.Destroy();
mix_object.Destroy(); mix_object.Destroy();
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Play.GetInterface(IID_ANDROIDSIMPLEBUFFERQUEUE) failed");
} }
queue = SLES::AndroidSimpleBufferQueue(_queue); queue = SLES::AndroidSimpleBufferQueue(_queue);
result = queue.RegisterCallback(PlayedCallback, (void *)this); result = queue.RegisterCallback(PlayedCallback, (void *)this);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Play.RegisterCallback() failed");
play_object.Destroy(); play_object.Destroy();
mix_object.Destroy(); mix_object.Destroy();
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Play.RegisterCallback() failed");
} }
result = play.SetPlayState(SL_PLAYSTATE_PLAYING); result = play.SetPlayState(SL_PLAYSTATE_PLAYING);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS) {
error.Set(sles_domain, int(result),
"Play.SetPlayState(PLAYING) failed");
play_object.Destroy(); play_object.Destroy();
mix_object.Destroy(); mix_object.Destroy();
engine_object.Destroy(); engine_object.Destroy();
return false; throw std::runtime_error("Play.SetPlayState(PLAYING) failed");
} }
pause = cancel = false; pause = cancel = false;
@ -321,7 +294,6 @@ SlesOutput::Open(AudioFormat &audio_format, Error &error)
// TODO: support other sample formats // TODO: support other sample formats
audio_format.format = SampleFormat::S16; audio_format.format = SampleFormat::S16;
return true; return true;
} }
@ -335,17 +307,14 @@ SlesOutput::Close()
} }
inline size_t inline size_t
SlesOutput::Play(const void *chunk, size_t size, Error &error) SlesOutput::Play(const void *chunk, size_t size, Error &)
{ {
cancel = false; cancel = false;
if (pause) { if (pause) {
SLresult result = play.SetPlayState(SL_PLAYSTATE_PLAYING); SLresult result = play.SetPlayState(SL_PLAYSTATE_PLAYING);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS)
error.Set(sles_domain, int(result), throw std::runtime_error("Play.SetPlayState(PLAYING) failed");
"Play.SetPlayState(PLAYING) failed");
return false;
}
pause = false; pause = false;
} }
@ -366,11 +335,8 @@ SlesOutput::Play(const void *chunk, size_t size, Error &error)
return nbytes; return nbytes;
SLresult result = queue.Enqueue(buffers[next], BUFFER_SIZE); SLresult result = queue.Enqueue(buffers[next], BUFFER_SIZE);
if (result != SL_RESULT_SUCCESS) { if (result != SL_RESULT_SUCCESS)
error.Set(sles_domain, int(result), throw std::runtime_error("AndroidSimpleBufferQueue.Enqueue() failed");
"AndroidSimpleBufferQueue.Enqueue() failed");
return 0;
}
++n_queued; ++n_queued;
next = (next + 1) % N_BUFFERS; next = (next + 1) % N_BUFFERS;
@ -447,17 +413,9 @@ sles_test_default_device()
} }
inline SlesOutput * inline SlesOutput *
SlesOutput::Create(const ConfigBlock &block, Error &error) SlesOutput::Create(const ConfigBlock &block, Error &)
{ {
SlesOutput *sles = new SlesOutput(); return new SlesOutput(block);
if (!sles->Initialize(block, error) ||
!sles->Configure(block, error)) {
delete sles;
return nullptr;
}
return sles;
} }
typedef AudioOutputWrapper<SlesOutput> Wrapper; typedef AudioOutputWrapper<SlesOutput> Wrapper;