output/sles: migrate from class Error to C++ exceptions
This commit is contained in:
parent
b4e5fa5c1b
commit
dce211dbba
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user