From 29030b54c98b0aee65fbc10ebf7ba36bed98c02c Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 10 Aug 2013 18:02:44 +0200 Subject: util/Error: new error passing library Replaces GLib's GError. --- src/output/AlsaOutputPlugin.cxx | 78 +++++++++--------- src/output/AoOutputPlugin.cxx | 49 ++++++------ src/output/FifoOutputPlugin.cxx | 90 +++++++++------------ src/output/HttpdClient.cxx | 5 +- src/output/HttpdClient.hxx | 2 +- src/output/HttpdInternal.hxx | 12 +-- src/output/HttpdOutputPlugin.cxx | 65 +++++++-------- src/output/JackOutputPlugin.cxx | 88 ++++++++++----------- src/output/NullOutputPlugin.cxx | 12 +-- src/output/OSXOutputPlugin.cxx | 84 ++++++++++---------- src/output/OpenALOutputPlugin.cxx | 40 ++++------ src/output/OssOutputPlugin.cxx | 114 ++++++++++++-------------- src/output/PipeOutputPlugin.cxx | 43 +++++----- src/output/PulseOutputPlugin.cxx | 152 +++++++++++++++-------------------- src/output/PulseOutputPlugin.hxx | 5 +- src/output/RecorderOutputPlugin.cxx | 71 ++++++++--------- src/output/RoarOutputPlugin.cxx | 30 ++++--- src/output/ShoutOutputPlugin.cxx | 154 ++++++++++++++++-------------------- src/output/SolarisOutputPlugin.cxx | 34 +++----- src/output/WinmmOutputPlugin.cxx | 61 +++++++------- 20 files changed, 528 insertions(+), 661 deletions(-) (limited to 'src/output') diff --git a/src/output/AlsaOutputPlugin.cxx b/src/output/AlsaOutputPlugin.cxx index d707166c5..c9bf01909 100644 --- a/src/output/AlsaOutputPlugin.cxx +++ b/src/output/AlsaOutputPlugin.cxx @@ -23,6 +23,8 @@ #include "MixerList.hxx" #include "pcm/PcmExport.hxx" #include "util/Manual.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include #include @@ -115,9 +117,9 @@ struct AlsaOutput { AlsaOutput():mode(0), writei(snd_pcm_writei) { } - bool Init(const config_param ¶m, GError **error_r) { + bool Init(const config_param ¶m, Error &error) { return ao_base_init(&base, &alsa_output_plugin, - param, error_r); + param, error); } void Deinit() { @@ -125,14 +127,7 @@ struct AlsaOutput { } }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -alsa_output_quark(void) -{ - return g_quark_from_static_string("alsa_output"); -} +static constexpr Domain alsa_output_domain("alsa_output"); static const char * alsa_device(const AlsaOutput *ad) @@ -170,11 +165,11 @@ alsa_configure(AlsaOutput *ad, const config_param ¶m) } static struct audio_output * -alsa_init(const config_param ¶m, GError **error_r) +alsa_init(const config_param ¶m, Error &error) { AlsaOutput *ad = new AlsaOutput(); - if (!ad->Init(param, error_r)) { + if (!ad->Init(param, error)) { delete ad; return NULL; } @@ -197,7 +192,7 @@ alsa_finish(struct audio_output *ao) } static bool -alsa_output_enable(struct audio_output *ao, gcc_unused GError **error_r) +alsa_output_enable(struct audio_output *ao, gcc_unused Error &error) { AlsaOutput *ad = (AlsaOutput *)ao; @@ -394,7 +389,7 @@ alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, */ static bool alsa_setup(AlsaOutput *ad, AudioFormat &audio_format, - bool *packed_r, bool *reverse_endian_r, GError **error) + bool *packed_r, bool *reverse_endian_r, Error &error) { unsigned int sample_rate = audio_format.sample_rate; unsigned int channels = audio_format.channels; @@ -438,11 +433,11 @@ configure_hw: err = alsa_output_setup_format(ad->pcm, hwparams, audio_format, packed_r, reverse_endian_r); if (err < 0) { - g_set_error(error, alsa_output_quark(), err, - "ALSA device \"%s\" does not support format %s: %s", - alsa_device(ad), - sample_format_to_string(audio_format.format), - snd_strerror(-err)); + error.Format(alsa_output_domain, err, + "ALSA device \"%s\" does not support format %s: %s", + alsa_device(ad), + sample_format_to_string(audio_format.format), + snd_strerror(-err)); return false; } @@ -454,10 +449,10 @@ configure_hw: err = snd_pcm_hw_params_set_channels_near(ad->pcm, hwparams, &channels); if (err < 0) { - g_set_error(error, alsa_output_quark(), err, - "ALSA device \"%s\" does not support %i channels: %s", - alsa_device(ad), (int)audio_format.channels, - snd_strerror(-err)); + error.Format(alsa_output_domain, err, + "ALSA device \"%s\" does not support %i channels: %s", + alsa_device(ad), (int)audio_format.channels, + snd_strerror(-err)); return false; } audio_format.channels = (int8_t)channels; @@ -465,9 +460,9 @@ configure_hw: err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams, &sample_rate, NULL); if (err < 0 || sample_rate == 0) { - g_set_error(error, alsa_output_quark(), err, - "ALSA device \"%s\" does not support %u Hz audio", - alsa_device(ad), audio_format.sample_rate); + error.Format(alsa_output_domain, err, + "ALSA device \"%s\" does not support %u Hz audio", + alsa_device(ad), audio_format.sample_rate); return false; } audio_format.sample_rate = sample_rate; @@ -594,16 +589,16 @@ configure_hw: return true; error: - g_set_error(error, alsa_output_quark(), err, - "Error opening ALSA device \"%s\" (%s): %s", - alsa_device(ad), cmd, snd_strerror(-err)); + error.Format(alsa_output_domain, err, + "Error opening ALSA device \"%s\" (%s): %s", + alsa_device(ad), cmd, snd_strerror(-err)); return false; } static bool alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, bool *shift8_r, bool *packed_r, bool *reverse_endian_r, - GError **error_r) + Error &error) { assert(ad->dsd_usb); assert(audio_format.format == SampleFormat::DSD); @@ -616,7 +611,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, const AudioFormat check = usb_format; - if (!alsa_setup(ad, usb_format, packed_r, reverse_endian_r, error_r)) + if (!alsa_setup(ad, usb_format, packed_r, reverse_endian_r, error)) return false; /* if the device allows only 32 bit, shift all DSD-over-USB @@ -631,9 +626,9 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, if (usb_format != check) { /* no bit-perfect playback, which is required for DSD over USB */ - g_set_error(error_r, alsa_output_quark(), 0, - "Failed to configure DSD-over-USB on ALSA device \"%s\"", - alsa_device(ad)); + error.Format(alsa_output_domain, + "Failed to configure DSD-over-USB on ALSA device \"%s\"", + alsa_device(ad)); g_free(ad->silence); return false; } @@ -643,7 +638,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, static bool alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format, - GError **error_r) + Error &error) { bool shift8 = false, packed, reverse_endian; @@ -652,9 +647,9 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format, const bool success = dsd_usb ? alsa_setup_dsd(ad, audio_format, &shift8, &packed, &reverse_endian, - error_r) + error) : alsa_setup(ad, audio_format, &packed, &reverse_endian, - error_r); + error); if (!success) return false; @@ -665,14 +660,14 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format, } static bool -alsa_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) +alsa_open(struct audio_output *ao, AudioFormat &audio_format, Error &error) { AlsaOutput *ad = (AlsaOutput *)ao; int err = snd_pcm_open(&ad->pcm, alsa_device(ad), SND_PCM_STREAM_PLAYBACK, ad->mode); if (err < 0) { - g_set_error(error, alsa_output_quark(), err, + error.Format(alsa_output_domain, err, "Failed to open ALSA device \"%s\": %s", alsa_device(ad), snd_strerror(err)); return false; @@ -800,7 +795,7 @@ alsa_close(struct audio_output *ao) static size_t alsa_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error) + Error &error) { AlsaOutput *ad = (AlsaOutput *)ao; @@ -824,8 +819,7 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size, if (ret < 0 && ret != -EAGAIN && ret != -EINTR && alsa_recover(ad, ret) < 0) { - g_set_error(error, alsa_output_quark(), errno, - "%s", snd_strerror(-errno)); + error.Set(alsa_output_domain, ret, snd_strerror(-ret)); return 0; } } diff --git a/src/output/AoOutputPlugin.cxx b/src/output/AoOutputPlugin.cxx index db7b9a360..a54611511 100644 --- a/src/output/AoOutputPlugin.cxx +++ b/src/output/AoOutputPlugin.cxx @@ -20,6 +20,8 @@ #include "config.h" #include "AoOutputPlugin.hxx" #include "OutputAPI.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include #include @@ -42,26 +44,22 @@ struct AoOutput { ao_option *options; ao_device *device; - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error) { return ao_base_init(&base, &ao_output_plugin, param, - error_r); + error); } void Deinitialize() { ao_base_finish(&base); } - bool Configure(const config_param ¶m, GError **error_r); + bool Configure(const config_param ¶m, Error &error); }; -static inline GQuark -ao_output_quark(void) -{ - return g_quark_from_static_string("ao_output"); -} +static constexpr Domain ao_output_domain("ao_output"); static void -ao_output_error(GError **error_r) +ao_output_error(Error &error_r) { const char *error; @@ -87,15 +85,15 @@ ao_output_error(GError **error_r) break; default: - error = g_strerror(errno); + error_r.SetErrno(); + return; } - g_set_error(error_r, ao_output_quark(), errno, - "%s", error); + error_r.Set(ao_output_domain, errno, error); } inline bool -AoOutput::Configure(const config_param ¶m, GError **error_r) +AoOutput::Configure(const config_param ¶m, Error &error) { const char *value; @@ -115,16 +113,15 @@ AoOutput::Configure(const config_param ¶m, GError **error_r) driver = ao_driver_id(value); if (driver < 0) { - g_set_error(error_r, ao_output_quark(), 0, - "\"%s\" is not a valid ao driver", - value); + error.Format(ao_output_domain, + "\"%s\" is not a valid ao driver", + value); return false; } ao_info *ai = ao_driver_info(driver); if (ai == nullptr) { - g_set_error(error_r, ao_output_quark(), 0, - "problems getting driver info"); + error.Set(ao_output_domain, "problems getting driver info"); return false; } @@ -139,9 +136,9 @@ AoOutput::Configure(const config_param ¶m, GError **error_r) gchar **key_value = g_strsplit(_options[i], "=", 2); if (key_value[0] == nullptr || key_value[1] == nullptr) { - g_set_error(error_r, ao_output_quark(), 0, - "problems parsing options \"%s\"", - _options[i]); + error.Format(ao_output_domain, + "problems parsing options \"%s\"", + _options[i]); return false; } @@ -158,16 +155,16 @@ AoOutput::Configure(const config_param ¶m, GError **error_r) } static struct audio_output * -ao_output_init(const config_param ¶m, GError **error_r) +ao_output_init(const config_param ¶m, Error &error) { AoOutput *ad = new AoOutput(); - if (!ad->Initialize(param, error_r)) { + if (!ad->Initialize(param, error)) { delete ad; return nullptr; } - if (!ad->Configure(param, error_r)) { + if (!ad->Configure(param, error)) { ad->Deinitialize(); delete ad; return nullptr; @@ -201,7 +198,7 @@ ao_output_close(struct audio_output *ao) static bool ao_output_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error) + Error &error) { ao_sample_format format = OUR_AO_FORMAT_INITIALIZER; AoOutput *ad = (AoOutput *)ao; @@ -257,7 +254,7 @@ static int ao_play_deconst(ao_device *device, const void *output_samples, static size_t ao_output_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error) + Error &error) { AoOutput *ad = (AoOutput *)ao; diff --git a/src/output/FifoOutputPlugin.cxx b/src/output/FifoOutputPlugin.cxx index 29dd50cb1..34199bff9 100644 --- a/src/output/FifoOutputPlugin.cxx +++ b/src/output/FifoOutputPlugin.cxx @@ -19,11 +19,14 @@ #include "config.h" #include "FifoOutputPlugin.hxx" +#include "ConfigError.hxx" #include "OutputAPI.hxx" #include "Timer.hxx" #include "system/fd_util.h" #include "fs/Path.hxx" #include "fs/FileSystem.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "open.h" #include @@ -53,31 +56,24 @@ struct FifoOutput { FifoOutput() :path(Path::Null()), input(-1), output(-1), created(false) {} - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error) { return ao_base_init(&base, &fifo_output_plugin, param, - error_r); + error); } void Deinitialize() { ao_base_finish(&base); } - bool Create(GError **error_r); - bool Check(GError **error_r); + bool Create(Error &error); + bool Check(Error &error); void Delete(); - bool Open(GError **error_r); + bool Open(Error &error); void Close(); }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -fifo_output_quark(void) -{ - return g_quark_from_static_string("fifo_output"); -} +static constexpr Domain fifo_output_domain("fifo_output"); inline void FifoOutput::Delete() @@ -112,12 +108,11 @@ FifoOutput::Close() } inline bool -FifoOutput::Create(GError **error_r) +FifoOutput::Create(Error &error) { if (!MakeFifo(path, 0666)) { - g_set_error(error_r, fifo_output_quark(), errno, - "Couldn't create FIFO \"%s\": %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Couldn't create FIFO \"%s\"", + path_utf8.c_str()); return false; } @@ -126,25 +121,24 @@ FifoOutput::Create(GError **error_r) } inline bool -FifoOutput::Check(GError **error_r) +FifoOutput::Check(Error &error) { struct stat st; if (!StatFile(path, st)) { if (errno == ENOENT) { /* Path doesn't exist */ - return Create(error_r); + return Create(error); } - g_set_error(error_r, fifo_output_quark(), errno, - "Failed to stat FIFO \"%s\": %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Failed to stat FIFO \"%s\"", + path_utf8.c_str()); return false; } if (!S_ISFIFO(st.st_mode)) { - g_set_error(error_r, fifo_output_quark(), 0, - "\"%s\" already exists, but is not a FIFO", - path_utf8.c_str()); + error.Format(fifo_output_domain, + "\"%s\" already exists, but is not a FIFO", + path_utf8.c_str()); return false; } @@ -152,25 +146,23 @@ FifoOutput::Check(GError **error_r) } inline bool -FifoOutput::Open(GError **error_r) +FifoOutput::Open(Error &error) { - if (!Check(error_r)) + if (!Check(error)) return false; input = OpenFile(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0); if (input < 0) { - g_set_error(error_r, fifo_output_quark(), errno, - "Could not open FIFO \"%s\" for reading: %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Could not open FIFO \"%s\" for reading", + path_utf8.c_str()); Close(); return false; } output = OpenFile(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0); if (output < 0) { - g_set_error(error_r, fifo_output_quark(), errno, - "Could not open FIFO \"%s\" for writing: %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Could not open FIFO \"%s\" for writing", + path_utf8.c_str()); Close(); return false; } @@ -179,37 +171,34 @@ FifoOutput::Open(GError **error_r) } static bool -fifo_open(FifoOutput *fd, GError **error_r) +fifo_open(FifoOutput *fd, Error &error) { - return fd->Open(error_r); + return fd->Open(error); } static struct audio_output * -fifo_output_init(const config_param ¶m, GError **error_r) +fifo_output_init(const config_param ¶m, Error &error) { - GError *error = nullptr; - FifoOutput *fd = new FifoOutput(); - fd->path = param.GetBlockPath("path", &error); + fd->path = param.GetBlockPath("path", error); if (fd->path.IsNull()) { delete fd; - if (error != nullptr) - g_propagate_error(error_r, error); - else - g_set_error(error_r, fifo_output_quark(), 0, - "No \"path\" parameter specified"); + + if (!error.IsDefined()) + error.Set(config_domain, + "No \"path\" parameter specified"); return nullptr; } fd->path_utf8 = fd->path.ToUTF8(); - if (!fd->Initialize(param, error_r)) { + if (!fd->Initialize(param, error)) { delete fd; return nullptr; } - if (!fifo_open(fd, error_r)) { + if (!fifo_open(fd, error)) { fd->Deinitialize(); delete fd; return nullptr; @@ -230,7 +219,7 @@ fifo_output_finish(struct audio_output *ao) static bool fifo_output_open(struct audio_output *ao, AudioFormat &audio_format, - gcc_unused GError **error) + gcc_unused Error &error) { FifoOutput *fd = (FifoOutput *)ao; @@ -277,7 +266,7 @@ fifo_output_delay(struct audio_output *ao) static size_t fifo_output_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error) + Error &error) { FifoOutput *fd = (FifoOutput *)ao; ssize_t bytes; @@ -301,9 +290,8 @@ fifo_output_play(struct audio_output *ao, const void *chunk, size_t size, continue; } - g_set_error(error, fifo_output_quark(), errno, - "Failed to write to FIFO %s: %s", - fd->path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Failed to write to FIFO %s", + fd->path_utf8.c_str()); return 0; } } diff --git a/src/output/HttpdClient.cxx b/src/output/HttpdClient.cxx index c097e48f1..9ed7805dc 100644 --- a/src/output/HttpdClient.cxx +++ b/src/output/HttpdClient.cxx @@ -431,10 +431,9 @@ HttpdClient::OnSocketInput(const void *data, size_t length) } void -HttpdClient::OnSocketError(GError *error) +HttpdClient::OnSocketError(Error &&error) { - g_warning("error on HTTP client: %s", error->message); - g_error_free(error); + g_warning("error on HTTP client: %s", error.GetMessage()); } void diff --git a/src/output/HttpdClient.hxx b/src/output/HttpdClient.hxx index 38e4ea96d..a596814ee 100644 --- a/src/output/HttpdClient.hxx +++ b/src/output/HttpdClient.hxx @@ -179,7 +179,7 @@ protected: virtual bool OnSocketReady(unsigned flags) override; virtual InputResult OnSocketInput(const void *data, size_t length) override; - virtual void OnSocketError(GError *error) override; + virtual void OnSocketError(Error &&error) override; virtual void OnSocketClosed() override; }; diff --git a/src/output/HttpdInternal.hxx b/src/output/HttpdInternal.hxx index e8a37e033..39fc700a3 100644 --- a/src/output/HttpdInternal.hxx +++ b/src/output/HttpdInternal.hxx @@ -33,6 +33,7 @@ #include struct config_param; +class Error; class EventLoop; class ServerSocket; class HttpdClient; @@ -123,21 +124,20 @@ struct HttpdOutput final : private ServerSocket { HttpdOutput(EventLoop &_loop); ~HttpdOutput(); - bool Configure(const config_param ¶m, GError **error_r); + bool Configure(const config_param ¶m, Error &error); - bool Bind(GError **error_r); + bool Bind(Error &error); void Unbind(); /** * Caller must lock the mutex. */ - bool OpenEncoder(AudioFormat &audio_format, - GError **error_r); + bool OpenEncoder(AudioFormat &audio_format, Error &error); /** * Caller must lock the mutex. */ - bool Open(AudioFormat &audio_format, GError **error_r); + bool Open(AudioFormat &audio_format, Error &error); /** * Caller must lock the mutex. @@ -194,7 +194,7 @@ struct HttpdOutput final : private ServerSocket { */ void BroadcastFromEncoder(); - bool EncodeAndPlay(const void *chunk, size_t size, GError **error_r); + bool EncodeAndPlay(const void *chunk, size_t size, Error &error); void SendTag(const Tag *tag); diff --git a/src/output/HttpdOutputPlugin.cxx b/src/output/HttpdOutputPlugin.cxx index 745ed26a2..db395069e 100644 --- a/src/output/HttpdOutputPlugin.cxx +++ b/src/output/HttpdOutputPlugin.cxx @@ -29,6 +29,8 @@ #include "IcyMetaDataServer.hxx" #include "system/fd_util.h" #include "Main.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include @@ -45,14 +47,7 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "httpd_output" -/** - * The quark used for GError.domain. - */ -static inline GQuark -httpd_output_quark(void) -{ - return g_quark_from_static_string("httpd_output"); -} +static constexpr Domain httpd_output_domain("httpd_output"); inline HttpdOutput::HttpdOutput(EventLoop &_loop) @@ -73,12 +68,12 @@ HttpdOutput::~HttpdOutput() } inline bool -HttpdOutput::Bind(GError **error_r) +HttpdOutput::Bind(Error &error) { open = false; const ScopeLock protect(mutex); - return ServerSocket::Open(error_r); + return ServerSocket::Open(error); } inline void @@ -91,7 +86,7 @@ HttpdOutput::Unbind() } inline bool -HttpdOutput::Configure(const config_param ¶m, GError **error_r) +HttpdOutput::Configure(const config_param ¶m, Error &error) { /* read configuration */ name = param.GetBlockValue("name", "Set name in config"); @@ -104,8 +99,8 @@ HttpdOutput::Configure(const config_param ¶m, GError **error_r) param.GetBlockValue("encoder", "vorbis"); const auto encoder_plugin = encoder_plugin_get(encoder_name); if (encoder_plugin == NULL) { - g_set_error(error_r, httpd_output_quark(), 0, - "No such encoder: %s", encoder_name); + error.Format(httpd_output_domain, + "No such encoder: %s", encoder_name); return false; } @@ -116,14 +111,14 @@ HttpdOutput::Configure(const config_param ¶m, GError **error_r) const char *bind_to_address = param.GetBlockValue("bind_to_address"); bool success = bind_to_address != NULL && strcmp(bind_to_address, "any") != 0 - ? AddHost(bind_to_address, port, error_r) - : AddPort(port, error_r); + ? AddHost(bind_to_address, port, error) + : AddPort(port, error); if (!success) return false; /* initialize encoder */ - encoder = encoder_init(*encoder_plugin, param, error_r); + encoder = encoder_init(*encoder_plugin, param, error); if (encoder == nullptr) return false; @@ -136,18 +131,17 @@ HttpdOutput::Configure(const config_param ¶m, GError **error_r) } static struct audio_output * -httpd_output_init(const struct config_param ¶m, - GError **error_r) +httpd_output_init(const config_param ¶m, Error &error) { HttpdOutput *httpd = new HttpdOutput(*main_loop); if (!ao_base_init(&httpd->base, &httpd_output_plugin, param, - error_r)) { + error)) { delete httpd; return nullptr; } - if (!httpd->Configure(param, error_r)) { + if (!httpd->Configure(param, error)) { ao_base_finish(&httpd->base); delete httpd; return nullptr; @@ -205,7 +199,8 @@ HttpdOutput::OnAccept(int fd, const sockaddr &address, #ifdef HAVE_LIBWRAP if (address.sa_family != AF_UNIX) { - char *hostaddr = sockaddr_to_string(&address, address_length, NULL); + char *hostaddr = sockaddr_to_string(&address, address_length, + IgnoreError()); const char *progname = g_get_prgname(); struct request_info req; @@ -249,7 +244,7 @@ HttpdOutput::ReadPage() /* we have fed a lot of input into the encoder, but it didn't give anything back yet - flush now to avoid buffer underruns */ - encoder_flush(encoder, NULL); + encoder_flush(encoder, IgnoreError()); unflushed_input = 0; } @@ -273,11 +268,11 @@ HttpdOutput::ReadPage() } static bool -httpd_output_enable(struct audio_output *ao, GError **error_r) +httpd_output_enable(struct audio_output *ao, Error &error) { HttpdOutput *httpd = Cast(ao); - return httpd->Bind(error_r); + return httpd->Bind(error); } static void @@ -289,7 +284,7 @@ httpd_output_disable(struct audio_output *ao) } inline bool -HttpdOutput::OpenEncoder(AudioFormat &audio_format, GError **error) +HttpdOutput::OpenEncoder(AudioFormat &audio_format, Error &error) { if (!encoder_open(encoder, audio_format, error)) return false; @@ -305,14 +300,14 @@ HttpdOutput::OpenEncoder(AudioFormat &audio_format, GError **error) } inline bool -HttpdOutput::Open(AudioFormat &audio_format, GError **error_r) +HttpdOutput::Open(AudioFormat &audio_format, Error &error) { assert(!open); assert(clients.empty()); /* open the encoder */ - if (!OpenEncoder(audio_format, error_r)) + if (!OpenEncoder(audio_format, error)) return false; /* initialize other attributes */ @@ -327,7 +322,7 @@ HttpdOutput::Open(AudioFormat &audio_format, GError **error_r) static bool httpd_output_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error) + Error &error) { HttpdOutput *httpd = Cast(ao); @@ -439,9 +434,9 @@ HttpdOutput::BroadcastFromEncoder() } inline bool -HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, GError **error_r) +HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, Error &error) { - if (!encoder_write(encoder, chunk, size, error_r)) + if (!encoder_write(encoder, chunk, size, error)) return false; unflushed_input += size; @@ -452,12 +447,12 @@ HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, GError **error_r) static size_t httpd_output_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error_r) + Error &error) { HttpdOutput *httpd = Cast(ao); if (httpd->LockHasClients()) { - if (!httpd->EncodeAndPlay(chunk, size, error_r)) + if (!httpd->EncodeAndPlay(chunk, size, error)) return 0; } @@ -476,7 +471,7 @@ httpd_output_pause(struct audio_output *ao) if (httpd->LockHasClients()) { static const char silence[1020] = { 0 }; return httpd_output_play(ao, silence, sizeof(silence), - NULL) > 0; + IgnoreError()) > 0; } else { return true; } @@ -492,13 +487,13 @@ HttpdOutput::SendTag(const Tag *tag) /* flush the current stream, and end it */ - encoder_pre_tag(encoder, NULL); + encoder_pre_tag(encoder, IgnoreError()); BroadcastFromEncoder(); /* send the tag to the encoder - which starts a new stream now */ - encoder_tag(encoder, tag, NULL); + encoder_tag(encoder, tag, IgnoreError()); /* the first page generated by the encoder will now be used as the new "header" page, which is sent to all diff --git a/src/output/JackOutputPlugin.cxx b/src/output/JackOutputPlugin.cxx index bca57cfc1..63e46ef5a 100644 --- a/src/output/JackOutputPlugin.cxx +++ b/src/output/JackOutputPlugin.cxx @@ -20,6 +20,9 @@ #include "config.h" #include "JackOutputPlugin.hxx" #include "OutputAPI.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include @@ -82,7 +85,7 @@ struct JackOutput { */ bool pause; - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error_r) { return ao_base_init(&base, &jack_output_plugin, param, error_r); } @@ -92,14 +95,7 @@ struct JackOutput { } }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -jack_output_quark(void) -{ - return g_quark_from_static_string("jack_output"); -} +static constexpr Domain jack_output_domain("jack_output"); /** * Determine the number of frames guaranteed to be available on all @@ -250,7 +246,7 @@ mpd_jack_disconnect(JackOutput *jd) * (e.g. register callbacks). */ static bool -mpd_jack_connect(JackOutput *jd, GError **error_r) +mpd_jack_connect(JackOutput *jd, Error &error) { jack_status_t status; @@ -261,9 +257,9 @@ mpd_jack_connect(JackOutput *jd, GError **error_r) jd->client = jack_client_open(jd->name, jd->options, &status, jd->server_name); if (jd->client == nullptr) { - g_set_error(error_r, jack_output_quark(), 0, - "Failed to connect to JACK server, status=%d", - status); + error.Format(jack_output_domain, status, + "Failed to connect to JACK server, status=%d", + status); return false; } @@ -276,9 +272,9 @@ mpd_jack_connect(JackOutput *jd, GError **error_r) JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (jd->ports[i] == nullptr) { - g_set_error(error_r, jack_output_quark(), 0, - "Cannot register output port \"%s\"", - jd->source_ports[i]); + error.Format(jack_output_domain, + "Cannot register output port \"%s\"", + jd->source_ports[i]); mpd_jack_disconnect(jd); return false; } @@ -294,16 +290,16 @@ mpd_jack_test_default_device(void) } static unsigned -parse_port_list(int line, const char *source, char **dest, GError **error_r) +parse_port_list(int line, const char *source, char **dest, Error &error) { char **list = g_strsplit(source, ",", 0); unsigned n = 0; for (n = 0; list[n] != nullptr; ++n) { if (n >= MAX_PORTS) { - g_set_error(error_r, jack_output_quark(), 0, - "too many port names in line %d", - line); + error.Format(config_domain, + "too many port names in line %d", + line); return 0; } @@ -313,9 +309,9 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r) g_free(list); if (n == 0) { - g_set_error(error_r, jack_output_quark(), 0, - "at least one port name expected in line %d", - line); + error.Format(config_domain, + "at least one port name expected in line %d", + line); return 0; } @@ -323,11 +319,11 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r) } static struct audio_output * -mpd_jack_init(const config_param ¶m, GError **error_r) +mpd_jack_init(const config_param ¶m, Error &error) { JackOutput *jd = new JackOutput(); - if (!jd->Initialize(param, error_r)) { + if (!jd->Initialize(param, error)) { delete jd; return nullptr; } @@ -355,7 +351,7 @@ mpd_jack_init(const config_param ¶m, GError **error_r) value = param.GetBlockValue("source_ports", "left,right"); jd->num_source_ports = parse_port_list(param.line, value, - jd->source_ports, error_r); + jd->source_ports, error); if (jd->num_source_ports == 0) return nullptr; @@ -373,7 +369,7 @@ mpd_jack_init(const config_param ¶m, GError **error_r) if (value != nullptr) { jd->num_destination_ports = parse_port_list(param.line, value, - jd->destination_ports, error_r); + jd->destination_ports, error); if (jd->num_destination_ports == 0) return nullptr; } else { @@ -414,14 +410,14 @@ mpd_jack_finish(struct audio_output *ao) } static bool -mpd_jack_enable(struct audio_output *ao, GError **error_r) +mpd_jack_enable(struct audio_output *ao, Error &error) { JackOutput *jd = (JackOutput *)ao; for (unsigned i = 0; i < jd->num_source_ports; ++i) jd->ringbuffer[i] = nullptr; - return mpd_jack_connect(jd, error_r); + return mpd_jack_connect(jd, error); } static void @@ -460,7 +456,7 @@ mpd_jack_stop(JackOutput *jd) } static bool -mpd_jack_start(JackOutput *jd, GError **error_r) +mpd_jack_start(JackOutput *jd, Error &error) { const char *destination_ports[MAX_PORTS], **jports; const char *duplicate_port = nullptr; @@ -484,8 +480,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r) } if ( jack_activate(jd->client) ) { - g_set_error(error_r, jack_output_quark(), 0, - "cannot activate client"); + error.Set(jack_output_domain, "cannot activate client"); mpd_jack_stop(jd); return false; } @@ -496,8 +491,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r) jports = jack_get_ports(jd->client, nullptr, nullptr, JackPortIsPhysical | JackPortIsInput); if (jports == nullptr) { - g_set_error(error_r, jack_output_quark(), 0, - "no ports found"); + error.Set(jack_output_domain, "no ports found"); mpd_jack_stop(jd); return false; } @@ -551,9 +545,9 @@ mpd_jack_start(JackOutput *jd, GError **error_r) ret = jack_connect(jd->client, jack_port_name(jd->ports[i]), destination_ports[i]); if (ret != 0) { - g_set_error(error_r, jack_output_quark(), 0, - "Not a valid JACK port: %s", - destination_ports[i]); + error.Format(jack_output_domain, + "Not a valid JACK port: %s", + destination_ports[i]); if (jports != nullptr) free(jports); @@ -571,9 +565,9 @@ mpd_jack_start(JackOutput *jd, GError **error_r) ret = jack_connect(jd->client, jack_port_name(jd->ports[0]), duplicate_port); if (ret != 0) { - g_set_error(error_r, jack_output_quark(), 0, - "Not a valid JACK port: %s", - duplicate_port); + error.Format(jack_output_domain, + "Not a valid JACK port: %s", + duplicate_port); if (jports != nullptr) free(jports); @@ -591,7 +585,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r) static bool mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error_r) + Error &error) { JackOutput *jd = (JackOutput *)ao; @@ -602,13 +596,13 @@ mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format, if (jd->client != nullptr && jd->shutdown) mpd_jack_disconnect(jd); - if (jd->client == nullptr && !mpd_jack_connect(jd, error_r)) + if (jd->client == nullptr && !mpd_jack_connect(jd, error)) return false; set_audioformat(jd, audio_format); jd->audio_format = audio_format; - if (!mpd_jack_start(jd, error_r)) + if (!mpd_jack_start(jd, error)) return false; return true; @@ -701,7 +695,7 @@ mpd_jack_write_samples(JackOutput *jd, const void *src, static size_t mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error_r) + Error &error) { JackOutput *jd = (JackOutput *)ao; const size_t frame_size = jd->audio_format.GetFrameSize(); @@ -714,9 +708,9 @@ mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size, while (true) { if (jd->shutdown) { - g_set_error(error_r, jack_output_quark(), 0, - "Refusing to play, because " - "there is no client thread"); + error.Set(jack_output_domain, + "Refusing to play, because " + "there is no client thread"); return 0; } diff --git a/src/output/NullOutputPlugin.cxx b/src/output/NullOutputPlugin.cxx index 0ce32fbda..e2eec9dbc 100644 --- a/src/output/NullOutputPlugin.cxx +++ b/src/output/NullOutputPlugin.cxx @@ -31,9 +31,9 @@ struct NullOutput { Timer *timer; - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error) { return ao_base_init(&base, &null_output_plugin, param, - error_r); + error); } void Deinitialize() { @@ -42,11 +42,11 @@ struct NullOutput { }; static struct audio_output * -null_init(const config_param ¶m, GError **error_r) +null_init(const config_param ¶m, Error &error) { NullOutput *nd = new NullOutput(); - if (!nd->Initialize(param, error_r)) { + if (!nd->Initialize(param, error)) { delete nd; return nullptr; } @@ -67,7 +67,7 @@ null_finish(struct audio_output *ao) static bool null_open(struct audio_output *ao, AudioFormat &audio_format, - gcc_unused GError **error) + gcc_unused Error &error) { NullOutput *nd = (NullOutput *)ao; @@ -98,7 +98,7 @@ null_delay(struct audio_output *ao) static size_t null_play(struct audio_output *ao, gcc_unused const void *chunk, size_t size, - gcc_unused GError **error) + gcc_unused Error &error) { NullOutput *nd = (NullOutput *)ao; Timer *timer = nd->timer; diff --git a/src/output/OSXOutputPlugin.cxx b/src/output/OSXOutputPlugin.cxx index 09f5581d5..8445a8028 100644 --- a/src/output/OSXOutputPlugin.cxx +++ b/src/output/OSXOutputPlugin.cxx @@ -21,6 +21,8 @@ #include "OSXOutputPlugin.hxx" #include "OutputAPI.hxx" #include "util/fifo_buffer.h" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" @@ -47,14 +49,7 @@ struct OSXOutput { struct fifo_buffer *buffer; }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -osx_output_quark(void) -{ - return g_quark_from_static_string("osx_output"); -} +static constexpr Domain osx_output_domain("osx_output"); static bool osx_output_test_default_device(void) @@ -85,10 +80,10 @@ osx_output_configure(OSXOutput *oo, const config_param ¶m) } static struct audio_output * -osx_output_init(const config_param ¶m, GError **error_r) +osx_output_init(const config_param ¶m, Error &error) { OSXOutput *oo = new OSXOutput(); - if (!ao_base_init(&oo->base, &osx_output_plugin, param, error_r)) { + if (!ao_base_init(&oo->base, &osx_output_plugin, param, error)) { delete oo; return NULL; } @@ -107,7 +102,7 @@ osx_output_finish(struct audio_output *ao) } static bool -osx_output_set_device(OSXOutput *oo, GError **error) +osx_output_set_device(OSXOutput *oo, Error &error) { bool ret = true; OSStatus status; @@ -124,9 +119,9 @@ osx_output_set_device(OSXOutput *oo, GError **error) &size, NULL); if (status != noErr) { - g_set_error(error, osx_output_quark(), status, - "Unable to determine number of OS X audio devices: %s", - GetMacOSStatusCommentString(status)); + error.Format(osx_output_domain, status, + "Unable to determine number of OS X audio devices: %s", + GetMacOSStatusCommentString(status)); ret = false; goto done; } @@ -138,9 +133,9 @@ osx_output_set_device(OSXOutput *oo, GError **error) &size, deviceids); if (status != noErr) { - g_set_error(error, osx_output_quark(), status, - "Unable to determine OS X audio device IDs: %s", - GetMacOSStatusCommentString(status)); + error.Format(osx_output_domain, status, + "Unable to determine OS X audio device IDs: %s", + GetMacOSStatusCommentString(status)); ret = false; goto done; } @@ -152,11 +147,11 @@ osx_output_set_device(OSXOutput *oo, GError **error) kAudioDevicePropertyDeviceName, &size, name); if (status != noErr) { - g_set_error(error, osx_output_quark(), status, - "Unable to determine OS X device name " - "(device %u): %s", - (unsigned int) deviceids[i], - GetMacOSStatusCommentString(status)); + error.Format(osx_output_domain, status, + "Unable to determine OS X device name " + "(device %u): %s", + (unsigned int) deviceids[i], + GetMacOSStatusCommentString(status)); ret = false; goto done; } @@ -180,9 +175,9 @@ osx_output_set_device(OSXOutput *oo, GError **error) &(deviceids[i]), sizeof(AudioDeviceID)); if (status != noErr) { - g_set_error(error, osx_output_quark(), status, - "Unable to set OS X audio output device: %s", - GetMacOSStatusCommentString(status)); + error.Format(osx_output_domain, status, + "Unable to set OS X audio output device: %s", + GetMacOSStatusCommentString(status)); ret = false; goto done; } @@ -237,7 +232,7 @@ osx_render(void *vdata, } static bool -osx_output_enable(struct audio_output *ao, GError **error_r) +osx_output_enable(struct audio_output *ao, Error &error) { OSXOutput *oo = (OSXOutput *)ao; @@ -250,20 +245,20 @@ osx_output_enable(struct audio_output *ao, GError **error_r) Component comp = FindNextComponent(NULL, &desc); if (comp == 0) { - g_set_error(error_r, osx_output_quark(), 0, - "Error finding OS X component"); + error.Set(osx_output_domain, + "Error finding OS X component"); return false; } OSStatus status = OpenAComponent(comp, &oo->au); if (status != noErr) { - g_set_error(error_r, osx_output_quark(), status, - "Unable to open OS X component: %s", - GetMacOSStatusCommentString(status)); + error.Format(osx_output_domain, status, + "Unable to open OS X component: %s", + GetMacOSStatusCommentString(status)); return false; } - if (!osx_output_set_device(oo, error_r)) { + if (!osx_output_set_device(oo, error)) { CloseComponent(oo->au); return false; } @@ -279,8 +274,8 @@ osx_output_enable(struct audio_output *ao, GError **error_r) &callback, sizeof(callback)); if (result != noErr) { CloseComponent(oo->au); - g_set_error(error_r, osx_output_quark(), result, - "unable to set callback for OS X audio unit"); + error.Set(osx_output_domain, result, + "unable to set callback for OS X audio unit"); return false; } @@ -316,7 +311,8 @@ osx_output_close(struct audio_output *ao) } static bool -osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) +osx_output_open(struct audio_output *ao, AudioFormat &audio_format, + Error &error) { OSXOutput *od = (OSXOutput *)ao; @@ -359,16 +355,16 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err &stream_description, sizeof(stream_description)); if (result != noErr) { - g_set_error(error, osx_output_quark(), result, - "Unable to set format on OS X device"); + error.Set(osx_output_domain, result, + "Unable to set format on OS X device"); return false; } OSStatus status = AudioUnitInitialize(od->au); if (status != noErr) { - g_set_error(error, osx_output_quark(), status, - "Unable to initialize OS X audio unit: %s", - GetMacOSStatusCommentString(status)); + error.Set(osx_output_domain, status, + "Unable to initialize OS X audio unit: %s", + GetMacOSStatusCommentString(status)); return false; } @@ -379,9 +375,9 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err status = AudioOutputUnitStart(od->au); if (status != 0) { AudioUnitUninitialize(od->au); - g_set_error(error, osx_output_quark(), status, - "unable to start audio output: %s", - GetMacOSStatusCommentString(status)); + error.Format(osx_output_domain, status, + "unable to start audio output: %s", + GetMacOSStatusCommentString(status)); return false; } @@ -390,7 +386,7 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err static size_t osx_output_play(struct audio_output *ao, const void *chunk, size_t size, - gcc_unused GError **error) + gcc_unused Error &error) { OSXOutput *od = (OSXOutput *)ao; diff --git a/src/output/OpenALOutputPlugin.cxx b/src/output/OpenALOutputPlugin.cxx index bf4f58aa7..f8b1f5417 100644 --- a/src/output/OpenALOutputPlugin.cxx +++ b/src/output/OpenALOutputPlugin.cxx @@ -20,6 +20,8 @@ #include "config.h" #include "OpenALOutputPlugin.hxx" #include "OutputAPI.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include @@ -49,7 +51,7 @@ struct OpenALOutput { ALenum format; ALuint frequency; - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error_r) { return ao_base_init(&base, &openal_output_plugin, param, error_r); } @@ -59,12 +61,7 @@ struct OpenALOutput { } }; -gcc_const -static inline GQuark -openal_output_quark(void) -{ - return g_quark_from_static_string("openal_output"); -} +static constexpr Domain openal_output_domain("openal_output"); static ALenum openal_audio_format(AudioFormat &audio_format) @@ -115,24 +112,23 @@ openal_is_playing(const OpenALOutput *od) } static bool -openal_setup_context(OpenALOutput *od, - GError **error) +openal_setup_context(OpenALOutput *od, Error &error) { od->device = alcOpenDevice(od->device_name); if (od->device == nullptr) { - g_set_error(error, openal_output_quark(), 0, - "Error opening OpenAL device \"%s\"\n", - od->device_name); + error.Format(openal_output_domain, + "Error opening OpenAL device \"%s\"", + od->device_name); return false; } od->context = alcCreateContext(od->device, nullptr); if (od->context == nullptr) { - g_set_error(error, openal_output_quark(), 0, - "Error creating context for \"%s\"\n", - od->device_name); + error.Format(openal_output_domain, + "Error creating context for \"%s\"", + od->device_name); alcCloseDevice(od->device); return false; } @@ -141,7 +137,7 @@ openal_setup_context(OpenALOutput *od, } static struct audio_output * -openal_init(const config_param ¶m, GError **error_r) +openal_init(const config_param ¶m, Error &error) { const char *device_name = param.GetBlockValue("device"); if (device_name == nullptr) { @@ -149,7 +145,7 @@ openal_init(const config_param ¶m, GError **error_r) } OpenALOutput *od = new OpenALOutput(); - if (!od->Initialize(param, error_r)) { + if (!od->Initialize(param, error)) { delete od; return nullptr; } @@ -170,7 +166,7 @@ openal_finish(struct audio_output *ao) static bool openal_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error) + Error &error) { OpenALOutput *od = (OpenALOutput *)ao; @@ -184,16 +180,14 @@ openal_open(struct audio_output *ao, AudioFormat &audio_format, alGenBuffers(NUM_BUFFERS, od->buffers); if (alGetError() != AL_NO_ERROR) { - g_set_error(error, openal_output_quark(), 0, - "Failed to generate buffers"); + error.Set(openal_output_domain, "Failed to generate buffers"); return false; } alGenSources(1, &od->source); if (alGetError() != AL_NO_ERROR) { - g_set_error(error, openal_output_quark(), 0, - "Failed to generate source"); + error.Set(openal_output_domain, "Failed to generate source"); alDeleteBuffers(NUM_BUFFERS, od->buffers); return false; } @@ -231,7 +225,7 @@ openal_delay(struct audio_output *ao) static size_t openal_play(struct audio_output *ao, const void *chunk, size_t size, - gcc_unused GError **error) + gcc_unused Error &error) { OpenALOutput *od = (OpenALOutput *)ao; ALuint buffer; diff --git a/src/output/OssOutputPlugin.cxx b/src/output/OssOutputPlugin.cxx index b31db6c43..7bf741397 100644 --- a/src/output/OssOutputPlugin.cxx +++ b/src/output/OssOutputPlugin.cxx @@ -22,6 +22,8 @@ #include "OutputAPI.hxx" #include "MixerList.hxx" #include "system/fd_util.h" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include @@ -80,7 +82,7 @@ struct OssOutput { OssOutput():fd(-1), device(nullptr) {} - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error_r) { return ao_base_init(&base, &oss_output_plugin, param, error_r); } @@ -90,14 +92,7 @@ struct OssOutput { } }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -oss_output_quark(void) -{ - return g_quark_from_static_string("oss_output"); -} +static constexpr Domain oss_output_domain("oss_output"); enum oss_stat { OSS_STAT_NO_ERROR = 0, @@ -155,7 +150,7 @@ oss_output_test_default_device(void) } static struct audio_output * -oss_open_default(GError **error) +oss_open_default(Error &error) { int err[G_N_ELEMENTS(default_devices)]; enum oss_stat ret[G_N_ELEMENTS(default_devices)]; @@ -196,18 +191,18 @@ oss_open_default(GError **error) } } - g_set_error(error, oss_output_quark(), 0, - "error trying to open default OSS device"); + error.Set(oss_output_domain, + "error trying to open default OSS device"); return NULL; } static struct audio_output * -oss_output_init(const config_param ¶m, GError **error_r) +oss_output_init(const config_param ¶m, Error &error) { const char *device = param.GetBlockValue("device"); if (device != NULL) { OssOutput *od = new OssOutput(); - if (!od->Initialize(param, error_r)) { + if (!od->Initialize(param, error)) { delete od; return NULL; } @@ -216,7 +211,7 @@ oss_output_init(const config_param ¶m, GError **error_r) return &od->base; } - return oss_open_default(error_r); + return oss_open_default(error); } static void @@ -231,7 +226,7 @@ oss_output_finish(struct audio_output *ao) #ifdef AFMT_S24_PACKED static bool -oss_output_enable(struct audio_output *ao, gcc_unused GError **error_r) +oss_output_enable(struct audio_output *ao, gcc_unused Error &error) { OssOutput *od = (OssOutput *)ao; @@ -269,16 +264,16 @@ enum oss_setup_result { /** * Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is * returned. If the parameter is not supported, UNSUPPORTED is - * returned. Any other failure returns ERROR and allocates a GError. + * returned. Any other failure returns ERROR and allocates an #Error. */ static enum oss_setup_result oss_try_ioctl_r(int fd, unsigned long request, int *value_r, - const char *msg, GError **error_r) + const char *msg, Error &error) { assert(fd >= 0); assert(value_r != NULL); assert(msg != NULL); - assert(error_r == NULL || *error_r == NULL); + assert(!error.IsDefined()); int ret = ioctl(fd, request, value_r); if (ret >= 0) @@ -287,19 +282,18 @@ oss_try_ioctl_r(int fd, unsigned long request, int *value_r, if (errno == EINVAL) return UNSUPPORTED; - g_set_error(error_r, oss_output_quark(), errno, - "%s: %s", msg, g_strerror(errno)); + error.SetErrno(msg); return ERROR; } /** * Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is * returned. If the parameter is not supported, UNSUPPORTED is - * returned. Any other failure returns ERROR and allocates a GError. + * returned. Any other failure returns ERROR and allocates an #Error. */ static enum oss_setup_result oss_try_ioctl(int fd, unsigned long request, int value, - const char *msg, GError **error_r) + const char *msg, Error &error_r) { return oss_try_ioctl_r(fd, request, &value, msg, error_r); } @@ -309,12 +303,12 @@ oss_try_ioctl(int fd, unsigned long request, int value, * specified number is not supported. */ static bool -oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r) +oss_setup_channels(int fd, AudioFormat &audio_format, Error &error) { const char *const msg = "Failed to set channel count"; int channels = audio_format.channels; enum oss_setup_result result = - oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error_r); + oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error); switch (result) { case SUCCESS: if (!audio_valid_channel_count(channels)) @@ -337,7 +331,7 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r) channels = i; result = oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, - msg, error_r); + msg, error); switch (result) { case SUCCESS: if (!audio_valid_channel_count(channels)) @@ -354,7 +348,7 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r) } } - g_set_error(error_r, oss_output_quark(), EINVAL, "%s", msg); + error.Set(oss_output_domain, msg); return false; } @@ -364,13 +358,13 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r) */ static bool oss_setup_sample_rate(int fd, AudioFormat &audio_format, - GError **error_r) + Error &error) { const char *const msg = "Failed to set sample rate"; int sample_rate = audio_format.sample_rate; enum oss_setup_result result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate, - msg, error_r); + msg, error); switch (result) { case SUCCESS: if (!audio_valid_sample_rate(sample_rate)) @@ -393,7 +387,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format, continue; result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate, - msg, error_r); + msg, error); switch (result) { case SUCCESS: if (!audio_valid_sample_rate(sample_rate)) @@ -410,7 +404,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format, } } - g_set_error(error_r, oss_output_quark(), EINVAL, "%s", msg); + error.Set(oss_output_domain, msg); return false; } @@ -498,7 +492,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format, #ifdef AFMT_S24_PACKED PcmExport &pcm_export, #endif - GError **error_r) + Error &error) { int oss_format = sample_format_to_oss(sample_format); if (oss_format == AFMT_QUERY) @@ -507,7 +501,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format, enum oss_setup_result result = oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE, &oss_format, - "Failed to set sample format", error_r); + "Failed to set sample format", error); #ifdef AFMT_S24_PACKED if (result == UNSUPPORTED && sample_format == SampleFormat::S24_P32) { @@ -516,7 +510,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format, oss_format = AFMT_S24_PACKED; result = oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE, &oss_format, - "Failed to set sample format", error_r); + "Failed to set sample format", error); } #endif @@ -550,7 +544,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, #ifdef AFMT_S24_PACKED PcmExport &pcm_export, #endif - GError **error_r) + Error &error) { SampleFormat mpd_format; enum oss_setup_result result = @@ -559,7 +553,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, #ifdef AFMT_S24_PACKED pcm_export, #endif - error_r); + error); switch (result) { case SUCCESS: audio_format.format = mpd_format; @@ -597,7 +591,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, #ifdef AFMT_S24_PACKED pcm_export, #endif - error_r); + error); switch (result) { case SUCCESS: audio_format.format = mpd_format; @@ -611,8 +605,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, } } - g_set_error_literal(error_r, oss_output_quark(), EINVAL, - "Failed to set sample format"); + error.Set(oss_output_domain, "Failed to set sample format"); return false; } @@ -621,30 +614,29 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, */ static bool oss_setup(OssOutput *od, AudioFormat &audio_format, - GError **error_r) + Error &error) { - return oss_setup_channels(od->fd, audio_format, error_r) && - oss_setup_sample_rate(od->fd, audio_format, error_r) && + return oss_setup_channels(od->fd, audio_format, error) && + oss_setup_sample_rate(od->fd, audio_format, error) && oss_setup_sample_format(od->fd, audio_format, &od->oss_format, #ifdef AFMT_S24_PACKED od->pcm_export, #endif - error_r); + error); } /** * Reopen the device with the saved audio_format, without any probing. */ static bool -oss_reopen(OssOutput *od, GError **error_r) +oss_reopen(OssOutput *od, Error &error) { assert(od->fd < 0); od->fd = open_cloexec(od->device, O_WRONLY, 0); if (od->fd < 0) { - g_set_error(error_r, oss_output_quark(), errno, - "Error opening OSS device \"%s\": %s", - od->device, g_strerror(errno)); + error.FormatErrno("Error opening OSS device \"%s\"", + od->device); return false; } @@ -652,35 +644,32 @@ oss_reopen(OssOutput *od, GError **error_r) const char *const msg1 = "Failed to set channel count"; result = oss_try_ioctl(od->fd, SNDCTL_DSP_CHANNELS, - od->audio_format.channels, msg1, error_r); + od->audio_format.channels, msg1, error); if (result != SUCCESS) { oss_close(od); if (result == UNSUPPORTED) - g_set_error(error_r, oss_output_quark(), EINVAL, - "%s", msg1); + error.Set(oss_output_domain, msg1); return false; } const char *const msg2 = "Failed to set sample rate"; result = oss_try_ioctl(od->fd, SNDCTL_DSP_SPEED, - od->audio_format.sample_rate, msg2, error_r); + od->audio_format.sample_rate, msg2, error); if (result != SUCCESS) { oss_close(od); if (result == UNSUPPORTED) - g_set_error(error_r, oss_output_quark(), EINVAL, - "%s", msg2); + error.Set(oss_output_domain, msg2); return false; } const char *const msg3 = "Failed to set sample format"; result = oss_try_ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE, od->oss_format, - msg3, error_r); + msg3, error); if (result != SUCCESS) { oss_close(od); if (result == UNSUPPORTED) - g_set_error(error_r, oss_output_quark(), EINVAL, - "%s", msg3); + error.Set(oss_output_domain, msg3); return false; } @@ -689,15 +678,14 @@ oss_reopen(OssOutput *od, GError **error_r) static bool oss_output_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error) + Error &error) { OssOutput *od = (OssOutput *)ao; od->fd = open_cloexec(od->device, O_WRONLY, 0); if (od->fd < 0) { - g_set_error(error, oss_output_quark(), errno, - "Error opening OSS device \"%s\": %s", - od->device, g_strerror(errno)); + error.FormatErrno("Error opening OSS device \"%s\"", + od->device); return false; } @@ -731,7 +719,7 @@ oss_output_cancel(struct audio_output *ao) static size_t oss_output_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error) + Error &error) { OssOutput *od = (OssOutput *)ao; ssize_t ret; @@ -754,9 +742,7 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size, } if (ret < 0 && errno != EINTR) { - g_set_error(error, oss_output_quark(), errno, - "Write error on %s: %s", - od->device, g_strerror(errno)); + error.FormatErrno("Write error on %s", od->device); return 0; } } diff --git a/src/output/PipeOutputPlugin.cxx b/src/output/PipeOutputPlugin.cxx index 9ff3bb120..ca8f398da 100644 --- a/src/output/PipeOutputPlugin.cxx +++ b/src/output/PipeOutputPlugin.cxx @@ -20,6 +20,9 @@ #include "config.h" #include "PipeOutputPlugin.hxx" #include "OutputAPI.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include #include @@ -30,34 +33,27 @@ struct PipeOutput { char *cmd; FILE *fh; - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error) { return ao_base_init(&base, &pipe_output_plugin, param, - error_r); + error); } void Deinitialize() { ao_base_finish(&base); } - bool Configure(const config_param ¶m, GError **error_r); + bool Configure(const config_param ¶m, Error &error); }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -pipe_output_quark(void) -{ - return g_quark_from_static_string("pipe_output"); -} +static constexpr Domain pipe_output_domain("pipe_output"); inline bool -PipeOutput::Configure(const config_param ¶m, GError **error_r) +PipeOutput::Configure(const config_param ¶m, Error &error) { cmd = param.DupBlockString("command"); if (cmd == nullptr) { - g_set_error(error_r, pipe_output_quark(), 0, - "No \"command\" parameter specified"); + error.Set(config_domain, + "No \"command\" parameter specified"); return false; } @@ -65,16 +61,16 @@ PipeOutput::Configure(const config_param ¶m, GError **error_r) } static struct audio_output * -pipe_output_init(const config_param ¶m, GError **error_r) +pipe_output_init(const config_param ¶m, Error &error) { PipeOutput *pd = new PipeOutput(); - if (!pd->Initialize(param, error_r)) { + if (!pd->Initialize(param, error)) { delete pd; return nullptr; } - if (!pd->Configure(param, error_r)) { + if (!pd->Configure(param, error)) { pd->Deinitialize(); delete pd; return nullptr; @@ -96,15 +92,14 @@ pipe_output_finish(struct audio_output *ao) static bool pipe_output_open(struct audio_output *ao, gcc_unused AudioFormat &audio_format, - gcc_unused GError **error) + Error &error) { PipeOutput *pd = (PipeOutput *)ao; pd->fh = popen(pd->cmd, "w"); if (pd->fh == nullptr) { - g_set_error(error, pipe_output_quark(), errno, - "Error opening pipe \"%s\": %s", - pd->cmd, g_strerror(errno)); + error.FormatErrno("Error opening pipe \"%s\"", + pd->cmd); return false; } @@ -120,15 +115,15 @@ pipe_output_close(struct audio_output *ao) } static size_t -pipe_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error) +pipe_output_play(struct audio_output *ao, const void *chunk, size_t size, + Error &error) { PipeOutput *pd = (PipeOutput *)ao; size_t ret; ret = fwrite(chunk, 1, size, pd->fh); if (ret == 0) - g_set_error(error, pipe_output_quark(), errno, - "Write error on pipe: %s", g_strerror(errno)); + error.SetErrno("Write error on pipe"); return ret; } diff --git a/src/output/PulseOutputPlugin.cxx b/src/output/PulseOutputPlugin.cxx index 5394edfac..d64e0af16 100644 --- a/src/output/PulseOutputPlugin.cxx +++ b/src/output/PulseOutputPlugin.cxx @@ -22,6 +22,8 @@ #include "OutputAPI.hxx" #include "MixerList.hxx" #include "mixer/PulseMixerPlugin.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include @@ -54,13 +56,13 @@ struct PulseOutput { size_t writable; }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -pulse_output_quark(void) +static constexpr Domain pulse_output_domain("pulse_output"); + +static void +SetError(Error &error, pa_context *context, const char *msg) { - return g_quark_from_static_string("pulse_output"); + const int e = pa_context_errno(context); + error.Format(pulse_output_domain, e, "%s: %s", msg, pa_strerror(e)); } void @@ -112,14 +114,14 @@ pulse_output_clear_mixer(PulseOutput *po, gcc_unused PulseMixer *pm) } bool -pulse_output_set_volume(PulseOutput *po, - const struct pa_cvolume *volume, GError **error_r) +pulse_output_set_volume(PulseOutput *po, const pa_cvolume *volume, + Error &error) { pa_operation *o; if (po->context == nullptr || po->stream == nullptr || pa_stream_get_state(po->stream) != PA_STREAM_READY) { - g_set_error(error_r, pulse_output_quark(), 0, "disconnected"); + error.Set(pulse_output_domain, "disconnected"); return false; } @@ -127,9 +129,8 @@ pulse_output_set_volume(PulseOutput *po, pa_stream_get_index(po->stream), volume, nullptr, nullptr); if (o == nullptr) { - g_set_error(error_r, pulse_output_quark(), 0, - "failed to set PulseAudio volume: %s", - pa_strerror(pa_context_errno(po->context))); + SetError(error, po->context, + "failed to set PulseAudio volume"); return false; } @@ -235,19 +236,15 @@ pulse_output_subscribe_cb(pa_context *context, * @return true on success, false on error */ static bool -pulse_output_connect(PulseOutput *po, GError **error_r) +pulse_output_connect(PulseOutput *po, Error &error) { assert(po != nullptr); assert(po->context != nullptr); - int error; - - error = pa_context_connect(po->context, po->server, - (pa_context_flags_t)0, nullptr); - if (error < 0) { - g_set_error(error_r, pulse_output_quark(), 0, - "pa_context_connect() has failed: %s", - pa_strerror(pa_context_errno(po->context))); + if (pa_context_connect(po->context, po->server, + (pa_context_flags_t)0, nullptr) < 0) { + SetError(error, po->context, + "pa_context_connect() has failed"); return false; } @@ -300,7 +297,7 @@ pulse_output_delete_context(PulseOutput *po) * @return true on success, false on error */ static bool -pulse_output_setup_context(PulseOutput *po, GError **error_r) +pulse_output_setup_context(PulseOutput *po, Error &error) { assert(po != nullptr); assert(po->mainloop != nullptr); @@ -308,8 +305,7 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r) po->context = pa_context_new(pa_threaded_mainloop_get_api(po->mainloop), MPD_PULSE_NAME); if (po->context == nullptr) { - g_set_error(error_r, pulse_output_quark(), 0, - "pa_context_new() has failed"); + error.Set(pulse_output_domain, "pa_context_new() has failed"); return false; } @@ -318,7 +314,7 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r) pa_context_set_subscribe_callback(po->context, pulse_output_subscribe_cb, po); - if (!pulse_output_connect(po, error_r)) { + if (!pulse_output_connect(po, error)) { pulse_output_delete_context(po); return false; } @@ -327,14 +323,14 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r) } static struct audio_output * -pulse_output_init(const config_param ¶m, GError **error_r) +pulse_output_init(const config_param ¶m, Error &error) { PulseOutput *po; g_setenv("PULSE_PROP_media.role", "music", true); po = new PulseOutput(); - if (!ao_base_init(&po->base, &pulse_output_plugin, param, error_r)) { + if (!ao_base_init(&po->base, &pulse_output_plugin, param, error)) { delete po; return nullptr; } @@ -361,7 +357,7 @@ pulse_output_finish(struct audio_output *ao) } static bool -pulse_output_enable(struct audio_output *ao, GError **error_r) +pulse_output_enable(struct audio_output *ao, Error &error) { PulseOutput *po = (PulseOutput *)ao; @@ -374,8 +370,8 @@ pulse_output_enable(struct audio_output *ao, GError **error_r) if (po->mainloop == nullptr) { g_free(po); - g_set_error(error_r, pulse_output_quark(), 0, - "pa_threaded_mainloop_new() has failed"); + error.Set(pulse_output_domain, + "pa_threaded_mainloop_new() has failed"); return false; } @@ -386,14 +382,14 @@ pulse_output_enable(struct audio_output *ao, GError **error_r) pa_threaded_mainloop_free(po->mainloop); po->mainloop = nullptr; - g_set_error(error_r, pulse_output_quark(), 0, - "pa_threaded_mainloop_start() has failed"); + error.Set(pulse_output_domain, + "pa_threaded_mainloop_start() has failed"); return false; } /* create the libpulse context and connect it */ - if (!pulse_output_setup_context(po, error_r)) { + if (!pulse_output_setup_context(po, error)) { pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_stop(po->mainloop); pa_threaded_mainloop_free(po->mainloop); @@ -429,13 +425,13 @@ pulse_output_disable(struct audio_output *ao) * @return true on success, false on error */ static bool -pulse_output_wait_connection(PulseOutput *po, GError **error_r) +pulse_output_wait_connection(PulseOutput *po, Error &error) { assert(po->mainloop != nullptr); pa_context_state_t state; - if (po->context == nullptr && !pulse_output_setup_context(po, error_r)) + if (po->context == nullptr && !pulse_output_setup_context(po, error)) return false; while (true) { @@ -449,9 +445,7 @@ pulse_output_wait_connection(PulseOutput *po, GError **error_r) case PA_CONTEXT_TERMINATED: case PA_CONTEXT_FAILED: /* failure */ - g_set_error(error_r, pulse_output_quark(), 0, - "failed to connect: %s", - pa_strerror(pa_context_errno(po->context))); + SetError(error, po->context, "failed to connect"); pulse_output_delete_context(po); return false; @@ -530,16 +524,14 @@ pulse_output_stream_write_cb(gcc_unused pa_stream *stream, size_t nbytes, */ static bool pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss, - GError **error_r) + Error &error) { assert(po != nullptr); assert(po->context != nullptr); po->stream = pa_stream_new(po->context, po->name, ss, nullptr); if (po->stream == nullptr) { - g_set_error(error_r, pulse_output_quark(), 0, - "pa_stream_new() has failed: %s", - pa_strerror(pa_context_errno(po->context))); + SetError(error, po->context, "pa_stream_new() has failed"); return false; } @@ -556,11 +548,10 @@ pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss, static bool pulse_output_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error_r) + Error &error) { PulseOutput *po = (PulseOutput *)ao; pa_sample_spec ss; - int error; assert(po->mainloop != nullptr); @@ -585,7 +576,7 @@ pulse_output_open(struct audio_output *ao, AudioFormat &audio_format, } } - if (!pulse_output_wait_connection(po, error_r)) { + if (!pulse_output_wait_connection(po, error)) { pa_threaded_mainloop_unlock(po->mainloop); return false; } @@ -600,22 +591,20 @@ pulse_output_open(struct audio_output *ao, AudioFormat &audio_format, /* create a stream .. */ - if (!pulse_output_setup_stream(po, &ss, error_r)) { + if (!pulse_output_setup_stream(po, &ss, error)) { pa_threaded_mainloop_unlock(po->mainloop); return false; } /* .. and connect it (asynchronously) */ - error = pa_stream_connect_playback(po->stream, po->sink, - nullptr, pa_stream_flags_t(0), - nullptr, nullptr); - if (error < 0) { + if (pa_stream_connect_playback(po->stream, po->sink, + nullptr, pa_stream_flags_t(0), + nullptr, nullptr) < 0) { pulse_output_delete_stream(po); - g_set_error(error_r, pulse_output_quark(), 0, - "pa_stream_connect_playback() has failed: %s", - pa_strerror(pa_context_errno(po->context))); + SetError(error, po->context, + "pa_stream_connect_playback() has failed"); pa_threaded_mainloop_unlock(po->mainloop); return false; } @@ -661,7 +650,7 @@ pulse_output_close(struct audio_output *ao) * @return true on success, false on error */ static bool -pulse_output_wait_stream(PulseOutput *po, GError **error_r) +pulse_output_wait_stream(PulseOutput *po, Error &error) { while (true) { switch (pa_stream_get_state(po->stream)) { @@ -671,10 +660,8 @@ pulse_output_wait_stream(PulseOutput *po, GError **error_r) case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: case PA_STREAM_UNCONNECTED: - g_set_error(error_r, pulse_output_quark(), - pa_context_errno(po->context), - "failed to connect the stream: %s", - pa_strerror(pa_context_errno(po->context))); + SetError(error, po->context, + "failed to connect the stream"); return false; case PA_STREAM_CREATING: @@ -689,7 +676,7 @@ pulse_output_wait_stream(PulseOutput *po, GError **error_r) */ static bool pulse_output_stream_pause(PulseOutput *po, bool pause, - GError **error_r) + Error &error) { pa_operation *o; @@ -700,16 +687,12 @@ pulse_output_stream_pause(PulseOutput *po, bool pause, o = pa_stream_cork(po->stream, pause, pulse_output_stream_success_cb, po); if (o == nullptr) { - g_set_error(error_r, pulse_output_quark(), 0, - "pa_stream_cork() has failed: %s", - pa_strerror(pa_context_errno(po->context))); + SetError(error, po->context, "pa_stream_cork() has failed"); return false; } if (!pulse_wait_for_operation(po->mainloop, o)) { - g_set_error(error_r, pulse_output_quark(), 0, - "pa_stream_cork() has failed: %s", - pa_strerror(pa_context_errno(po->context))); + SetError(error, po->context, "pa_stream_cork() has failed"); return false; } @@ -736,10 +719,9 @@ pulse_output_delay(struct audio_output *ao) static size_t pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error_r) + Error &error) { PulseOutput *po = (PulseOutput *)ao; - int error; assert(po->mainloop != nullptr); assert(po->stream != nullptr); @@ -748,7 +730,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, /* check if the stream is (already) connected */ - if (!pulse_output_wait_stream(po, error_r)) { + if (!pulse_output_wait_stream(po, error)) { pa_threaded_mainloop_unlock(po->mainloop); return 0; } @@ -758,7 +740,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, /* unpause if previously paused */ if (pa_stream_is_corked(po->stream) && - !pulse_output_stream_pause(po, false, error_r)) { + !pulse_output_stream_pause(po, false, error)) { pa_threaded_mainloop_unlock(po->mainloop); return 0; } @@ -768,8 +750,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, while (po->writable == 0) { if (pa_stream_is_suspended(po->stream)) { pa_threaded_mainloop_unlock(po->mainloop); - g_set_error(error_r, pulse_output_quark(), 0, - "suspended"); + error.Set(pulse_output_domain, "suspended"); return 0; } @@ -777,8 +758,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, if (pa_stream_get_state(po->stream) != PA_STREAM_READY) { pa_threaded_mainloop_unlock(po->mainloop); - g_set_error(error_r, pulse_output_quark(), 0, - "disconnected"); + error.Set(pulse_output_domain, "disconnected"); return 0; } } @@ -791,12 +771,11 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, po->writable -= size; - error = pa_stream_write(po->stream, chunk, size, nullptr, - 0, PA_SEEK_RELATIVE); + int result = pa_stream_write(po->stream, chunk, size, nullptr, + 0, PA_SEEK_RELATIVE); pa_threaded_mainloop_unlock(po->mainloop); - if (error < 0) { - g_set_error(error_r, pulse_output_quark(), error, - "%s", pa_strerror(error)); + if (result < 0) { + SetError(error, po->context, "pa_stream_write() failed"); return 0; } @@ -839,7 +818,6 @@ static bool pulse_output_pause(struct audio_output *ao) { PulseOutput *po = (PulseOutput *)ao; - GError *error = nullptr; assert(po->mainloop != nullptr); assert(po->stream != nullptr); @@ -848,10 +826,10 @@ pulse_output_pause(struct audio_output *ao) /* check if the stream is (already/still) connected */ - if (!pulse_output_wait_stream(po, &error)) { + Error error; + if (!pulse_output_wait_stream(po, error)) { pa_threaded_mainloop_unlock(po->mainloop); - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); return false; } @@ -860,10 +838,9 @@ pulse_output_pause(struct audio_output *ao) /* cork the stream */ if (!pa_stream_is_corked(po->stream) && - !pulse_output_stream_pause(po, true, &error)) { + !pulse_output_stream_pause(po, true, error)) { pa_threaded_mainloop_unlock(po->mainloop); - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); return false; } @@ -878,11 +855,12 @@ pulse_output_test_default_device(void) bool success; const config_param empty; - PulseOutput *po = (PulseOutput *)pulse_output_init(empty, nullptr); + PulseOutput *po = (PulseOutput *) + pulse_output_init(empty, IgnoreError()); if (po == nullptr) return false; - success = pulse_output_wait_connection(po, nullptr); + success = pulse_output_wait_connection(po, IgnoreError()); pulse_output_finish(&po->base); return success; diff --git a/src/output/PulseOutputPlugin.hxx b/src/output/PulseOutputPlugin.hxx index 278969f8d..0ed8404bc 100644 --- a/src/output/PulseOutputPlugin.hxx +++ b/src/output/PulseOutputPlugin.hxx @@ -20,11 +20,10 @@ #ifndef MPD_PULSE_OUTPUT_PLUGIN_HXX #define MPD_PULSE_OUTPUT_PLUGIN_HXX -#include "gerror.h" - struct PulseOutput; struct PulseMixer; struct pa_cvolume; +class Error; extern const struct audio_output_plugin pulse_output_plugin; @@ -42,6 +41,6 @@ pulse_output_clear_mixer(PulseOutput *po, PulseMixer *pm); bool pulse_output_set_volume(PulseOutput *po, - const struct pa_cvolume *volume, GError **error_r); + const struct pa_cvolume *volume, Error &error); #endif diff --git a/src/output/RecorderOutputPlugin.cxx b/src/output/RecorderOutputPlugin.cxx index 9374e4c20..31c378c56 100644 --- a/src/output/RecorderOutputPlugin.cxx +++ b/src/output/RecorderOutputPlugin.cxx @@ -22,6 +22,9 @@ #include "OutputAPI.hxx" #include "EncoderPlugin.hxx" #include "EncoderList.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "system/fd_util.h" #include "open.h" @@ -57,7 +60,7 @@ struct RecorderOutput { */ char buffer[32768]; - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error_r) { return ao_base_init(&base, &recorder_output_plugin, param, error_r); } @@ -66,27 +69,20 @@ struct RecorderOutput { ao_base_finish(&base); } - bool Configure(const config_param ¶m, GError **error_r); + bool Configure(const config_param ¶m, Error &error); - bool WriteToFile(const void *data, size_t length, GError **error_r); + bool WriteToFile(const void *data, size_t length, Error &error); /** * Writes pending data from the encoder to the output file. */ - bool EncoderToFile(GError **error_r); + bool EncoderToFile(Error &error); }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -recorder_output_quark(void) -{ - return g_quark_from_static_string("recorder_output"); -} +static constexpr Domain recorder_output_domain("recorder_output"); inline bool -RecorderOutput::Configure(const config_param ¶m, GError **error_r) +RecorderOutput::Configure(const config_param ¶m, Error &error) { /* read configuration */ @@ -94,21 +90,20 @@ RecorderOutput::Configure(const config_param ¶m, GError **error_r) param.GetBlockValue("encoder", "vorbis"); const auto encoder_plugin = encoder_plugin_get(encoder_name); if (encoder_plugin == nullptr) { - g_set_error(error_r, recorder_output_quark(), 0, - "No such encoder: %s", encoder_name); + error.Format(config_domain, + "No such encoder: %s", encoder_name); return false; } path = param.GetBlockValue("path"); if (path == nullptr) { - g_set_error(error_r, recorder_output_quark(), 0, - "'path' not configured"); + error.Set(config_domain, "'path' not configured"); return false; } /* initialize encoder */ - encoder = encoder_init(*encoder_plugin, param, error_r); + encoder = encoder_init(*encoder_plugin, param, error); if (encoder == nullptr) return false; @@ -116,16 +111,16 @@ RecorderOutput::Configure(const config_param ¶m, GError **error_r) } static audio_output * -recorder_output_init(const config_param ¶m, GError **error_r) +recorder_output_init(const config_param ¶m, Error &error) { RecorderOutput *recorder = new RecorderOutput(); - if (!recorder->Initialize(param, error_r)) { + if (!recorder->Initialize(param, error)) { delete recorder; return nullptr; } - if (!recorder->Configure(param, error_r)) { + if (!recorder->Configure(param, error)) { recorder->Deinitialize(); delete recorder; return nullptr; @@ -145,7 +140,7 @@ recorder_output_finish(struct audio_output *ao) } inline bool -RecorderOutput::WriteToFile(const void *_data, size_t length, GError **error_r) +RecorderOutput::WriteToFile(const void *_data, size_t length, Error &error) { assert(length > 0); @@ -159,20 +154,18 @@ RecorderOutput::WriteToFile(const void *_data, size_t length, GError **error_r) return true; } else if (nbytes == 0) { /* shouldn't happen for files */ - g_set_error(error_r, recorder_output_quark(), 0, - "write() returned 0"); + error.Set(recorder_output_domain, + "write() returned 0"); return false; } else if (errno != EINTR) { - g_set_error(error_r, recorder_output_quark(), 0, - "Failed to write to '%s': %s", - path, g_strerror(errno)); + error.FormatErrno("Failed to write to '%s'", path); return false; } } } inline bool -RecorderOutput::EncoderToFile(GError **error_r) +RecorderOutput::EncoderToFile(Error &error) { assert(fd >= 0); @@ -185,7 +178,7 @@ RecorderOutput::EncoderToFile(GError **error_r) /* write everything into the file */ - if (!WriteToFile(buffer, size, error_r)) + if (!WriteToFile(buffer, size, error)) return false; } } @@ -193,7 +186,7 @@ RecorderOutput::EncoderToFile(GError **error_r) static bool recorder_output_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error_r) + Error &error) { RecorderOutput *recorder = (RecorderOutput *)ao; @@ -203,21 +196,19 @@ recorder_output_open(struct audio_output *ao, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 0666); if (recorder->fd < 0) { - g_set_error(error_r, recorder_output_quark(), 0, - "Failed to create '%s': %s", - recorder->path, g_strerror(errno)); + error.FormatErrno("Failed to create '%s'", recorder->path); return false; } /* open the encoder */ - if (!encoder_open(recorder->encoder, audio_format, error_r)) { + if (!encoder_open(recorder->encoder, audio_format, error)) { close(recorder->fd); unlink(recorder->path); return false; } - if (!recorder->EncoderToFile(error_r)) { + if (!recorder->EncoderToFile(error)) { encoder_close(recorder->encoder); close(recorder->fd); unlink(recorder->path); @@ -234,8 +225,8 @@ recorder_output_close(struct audio_output *ao) /* flush the encoder and write the rest to the file */ - if (encoder_end(recorder->encoder, nullptr)) - recorder->EncoderToFile(nullptr); + if (encoder_end(recorder->encoder, IgnoreError())) + recorder->EncoderToFile(IgnoreError()); /* now really close everything */ @@ -246,12 +237,12 @@ recorder_output_close(struct audio_output *ao) static size_t recorder_output_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error_r) + Error &error) { RecorderOutput *recorder = (RecorderOutput *)ao; - return encoder_write(recorder->encoder, chunk, size, error_r) && - recorder->EncoderToFile(error_r) + return encoder_write(recorder->encoder, chunk, size, error) && + recorder->EncoderToFile(error) ? size : 0; } diff --git a/src/output/RoarOutputPlugin.cxx b/src/output/RoarOutputPlugin.cxx index 36f7c395b..f6d261372 100644 --- a/src/output/RoarOutputPlugin.cxx +++ b/src/output/RoarOutputPlugin.cxx @@ -23,6 +23,8 @@ #include "OutputAPI.hxx" #include "MixerList.hxx" #include "thread/Mutex.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include @@ -58,11 +60,7 @@ struct RoarOutput { } }; -static inline GQuark -roar_output_quark(void) -{ - return g_quark_from_static_string("roar_output"); -} +static constexpr Domain roar_output_domain("roar_output"); static int roar_output_get_volume_locked(RoarOutput *roar) @@ -120,11 +118,11 @@ roar_configure(RoarOutput *self, const config_param ¶m) } static struct audio_output * -roar_init(const config_param ¶m, GError **error_r) +roar_init(const config_param ¶m, Error &error) { RoarOutput *self = new RoarOutput(); - if (!ao_base_init(&self->base, &roar_output_plugin, param, error_r)) { + if (!ao_base_init(&self->base, &roar_output_plugin, param, error)) { delete self; return nullptr; } @@ -178,15 +176,15 @@ roar_use_audio_format(struct roar_audio_info *info, } static bool -roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) +roar_open(struct audio_output *ao, AudioFormat &audio_format, Error &error) { RoarOutput *self = (RoarOutput *)ao; const ScopeLock protect(self->mutex); if (roar_simple_connect(&(self->con), self->host, self->name) < 0) { - g_set_error(error, roar_output_quark(), 0, - "Failed to connect to Roar server"); + error.Set(roar_output_domain, + "Failed to connect to Roar server"); return false; } @@ -194,8 +192,7 @@ roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) if (self->vss == nullptr || self->err != ROAR_ERROR_NONE) { - g_set_error(error, roar_output_quark(), 0, - "Failed to connect to server"); + error.Set(roar_output_domain, "Failed to connect to server"); return false; } @@ -204,7 +201,7 @@ roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) if (roar_vs_stream(self->vss, &(self->info), ROAR_DIR_PLAY, &(self->err)) < 0) { - g_set_error(error, roar_output_quark(), 0, "Failed to start stream"); + error.Set(roar_output_domain, "Failed to start stream"); return false; } roar_vs_role(self->vss, self->role, &(self->err)); @@ -264,21 +261,22 @@ roar_cancel(struct audio_output *ao) } static size_t -roar_play(struct audio_output *ao, const void *chunk, size_t size, GError **error) +roar_play(struct audio_output *ao, const void *chunk, size_t size, + Error &error) { RoarOutput *self = (RoarOutput *)ao; ssize_t rc; if (self->vss == nullptr) { - g_set_error(error, roar_output_quark(), 0, "Connection is invalid"); + error.Set(roar_output_domain, "Connection is invalid"); return 0; } rc = roar_vs_write(self->vss, chunk, size, &(self->err)); if ( rc <= 0 ) { - g_set_error(error, roar_output_quark(), 0, "Failed to play data"); + error.Set(roar_output_domain, "Failed to play data"); return 0; } diff --git a/src/output/ShoutOutputPlugin.cxx b/src/output/ShoutOutputPlugin.cxx index 40f468031..82b61f7c8 100644 --- a/src/output/ShoutOutputPlugin.cxx +++ b/src/output/ShoutOutputPlugin.cxx @@ -22,6 +22,9 @@ #include "OutputAPI.hxx" #include "EncoderPlugin.hxx" #include "EncoderList.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "mpd_error.h" #include @@ -66,28 +69,21 @@ struct ShoutOutput final { shout_free(shout_conn); } - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error) { return ao_base_init(&base, &shout_output_plugin, param, - error_r); + error); } void Deinitialize() { ao_base_finish(&base); } - bool Configure(const config_param ¶m, GError **error_r); + bool Configure(const config_param ¶m, Error &error); }; static int shout_init_count; -/** - * The quark used for GError.domain. - */ -static inline GQuark -shout_output_quark(void) -{ - return g_quark_from_static_string("shout_output"); -} +static constexpr Domain shout_output_domain("shout_output"); static const EncoderPlugin * shout_encoder_plugin_get(const char *name) @@ -113,13 +109,13 @@ require_block_string(const config_param ¶m, const char *name) } inline bool -ShoutOutput::Configure(const config_param ¶m, GError **error_r) +ShoutOutput::Configure(const config_param ¶m, Error &error) { const AudioFormat audio_format = base.config_audio_format; if (!audio_format.IsFullyDefined()) { - g_set_error(error_r, shout_output_quark(), 0, - "Need full audio format specification"); + error.Set(config_domain, + "Need full audio format specification"); return nullptr; } @@ -127,8 +123,7 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) const char *mount = require_block_string(param, "mount"); unsigned port = param.GetBlockValue("port", 0u); if (port == 0) { - g_set_error(error_r, shout_output_quark(), 0, - "shout port must be configured"); + error.Set(config_domain, "shout port must be configured"); return false; } @@ -145,24 +140,24 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) quality = strtod(value, &test); if (*test != '\0' || quality < -1.0 || quality > 10.0) { - g_set_error(error_r, shout_output_quark(), 0, - "shout quality \"%s\" is not a number in the " - "range -1 to 10, line %i", - value, param.line); + error.Format(config_domain, + "shout quality \"%s\" is not a number in the " + "range -1 to 10, line %i", + value, param.line); return false; } if (param.GetBlockValue("bitrate") != nullptr) { - g_set_error(error_r, shout_output_quark(), 0, - "quality and bitrate are " - "both defined"); + error.Set(config_domain, + "quality and bitrate are " + "both defined"); return false; } } else { value = param.GetBlockValue("bitrate"); if (value == nullptr) { - g_set_error(error_r, shout_output_quark(), 0, - "neither bitrate nor quality defined"); + error.Set(config_domain, + "neither bitrate nor quality defined"); return false; } @@ -170,8 +165,8 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) bitrate = strtol(value, &test, 10); if (*test != '\0' || bitrate <= 0) { - g_set_error(error_r, shout_output_quark(), 0, - "bitrate must be a positive integer"); + error.Set(config_domain, + "bitrate must be a positive integer"); return false; } } @@ -179,13 +174,13 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) const char *encoding = param.GetBlockValue("encoding", "ogg"); const auto encoder_plugin = shout_encoder_plugin_get(encoding); if (encoder_plugin == nullptr) { - g_set_error(error_r, shout_output_quark(), 0, - "couldn't find shout encoder plugin \"%s\"", - encoding); + error.Format(config_domain, + "couldn't find shout encoder plugin \"%s\"", + encoding); return false; } - encoder = encoder_init(*encoder_plugin, param, error_r); + encoder = encoder_init(*encoder_plugin, param, error); if (encoder == nullptr) return false; @@ -200,9 +195,9 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) if (value != nullptr) { if (0 == strcmp(value, "shoutcast") && 0 != strcmp(encoding, "mp3")) { - g_set_error(error_r, shout_output_quark(), 0, - "you cannot stream \"%s\" to shoutcast, use mp3", - encoding); + error.Format(config_domain, + "you cannot stream \"%s\" to shoutcast, use mp3", + encoding); return false; } else if (0 == strcmp(value, "shoutcast")) protocol = SHOUT_PROTOCOL_ICY; @@ -211,10 +206,10 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) else if (0 == strcmp(value, "icecast2")) protocol = SHOUT_PROTOCOL_HTTP; else { - g_set_error(error_r, shout_output_quark(), 0, - "shout protocol \"%s\" is not \"shoutcast\" or " - "\"icecast1\"or \"icecast2\"", - value); + error.Format(config_domain, + "shout protocol \"%s\" is not \"shoutcast\" or " + "\"icecast1\"or \"icecast2\"", + value); return false; } } else { @@ -232,8 +227,7 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) != SHOUTERR_SUCCESS || shout_set_protocol(shout_conn, protocol) != SHOUTERR_SUCCESS || shout_set_agent(shout_conn, "MPD") != SHOUTERR_SUCCESS) { - g_set_error(error_r, shout_output_quark(), 0, - "%s", shout_get_error(shout_conn)); + error.Set(shout_output_domain, shout_get_error(shout_conn)); return false; } @@ -242,22 +236,19 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) value = param.GetBlockValue("genre"); if (value != nullptr && shout_set_genre(shout_conn, value)) { - g_set_error(error_r, shout_output_quark(), 0, - "%s", shout_get_error(shout_conn)); + error.Set(shout_output_domain, shout_get_error(shout_conn)); return false; } value = param.GetBlockValue("description"); if (value != nullptr && shout_set_description(shout_conn, value)) { - g_set_error(error_r, shout_output_quark(), 0, - "%s", shout_get_error(shout_conn)); + error.Set(shout_output_domain, shout_get_error(shout_conn)); return false; } value = param.GetBlockValue("url"); if (value != nullptr && shout_set_url(shout_conn, value)) { - g_set_error(error_r, shout_output_quark(), 0, - "%s", shout_get_error(shout_conn)); + error.Set(shout_output_domain, shout_get_error(shout_conn)); return false; } @@ -287,15 +278,15 @@ ShoutOutput::Configure(const config_param ¶m, GError **error_r) } static struct audio_output * -my_shout_init_driver(const config_param ¶m, GError **error_r) +my_shout_init_driver(const config_param ¶m, Error &error) { ShoutOutput *sd = new ShoutOutput(); - if (!sd->Initialize(param, error_r)) { + if (!sd->Initialize(param, error)) { delete sd; return nullptr; } - if (!sd->Configure(param, error_r)) { + if (!sd->Configure(param, error)) { sd->Deinitialize(); delete sd; return nullptr; @@ -310,7 +301,7 @@ my_shout_init_driver(const config_param ¶m, GError **error_r) } static bool -handle_shout_error(ShoutOutput *sd, int err, GError **error) +handle_shout_error(ShoutOutput *sd, int err, Error &error) { switch (err) { case SHOUTERR_SUCCESS: @@ -318,19 +309,19 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error) case SHOUTERR_UNCONNECTED: case SHOUTERR_SOCKET: - g_set_error(error, shout_output_quark(), err, - "Lost shout connection to %s:%i: %s", - shout_get_host(sd->shout_conn), - shout_get_port(sd->shout_conn), - shout_get_error(sd->shout_conn)); + error.Format(shout_output_domain, err, + "Lost shout connection to %s:%i: %s", + shout_get_host(sd->shout_conn), + shout_get_port(sd->shout_conn), + shout_get_error(sd->shout_conn)); return false; default: - g_set_error(error, shout_output_quark(), err, - "connection to %s:%i error: %s", - shout_get_host(sd->shout_conn), - shout_get_port(sd->shout_conn), - shout_get_error(sd->shout_conn)); + error.Format(shout_output_domain, err, + "connection to %s:%i error: %s", + shout_get_host(sd->shout_conn), + shout_get_port(sd->shout_conn), + shout_get_error(sd->shout_conn)); return false; } @@ -338,7 +329,7 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error) } static bool -write_page(ShoutOutput *sd, GError **error) +write_page(ShoutOutput *sd, Error &error) { assert(sd->encoder != nullptr); @@ -359,8 +350,8 @@ write_page(ShoutOutput *sd, GError **error) static void close_shout_conn(ShoutOutput * sd) { if (sd->encoder != nullptr) { - if (encoder_end(sd->encoder, nullptr)) - write_page(sd, nullptr); + if (encoder_end(sd->encoder, IgnoreError())) + write_page(sd, IgnoreError()); encoder_close(sd->encoder); } @@ -406,7 +397,7 @@ my_shout_close_device(struct audio_output *ao) } static bool -shout_connect(ShoutOutput *sd, GError **error) +shout_connect(ShoutOutput *sd, Error &error) { switch (shout_open(sd->shout_conn)) { case SHOUTERR_SUCCESS: @@ -414,18 +405,18 @@ shout_connect(ShoutOutput *sd, GError **error) return true; default: - g_set_error(error, shout_output_quark(), 0, - "problem opening connection to shout server %s:%i: %s", - shout_get_host(sd->shout_conn), - shout_get_port(sd->shout_conn), - shout_get_error(sd->shout_conn)); + error.Format(shout_output_domain, + "problem opening connection to shout server %s:%i: %s", + shout_get_host(sd->shout_conn), + shout_get_port(sd->shout_conn), + shout_get_error(sd->shout_conn)); return false; } } static bool my_shout_open_device(struct audio_output *ao, AudioFormat &audio_format, - GError **error) + Error &error) { ShoutOutput *sd = (ShoutOutput *)ao; @@ -460,7 +451,7 @@ my_shout_delay(struct audio_output *ao) static size_t my_shout_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error) + Error &error) { ShoutOutput *sd = (ShoutOutput *)ao; @@ -475,7 +466,7 @@ my_shout_pause(struct audio_output *ao) { static char silence[1020]; - return my_shout_play(ao, silence, sizeof(silence), nullptr); + return my_shout_play(ao, silence, sizeof(silence), IgnoreError()); } static void @@ -508,24 +499,17 @@ static void my_shout_set_tag(struct audio_output *ao, const Tag *tag) { ShoutOutput *sd = (ShoutOutput *)ao; - GError *error = nullptr; if (sd->encoder->plugin.tag != nullptr) { /* encoder plugin supports stream tags */ - if (!encoder_pre_tag(sd->encoder, &error)) { - g_warning("%s", error->message); - g_error_free(error); + Error error; + if (!encoder_pre_tag(sd->encoder, error) || + !write_page(sd, error) || + !encoder_tag(sd->encoder, tag, error)) { + g_warning("%s", error.GetMessage()); return; } - - if (!write_page(sd, nullptr)) - return; - - if (!encoder_tag(sd->encoder, tag, &error)) { - g_warning("%s", error->message); - g_error_free(error); - } } else { /* no stream tag support: fall back to icy-metadata */ char song[1024]; @@ -538,7 +522,7 @@ static void my_shout_set_tag(struct audio_output *ao, } } - write_page(sd, nullptr); + write_page(sd, IgnoreError()); } const struct audio_output_plugin shout_output_plugin = { diff --git a/src/output/SolarisOutputPlugin.cxx b/src/output/SolarisOutputPlugin.cxx index aa2f853e6..e3428cbc2 100644 --- a/src/output/SolarisOutputPlugin.cxx +++ b/src/output/SolarisOutputPlugin.cxx @@ -21,8 +21,7 @@ #include "SolarisOutputPlugin.hxx" #include "OutputAPI.hxx" #include "system/fd_util.h" - -#include +#include "util/Error.hxx" #include #include @@ -61,7 +60,7 @@ struct SolarisOutput { int fd; - bool Initialize(const config_param ¶m, GError **error_r) { + bool Initialize(const config_param ¶m, Error &error_r) { return ao_base_init(&base, &solaris_output_plugin, param, error_r); } @@ -71,15 +70,6 @@ struct SolarisOutput { } }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -solaris_output_quark(void) -{ - return g_quark_from_static_string("solaris_output"); -} - static bool solaris_output_test_default_device(void) { @@ -90,7 +80,7 @@ solaris_output_test_default_device(void) } static struct audio_output * -solaris_output_init(const config_param ¶m, GError **error_r) +solaris_output_init(const config_param ¶m, Error &error_r) { SolarisOutput *so = new SolarisOutput(); if (!so->Initialize(param, error_r)) { @@ -114,7 +104,7 @@ solaris_output_finish(struct audio_output *ao) static bool solaris_output_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error) + Error &error) { SolarisOutput *so = (SolarisOutput *)ao; struct audio_info info; @@ -128,9 +118,8 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format, so->fd = open_cloexec(so->device, O_WRONLY|O_NONBLOCK, 0); if (so->fd < 0) { - g_set_error(error, solaris_output_quark(), errno, - "Failed to open %s: %s", - so->device, g_strerror(errno)); + error.FormatErrno("Failed to open %s", + so->device); return false; } @@ -144,8 +133,7 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format, ret = ioctl(so->fd, AUDIO_GETINFO, &info); if (ret < 0) { - g_set_error(error, solaris_output_quark(), errno, - "AUDIO_GETINFO failed: %s", g_strerror(errno)); + error.SetErrno("AUDIO_GETINFO failed"); close(so->fd); return false; } @@ -157,8 +145,7 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format, ret = ioctl(so->fd, AUDIO_SETINFO, &info); if (ret < 0) { - g_set_error(error, solaris_output_quark(), errno, - "AUDIO_SETINFO failed: %s", g_strerror(errno)); + error.SetErrno("AUDIO_SETINFO failed"); close(so->fd); return false; } @@ -176,15 +163,14 @@ solaris_output_close(struct audio_output *ao) static size_t solaris_output_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error) + Error &error) { SolarisOutput *so = (SolarisOutput *)ao; ssize_t nbytes; nbytes = write(so->fd, chunk, size); if (nbytes <= 0) { - g_set_error(error, solaris_output_quark(), errno, - "Write failed: %s", g_strerror(errno)); + error.SetErrno("Write failed"); return 0; } diff --git a/src/output/WinmmOutputPlugin.cxx b/src/output/WinmmOutputPlugin.cxx index d02b52c58..7d81576e8 100644 --- a/src/output/WinmmOutputPlugin.cxx +++ b/src/output/WinmmOutputPlugin.cxx @@ -22,6 +22,8 @@ #include "OutputAPI.hxx" #include "pcm/PcmBuffer.hxx" #include "MixerList.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include #include @@ -51,14 +53,7 @@ struct WinmmOutput { unsigned next_buffer; }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -winmm_output_quark(void) -{ - return g_quark_from_static_string("winmm_output"); -} +static constexpr Domain winmm_output_domain("winmm_output"); HWAVEOUT winmm_output_get_handle(WinmmOutput *output) @@ -73,7 +68,7 @@ winmm_output_test_default_device(void) } static bool -get_device_id(const char *device_name, UINT *device_id, GError **error_r) +get_device_id(const char *device_name, UINT *device_id, Error &error) { /* if device is not specified use wave mapper */ if (device_name == nullptr) { @@ -108,22 +103,22 @@ get_device_id(const char *device_name, UINT *device_id, GError **error_r) } fail: - g_set_error(error_r, winmm_output_quark(), 0, - "device \"%s\" is not found", device_name); + error.Format(winmm_output_domain, + "device \"%s\" is not found", device_name); return false; } static struct audio_output * -winmm_output_init(const config_param ¶m, GError **error_r) +winmm_output_init(const config_param ¶m, Error &error) { WinmmOutput *wo = new WinmmOutput(); - if (!ao_base_init(&wo->base, &winmm_output_plugin, param, error_r)) { + if (!ao_base_init(&wo->base, &winmm_output_plugin, param, error)) { g_free(wo); return nullptr; } const char *device = param.GetBlockValue("device"); - if (!get_device_id(device, &wo->device_id, error_r)) { + if (!get_device_id(device, &wo->device_id, error)) { ao_base_finish(&wo->base); g_free(wo); return nullptr; @@ -143,14 +138,13 @@ winmm_output_finish(struct audio_output *ao) static bool winmm_output_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error_r) + Error &error) { WinmmOutput *wo = (WinmmOutput *)ao; wo->event = CreateEvent(nullptr, false, false, nullptr); if (wo->event == nullptr) { - g_set_error(error_r, winmm_output_quark(), 0, - "CreateEvent() failed"); + error.Set(winmm_output_domain, "CreateEvent() failed"); return false; } @@ -186,8 +180,7 @@ winmm_output_open(struct audio_output *ao, AudioFormat &audio_format, (DWORD_PTR)wo->event, 0, CALLBACK_EVENT); if (result != MMSYSERR_NOERROR) { CloseHandle(wo->event); - g_set_error(error_r, winmm_output_quark(), result, - "waveOutOpen() failed"); + error.Set(winmm_output_domain, "waveOutOpen() failed"); return false; } @@ -219,7 +212,7 @@ winmm_output_close(struct audio_output *ao) static bool winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer, const void *data, size_t size, - GError **error_r) + Error &error) { void *dest = buffer->buffer.Get(size); assert(dest != nullptr); @@ -233,8 +226,8 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer, MMRESULT result = waveOutPrepareHeader(wo->handle, &buffer->hdr, sizeof(buffer->hdr)); if (result != MMSYSERR_NOERROR) { - g_set_error(error_r, winmm_output_quark(), result, - "waveOutPrepareHeader() failed"); + error.Set(winmm_output_domain, result, + "waveOutPrepareHeader() failed"); return false; } @@ -246,7 +239,7 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer, */ static bool winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer, - GError **error_r) + Error &error) { if ((buffer->hdr.dwFlags & WHDR_DONE) == WHDR_DONE) /* already finished */ @@ -259,8 +252,8 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer, if (result == MMSYSERR_NOERROR) return true; else if (result != WAVERR_STILLPLAYING) { - g_set_error(error_r, winmm_output_quark(), result, - "waveOutUnprepareHeader() failed"); + error.Set(winmm_output_domain, result, + "waveOutUnprepareHeader() failed"); return false; } @@ -270,14 +263,14 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer, } static size_t -winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error_r) +winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, Error &error) { WinmmOutput *wo = (WinmmOutput *)ao; /* get the next buffer from the ring and prepare it */ WinmmBuffer *buffer = &wo->buffers[wo->next_buffer]; - if (!winmm_drain_buffer(wo, buffer, error_r) || - !winmm_set_buffer(wo, buffer, chunk, size, error_r)) + if (!winmm_drain_buffer(wo, buffer, error) || + !winmm_set_buffer(wo, buffer, chunk, size, error)) return 0; /* enqueue the buffer */ @@ -286,8 +279,8 @@ winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GErro if (result != MMSYSERR_NOERROR) { waveOutUnprepareHeader(wo->handle, &buffer->hdr, sizeof(buffer->hdr)); - g_set_error(error_r, winmm_output_quark(), result, - "waveOutWrite() failed"); + error.Set(winmm_output_domain, result, + "waveOutWrite() failed"); return 0; } @@ -299,14 +292,14 @@ winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GErro } static bool -winmm_drain_all_buffers(WinmmOutput *wo, GError **error_r) +winmm_drain_all_buffers(WinmmOutput *wo, Error &error) { for (unsigned i = wo->next_buffer; i < G_N_ELEMENTS(wo->buffers); ++i) - if (!winmm_drain_buffer(wo, &wo->buffers[i], error_r)) + if (!winmm_drain_buffer(wo, &wo->buffers[i], error)) return false; for (unsigned i = 0; i < wo->next_buffer; ++i) - if (!winmm_drain_buffer(wo, &wo->buffers[i], error_r)) + if (!winmm_drain_buffer(wo, &wo->buffers[i], error)) return false; return true; @@ -329,7 +322,7 @@ winmm_output_drain(struct audio_output *ao) { WinmmOutput *wo = (WinmmOutput *)ao; - if (!winmm_drain_all_buffers(wo, nullptr)) + if (!winmm_drain_all_buffers(wo, IgnoreError())) winmm_stop(wo); } -- cgit v1.2.3