Filter/Internal: migrate from class Error to C++ exceptions

This commit is contained in:
Max Kellermann 2016-09-04 14:32:09 +02:00
parent 28c6975732
commit 13c32111a0
14 changed files with 142 additions and 191 deletions

View File

@ -54,13 +54,15 @@ public:
/** /**
* Filters a block of PCM data. * Filters a block of PCM data.
* *
* Throws std::runtime_error on error.
*
* @param src the input buffer * @param src the input buffer
* @param error location to store the error occurring * @param error location to store the error occurring
* @return the destination buffer on success (will be * @return the destination buffer on success (will be
* invalidated by deleting this object or the next FilterPCM() * invalidated by deleting this object or the next FilterPCM()
* call), nullptr on error * call)
*/ */
virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src, Error &error) = 0; virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src) = 0;
}; };
class PreparedFilter { class PreparedFilter {
@ -70,12 +72,13 @@ public:
/** /**
* Opens the filter, preparing it for FilterPCM(). * Opens the filter, preparing it for FilterPCM().
* *
* Throws std::runtime_error on error.
*
* @param af the audio format of incoming data; the * @param af the audio format of incoming data; the
* plugin may modify the object to enforce another input * plugin may modify the object to enforce another input
* format * format
* @param error location to store the error occurring
*/ */
virtual Filter *Open(AudioFormat &af, Error &error) = 0; virtual Filter *Open(AudioFormat &af) = 0;
}; };
#endif #endif

View File

@ -51,7 +51,7 @@ public:
Filter *Get(); Filter *Get();
Filter *Open(AudioFormat &af, Error &error) override; Filter *Open(AudioFormat &af) override;
}; };
class FilterObserver::Proxy final : public Filter { class FilterObserver::Proxy final : public Filter {
@ -73,9 +73,8 @@ public:
return filter; return filter;
} }
ConstBuffer<void> FilterPCM(ConstBuffer<void> src, ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override {
Error &error) override { return filter->FilterPCM(src);
return filter->FilterPCM(src, error);
} }
}; };
@ -88,14 +87,11 @@ FilterObserver::PreparedProxy::Get()
} }
Filter * Filter *
FilterObserver::PreparedProxy::Open(AudioFormat &af, Error &error) FilterObserver::PreparedProxy::Open(AudioFormat &af)
{ {
assert(child == nullptr); assert(child == nullptr);
Filter *f = prepared_filter->Open(af, error); Filter *f = prepared_filter->Open(af);
if (f == nullptr)
return f;
return child = new Proxy(*this, f); return child = new Proxy(*this, f);
} }

View File

@ -47,8 +47,7 @@ public:
std::unique_ptr<Filter> &&_convert) std::unique_ptr<Filter> &&_convert)
:filter(std::move(_filter)), convert(std::move(_convert)) {} :filter(std::move(_filter)), convert(std::move(_convert)) {}
virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src, ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
Error &error) override;
}; };
class PreparedAutoConvertFilter final : public PreparedFilter { class PreparedAutoConvertFilter final : public PreparedFilter {
@ -63,20 +62,18 @@ public:
delete filter; delete filter;
} }
virtual Filter *Open(AudioFormat &af, Error &error) override; Filter *Open(AudioFormat &af) override;
}; };
Filter * Filter *
PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error) PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format)
{ {
assert(in_audio_format.IsValid()); assert(in_audio_format.IsValid());
/* open the "real" filter */ /* open the "real" filter */
AudioFormat child_audio_format = in_audio_format; AudioFormat child_audio_format = in_audio_format;
std::unique_ptr<Filter> new_filter(filter->Open(child_audio_format, error)); std::unique_ptr<Filter> new_filter(filter->Open(child_audio_format));
if (!new_filter)
return nullptr;
/* need to convert? */ /* need to convert? */
@ -85,10 +82,7 @@ PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error)
/* yes - create a convert_filter */ /* yes - create a convert_filter */
convert.reset(convert_filter_new(in_audio_format, convert.reset(convert_filter_new(in_audio_format,
child_audio_format, child_audio_format));
error));
if (!convert)
return nullptr;
} }
return new AutoConvertFilter(std::move(new_filter), return new AutoConvertFilter(std::move(new_filter),
@ -96,15 +90,15 @@ PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error)
} }
ConstBuffer<void> ConstBuffer<void>
AutoConvertFilter::FilterPCM(ConstBuffer<void> src, Error &error) AutoConvertFilter::FilterPCM(ConstBuffer<void> src)
{ {
if (convert != nullptr) { if (convert != nullptr) {
src = convert->FilterPCM(src, error); src = convert->FilterPCM(src);
if (src.IsNull()) if (src.IsNull())
return nullptr; return nullptr;
} }
return filter->FilterPCM(src, error); return filter->FilterPCM(src);
} }
PreparedFilter * PreparedFilter *

