Filter/Internal: migrate from class Error to C++ exceptions
This commit is contained in:
parent
28c6975732
commit
13c32111a0
@ -54,13 +54,15 @@ public:
|
||||
/**
|
||||
* Filters a block of PCM data.
|
||||
*
|
||||
* Throws std::runtime_error on error.
|
||||
*
|
||||
* @param src the input buffer
|
||||
* @param error location to store the error occurring
|
||||
* @return the destination buffer on success (will be
|
||||
* 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 {
|
||||
@ -70,12 +72,13 @@ public:
|
||||
/**
|
||||
* Opens the filter, preparing it for FilterPCM().
|
||||
*
|
||||
* Throws std::runtime_error on error.
|
||||
*
|
||||
* @param af the audio format of incoming data; the
|
||||
* plugin may modify the object to enforce another input
|
||||
* format
|
||||
* @param error location to store the error occurring
|
||||
*/
|
||||
virtual Filter *Open(AudioFormat &af, Error &error) = 0;
|
||||
virtual Filter *Open(AudioFormat &af) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
|
||||
Filter *Get();
|
||||
|
||||
Filter *Open(AudioFormat &af, Error &error) override;
|
||||
Filter *Open(AudioFormat &af) override;
|
||||
};
|
||||
|
||||
class FilterObserver::Proxy final : public Filter {
|
||||
@ -73,9 +73,8 @@ public:
|
||||
return filter;
|
||||
}
|
||||
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
Error &error) override {
|
||||
return filter->FilterPCM(src, error);
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override {
|
||||
return filter->FilterPCM(src);
|
||||
}
|
||||
};
|
||||
|
||||
@ -88,14 +87,11 @@ FilterObserver::PreparedProxy::Get()
|
||||
}
|
||||
|
||||
Filter *
|
||||
FilterObserver::PreparedProxy::Open(AudioFormat &af, Error &error)
|
||||
FilterObserver::PreparedProxy::Open(AudioFormat &af)
|
||||
{
|
||||
assert(child == nullptr);
|
||||
|
||||
Filter *f = prepared_filter->Open(af, error);
|
||||
if (f == nullptr)
|
||||
return f;
|
||||
|
||||
Filter *f = prepared_filter->Open(af);
|
||||
return child = new Proxy(*this, f);
|
||||
}
|
||||
|
||||
|
@ -47,8 +47,7 @@ public:
|
||||
std::unique_ptr<Filter> &&_convert)
|
||||
:filter(std::move(_filter)), convert(std::move(_convert)) {}
|
||||
|
||||
virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
Error &error) override;
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||
};
|
||||
|
||||
class PreparedAutoConvertFilter final : public PreparedFilter {
|
||||
@ -63,20 +62,18 @@ public:
|
||||
delete filter;
|
||||
}
|
||||
|
||||
virtual Filter *Open(AudioFormat &af, Error &error) override;
|
||||
Filter *Open(AudioFormat &af) override;
|
||||
};
|
||||
|
||||
Filter *
|
||||
PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error)
|
||||
PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format)
|
||||
{
|
||||
assert(in_audio_format.IsValid());
|
||||
|
||||
/* open the "real" filter */
|
||||
|
||||
AudioFormat child_audio_format = in_audio_format;
|
||||
std::unique_ptr<Filter> new_filter(filter->Open(child_audio_format, error));
|
||||
if (!new_filter)
|
||||
return nullptr;
|
||||
std::unique_ptr<Filter> new_filter(filter->Open(child_audio_format));
|
||||
|
||||
/* need to convert? */
|
||||
|
||||
@ -85,10 +82,7 @@ PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error)
|
||||
/* yes - create a convert_filter */
|
||||
|
||||
convert.reset(convert_filter_new(in_audio_format,
|
||||
child_audio_format,
|
||||
error));
|
||||
if (!convert)
|
||||
return nullptr;
|
||||
child_audio_format));
|
||||
}
|
||||
|
||||
return new AutoConvertFilter(std::move(new_filter),
|
||||
@ -96,15 +90,15 @@ PreparedAutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error)
|
||||
}
|
||||
|
||||
ConstBuffer<void>
|
||||
AutoConvertFilter::FilterPCM(ConstBuffer<void> src, Error &error)
|
||||
AutoConvertFilter::FilterPCM(ConstBuffer<void> src)
|
||||
{
|
||||
if (convert != nullptr) {
|
||||
src = convert->FilterPCM(src, error);
|
||||
src = convert->FilterPCM(src);
|
||||
if (src.IsNull())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return filter->FilterPCM(src, error);
|
||||
return filter->FilterPCM(src);
|
||||
}
|
||||
|
||||
PreparedFilter *
|
||||
|
@ -23,9 +23,8 @@
|
||||
#include "filter/FilterInternal.hxx"
|
||||
#include "filter/FilterRegistry.hxx"
|
||||
#include "AudioFormat.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "util/ConstBuffer.hxx"
|
||||
#include "util/RuntimeError.hxx"
|
||||
|
||||
#include <memory>
|
||||
#include <list>
|
||||
@ -62,8 +61,7 @@ public:
|
||||
}
|
||||
|
||||
/* virtual methods from class Filter */
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
Error &error) override;
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||
};
|
||||
|
||||
class PreparedChainFilter final : public PreparedFilter {
|
||||
@ -80,8 +78,7 @@ class PreparedChainFilter final : public PreparedFilter {
|
||||
Child(const Child &) = delete;
|
||||
Child &operator=(const Child &) = delete;
|
||||
|
||||
Filter *Open(const AudioFormat &prev_audio_format,
|
||||
Error &error);
|
||||
Filter *Open(const AudioFormat &prev_audio_format);
|
||||
};
|
||||
|
||||
std::list<Child> children;
|
||||
@ -92,11 +89,9 @@ public:
|
||||
}
|
||||
|
||||
/* 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 *
|
||||
chain_filter_init(gcc_unused const ConfigBlock &block,
|
||||
gcc_unused Error &error)
|
||||
@ -105,39 +100,31 @@ chain_filter_init(gcc_unused const ConfigBlock &block,
|
||||
}
|
||||
|
||||
Filter *
|
||||
PreparedChainFilter::Child::Open(const AudioFormat &prev_audio_format,
|
||||
Error &error)
|
||||
PreparedChainFilter::Child::Open(const AudioFormat &prev_audio_format)
|
||||
{
|
||||
AudioFormat conv_audio_format = prev_audio_format;
|
||||
Filter *new_filter = filter->Open(conv_audio_format, error);
|
||||
if (new_filter == nullptr)
|
||||
return nullptr;
|
||||
Filter *new_filter = filter->Open(conv_audio_format);
|
||||
|
||||
if (conv_audio_format != prev_audio_format) {
|
||||
delete new_filter;
|
||||
|
||||
struct audio_format_string s;
|
||||
error.Format(chain_filter_domain,
|
||||
"Audio format not supported by filter '%s': %s",
|
||||
name,
|
||||
audio_format_to_string(prev_audio_format, &s));
|
||||
return nullptr;
|
||||
throw FormatRuntimeError("Audio format not supported by filter '%s': %s",
|
||||
name,
|
||||
audio_format_to_string(prev_audio_format, &s));
|
||||
}
|
||||
|
||||
return new_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));
|
||||
|
||||
for (auto &child : children) {
|
||||
AudioFormat audio_format = chain->GetOutAudioFormat();
|
||||
auto *filter = child.Open(audio_format, error);
|
||||
if (filter == nullptr)
|
||||
return nullptr;
|
||||
|
||||
auto *filter = child.Open(audio_format);
|
||||
chain->Append(child.name, filter);
|
||||
}
|
||||
|
||||
@ -145,14 +132,12 @@ PreparedChainFilter::Open(AudioFormat &in_audio_format, Error &error)
|
||||
}
|
||||
|
||||
ConstBuffer<void>
|
||||
ChainFilter::FilterPCM(ConstBuffer<void> src, Error &error)
|
||||
ChainFilter::FilterPCM(ConstBuffer<void> src)
|
||||
{
|
||||
for (auto &child : children) {
|
||||
/* feed the output of the previous filter as input
|
||||
into the current one */
|
||||
src = child.filter->FilterPCM(src, error);
|
||||
if (src.IsNull())
|
||||
return nullptr;
|
||||
src = child.filter->FilterPCM(src);
|
||||
}
|
||||
|
||||
/* return the output of the last filter */
|
||||
|
@ -25,9 +25,13 @@
|
||||
#include "pcm/PcmConvert.hxx"
|
||||
#include "util/Manual.hxx"
|
||||
#include "util/ConstBuffer.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "AudioFormat.hxx"
|
||||
#include "poison.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
class ConvertFilter final : public Filter {
|
||||
@ -47,17 +51,16 @@ public:
|
||||
ConvertFilter(const AudioFormat &audio_format);
|
||||
~ConvertFilter();
|
||||
|
||||
bool Set(const AudioFormat &_out_audio_format, Error &error);
|
||||
void Set(const AudioFormat &_out_audio_format);
|
||||
|
||||
virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
Error &error) override;
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||
};
|
||||
|
||||
class PreparedConvertFilter final : public PreparedFilter {
|
||||
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 *
|
||||
@ -67,15 +70,15 @@ convert_filter_init(gcc_unused const ConfigBlock &block,
|
||||
return new PreparedConvertFilter();
|
||||
}
|
||||
|
||||
bool
|
||||
ConvertFilter::Set(const AudioFormat &_out_audio_format, Error &error)
|
||||
void
|
||||
ConvertFilter::Set(const AudioFormat &_out_audio_format)
|
||||
{
|
||||
assert(in_audio_format.IsValid());
|
||||
assert(_out_audio_format.IsValid());
|
||||
|
||||
if (_out_audio_format == out_audio_format)
|
||||
/* no change */
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (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)
|
||||
/* optimized special case: no-op */
|
||||
return true;
|
||||
return;
|
||||
|
||||
Error 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;
|
||||
return true;
|
||||
}
|
||||
|
||||
ConvertFilter::ConvertFilter(const AudioFormat &audio_format)
|
||||
@ -99,7 +102,7 @@ ConvertFilter::ConvertFilter(const AudioFormat &audio_format)
|
||||
}
|
||||
|
||||
Filter *
|
||||
PreparedConvertFilter::Open(AudioFormat &audio_format, gcc_unused Error &error)
|
||||
PreparedConvertFilter::Open(AudioFormat &audio_format)
|
||||
{
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
@ -115,7 +118,7 @@ ConvertFilter::~ConvertFilter()
|
||||
}
|
||||
|
||||
ConstBuffer<void>
|
||||
ConvertFilter::FilterPCM(ConstBuffer<void> src, Error &error)
|
||||
ConvertFilter::FilterPCM(ConstBuffer<void> src)
|
||||
{
|
||||
assert(in_audio_format.IsValid());
|
||||
|
||||
@ -123,7 +126,12 @@ ConvertFilter::FilterPCM(ConstBuffer<void> src, Error &error)
|
||||
/* optimized special case: no-op */
|
||||
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 = {
|
||||
@ -133,23 +141,17 @@ const struct filter_plugin convert_filter_plugin = {
|
||||
|
||||
Filter *
|
||||
convert_filter_new(const AudioFormat in_audio_format,
|
||||
const AudioFormat out_audio_format,
|
||||
Error &error)
|
||||
const AudioFormat out_audio_format)
|
||||
{
|
||||
auto *filter = new ConvertFilter(in_audio_format);
|
||||
if (!filter->Set(out_audio_format, error)) {
|
||||
delete filter;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return filter;
|
||||
std::unique_ptr<ConvertFilter> filter(new ConvertFilter(in_audio_format));
|
||||
filter->Set(out_audio_format);
|
||||
return filter.release();
|
||||
}
|
||||
|
||||
bool
|
||||
convert_filter_set(Filter *_filter, AudioFormat out_audio_format,
|
||||
Error &error)
|
||||
void
|
||||
convert_filter_set(Filter *_filter, AudioFormat out_audio_format)
|
||||
{
|
||||
ConvertFilter *filter = (ConvertFilter *)_filter;
|
||||
|
||||
return filter->Set(out_audio_format, error);
|
||||
filter->Set(out_audio_format);
|
||||
}
|
||||
|
@ -26,17 +26,17 @@ struct AudioFormat;
|
||||
|
||||
Filter *
|
||||
convert_filter_new(AudioFormat in_audio_format,
|
||||
AudioFormat out_audio_format,
|
||||
Error &error);
|
||||
AudioFormat out_audio_format);
|
||||
|
||||
/**
|
||||
* Sets the output audio format for the specified filter. You must
|
||||
* call this after the filter has been opened. Since this audio
|
||||
* format switch is a violation of the filter API, this filter must be
|
||||
* the last in a chain.
|
||||
*
|
||||
* Throws std::runtime_error on error.
|
||||
*/
|
||||
bool
|
||||
convert_filter_set(Filter *filter, AudioFormat out_audio_format,
|
||||
Error &error);
|
||||
void
|
||||
convert_filter_set(Filter *filter, AudioFormat out_audio_format);
|
||||
|
||||
#endif
|
||||
|
@ -43,14 +43,13 @@ public:
|
||||
}
|
||||
|
||||
/* virtual methods from class Filter */
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
Error &error) override;
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||
};
|
||||
|
||||
class PreparedNormalizeFilter final : public PreparedFilter {
|
||||
public:
|
||||
/* virtual methods from class PreparedFilter */
|
||||
Filter *Open(AudioFormat &af, Error &error) override;
|
||||
Filter *Open(AudioFormat &af) override;
|
||||
};
|
||||
|
||||
static PreparedFilter *
|
||||
@ -61,7 +60,7 @@ normalize_filter_init(gcc_unused const ConfigBlock &block,
|
||||
}
|
||||
|
||||
Filter *
|
||||
PreparedNormalizeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error)
|
||||
PreparedNormalizeFilter::Open(AudioFormat &audio_format)
|
||||
{
|
||||
audio_format.format = SampleFormat::S16;
|
||||
|
||||
@ -69,7 +68,7 @@ PreparedNormalizeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error
|
||||
}
|
||||
|
||||
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);
|
||||
memcpy(dest, src.data, src.size);
|
||||
|
@ -36,16 +36,14 @@ class NullFilter final : public Filter {
|
||||
public:
|
||||
explicit NullFilter(const AudioFormat &af):Filter(af) {}
|
||||
|
||||
virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
gcc_unused Error &error) override {
|
||||
virtual ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override {
|
||||
return src;
|
||||
}
|
||||
};
|
||||
|
||||
class PreparedNullFilter final : public PreparedFilter {
|
||||
public:
|
||||
virtual Filter *Open(AudioFormat &af,
|
||||
gcc_unused Error &error) override {
|
||||
virtual Filter *Open(AudioFormat &af) override {
|
||||
return new NullFilter(af);
|
||||
}
|
||||
};
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "util/Domain.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static constexpr Domain replay_gain_domain("replay_gain");
|
||||
@ -73,10 +75,10 @@ public:
|
||||
:Filter(audio_format),
|
||||
mixer(_mixer), base(_base), mode(REPLAY_GAIN_OFF) {
|
||||
info.Clear();
|
||||
}
|
||||
|
||||
bool Open(Error &error) {
|
||||
return pv.Open(out_audio_format.format, error);
|
||||
Error error;
|
||||
if (!pv.Open(out_audio_format.format, error))
|
||||
throw std::runtime_error(error.GetMessage());
|
||||
}
|
||||
|
||||
void SetInfo(const ReplayGainInfo *_info) {
|
||||
@ -108,8 +110,7 @@ public:
|
||||
void Update();
|
||||
|
||||
/* virtual methods from class Filter */
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
Error &error) override;
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||
};
|
||||
|
||||
class PreparedReplayGainFilter final : public PreparedFilter {
|
||||
@ -134,7 +135,7 @@ public:
|
||||
}
|
||||
|
||||
/* virtual methods from class Filter */
|
||||
Filter *Open(AudioFormat &af, Error &error) override;
|
||||
Filter *Open(AudioFormat &af) override;
|
||||
};
|
||||
|
||||
void
|
||||
@ -174,19 +175,13 @@ replay_gain_filter_init(gcc_unused const ConfigBlock &block,
|
||||
}
|
||||
|
||||
Filter *
|
||||
PreparedReplayGainFilter::Open(AudioFormat &af, gcc_unused Error &error)
|
||||
PreparedReplayGainFilter::Open(AudioFormat &af)
|
||||
{
|
||||
auto *filter = new ReplayGainFilter(af, mixer, base);
|
||||
if (!filter->Open(error)) {
|
||||
delete filter;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return filter;
|
||||
return new ReplayGainFilter(af, mixer, base);
|
||||
}
|
||||
|
||||
ConstBuffer<void>
|
||||
ReplayGainFilter::FilterPCM(ConstBuffer<void> src, gcc_unused Error &error)
|
||||
ReplayGainFilter::FilterPCM(ConstBuffer<void> src)
|
||||
{
|
||||
return mixer != nullptr
|
||||
? src
|
||||
|
@ -96,8 +96,7 @@ public:
|
||||
const std::array<int8_t, MAX_CHANNELS> &_sources);
|
||||
|
||||
/* virtual methods from class Filter */
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
Error &error) override;
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||
};
|
||||
|
||||
class PreparedRouteFilter final : public PreparedFilter {
|
||||
@ -136,7 +135,7 @@ public:
|
||||
bool Configure(const ConfigBlock &block, Error &error);
|
||||
|
||||
/* virtual methods from class PreparedFilter */
|
||||
Filter *Open(AudioFormat &af, Error &error) override;
|
||||
Filter *Open(AudioFormat &af) override;
|
||||
};
|
||||
|
||||
bool
|
||||
@ -243,13 +242,13 @@ RouteFilter::RouteFilter(const AudioFormat &audio_format,
|
||||
}
|
||||
|
||||
Filter *
|
||||
PreparedRouteFilter::Open(AudioFormat &audio_format, gcc_unused Error &error)
|
||||
PreparedRouteFilter::Open(AudioFormat &audio_format)
|
||||
{
|
||||
return new RouteFilter(audio_format, min_output_channels, sources);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -25,16 +25,19 @@
|
||||
#include "pcm/Volume.hxx"
|
||||
#include "AudioFormat.hxx"
|
||||
#include "util/ConstBuffer.hxx"
|
||||
#include "util/Error.hxx"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
class VolumeFilter final : public Filter {
|
||||
PcmVolume pv;
|
||||
|
||||
public:
|
||||
explicit VolumeFilter(const AudioFormat &audio_format)
|
||||
:Filter(audio_format) {}
|
||||
|
||||
bool Open(Error &error) {
|
||||
return pv.Open(out_audio_format.format, error);
|
||||
:Filter(audio_format) {
|
||||
Error error;
|
||||
if (!pv.Open(out_audio_format.format, error))
|
||||
throw std::runtime_error(error.GetMessage());
|
||||
}
|
||||
|
||||
unsigned GetVolume() const {
|
||||
@ -46,8 +49,7 @@ public:
|
||||
}
|
||||
|
||||
/* virtual methods from class Filter */
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src,
|
||||
Error &error) override;
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||
};
|
||||
|
||||
class PreparedVolumeFilter final : public PreparedFilter {
|
||||
@ -55,7 +57,7 @@ class PreparedVolumeFilter final : public PreparedFilter {
|
||||
|
||||
public:
|
||||
/* virtual methods from class Filter */
|
||||
Filter *Open(AudioFormat &af, Error &error) override;
|
||||
Filter *Open(AudioFormat &af) override;
|
||||
};
|
||||
|
||||
static PreparedFilter *
|
||||
@ -66,19 +68,13 @@ volume_filter_init(gcc_unused const ConfigBlock &block,
|
||||
}
|
||||
|
||||
Filter *
|
||||
PreparedVolumeFilter::Open(AudioFormat &audio_format, Error &error)
|
||||
PreparedVolumeFilter::Open(AudioFormat &audio_format)
|
||||
{
|
||||
auto *filter = new VolumeFilter(audio_format);
|
||||
if (!filter->Open(error)) {
|
||||
delete filter;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return filter;
|
||||
return new VolumeFilter(audio_format);
|
||||
}
|
||||
|
||||
ConstBuffer<void>
|
||||
VolumeFilter::FilterPCM(ConstBuffer<void> src, gcc_unused Error &error)
|
||||
VolumeFilter::FilterPCM(ConstBuffer<void> src)
|
||||
{
|
||||
return pv.Apply(src);
|
||||
}
|
||||
|
@ -404,7 +404,10 @@ private:
|
||||
*/
|
||||
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.
|
||||
|
@ -93,38 +93,28 @@ AudioOutput::Disable()
|
||||
}
|
||||
|
||||
inline AudioFormat
|
||||
AudioOutput::OpenFilter(AudioFormat &format, Error &error_r)
|
||||
{
|
||||
AudioOutput::OpenFilter(AudioFormat &format)
|
||||
try {
|
||||
assert(format.IsValid());
|
||||
|
||||
/* the replay_gain filter cannot fail here */
|
||||
if (prepared_replay_gain_filter != nullptr) {
|
||||
if (prepared_replay_gain_filter != nullptr)
|
||||
replay_gain_filter_instance =
|
||||
prepared_replay_gain_filter->Open(format, error_r);
|
||||
if (replay_gain_filter_instance == nullptr)
|
||||
return AudioFormat::Undefined();
|
||||
}
|
||||
prepared_replay_gain_filter->Open(format);
|
||||
|
||||
if (prepared_other_replay_gain_filter != nullptr) {
|
||||
if (prepared_other_replay_gain_filter != nullptr)
|
||||
other_replay_gain_filter_instance =
|
||||
prepared_other_replay_gain_filter->Open(format, error_r);
|
||||
if (other_replay_gain_filter_instance == nullptr) {
|
||||
delete replay_gain_filter_instance;
|
||||
return AudioFormat::Undefined();
|
||||
}
|
||||
}
|
||||
prepared_other_replay_gain_filter->Open(format);
|
||||
|
||||
filter_instance = prepared_filter->Open(format, error_r);
|
||||
if (filter_instance == nullptr) {
|
||||
delete other_replay_gain_filter_instance;
|
||||
delete replay_gain_filter_instance;
|
||||
return AudioFormat::Undefined();
|
||||
}
|
||||
filter_instance = prepared_filter->Open(format);
|
||||
|
||||
if (mixer != nullptr && mixer->IsPlugin(software_mixer_plugin))
|
||||
software_mixer_set_filter(*mixer, volume_filter.Get());
|
||||
|
||||
return filter_instance->GetOutAudioFormat();
|
||||
} catch (...) {
|
||||
CloseFilter();
|
||||
throw;
|
||||
}
|
||||
|
||||
void
|
||||
@ -165,10 +155,11 @@ AudioOutput::Open()
|
||||
|
||||
/* open the filter */
|
||||
|
||||
const AudioFormat filter_audio_format =
|
||||
OpenFilter(in_audio_format, error);
|
||||
if (!filter_audio_format.IsDefined()) {
|
||||
FormatError(error, "Failed to open filter for \"%s\" [%s]",
|
||||
AudioFormat filter_audio_format;
|
||||
try {
|
||||
filter_audio_format = OpenFilter(in_audio_format);
|
||||
} catch (const std::runtime_error &e) {
|
||||
FormatError(e, "Failed to open filter for \"%s\" [%s]",
|
||||
name, plugin.name);
|
||||
|
||||
fail_timer.Update();
|
||||
@ -202,9 +193,10 @@ AudioOutput::Open()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!convert_filter_set(convert_filter.Get(), out_audio_format,
|
||||
error)) {
|
||||
FormatError(error, "Failed to convert for \"%s\" [%s]",
|
||||
try {
|
||||
convert_filter_set(convert_filter.Get(), out_audio_format);
|
||||
} catch (const std::runtime_error &e) {
|
||||
FormatError(e, "Failed to convert for \"%s\" [%s]",
|
||||
name, plugin.name);
|
||||
|
||||
mutex.unlock();
|
||||
@ -295,12 +287,12 @@ AudioOutput::ReopenFilter()
|
||||
CloseFilter();
|
||||
mutex.lock();
|
||||
|
||||
const AudioFormat filter_audio_format =
|
||||
OpenFilter(in_audio_format, error);
|
||||
if (!filter_audio_format.IsDefined() ||
|
||||
!convert_filter_set(convert_filter.Get(), out_audio_format,
|
||||
error)) {
|
||||
FormatError(error,
|
||||
AudioFormat filter_audio_format;
|
||||
try {
|
||||
filter_audio_format = OpenFilter(in_audio_format);
|
||||
convert_filter_set(convert_filter.Get(), out_audio_format);
|
||||
} catch (const std::runtime_error &e) {
|
||||
FormatError(e,
|
||||
"Failed to open filter for \"%s\" [%s]",
|
||||
name, plugin.name);
|
||||
|
||||
@ -383,11 +375,13 @@ ao_chunk_data(AudioOutput *ao, const MusicChunk *chunk,
|
||||
*replay_gain_serial_p = chunk->replay_gain_serial;
|
||||
}
|
||||
|
||||
Error error;
|
||||
data = replay_gain_filter->FilterPCM(data, error);
|
||||
if (data.IsNull())
|
||||
FormatError(error, "\"%s\" [%s] failed to filter",
|
||||
try {
|
||||
data = replay_gain_filter->FilterPCM(data);
|
||||
} catch (const std::runtime_error &e) {
|
||||
FormatError(e, "\"%s\" [%s] failed to filter",
|
||||
ao->name, ao->plugin.name);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
@ -449,15 +443,13 @@ ao_filter_chunk(AudioOutput *ao, const MusicChunk *chunk)
|
||||
|
||||
/* apply filter chain */
|
||||
|
||||
Error error;
|
||||
data = ao->filter_instance->FilterPCM(data, error);
|
||||
if (data.IsNull()) {
|
||||
FormatError(error, "\"%s\" [%s] failed to filter",
|
||||
try {
|
||||
return ao->filter_instance->FilterPCM(data);
|
||||
} catch (const std::runtime_error &e) {
|
||||
FormatError(e, "\"%s\" [%s] failed to filter",
|
||||
ao->name, ao->plugin.name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -105,13 +105,7 @@ try {
|
||||
|
||||
/* open the filter */
|
||||
|
||||
Error error;
|
||||
std::unique_ptr<Filter> filter(prepared_filter->Open(audio_format,
|
||||
error));
|
||||
if (!filter) {
|
||||
LogError(error, "Failed to open filter");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::unique_ptr<Filter> filter(prepared_filter->Open(audio_format));
|
||||
|
||||
const AudioFormat out_audio_format = filter->GetOutAudioFormat();
|
||||
|
||||
@ -127,12 +121,7 @@ try {
|
||||
if (nbytes <= 0)
|
||||
break;
|
||||
|
||||
auto dest = filter->FilterPCM({(const void *)buffer, (size_t)nbytes},
|
||||
error);
|
||||
if (dest.IsNull()) {
|
||||
LogError(error, "filter/Filter failed");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto dest = filter->FilterPCM({(const void *)buffer, (size_t)nbytes});
|
||||
|
||||
nbytes = write(1, dest.data, dest.size);
|
||||
if (nbytes < 0) {
|
||||
@ -147,7 +136,7 @@ try {
|
||||
config_global_finish();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
} catch (const std::exception &e) {
|
||||
} catch (const std::exception &e) {
|
||||
LogError(e);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user