diff options
27 files changed, 197 insertions, 305 deletions
diff --git a/src/Main.cxx b/src/Main.cxx index cb93a4c13..5838eeeae 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -520,10 +520,7 @@ try { archive_plugin_init_all(); #endif - if (!pcm_convert_global_init(error)) { - LogError(error); - return EXIT_FAILURE; - } + pcm_convert_global_init(); decoder_plugin_init_all(); diff --git a/src/decoder/DecoderAPI.cxx b/src/decoder/DecoderAPI.cxx index 87bbd0b13..cfcb44766 100644 --- a/src/decoder/DecoderAPI.cxx +++ b/src/decoder/DecoderAPI.cxx @@ -73,11 +73,12 @@ decoder_initialized(Decoder &decoder, decoder.convert = new PcmConvert(); - Error error; - if (!decoder.convert->Open(dc.in_audio_format, - dc.out_audio_format, - error)) - decoder.error = std::make_exception_ptr(std::move(error)); + try { + decoder.convert->Open(dc.in_audio_format, + dc.out_audio_format); + } catch (...) { + decoder.error = std::current_exception(); + } } const ScopeLock protect(dc.mutex); @@ -484,19 +485,17 @@ decoder_data(Decoder &decoder, if (decoder.convert != nullptr) { assert(dc.in_audio_format != dc.out_audio_format); - Error error; - auto result = decoder.convert->Convert({data, length}, - error); - if (data == nullptr) { + try { + auto result = decoder.convert->Convert({data, length}); + data = result.data; + length = result.size; + } catch (const std::runtime_error &e) { /* the PCM conversion has failed - stop playback, since we have no better way to bail out */ - LogError(error); + LogError(e); return DecoderCommand::STOP; } - - data = result.data; - length = result.size; } else { assert(dc.in_audio_format == dc.out_audio_format); } diff --git a/src/filter/plugins/ConvertFilterPlugin.cxx b/src/filter/plugins/ConvertFilterPlugin.cxx index f4dc37d73..55224de78 100644 --- a/src/filter/plugins/ConvertFilterPlugin.cxx +++ b/src/filter/plugins/ConvertFilterPlugin.cxx @@ -25,7 +25,6 @@ #include "pcm/PcmConvert.hxx" #include "util/Manual.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" #include "AudioFormat.hxx" #include "poison.h" @@ -88,9 +87,7 @@ ConvertFilter::Set(const AudioFormat &_out_audio_format) /* optimized special case: no-op */ return; - Error error; - if (!state.Open(in_audio_format, _out_audio_format, error)) - throw std::runtime_error(error.GetMessage()); + state.Open(in_audio_format, _out_audio_format); out_audio_format = _out_audio_format; } @@ -125,12 +122,7 @@ ConvertFilter::FilterPCM(ConstBuffer<void> src) /* optimized special case: no-op */ return src; - Error error; - auto result = state.Convert(src, error); - if (result.IsNull()) - throw std::runtime_error(error.GetMessage()); - - return result; + return state.Convert(src); } const struct filter_plugin convert_filter_plugin = { diff --git a/src/filter/plugins/ReplayGainFilterPlugin.cxx b/src/filter/plugins/ReplayGainFilterPlugin.cxx index b6c212c46..4e62d93c2 100644 --- a/src/filter/plugins/ReplayGainFilterPlugin.cxx +++ b/src/filter/plugins/ReplayGainFilterPlugin.cxx @@ -76,9 +76,7 @@ public: mixer(_mixer), base(_base), mode(REPLAY_GAIN_OFF) { info.Clear(); - Error error; - if (!pv.Open(out_audio_format.format, error)) - throw std::runtime_error(error.GetMessage()); + pv.Open(out_audio_format.format); } void SetInfo(const ReplayGainInfo *_info) { diff --git a/src/filter/plugins/VolumeFilterPlugin.cxx b/src/filter/plugins/VolumeFilterPlugin.cxx index 5ed86d222..64959916f 100644 --- a/src/filter/plugins/VolumeFilterPlugin.cxx +++ b/src/filter/plugins/VolumeFilterPlugin.cxx @@ -25,7 +25,6 @@ #include "pcm/Volume.hxx" #include "AudioFormat.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" #include <stdexcept> @@ -35,9 +34,7 @@ class VolumeFilter final : public Filter { public: explicit VolumeFilter(const AudioFormat &audio_format) :Filter(audio_format) { - Error error; - if (!pv.Open(out_audio_format.format, error)) - throw std::runtime_error(error.GetMessage()); + pv.Open(out_audio_format.format); } unsigned GetVolume() const { diff --git a/src/pcm/ChannelsConverter.cxx b/src/pcm/ChannelsConverter.cxx index ec0024581..cd6184f76 100644 --- a/src/pcm/ChannelsConverter.cxx +++ b/src/pcm/ChannelsConverter.cxx @@ -22,14 +22,13 @@ #include "PcmChannels.hxx" #include "Domain.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include <assert.h> -bool +void PcmChannelsConverter::Open(SampleFormat _format, - unsigned _src_channels, unsigned _dest_channels, - gcc_unused Error &error) + unsigned _src_channels, unsigned _dest_channels) { assert(_format != SampleFormat::UNDEFINED); @@ -41,16 +40,13 @@ PcmChannelsConverter::Open(SampleFormat _format, break; default: - error.Format(pcm_domain, - "PCM channel conversion for %s is not implemented", - sample_format_to_string(_format)); - return false; + throw FormatRuntimeError("PCM channel conversion for %s is not implemented", + sample_format_to_string(_format)); } format = _format; src_channels = _src_channels; dest_channels = _dest_channels; - return true; } void @@ -62,7 +58,7 @@ PcmChannelsConverter::Close() } ConstBuffer<void> -PcmChannelsConverter::Convert(ConstBuffer<void> src, gcc_unused Error &error) +PcmChannelsConverter::Convert(ConstBuffer<void> src) { switch (format) { case SampleFormat::UNDEFINED: diff --git a/src/pcm/ChannelsConverter.hxx b/src/pcm/ChannelsConverter.hxx index ce893a20f..8ad3ac5ee 100644 --- a/src/pcm/ChannelsConverter.hxx +++ b/src/pcm/ChannelsConverter.hxx @@ -28,7 +28,6 @@ #include <assert.h> #endif -class Error; template<typename T> struct ConstBuffer; /** @@ -53,15 +52,14 @@ public: /** * Opens the object, prepare for Convert(). * + * Throws std::runtime_error on error. + * * @param format the sample format * @param src_channels the number of source channels * @param dest_channels the number of destination channels - * @param error location to store the error - * @return true on success */ - bool Open(SampleFormat format, - unsigned src_channels, unsigned dest_channels, - Error &error); + void Open(SampleFormat format, + unsigned src_channels, unsigned dest_channels); /** * Closes the object. After that, you may call Open() again. @@ -71,13 +69,13 @@ public: /** * Convert a block of PCM data. * + * Throws std::runtime_error on error. + * * @param src the input buffer - * @param error location to store the error - * @return the destination buffer on success, - * ConstBuffer::Null() on error + * @return the destination buffer */ gcc_pure - ConstBuffer<void> Convert(ConstBuffer<void> src, Error &error); + ConstBuffer<void> Convert(ConstBuffer<void> src); }; #endif diff --git a/src/pcm/ConfiguredResampler.cxx b/src/pcm/ConfiguredResampler.cxx index 382eaf258..f66bf8a3f 100644 --- a/src/pcm/ConfiguredResampler.cxx +++ b/src/pcm/ConfiguredResampler.cxx @@ -25,7 +25,7 @@ #include "config/ConfigError.hxx" #include "config/Block.hxx" #include "config/Param.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #ifdef ENABLE_LIBSAMPLERATE #include "LibsamplerateResampler.hxx" @@ -112,7 +112,7 @@ MigrateResamplerConfig(const config_param *param, ConfigBlock &buffer) } static const ConfigBlock * -GetResamplerConfig(ConfigBlock &buffer, Error &error) +GetResamplerConfig(ConfigBlock &buffer) { const auto *old_param = config_get_param(ConfigOption::SAMPLERATE_CONVERTER); @@ -120,49 +120,39 @@ GetResamplerConfig(ConfigBlock &buffer, Error &error) if (block == nullptr) return MigrateResamplerConfig(old_param, buffer); - if (old_param != nullptr) { - error.Format(config_domain, - "Cannot use both 'resampler' (line %d) and 'samplerate_converter' (line %d)", - block->line, old_param->line); - return nullptr; - } + if (old_param != nullptr) + throw FormatRuntimeError("Cannot use both 'resampler' (line %d) and 'samplerate_converter' (line %d)", + block->line, old_param->line); return block; } -bool -pcm_resampler_global_init(Error &error) +void +pcm_resampler_global_init() { ConfigBlock buffer; - const auto *block = GetResamplerConfig(buffer, error); - if (block == nullptr) - return false; + const auto *block = GetResamplerConfig(buffer); const char *plugin_name = block->GetBlockValue("plugin"); - if (plugin_name == nullptr) { - error.Format(config_domain, - "'plugin' missing in line %d", block->line); - return false; - } + if (plugin_name == nullptr) + throw FormatRuntimeError("'plugin' missing in line %d", + block->line); if (strcmp(plugin_name, "internal") == 0) { selected_resampler = SelectedResampler::FALLBACK; - return true; #ifdef ENABLE_SOXR } else if (strcmp(plugin_name, "soxr") == 0) { selected_resampler = SelectedResampler::SOXR; - return pcm_resample_soxr_global_init(*block, error); + pcm_resample_soxr_global_init(*block); #endif #ifdef ENABLE_LIBSAMPLERATE } else if (strcmp(plugin_name, "libsamplerate") == 0) { selected_resampler = SelectedResampler::LIBSAMPLERATE; - return pcm_resample_lsr_global_init(*block, error); + pcm_resample_lsr_global_init(*block); #endif } else { - error.Format(config_domain, - "No such resampler plugin: %s", - plugin_name); - return false; + throw FormatRuntimeError("No such resampler plugin: %s", + plugin_name); } } diff --git a/src/pcm/ConfiguredResampler.hxx b/src/pcm/ConfiguredResampler.hxx index b871f1caf..1279faa57 100644 --- a/src/pcm/ConfiguredResampler.hxx +++ b/src/pcm/ConfiguredResampler.hxx @@ -22,11 +22,10 @@ #include "check.h" -class Error; class PcmResampler; -bool -pcm_resampler_global_init(Error &error); +void +pcm_resampler_global_init(); /** * Create a #PcmResampler instance from the implementation class diff --git a/src/pcm/FallbackResampler.cxx b/src/pcm/FallbackResampler.cxx index 61bdc1ed9..e57073d88 100644 --- a/src/pcm/FallbackResampler.cxx +++ b/src/pcm/FallbackResampler.cxx @@ -23,8 +23,7 @@ #include <assert.h> AudioFormat -FallbackPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate, - gcc_unused Error &error) +FallbackPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate) { assert(af.IsValid()); assert(audio_valid_sample_rate(new_sample_rate)); @@ -116,7 +115,7 @@ pcm_resample_fallback_void(PcmBuffer &buffer, } ConstBuffer<void> -FallbackPcmResampler::Resample(ConstBuffer<void> src, gcc_unused Error &error) +FallbackPcmResampler::Resample(ConstBuffer<void> src) { switch (format.format) { case SampleFormat::UNDEFINED: diff --git a/src/pcm/FallbackResampler.hxx b/src/pcm/FallbackResampler.hxx index 04944b301..c70494b4e 100644 --- a/src/pcm/FallbackResampler.hxx +++ b/src/pcm/FallbackResampler.hxx @@ -36,11 +36,9 @@ class FallbackPcmResampler final : public PcmResampler { PcmBuffer buffer; public: - virtual AudioFormat Open(AudioFormat &af, unsigned new_sample_rate, - Error &error) override; - virtual void Close() override; - virtual ConstBuffer<void> Resample(ConstBuffer<void> src, - Error &error) override; + AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override; + void Close() override; + ConstBuffer<void> Resample(ConstBuffer<void> src) override; }; #endif diff --git a/src/pcm/FormatConverter.cxx b/src/pcm/FormatConverter.cxx index ae52ec7c2..d51b9397c 100644 --- a/src/pcm/FormatConverter.cxx +++ b/src/pcm/FormatConverter.cxx @@ -20,15 +20,13 @@ #include "config.h" #include "FormatConverter.hxx" #include "PcmFormat.hxx" -#include "Domain.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include <assert.h> -bool -PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format, - Error &error) +void +PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format) { assert(_src_format != SampleFormat::UNDEFINED); assert(_dest_format != SampleFormat::UNDEFINED); @@ -40,11 +38,9 @@ PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format, case SampleFormat::S8: case SampleFormat::DSD: - error.Format(pcm_domain, - "PCM conversion from %s to %s is not implemented", - sample_format_to_string(_src_format), - sample_format_to_string(_dest_format)); - return false; + throw FormatRuntimeError("PCM conversion from %s to %s is not implemented", + sample_format_to_string(_src_format), + sample_format_to_string(_dest_format)); case SampleFormat::S16: case SampleFormat::S24_P32: @@ -55,7 +51,6 @@ PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format, src_format = _src_format; dest_format = _dest_format; - return true; } void @@ -68,7 +63,7 @@ PcmFormatConverter::Close() } ConstBuffer<void> -PcmFormatConverter::Convert(ConstBuffer<void> src, gcc_unused Error &error) +PcmFormatConverter::Convert(ConstBuffer<void> src) { switch (dest_format) { case SampleFormat::UNDEFINED: diff --git a/src/pcm/FormatConverter.hxx b/src/pcm/FormatConverter.hxx index d7368e7e1..a9cd42a0e 100644 --- a/src/pcm/FormatConverter.hxx +++ b/src/pcm/FormatConverter.hxx @@ -29,7 +29,6 @@ #include <assert.h> #endif -class Error; template<typename T> struct ConstBuffer; /** @@ -56,13 +55,12 @@ public: /** * Opens the object, prepare for Convert(). * + * Throws std::runtime_error on error. + * * @param src_format the sample format of incoming data * @param dest_format the sample format of outgoing data - * @param error location to store the error - * @return true on success */ - bool Open(SampleFormat src_format, SampleFormat dest_format, - Error &error); + void Open(SampleFormat src_format, SampleFormat dest_format); /** * Closes the object. After that, you may call Open() again. @@ -72,13 +70,13 @@ public: /** * Convert a block of PCM data. * + * Throws std::runtime_error on error. + * * @param src the input buffer - * @param error location to store the error - * @return the destination buffer on success, - * ConstBuffer::Null() on error + * @return the destination buffer */ gcc_pure - ConstBuffer<void> Convert(ConstBuffer<void> src, Error &error); + ConstBuffer<void> Convert(ConstBuffer<void> src); }; #endif diff --git a/src/pcm/GlueResampler.cxx b/src/pcm/GlueResampler.cxx index 37b12584a..bf8f995eb 100644 --- a/src/pcm/GlueResampler.cxx +++ b/src/pcm/GlueResampler.cxx @@ -32,33 +32,28 @@ GluePcmResampler::~GluePcmResampler() delete resampler; } -bool -GluePcmResampler::Open(AudioFormat src_format, unsigned new_sample_rate, - Error &error) +void +GluePcmResampler::Open(AudioFormat src_format, unsigned new_sample_rate) { assert(src_format.IsValid()); assert(audio_valid_sample_rate(new_sample_rate)); AudioFormat requested_format = src_format; AudioFormat dest_format = resampler->Open(requested_format, - new_sample_rate, - error); - if (!dest_format.IsValid()) - return false; + new_sample_rate); + assert(dest_format.IsValid()); assert(requested_format.channels == src_format.channels); assert(dest_format.channels == src_format.channels); assert(dest_format.sample_rate == new_sample_rate); - if (requested_format.format != src_format.format && - !format_converter.Open(src_format.format, requested_format.format, - error)) - return false; + if (requested_format.format != src_format.format) + format_converter.Open(src_format.format, + requested_format.format); src_sample_format = src_format.format; requested_sample_format = requested_format.format; output_sample_format = dest_format.format; - return true; } void @@ -71,15 +66,12 @@ GluePcmResampler::Close() } ConstBuffer<void> -GluePcmResampler::Resample(ConstBuffer<void> src, Error &error) +GluePcmResampler::Resample(ConstBuffer<void> src) { assert(!src.IsNull()); - if (requested_sample_format != src_sample_format) { - src = format_converter.Convert(src, error); - if (src.IsNull()) - return nullptr; - } + if (requested_sample_format != src_sample_format) + src = format_converter.Convert(src); - return resampler->Resample(src, error); + return resampler->Resample(src); } diff --git a/src/pcm/GlueResampler.hxx b/src/pcm/GlueResampler.hxx index e2107e478..da0d81e49 100644 --- a/src/pcm/GlueResampler.hxx +++ b/src/pcm/GlueResampler.hxx @@ -24,7 +24,6 @@ #include "AudioFormat.hxx" #include "FormatConverter.hxx" -class Error; class PcmResampler; template<typename T> struct ConstBuffer; @@ -49,15 +48,14 @@ public: GluePcmResampler(); ~GluePcmResampler(); - bool Open(AudioFormat src_format, unsigned new_sample_rate, - Error &error); + void Open(AudioFormat src_format, unsigned new_sample_rate); void Close(); SampleFormat GetOutputSampleFormat() const { return output_sample_format; } - ConstBuffer<void> Resample(ConstBuffer<void> src, Error &error); + ConstBuffer<void> Resample(ConstBuffer<void> src); }; #endif diff --git a/src/pcm/LibsamplerateResampler.cxx b/src/pcm/LibsamplerateResampler.cxx index b660cb995..7c0637635 100644 --- a/src/pcm/LibsamplerateResampler.cxx +++ b/src/pcm/LibsamplerateResampler.cxx @@ -21,7 +21,7 @@ #include "LibsamplerateResampler.hxx" #include "config/Block.hxx" #include "util/ASCII.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -63,26 +63,21 @@ lsr_parse_converter(const char *s) return false; } -bool -pcm_resample_lsr_global_init(const ConfigBlock &block, Error &error) +void +pcm_resample_lsr_global_init(const ConfigBlock &block) { const char *converter = block.GetBlockValue("type", "2"); - if (!lsr_parse_converter(converter)) { - error.Format(libsamplerate_domain, - "unknown samplerate converter '%s'", converter); - return false; - } + if (!lsr_parse_converter(converter)) + throw FormatRuntimeError("unknown samplerate converter '%s'", + converter); FormatDebug(libsamplerate_domain, "libsamplerate converter '%s'", src_get_name(lsr_converter)); - - return true; } AudioFormat -LibsampleratePcmResampler::Open(AudioFormat &af, unsigned new_sample_rate, - Error &error) +LibsampleratePcmResampler::Open(AudioFormat &af, unsigned new_sample_rate) { assert(af.IsValid()); assert(audio_valid_sample_rate(new_sample_rate)); @@ -96,12 +91,9 @@ LibsampleratePcmResampler::Open(AudioFormat &af, unsigned new_sample_rate, int src_error; state = src_new(lsr_converter, channels, &src_error); - if (!state) { - error.Format(libsamplerate_domain, src_error, - "libsamplerate initialization has failed: %s", - src_strerror(src_error)); - return AudioFormat::Undefined(); - } + if (!state) + throw FormatRuntimeError("libsamplerate initialization has failed: %s", + src_strerror(src_error)); memset(&data, 0, sizeof(data)); @@ -122,22 +114,8 @@ LibsampleratePcmResampler::Close() state = src_delete(state); } -static bool -src_process(SRC_STATE *state, SRC_DATA *data, Error &error) -{ - int result = src_process(state, data); - if (result != 0) { - error.Format(libsamplerate_domain, result, - "libsamplerate has failed: %s", - src_strerror(result)); - return false; - } - - return true; -} - inline ConstBuffer<float> -LibsampleratePcmResampler::Resample2(ConstBuffer<float> src, Error &error) +LibsampleratePcmResampler::Resample2(ConstBuffer<float> src) { assert(src.size % channels == 0); @@ -151,15 +129,17 @@ LibsampleratePcmResampler::Resample2(ConstBuffer<float> src, Error &error) data.input_frames = src_frames; data.output_frames = dest_frames; - if (!src_process(state, &data, error)) - return nullptr; + int result = src_process(state, &data); + if (result != 0) + throw FormatRuntimeError("libsamplerate has failed: %s", + src_strerror(result)); return ConstBuffer<float>(data.data_out, data.output_frames_gen * channels); } ConstBuffer<void> -LibsampleratePcmResampler::Resample(ConstBuffer<void> src, Error &error) +LibsampleratePcmResampler::Resample(ConstBuffer<void> src) { - return Resample2(ConstBuffer<float>::FromVoid(src), error).ToVoid(); + return Resample2(ConstBuffer<float>::FromVoid(src)).ToVoid(); } diff --git a/src/pcm/LibsamplerateResampler.hxx b/src/pcm/LibsamplerateResampler.hxx index 8161219c2..3c4c9bcd8 100644 --- a/src/pcm/LibsamplerateResampler.hxx +++ b/src/pcm/LibsamplerateResampler.hxx @@ -42,17 +42,15 @@ class LibsampleratePcmResampler final : public PcmResampler { PcmBuffer buffer; public: - virtual AudioFormat Open(AudioFormat &af, unsigned new_sample_rate, - Error &error) override; - virtual void Close() override; - virtual ConstBuffer<void> Resample(ConstBuffer<void> src, - Error &error) override; + AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override; + void Close() override; + ConstBuffer<void> Resample(ConstBuffer<void> src) override; private: - ConstBuffer<float> Resample2(ConstBuffer<float> src, Error &error); + ConstBuffer<float> Resample2(ConstBuffer<float> src); }; -bool -pcm_resample_lsr_global_init(const ConfigBlock &block, Error &error); +void +pcm_resample_lsr_global_init(const ConfigBlock &block); #endif diff --git a/src/pcm/PcmConvert.cxx b/src/pcm/PcmConvert.cxx index 81bec1c75..2470583c8 100644 --- a/src/pcm/PcmConvert.cxx +++ b/src/pcm/PcmConvert.cxx @@ -22,15 +22,14 @@ #include "Domain.hxx" #include "ConfiguredResampler.hxx" #include "AudioFormat.hxx" -#include "util/Error.hxx" #include "util/ConstBuffer.hxx" #include <assert.h> -bool -pcm_convert_global_init(Error &error) +void +pcm_convert_global_init() { - return pcm_resampler_global_init(error); + pcm_resampler_global_init(); } PcmConvert::PcmConvert() @@ -47,9 +46,8 @@ PcmConvert::~PcmConvert() assert(!dest_format.IsValid()); } -bool -PcmConvert::Open(const AudioFormat _src_format, const AudioFormat _dest_format, - Error &error) +void +PcmConvert::Open(const AudioFormat _src_format, const AudioFormat _dest_format) { assert(!src_format.IsValid()); assert(!dest_format.IsValid()); @@ -62,39 +60,42 @@ PcmConvert::Open(const AudioFormat _src_format, const AudioFormat _dest_format, enable_resampler = format.sample_rate != _dest_format.sample_rate; if (enable_resampler) { - if (!resampler.Open(format, _dest_format.sample_rate, error)) - return false; + resampler.Open(format, _dest_format.sample_rate); format.format = resampler.GetOutputSampleFormat(); format.sample_rate = _dest_format.sample_rate; } enable_format = format.format != _dest_format.format; - if (enable_format && - !format_converter.Open(format.format, _dest_format.format, - error)) { - if (enable_resampler) - resampler.Close(); - return false; + if (enable_format) { + try { + format_converter.Open(format.format, + _dest_format.format); + } catch (...) { + if (enable_resampler) + resampler.Close(); + throw; + } } format.format = _dest_format.format; enable_channels = format.channels != _dest_format.channels; - if (enable_channels && - !channels_converter.Open(format.format, format.channels, - _dest_format.channels, error)) { - if (enable_format) - format_converter.Close(); - if (enable_resampler) - resampler.Close(); - return false; + if (enable_channels) { + try { + channels_converter.Open(format.format, format.channels, + _dest_format.channels); + } catch (...) { + if (enable_format) + format_converter.Close(); + if (enable_resampler) + resampler.Close(); + throw; + } } src_format = _src_format; dest_format = _dest_format; - - return true; } void @@ -118,39 +119,27 @@ PcmConvert::Close() } ConstBuffer<void> -PcmConvert::Convert(ConstBuffer<void> buffer, Error &error) +PcmConvert::Convert(ConstBuffer<void> buffer) { #ifdef ENABLE_DSD if (src_format.format == SampleFormat::DSD) { auto s = ConstBuffer<uint8_t>::FromVoid(buffer); auto d = dsd.ToFloat(src_format.channels, s); - if (d.IsNull()) { - error.Set(pcm_domain, - "DSD to PCM conversion failed"); - return nullptr; - } + if (d.IsNull()) + throw std::runtime_error("DSD to PCM conversion failed"); buffer = d.ToVoid(); } #endif - if (enable_resampler) { - buffer = resampler.Resample(buffer, error); - if (buffer.IsNull()) - return nullptr; - } + if (enable_resampler) + buffer = resampler.Resample(buffer); - if (enable_format) { - buffer = format_converter.Convert(buffer, error); - if (buffer.IsNull()) - return nullptr; - } + if (enable_format) + buffer = format_converter.Convert(buffer); - if (enable_channels) { - buffer = channels_converter.Convert(buffer, error); - if (buffer.IsNull()) - return nullptr; - } + if (enable_channels) + buffer = channels_converter.Convert(buffer); return buffer; } diff --git a/src/pcm/PcmConvert.hxx b/src/pcm/PcmConvert.hxx index 8b49c001f..c717a6ae2 100644 --- a/src/pcm/PcmConvert.hxx +++ b/src/pcm/PcmConvert.hxx @@ -31,7 +31,6 @@ #endif template<typename T> struct ConstBuffer; -class Error; /** * This object is statically allocated (within another struct), and @@ -57,9 +56,10 @@ public: /** * Prepare the object. Call Close() when done. + * + * Throws std::runtime_error on error. */ - bool Open(AudioFormat _src_format, AudioFormat _dest_format, - Error &error); + void Open(AudioFormat _src_format, AudioFormat _dest_format); /** * Close the object after it was prepared with Open(). After @@ -70,14 +70,15 @@ public: /** * Converts PCM data between two audio formats. * + * Throws std::runtime_error on error. + * * @param src the source PCM buffer - * @param error location to store the error occurring - * @return the destination buffer, or nullptr on error + * @return the destination buffer */ - ConstBuffer<void> Convert(ConstBuffer<void> src, Error &error); + ConstBuffer<void> Convert(ConstBuffer<void> src); }; -bool -pcm_convert_global_init(Error &error); +void +pcm_convert_global_init(); #endif diff --git a/src/pcm/Resampler.hxx b/src/pcm/Resampler.hxx index b88ebf161..404a7db28 100644 --- a/src/pcm/Resampler.hxx +++ b/src/pcm/Resampler.hxx @@ -24,7 +24,6 @@ #include "Compiler.h" struct AudioFormat; -class Error; /** * This is an interface for plugins that convert PCM data to a @@ -37,16 +36,17 @@ public: /** * Opens the resampler, preparing it for Resample(). * + * 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 (however, * it may not request a different input sample rate) * @param new_sample_rate the requested output sample rate * @param error location to store the error - * @return the format of outgoing data or - * AudioFormat::Undefined() on error + * @return the format of outgoing data */ - virtual AudioFormat Open(AudioFormat &af, unsigned new_sample_rate, - Error &error) = 0; + virtual AudioFormat Open(AudioFormat &af, + unsigned new_sample_rate) = 0; /** * Closes the resampler. After that, you may call Open() @@ -58,14 +58,11 @@ public: * Resamples a block of PCM data. * * @param src the input buffer - * @param error location to store the error occurring - * @return the destination buffer on success (will be - * invalidated by filter_close() or filter_filter()), nullptr on - * error + * @return the destination buffer (will be invalidated by + * filter_close() or filter_filter()) */ gcc_pure - virtual ConstBuffer<void> Resample(ConstBuffer<void> src, - Error &error) = 0; + virtual ConstBuffer<void> Resample(ConstBuffer<void> src) = 0; }; #endif diff --git a/src/pcm/SoxrResampler.cxx b/src/pcm/SoxrResampler.cxx index 1b8002115..c85f58c0b 100644 --- a/src/pcm/SoxrResampler.cxx +++ b/src/pcm/SoxrResampler.cxx @@ -21,7 +21,7 @@ #include "SoxrResampler.hxx" #include "AudioFormat.hxx" #include "config/Block.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -80,18 +80,16 @@ soxr_parse_quality(const char *quality) return SOXR_INVALID_RECIPE; } -bool -pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error) +void +pcm_resample_soxr_global_init(const ConfigBlock &block) { const char *quality_string = block.GetBlockValue("quality"); unsigned long recipe = soxr_parse_quality(quality_string); if (recipe == SOXR_INVALID_RECIPE) { assert(quality_string != nullptr); - error.Format(soxr_domain, - "unknown quality setting '%s' in line %d", - quality_string, block.line); - return false; + throw FormatRuntimeError("unknown quality setting '%s' in line %d", + quality_string, block.line); } soxr_quality = soxr_quality_spec(recipe, 0); @@ -102,13 +100,10 @@ pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error) const unsigned n_threads = block.GetBlockValue("threads", 1); soxr_runtime = soxr_runtime_spec(n_threads); - - return true; } AudioFormat -SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate, - Error &error) +SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate) { assert(af.IsValid()); assert(audio_valid_sample_rate(new_sample_rate)); @@ -117,11 +112,9 @@ SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate, soxr = soxr_create(af.sample_rate, new_sample_rate, af.channels, &e, nullptr, &soxr_quality, &soxr_runtime); - if (soxr == nullptr) { - error.Format(soxr_domain, - "soxr initialization has failed: %s", e); - return AudioFormat::Undefined(); - } + if (soxr == nullptr) + throw FormatRuntimeError("soxr initialization has failed: %s", + e); FormatDebug(soxr_domain, "soxr engine '%s'", soxr_engine(soxr)); @@ -147,7 +140,7 @@ SoxrPcmResampler::Close() } ConstBuffer<void> -SoxrPcmResampler::Resample(ConstBuffer<void> src, Error &error) +SoxrPcmResampler::Resample(ConstBuffer<void> src) { const size_t frame_size = channels * sizeof(float); assert(src.size % frame_size == 0); @@ -162,10 +155,8 @@ SoxrPcmResampler::Resample(ConstBuffer<void> src, Error &error) size_t i_done, o_done; soxr_error_t e = soxr_process(soxr, src.data, n_frames, &i_done, output_buffer, o_frames, &o_done); - if (e != nullptr) { - error.Format(soxr_domain, "soxr error: %s", e); - return nullptr; - } + if (e != nullptr) + throw FormatRuntimeError("soxr error: %s", e); return { output_buffer, o_done * frame_size }; } diff --git a/src/pcm/SoxrResampler.hxx b/src/pcm/SoxrResampler.hxx index 7c7ffd6ed..dc76d3206 100644 --- a/src/pcm/SoxrResampler.hxx +++ b/src/pcm/SoxrResampler.hxx @@ -39,14 +39,12 @@ class SoxrPcmResampler final : public PcmResampler { PcmBuffer buffer; public: - virtual AudioFormat Open(AudioFormat &af, unsigned new_sample_rate, - Error &error) override; - virtual void Close() override; - virtual ConstBuffer<void> Resample(ConstBuffer<void> src, - Error &error) override; + AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override; + void Close() override; + ConstBuffer<void> Resample(ConstBuffer<void> src) override; }; -bool -pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error); +void +pcm_resample_soxr_global_init(const ConfigBlock &block); #endif diff --git a/src/pcm/Volume.cxx b/src/pcm/Volume.cxx index 5e09fc3be..a50854190 100644 --- a/src/pcm/Volume.cxx +++ b/src/pcm/Volume.cxx @@ -24,7 +24,7 @@ #include "Traits.hxx" #include "util/ConstBuffer.hxx" #include "util/WritableBuffer.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "PcmDither.cxx" // including the .cxx file to get inlined templates @@ -97,17 +97,15 @@ pcm_volume_change_float(float *dest, const float *src, size_t n, dest[i] = src[i] * volume; } -bool -PcmVolume::Open(SampleFormat _format, Error &error) +void +PcmVolume::Open(SampleFormat _format) { assert(format == SampleFormat::UNDEFINED); switch (_format) { case SampleFormat::UNDEFINED: - error.Format(pcm_domain, - "Software volume for %s is not implemented", - sample_format_to_string(_format)); - return false; + throw FormatRuntimeError("Software volume for %s is not implemented", + sample_format_to_string(_format)); case SampleFormat::S8: case SampleFormat::S16: @@ -122,7 +120,6 @@ PcmVolume::Open(SampleFormat _format, Error &error) } format = _format; - return true; } ConstBuffer<void> diff --git a/src/pcm/Volume.hxx b/src/pcm/Volume.hxx index 1576b33b1..a68dc958f 100644 --- a/src/pcm/Volume.hxx +++ b/src/pcm/Volume.hxx @@ -28,7 +28,6 @@ #include <assert.h> #endif -class Error; template<typename T> struct ConstBuffer; /** @@ -93,11 +92,11 @@ public: /** * Opens the object, prepare for Apply(). * + * Throws std::runtime_error on error. + * * @param format the sample format - * @param error location to store the error - * @return true on success */ - bool Open(SampleFormat format, Error &error); + void Open(SampleFormat format); /** * Closes the object. After that, you may call Open() again. diff --git a/test/run_convert.cxx b/test/run_convert.cxx index 8b89831a5..a07e71f47 100644 --- a/test/run_convert.cxx +++ b/test/run_convert.cxx @@ -38,8 +38,9 @@ #include <stdio.h> #include <unistd.h> -int main(int argc, char **argv) -{ +int +main(int argc, char **argv) +try { AudioFormat in_audio_format, out_audio_format; if (argc != 3) { @@ -68,10 +69,7 @@ int main(int argc, char **argv) const size_t in_frame_size = in_audio_format.GetFrameSize(); PcmConvert state; - if (!state.Open(in_audio_format, out_audio_format_mask, error)) { - LogError(error, "Failed to open PcmConvert"); - return EXIT_FAILURE; - } + state.Open(in_audio_format, out_audio_format_mask); StaticFifoBuffer<uint8_t, 4096> buffer; @@ -96,12 +94,7 @@ int main(int argc, char **argv) buffer.Consume(src.size); - auto output = state.Convert({src.data, src.size}, error); - if (output.IsNull()) { - state.Close(); - LogError(error, "Failed to convert"); - return EXIT_FAILURE; - } + auto output = state.Convert({src.data, src.size}); gcc_unused ssize_t ignored = write(1, output.data, output.size); @@ -110,4 +103,7 @@ int main(int argc, char **argv) state.Close(); return EXIT_SUCCESS; +} catch (const std::exception &e) { + LogError(e); + return EXIT_FAILURE; } diff --git a/test/software_volume.cxx b/test/software_volume.cxx index d0b977ef2..45604b8a1 100644 --- a/test/software_volume.cxx +++ b/test/software_volume.cxx @@ -36,8 +36,9 @@ #include <stdlib.h> #include <unistd.h> -int main(int argc, char **argv) -{ +int +main(int argc, char **argv) +try { static char buffer[4096]; ssize_t nbytes; @@ -56,10 +57,7 @@ int main(int argc, char **argv) } PcmVolume pv; - if (!pv.Open(audio_format.format, error)) { - fprintf(stderr, "%s\n", error.GetMessage()); - return EXIT_FAILURE; - } + pv.Open(audio_format.format); while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { auto dest = pv.Apply({buffer, size_t(nbytes)}); @@ -67,4 +65,7 @@ int main(int argc, char **argv) } pv.Close(); +} catch (const std::exception &e) { + LogError(e); + return EXIT_FAILURE; } diff --git a/test/test_pcm_volume.cxx b/test/test_pcm_volume.cxx index 9cb693d7d..c774af49d 100644 --- a/test/test_pcm_volume.cxx +++ b/test/test_pcm_volume.cxx @@ -22,7 +22,6 @@ #include "pcm/Volume.hxx" #include "pcm/Traits.hxx" #include "util/ConstBuffer.hxx" -#include "util/Error.hxx" #include "test_pcm_util.hxx" #include <algorithm> @@ -37,7 +36,7 @@ TestVolume(G g=G()) typedef typename Traits::value_type value_type; PcmVolume pv; - CPPUNIT_ASSERT(pv.Open(F, IgnoreError())); + pv.Open(F); constexpr size_t N = 509; static value_type zero[N]; @@ -96,7 +95,7 @@ void PcmVolumeTest::TestVolumeFloat() { PcmVolume pv; - CPPUNIT_ASSERT(pv.Open(SampleFormat::FLOAT, IgnoreError())); + pv.Open(SampleFormat::FLOAT); constexpr size_t N = 509; static float zero[N]; |