View File

@ -23,9 +23,8 @@
#include "filter/FilterInternal.hxx" #include "filter/FilterInternal.hxx"
#include "filter/FilterRegistry.hxx" #include "filter/FilterRegistry.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
#include "util/RuntimeError.hxx"
#include <memory> #include <memory>
#include <list> #include <list>
@ -62,8 +61,7 @@ public:
} }
/* virtual methods from class Filter */ /* virtual methods from class Filter */
ConstBuffer<void> FilterPCM(ConstBuffer<void> src, ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
Error &error) override;
}; };
class PreparedChainFilter final : public PreparedFilter { class PreparedChainFilter final : public PreparedFilter {
@ -80,8 +78,7 @@ class PreparedChainFilter final : public PreparedFilter {
Child(const Child &) = delete; Child(const Child &) = delete;
Child &operator=(const Child &) = delete; Child &operator=(const Child &) = delete;
Filter *Open(const AudioFormat &prev_audio_format, Filter *Open(const AudioFormat &prev_audio_format);
Error &error);
}; };
std::list<Child> children; std::list<Child> children;
@ -92,11 +89,9 @@ public:
} }
/* virtual methods from class PreparedFilter */ /* virtual methods from class PreparedFilter */
Filter *Open(AudioFormat &af, Error &error) override; Filter *Open(AudioFormat &af) override;
}; };
static constexpr Domain chain_filter_domain("chain_filter");
static PreparedFilter * static PreparedFilter *
chain_filter_init(gcc_unused const ConfigBlock &block, chain_filter_init(gcc_unused const ConfigBlock &block,
gcc_unused Error &error) gcc_unused Error &error)
@ -105,39 +100,31 @@ chain_filter_init(gcc_unused const ConfigBlock &block,
} }
Filter * Filter *
PreparedChainFilter::Child::Open(const AudioFormat &prev_audio_format, PreparedChainFilter::Child::Open(const AudioFormat &prev_audio_format)
Error &error)
{ {
AudioFormat conv_audio_format = prev_audio_format; AudioFormat conv_audio_format = prev_audio_format;
Filter *new_filter = filter->Open(conv_audio_format, error); Filter *new_filter = filter->Open(conv_audio_format);
if (new_filter == nullptr)
return nullptr;
if (conv_audio_format != prev_audio_format) { if (conv_audio_format != prev_audio_format) {
delete new_filter; delete new_filter;
struct audio_format_string s; struct audio_format_string s;
error.Format(chain_filter_domain, throw FormatRuntimeError("Audio format not supported by filter '%s': %s",
"Audio format not supported by filter '%s': %s", name,
name, audio_format_to_string(prev_audio_format, &s));
audio_format_to_string(prev_audio_format, &s));
return nullptr;
} }
return new_filter; return new_filter;
} }
Filter * Filter *
PreparedChainFilter::Open(AudioFormat &in_audio_format, Error &error) PreparedChainFilter::Open(AudioFormat &in_audio_format)
{ {
std::unique_ptr<ChainFilter> chain(new ChainFilter(in_audio_format)); std::unique_ptr<ChainFilter> chain(new ChainFilter(in_audio_format));
for (auto &child : children) { for (auto &child : children) {
AudioFormat audio_format = chain->GetOutAudioFormat(); AudioFormat audio_format = chain->GetOutAudioFormat();
auto *filter = child.Open(audio_format, error); auto *filter = child.Open(audio_format);
if (filter == nullptr)
return nullptr;
chain->Append(child.name, filter); chain->Append(child.name, filter);
} }
@ -145,14 +132,12 @@ PreparedChainFilter::Open(AudioFormat &in_audio_format, Error &error)
} }
ConstBuffer<void> ConstBuffer<void>
ChainFilter::FilterPCM(ConstBuffer<void> src, Error &error) ChainFilter::FilterPCM(ConstBuffer<void> src)
{ {
for (auto &child : children) { for (auto &child : children) {
/* feed the output of the previous filter as input /* feed the output of the previous filter as input
into the current one */ into the current one */
src = child.filter->FilterPCM(src, error); src = child.filter->FilterPCM(src);
if (src.IsNull())
return nullptr;
} }
/* return the output of the last filter */ /* return the output of the last filter */

View File

@ -25,9 +25,13 @@
#include "pcm/PcmConvert.hxx" #include "pcm/PcmConvert.hxx"
#include "util/Manual.hxx" #include "util/Manual.hxx"
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "poison.h" #include "poison.h"
#include <stdexcept>
#include <memory>
#include <assert.h> #include <assert.h>
class ConvertFilter final : public Filter { class ConvertFilter final : public Filter {
@ -47,17 +51,16 @@ public:
ConvertFilter(const AudioFormat &audio_format); ConvertFilter(const AudioFormat &audio_format);
~ConvertFilter(); ~ConvertFilter();
bool Set(const AudioFormat &_out_audio_format, Error &error); void Set(const AudioFormat &_out_audio_format);
virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src, ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
Error &error) override;
}; };
class PreparedConvertFilter final : public PreparedFilter { class PreparedConvertFilter final : public PreparedFilter {
public: public:
bool Set(const AudioFormat &_out_audio_format, Error &error); void Set(const AudioFormat &_out_audio_format);
Filter *Open(AudioFormat &af, Error &error) override; Filter *Open(AudioFormat &af) override;
}; };
static PreparedFilter * static PreparedFilter *
@ -67,15 +70,15 @@ convert_filter_init(gcc_unused const ConfigBlock &block,
return new PreparedConvertFilter(); return new PreparedConvertFilter();
} }
bool void
ConvertFilter::Set(const AudioFormat &_out_audio_format, Error &error) ConvertFilter::Set(const AudioFormat &_out_audio_format)
{ {
assert(in_audio_format.IsValid()); assert(in_audio_format.IsValid());
assert(_out_audio_format.IsValid()); assert(_out_audio_format.IsValid());
if (_out_audio_format == out_audio_format) if (_out_audio_format == out_audio_format)
/* no change */ /* no change */
return true; return;
if (out_audio_format != in_audio_format) { if (out_audio_format != in_audio_format) {
out_audio_format = in_audio_format; out_audio_format = in_audio_format;
@ -84,13 +87,13 @@ ConvertFilter::Set(const AudioFormat &_out_audio_format, Error &error)
if (_out_audio_format == in_audio_format) if (_out_audio_format == in_audio_format)
/* optimized special case: no-op */ /* optimized special case: no-op */
return true; return;
Error error;
if (!state.Open(in_audio_format, _out_audio_format, error)) if (!state.Open(in_audio_format, _out_audio_format, error))
return false; throw std::runtime_error(error.GetMessage());
out_audio_format = _out_audio_format; out_audio_format = _out_audio_format;
return true;
} }
ConvertFilter::ConvertFilter(const AudioFormat &audio_format) ConvertFilter::ConvertFilter(const AudioFormat &audio_format)
@ -99,7 +102,7 @@ ConvertFilter::ConvertFilter(const AudioFormat &audio_format)
} }
Filter * Filter *
PreparedConvertFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) PreparedConvertFilter::Open(AudioFormat &audio_format)
{ {
assert(audio_format.IsValid()); assert(audio_format.IsValid());
@ -115,7 +118,7 @@ ConvertFilter::~ConvertFilter()
} }
ConstBuffer<void> ConstBuffer<void>
ConvertFilter::FilterPCM(ConstBuffer<void> src, Error &error) ConvertFilter::FilterPCM(ConstBuffer<void> src)
{ {
assert(in_audio_format.IsValid()); assert(in_audio_format.IsValid());
@ -123,7 +126,12 @@ ConvertFilter::FilterPCM(ConstBuffer<void> src, Error &error)
/* optimized special case: no-op */ /* optimized special case: no-op */
return src; return src;
return state.Convert(src, error); Error error;
auto result = state.Convert(src, error);
if (result.IsNull())
throw std::runtime_error(error.GetMessage());
return result;
} }
const struct filter_plugin convert_filter_plugin = { const struct filter_plugin convert_filter_plugin = {
@ -133,23 +141,17 @@ const struct filter_plugin convert_filter_plugin = {
Filter * Filter *
convert_filter_new(const AudioFormat in_audio_format, convert_filter_new(const AudioFormat in_audio_format,
const AudioFormat out_audio_format, const AudioFormat out_audio_format)
Error &error)
{ {
auto *filter = new ConvertFilter(in_audio_format); std::unique_ptr<ConvertFilter> filter(new ConvertFilter(in_audio_format));
if (!filter->Set(out_audio_format, error)) { filter->Set(out_audio_format);
delete filter; return filter.release();
return nullptr;
}
return filter;
} }
bool void
convert_filter_set(Filter *_filter, AudioFormat out_audio_format, convert_filter_set(Filter *_filter, AudioFormat out_audio_format)
Error &error)
{ {
ConvertFilter *filter = (ConvertFilter *)_filter; ConvertFilter *filter = (ConvertFilter *)_filter;
return filter->Set(out_audio_format, error); filter->Set(out_audio_format);
} }

View File

@ -26,17 +26,17 @@ struct AudioFormat;
Filter * Filter *
convert_filter_new(AudioFormat in_audio_format, convert_filter_new(AudioFormat in_audio_format,
AudioFormat out_audio_format, AudioFormat out_audio_format);
Error &error);
/** /**
* Sets the output audio format for the specified filter. You must * Sets the output audio format for the specified filter. You must
* call this after the filter has been opened. Since this audio * call this after the filter has been opened. Since this audio
* format switch is a violation of the filter API, this filter must be * format switch is a violation of the filter API, this filter must be
* the last in a chain. * the last in a chain.
*
* Throws std::runtime_error on error.
*/ */
bool void
convert_filter_set(Filter *filter, AudioFormat out_audio_format, convert_filter_set(Filter *filter, AudioFormat out_audio_format);
Error &error);
#endif #endif

View File

@ -43,14 +43,13 @@ public:
} }
/* virtual methods from class Filter */ /* virtual methods from class Filter */
ConstBuffer<void> FilterPCM(ConstBuffer<void> src, ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
Error &error) override;
}; };
class PreparedNormalizeFilter final : public PreparedFilter { class PreparedNormalizeFilter final : public PreparedFilter {
public: public:
/* virtual methods from class PreparedFilter */ /* virtual methods from class PreparedFilter */
Filter *Open(AudioFormat &af, Error &error) override; Filter *Open(AudioFormat &af) override;
}; };
static PreparedFilter * static PreparedFilter *
@ -61,7 +60,7 @@ normalize_filter_init(gcc_unused const ConfigBlock &block,
} }
Filter * Filter *
PreparedNormalizeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) PreparedNormalizeFilter::Open(AudioFormat &audio_format)
{ {
audio_format.format = SampleFormat::S16; audio_format.format = SampleFormat::S16;
@ -69,7 +68,7 @@ PreparedNormalizeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error
} }
ConstBuffer<void> ConstBuffer<void>
NormalizeFilter::FilterPCM(ConstBuffer<void> src, gcc_unused Error &error) NormalizeFilter::FilterPCM(ConstBuffer<void> src)
{ {
int16_t *dest = (int16_t *)buffer.Get(src.size); int16_t *dest = (int16_t *)buffer.Get(src.size);
memcpy(dest, src.data, src.size); memcpy(dest, src.data, src.size);

View File

@ -36,16 +36,14 @@ class NullFilter final : public Filter {
public: public:
explicit NullFilter(const AudioFormat &af):Filter(af) {} explicit NullFilter(const AudioFormat &af):Filter(af) {}
virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src, virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override {
gcc_unused Error &error) override {
return src; return src;
} }
}; };
class PreparedNullFilter final : public PreparedFilter { class PreparedNullFilter final : public PreparedFilter {
public: public:
virtual Filter *Open(AudioFormat &af, virtual Filter *Open(AudioFormat &af) override {
gcc_unused Error &error) override {
return new NullFilter(af); return new NullFilter(af);
} }
}; };

View File

@ -32,6 +32,8 @@
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <stdexcept>
#include <assert.h> #include <assert.h>
static constexpr Domain replay_gain_domain("replay_gain"); static constexpr Domain replay_gain_domain("replay_gain");
@ -73,10 +75,10 @@ public:
:Filter(audio_format), :Filter(audio_format),
mixer(_mixer), base(_base), mode(REPLAY_GAIN_OFF) { mixer(_mixer), base(_base), mode(REPLAY_GAIN_OFF) {
info.Clear(); info.Clear();
}
bool Open(Error &error) { Error error;
return pv.Open(out_audio_format.format, error); if (!pv.Open(out_audio_format.format, error))
throw std::runtime_error(error.GetMessage());
} }
void SetInfo(const ReplayGainInfo *_info) { void SetInfo(const ReplayGainInfo *_info) {
@ -108,8 +110,7 @@ public:
void Update(); void Update();
/* virtual methods from class Filter */ /* virtual methods from class Filter */
ConstBuffer<void> FilterPCM(ConstBuffer<void> src, ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
Error &error) override;
}; };
class PreparedReplayGainFilter final : public PreparedFilter { class PreparedReplayGainFilter final : public PreparedFilter {
@ -134,7 +135,7 @@ public:
} }
/* virtual methods from class Filter */ /* virtual methods from class Filter */
Filter *Open(AudioFormat &af, Error &error) override; Filter *Open(AudioFormat &af) override;
}; };
void void
@ -174,19 +175,13 @@ replay_gain_filter_init(gcc_unused const ConfigBlock &block,
} }
Filter * Filter *
PreparedReplayGainFilter::Open(AudioFormat &af, gcc_unused Error &error) PreparedReplayGainFilter::Open(AudioFormat &af)
{ {
auto *filter = new ReplayGainFilter(af, mixer, base); return new ReplayGainFilter(af, mixer, base);
if (!filter->Open(error)) {
delete filter;
return nullptr;
}
return filter;
} }
ConstBuffer<void> ConstBuffer<void>
ReplayGainFilter::FilterPCM(ConstBuffer<void> src, gcc_unused Error &error) ReplayGainFilter::FilterPCM(ConstBuffer<void> src)
{ {
return mixer != nullptr return mixer != nullptr
? src ? src

View File

@ -96,8 +96,7 @@ public:
const std::array<int8_t, MAX_CHANNELS> &_sources); const std::array<int8_t, MAX_CHANNELS> &_sources);
/* virtual methods from class Filter */ /* virtual methods from class Filter */
ConstBuffer<void> FilterPCM(ConstBuffer<void> src, ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
Error &error) override;
}; };
class PreparedRouteFilter final : public PreparedFilter { class PreparedRouteFilter final : public PreparedFilter {
@ -136,7 +135,7 @@ public:
bool Configure(const ConfigBlock &block, Error &error); bool Configure(const ConfigBlock &block, Error &error);
/* virtual methods from class PreparedFilter */ /* virtual methods from class PreparedFilter */
Filter *Open(AudioFormat &af, Error &error) override; Filter *Open(AudioFormat &af) override;
}; };
bool bool
@ -243,13 +242,13 @@ RouteFilter::RouteFilter(const AudioFormat &audio_format,
} }
Filter * Filter *
PreparedRouteFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) PreparedRouteFilter::Open(AudioFormat &audio_format)
{ {
return new RouteFilter(audio_format, min_output_channels, sources); return new RouteFilter(audio_format, min_output_channels, sources);
} }
ConstBuffer<void> ConstBuffer<void>
RouteFilter::FilterPCM(ConstBuffer<void> src, gcc_unused Error &error) RouteFilter::FilterPCM(ConstBuffer<void> src)
{ {
size_t number_of_frames = src.size / input_frame_size; size_t number_of_frames = src.size / input_frame_size;

View File

@ -25,16 +25,19 @@
#include "pcm/Volume.hxx" #include "pcm/Volume.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include <stdexcept>
class VolumeFilter final : public Filter { class VolumeFilter final : public Filter {
PcmVolume pv; PcmVolume pv;
public: public:
explicit VolumeFilter(const AudioFormat &audio_format) explicit VolumeFilter(const AudioFormat &audio_format)
:Filter(audio_format) {} :Filter(audio_format) {
Error error;
bool Open(Error &error) { if (!pv.Open(out_audio_format.format, error))
return pv.Open(out_audio_format.format, error); throw std::runtime_error(error.GetMessage());
} }
unsigned GetVolume() const { unsigned GetVolume() const {
@ -46,8 +49,7 @@ public:
} }
/* virtual methods from class Filter */ /* virtual methods from class Filter */
ConstBuffer<void> FilterPCM(ConstBuffer<void> src, ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
Error &error) override;
}; };
class PreparedVolumeFilter final : public PreparedFilter { class PreparedVolumeFilter final : public PreparedFilter {
@ -55,7 +57,7 @@ class PreparedVolumeFilter final : public PreparedFilter {
public: public:
/* virtual methods from class Filter */ /* virtual methods from class Filter */
Filter *Open(AudioFormat &af, Error &error) override; Filter *Open(AudioFormat &af) override;
}; };
static PreparedFilter * static PreparedFilter *
@ -66,19 +68,13 @@ volume_filter_init(gcc_unused const ConfigBlock &block,
} }
Filter * Filter *
PreparedVolumeFilter::Open(AudioFormat &audio_format, Error &error) PreparedVolumeFilter::Open(AudioFormat &audio_format)
{ {
auto *filter = new VolumeFilter(audio_format); return new VolumeFilter(audio_format);
if (!filter->Open(error)) {
delete filter;
return nullptr;
}
return filter;
} }
ConstBuffer<void> ConstBuffer<void>
VolumeFilter::FilterPCM(ConstBuffer<void> src, gcc_unused Error &error) VolumeFilter::FilterPCM(ConstBuffer<void> src)
{ {
return pv.Apply(src); return pv.Apply(src);
} }

View File

@ -404,7 +404,10 @@ private:
*/ */
void CloseOutput(bool drain); void CloseOutput(bool drain);
AudioFormat OpenFilter(AudioFormat &format, Error &error_r); /**
* Throws std::runtime_error on error.
*/
AudioFormat OpenFilter(AudioFormat &format);
/** /**
* Mutex must not be locked. * Mutex must not be locked.

View File

@ -93,38 +93,28 @@ AudioOutput::Disable()
} }
inline AudioFormat inline AudioFormat
AudioOutput::OpenFilter(AudioFormat &format, Error &error_r) AudioOutput::OpenFilter(AudioFormat &format)
{ try {
assert(format.IsValid()); assert(format.IsValid());
/* the replay_gain filter cannot fail here */ /* the replay_gain filter cannot fail here */
if (prepared_replay_gain_filter != nullptr) { if (prepared_replay_gain_filter != nullptr)
replay_gain_filter_instance = replay_gain_filter_instance =
prepared_replay_gain_filter->Open(format, error_r); prepared_replay_gain_filter->Open(format);
if (replay_gain_filter_instance == nullptr)
return AudioFormat::Undefined();
}
if (prepared_other_replay_gain_filter != nullptr) { if (prepared_other_replay_gain_filter != nullptr)
other_replay_gain_filter_instance = other_replay_gain_filter_instance =
prepared_other_replay_gain_filter->Open(format, error_r); prepared_other_replay_gain_filter->Open(format);
if (other_replay_gain_filter_instance == nullptr) {
delete replay_gain_filter_instance;
return AudioFormat::Undefined();
}
}
filter_instance = prepared_filter->Open(format, error_r); filter_instance = prepared_filter->Open(format);
if (filter_instance == nullptr) {
delete other_replay_gain_filter_instance;
delete replay_gain_filter_instance;
return AudioFormat::Undefined();
}
if (mixer != nullptr && mixer->IsPlugin(software_mixer_plugin)) if (mixer != nullptr && mixer->IsPlugin(software_mixer_plugin))
software_mixer_set_filter(*mixer, volume_filter.Get()); software_mixer_set_filter(*mixer, volume_filter.Get());
return filter_instance->GetOutAudioFormat(); return filter_instance->GetOutAudioFormat();
} catch (...) {
CloseFilter();
throw;
} }
void void
@ -165,10 +155,11 @@ AudioOutput::Open()
/* open the filter */ /* open the filter */
const AudioFormat filter_audio_format = AudioFormat filter_audio_format;
OpenFilter(in_audio_format, error); try {
if (!filter_audio_format.IsDefined()) { filter_audio_format = OpenFilter(in_audio_format);
FormatError(error, "Failed to open filter for \"%s\" [%s]", } catch (const std::runtime_error &e) {
FormatError(e, "Failed to open filter for \"%s\" [%s]",
name, plugin.name); name, plugin.name);
fail_timer.Update(); fail_timer.Update();
@ -202,9 +193,10 @@ AudioOutput::Open()
return; return;
} }
if (!convert_filter_set(convert_filter.Get(), out_audio_format, try {
error)) { convert_filter_set(convert_filter.Get(), out_audio_format);
FormatError(error, "Failed to convert for \"%s\" [%s]", } catch (const std::runtime_error &e) {
FormatError(e, "Failed to convert for \"%s\" [%s]",
name, plugin.name); name, plugin.name);
mutex.unlock(); mutex.unlock();
@ -295,12 +287,12 @@ AudioOutput::ReopenFilter()
CloseFilter(); CloseFilter();
mutex.lock(); mutex.lock();
const AudioFormat filter_audio_format = AudioFormat filter_audio_format;
OpenFilter(in_audio_format, error); try {
if (!filter_audio_format.IsDefined() || filter_audio_format = OpenFilter(in_audio_format);
!convert_filter_set(convert_filter.Get(), out_audio_format, convert_filter_set(convert_filter.Get(), out_audio_format);
error)) { } catch (const std::runtime_error &e) {
FormatError(error, FormatError(e,
"Failed to open filter for \"%s\" [%s]", "Failed to open filter for \"%s\" [%s]",
name, plugin.name); name, plugin.name);
@ -383,11 +375,13 @@ ao_chunk_data(AudioOutput *ao, const MusicChunk *chunk,
*replay_gain_serial_p = chunk->replay_gain_serial; *replay_gain_serial_p = chunk->replay_gain_serial;
} }
Error error; try {
data = replay_gain_filter->FilterPCM(data, error); data = replay_gain_filter->FilterPCM(data);
if (data.IsNull()) } catch (const std::runtime_error &e) {
FormatError(error, "\"%s\" [%s] failed to filter", FormatError(e, "\"%s\" [%s] failed to filter",
ao->name, ao->plugin.name); ao->name, ao->plugin.name);
return nullptr;
}
} }
return data; return data;
@ -449,15 +443,13 @@ ao_filter_chunk(AudioOutput *ao, const MusicChunk *chunk)
/* apply filter chain */ /* apply filter chain */
Error error; try {
data = ao->filter_instance->FilterPCM(data, error); return ao->filter_instance->FilterPCM(data);
if (data.IsNull()) { } catch (const std::runtime_error &e) {
FormatError(error, "\"%s\" [%s] failed to filter", FormatError(e, "\"%s\" [%s] failed to filter",
ao->name, ao->plugin.name); ao->name, ao->plugin.name);
return nullptr; return nullptr;
} }
return data;
} }
inline bool inline bool

View File

@ -105,13 +105,7 @@ try {
/* open the filter */ /* open the filter */
Error error; std::unique_ptr<Filter> filter(prepared_filter->Open(audio_format));
std::unique_ptr<Filter> filter(prepared_filter->Open(audio_format,
error));
if (!filter) {
LogError(error, "Failed to open filter");
return EXIT_FAILURE;
}
const AudioFormat out_audio_format = filter->GetOutAudioFormat(); const AudioFormat out_audio_format = filter->GetOutAudioFormat();
@ -127,12 +121,7 @@ try {
if (nbytes <= 0) if (nbytes <= 0)
break; break;
auto dest = filter->FilterPCM({(const void *)buffer, (size_t)nbytes}, auto dest = filter->FilterPCM({(const void *)buffer, (size_t)nbytes});
error);
if (dest.IsNull()) {
LogError(error, "filter/Filter failed");
return EXIT_FAILURE;
}
nbytes = write(1, dest.data, dest.size); nbytes = write(1, dest.data, dest.size);
if (nbytes < 0) { if (nbytes < 0) {
@ -147,7 +136,7 @@ try {
config_global_finish(); config_global_finish();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} catch (const std::exception &e) { } catch (const std::exception &e) {
LogError(e); LogError(e);
return EXIT_FAILURE; return EXIT_FAILURE;
} }