diff options
author | Max Kellermann <max@duempel.org> | 2013-08-10 18:02:44 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-09-04 18:14:22 +0200 |
commit | 29030b54c98b0aee65fbc10ebf7ba36bed98c02c (patch) | |
tree | 79766830b55ebca38ddbce84d8d548227eedb69e /src | |
parent | c9fcc7f14860777458153eb2d13c773ccfa1daa2 (diff) | |
download | mpd-29030b54c98b0aee65fbc10ebf7ba36bed98c02c.tar.gz mpd-29030b54c98b0aee65fbc10ebf7ba36bed98c02c.tar.xz mpd-29030b54c98b0aee65fbc10ebf7ba36bed98c02c.zip |
util/Error: new error passing library
Replaces GLib's GError.
Diffstat (limited to 'src')
236 files changed, 3070 insertions, 3115 deletions
diff --git a/src/AllCommands.cxx b/src/AllCommands.cxx index 88eee150e..acd7d263e 100644 --- a/src/AllCommands.cxx +++ b/src/AllCommands.cxx @@ -32,6 +32,7 @@ #include "protocol/Result.hxx" #include "Client.hxx" #include "util/Tokenizer.hxx" +#include "util/Error.hxx" #ifdef ENABLE_SQLITE #include "StickerCommands.hxx" @@ -315,7 +316,7 @@ command_checked_lookup(Client *client, unsigned permission, enum command_return command_process(Client *client, unsigned num, char *line) { - GError *error = NULL; + Error error; char *argv[COMMAND_ARGV_MAX] = { NULL }; const struct command *cmd; enum command_return ret = COMMAND_RETURN_ERROR; @@ -325,17 +326,16 @@ command_process(Client *client, unsigned num, char *line) /* get the command name (first word on the line) */ Tokenizer tokenizer(line); - argv[0] = tokenizer.NextWord(&error); + argv[0] = tokenizer.NextWord(error); if (argv[0] == NULL) { current_command = ""; if (tokenizer.IsEnd()) command_error(client, ACK_ERROR_UNKNOWN, "No command given"); - else { + else command_error(client, ACK_ERROR_UNKNOWN, - "%s", error->message); - g_error_free(error); - } + "%s", error.GetMessage()); + current_command = NULL; return COMMAND_RETURN_ERROR; @@ -347,7 +347,7 @@ command_process(Client *client, unsigned num, char *line) while (argc < COMMAND_ARGV_MAX && (argv[argc] = - tokenizer.NextParam(&error)) != NULL) + tokenizer.NextParam(error)) != NULL) ++argc; /* some error checks; we have to set current_command because @@ -362,10 +362,8 @@ command_process(Client *client, unsigned num, char *line) } if (!tokenizer.IsEnd()) { - command_error(client, ACK_ERROR_ARG, - "%s", error->message); + command_error(client, ACK_ERROR_ARG, "%s", error.GetMessage()); current_command = NULL; - g_error_free(error); return COMMAND_RETURN_ERROR; } diff --git a/src/ArchiveFile.hxx b/src/ArchiveFile.hxx index c7933ebd1..de0ecc1e8 100644 --- a/src/ArchiveFile.hxx +++ b/src/ArchiveFile.hxx @@ -20,6 +20,8 @@ #ifndef MPD_ARCHIVE_FILE_HXX #define MPD_ARCHIVE_FILE_HXX +class Error; + class ArchiveFile { public: const struct archive_plugin &plugin; @@ -50,7 +52,7 @@ public: */ virtual input_stream *OpenStream(const char *path, Mutex &mutex, Cond &cond, - GError **error_r) = 0; + Error &error) = 0; }; #endif diff --git a/src/ArchivePlugin.cxx b/src/ArchivePlugin.cxx index 7c5164220..dd2059c0f 100644 --- a/src/ArchivePlugin.cxx +++ b/src/ArchivePlugin.cxx @@ -17,27 +17,23 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "ArchivePlugin.hxx" #include "ArchiveFile.hxx" +#include "util/Error.hxx" #include <assert.h> ArchiveFile * archive_file_open(const struct archive_plugin *plugin, const char *path, - GError **error_r) + Error &error) { assert(plugin != NULL); assert(plugin->open != NULL); assert(path != NULL); - assert(error_r == NULL || *error_r == NULL); - ArchiveFile *file = plugin->open(path, error_r); - - if (file != NULL) { - assert(error_r == NULL || *error_r == NULL); - } else { - assert(error_r == NULL || *error_r != NULL); - } + ArchiveFile *file = plugin->open(path, error); + assert((file == nullptr) == error.IsDefined()); return file; } diff --git a/src/ArchivePlugin.hxx b/src/ArchivePlugin.hxx index 13952940f..ac8c1c8e3 100644 --- a/src/ArchivePlugin.hxx +++ b/src/ArchivePlugin.hxx @@ -22,11 +22,11 @@ #include "thread/Mutex.hxx" #include "thread/Cond.hxx" -#include "gerror.h" struct input_stream; class ArchiveFile; class ArchiveVisitor; +class Error; struct archive_plugin { const char *name; @@ -49,7 +49,7 @@ struct archive_plugin { * returns pointer to handle used is all operations with this archive * or NULL when opening fails */ - ArchiveFile *(*open)(const char *path_fs, GError **error_r); + ArchiveFile *(*open)(const char *path_fs, Error &error); /** * suffixes handled by this plugin. @@ -60,6 +60,6 @@ struct archive_plugin { ArchiveFile * archive_file_open(const struct archive_plugin *plugin, const char *path, - GError **error_r); + Error &error); #endif diff --git a/src/AudioConfig.cxx b/src/AudioConfig.cxx index 9ead61afe..64c9d76d5 100644 --- a/src/AudioConfig.cxx +++ b/src/AudioConfig.cxx @@ -23,6 +23,7 @@ #include "AudioParser.hxx" #include "conf.h" #include "mpd_error.h" +#include "util/Error.hxx" static AudioFormat configured_audio_format; @@ -37,15 +38,13 @@ getOutputAudioFormat(AudioFormat inAudioFormat) void initAudioConfig(void) { const struct config_param *param = config_get_param(CONF_AUDIO_OUTPUT_FORMAT); - GError *error = NULL; - bool ret; if (param == NULL) return; - ret = audio_format_parse(configured_audio_format, param->value, - true, &error); - if (!ret) + Error error; + if (!audio_format_parse(configured_audio_format, param->value, + true, error)) MPD_ERROR("error parsing line %i: %s", - param->line, error->message); + param->line, error.GetMessage()); } diff --git a/src/AudioParser.cxx b/src/AudioParser.cxx index 4c345ca33..db6d1d8e8 100644 --- a/src/AudioParser.cxx +++ b/src/AudioParser.cxx @@ -26,24 +26,16 @@ #include "AudioParser.hxx" #include "AudioFormat.hxx" #include "CheckAudioFormat.hxx" +#include "util/Error.hxx" #include "gcc.h" #include <assert.h> #include <string.h> #include <stdlib.h> -/** - * The GLib quark used for errors reported by this library. - */ -static inline GQuark -audio_parser_quark(void) -{ - return g_quark_from_static_string("audio_parser"); -} - static bool parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, - const char **endptr_r, GError **error_r) + const char **endptr_r, Error &error) { unsigned long value; char *endptr; @@ -56,10 +48,10 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, value = strtoul(src, &endptr, 10); if (endptr == src) { - g_set_error(error_r, audio_parser_quark(), 0, - "Failed to parse the sample rate"); + error.Set(audio_format_domain, + "Failed to parse the sample rate"); return false; - } else if (!audio_check_sample_rate(value, error_r)) + } else if (!audio_check_sample_rate(value, error)) return false; *sample_rate_r = value; @@ -70,7 +62,7 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, static bool parse_sample_format(const char *src, bool mask, SampleFormat *sample_format_r, - const char **endptr_r, GError **error_r) + const char **endptr_r, Error &error) { unsigned long value; char *endptr; @@ -96,8 +88,8 @@ parse_sample_format(const char *src, bool mask, value = strtoul(src, &endptr, 10); if (endptr == src) { - g_set_error(error_r, audio_parser_quark(), 0, - "Failed to parse the sample format"); + error.Set(audio_format_domain, + "Failed to parse the sample format"); return false; } @@ -123,8 +115,8 @@ parse_sample_format(const char *src, bool mask, break; default: - g_set_error(error_r, audio_parser_quark(), 0, - "Invalid sample format: %lu", value); + error.Format(audio_format_domain, + "Invalid sample format: %lu", value); return false; } @@ -137,7 +129,7 @@ parse_sample_format(const char *src, bool mask, static bool parse_channel_count(const char *src, bool mask, uint8_t *channels_r, - const char **endptr_r, GError **error_r) + const char **endptr_r, Error &error) { unsigned long value; char *endptr; @@ -150,10 +142,10 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r, value = strtoul(src, &endptr, 10); if (endptr == src) { - g_set_error(error_r, audio_parser_quark(), 0, - "Failed to parse the channel count"); + error.Set(audio_format_domain, + "Failed to parse the channel count"); return false; - } else if (!audio_check_channel_count(value, error_r)) + } else if (!audio_check_channel_count(value, error)) return false; *channels_r = value; @@ -163,7 +155,7 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r, bool audio_format_parse(AudioFormat &dest, const char *src, - bool mask, GError **error_r) + bool mask, Error &error) { uint32_t rate; SampleFormat sample_format; @@ -178,12 +170,11 @@ audio_format_parse(AudioFormat &dest, const char *src, rate = 0; #endif - if (!parse_sample_rate(src, mask, &rate, &src, error_r)) + if (!parse_sample_rate(src, mask, &rate, &src, error)) return false; if (*src++ != ':') { - g_set_error(error_r, audio_parser_quark(), 0, - "Sample format missing"); + error.Set(audio_format_domain, "Sample format missing"); return false; } @@ -194,22 +185,21 @@ audio_format_parse(AudioFormat &dest, const char *src, sample_format = SampleFormat::UNDEFINED; #endif - if (!parse_sample_format(src, mask, &sample_format, &src, error_r)) + if (!parse_sample_format(src, mask, &sample_format, &src, error)) return false; if (*src++ != ':') { - g_set_error(error_r, audio_parser_quark(), 0, - "Channel count missing"); + error.Set(audio_format_domain, "Channel count missing"); return false; } /* parse channel count */ - if (!parse_channel_count(src, mask, &channels, &src, error_r)) + if (!parse_channel_count(src, mask, &channels, &src, error)) return false; if (*src != 0) { - g_set_error(error_r, audio_parser_quark(), 0, + error.Format(audio_format_domain, "Extra data after channel count: %s", src); return false; } diff --git a/src/AudioParser.hxx b/src/AudioParser.hxx index 14c26392c..cb6eb3ca0 100644 --- a/src/AudioParser.hxx +++ b/src/AudioParser.hxx @@ -25,9 +25,8 @@ #ifndef MPD_AUDIO_PARSER_HXX #define MPD_AUDIO_PARSER_HXX -#include "gerror.h" - struct AudioFormat; +class Error; /** * Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an @@ -42,6 +41,6 @@ struct AudioFormat; */ bool audio_format_parse(AudioFormat &dest, const char *src, - bool mask, GError **error_r); + bool mask, Error &error); #endif diff --git a/src/CheckAudioFormat.cxx b/src/CheckAudioFormat.cxx index fabffd56c..1f3ef4925 100644 --- a/src/CheckAudioFormat.cxx +++ b/src/CheckAudioFormat.cxx @@ -17,17 +17,22 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "CheckAudioFormat.hxx" #include "AudioFormat.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <assert.h> +const Domain audio_format_domain("audio_format"); + bool -audio_check_sample_rate(unsigned long sample_rate, GError **error_r) +audio_check_sample_rate(unsigned long sample_rate, Error &error) { if (!audio_valid_sample_rate(sample_rate)) { - g_set_error(error_r, audio_format_quark(), 0, - "Invalid sample rate: %lu", sample_rate); + error.Format(audio_format_domain, + "Invalid sample rate: %lu", sample_rate); return false; } @@ -35,12 +40,12 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r) } bool -audio_check_sample_format(SampleFormat sample_format, GError **error_r) +audio_check_sample_format(SampleFormat sample_format, Error &error) { if (!audio_valid_sample_format(sample_format)) { - g_set_error(error_r, audio_format_quark(), 0, - "Invalid sample format: %u", - unsigned(sample_format)); + error.Format(audio_format_domain, + "Invalid sample format: %u", + unsigned(sample_format)); return false; } @@ -48,11 +53,11 @@ audio_check_sample_format(SampleFormat sample_format, GError **error_r) } bool -audio_check_channel_count(unsigned channels, GError **error_r) +audio_check_channel_count(unsigned channels, Error &error) { if (!audio_valid_channel_count(channels)) { - g_set_error(error_r, audio_format_quark(), 0, - "Invalid channel count: %u", channels); + error.Format(audio_format_domain, + "Invalid channel count: %u", channels); return false; } @@ -62,11 +67,11 @@ audio_check_channel_count(unsigned channels, GError **error_r) bool audio_format_init_checked(AudioFormat &af, unsigned long sample_rate, SampleFormat sample_format, unsigned channels, - GError **error_r) + Error &error) { - if (audio_check_sample_rate(sample_rate, error_r) && - audio_check_sample_format(sample_format, error_r) && - audio_check_channel_count(channels, error_r)) { + if (audio_check_sample_rate(sample_rate, error) && + audio_check_sample_format(sample_format, error) && + audio_check_channel_count(channels, error)) { af = AudioFormat(sample_rate, sample_format, channels); assert(af.IsValid()); return true; diff --git a/src/CheckAudioFormat.hxx b/src/CheckAudioFormat.hxx index 7fbce7f98..df952adc7 100644 --- a/src/CheckAudioFormat.hxx +++ b/src/CheckAudioFormat.hxx @@ -22,26 +22,18 @@ #include "AudioFormat.hxx" -#include <glib.h> +class Error; -/** - * The GLib quark used for errors reported by this library. - */ -gcc_const -static inline GQuark -audio_format_quark(void) -{ - return g_quark_from_static_string("audio_format"); -} +extern const class Domain audio_format_domain; bool -audio_check_sample_rate(unsigned long sample_rate, GError **error_r); +audio_check_sample_rate(unsigned long sample_rate, Error &error); bool -audio_check_sample_format(SampleFormat sample_format, GError **error_r); +audio_check_sample_format(SampleFormat sample_format, Error &error); bool -audio_check_channel_count(unsigned sample_format, GError **error_r); +audio_check_channel_count(unsigned sample_format, Error &error); /** * Wrapper for audio_format_init(), which checks all attributes. @@ -49,6 +41,6 @@ audio_check_channel_count(unsigned sample_format, GError **error_r); bool audio_format_init_checked(AudioFormat &af, unsigned long sample_rate, SampleFormat sample_format, unsigned channels, - GError **error_r); + Error &error); #endif diff --git a/src/ClientEvent.cxx b/src/ClientEvent.cxx index fe0f079b6..90b4a7499 100644 --- a/src/ClientEvent.cxx +++ b/src/ClientEvent.cxx @@ -19,14 +19,14 @@ #include "config.h" #include "ClientInternal.hxx" +#include "util/Error.hxx" #include <glib.h> void -Client::OnSocketError(GError *error) +Client::OnSocketError(Error &&error) { - g_warning("error on client %d: %s", num, error->message); - g_error_free(error); + g_warning("error on client %d: %s", num, error.GetMessage()); SetExpired(); } diff --git a/src/ClientFile.cxx b/src/ClientFile.cxx index 69bc465b4..a460310be 100644 --- a/src/ClientFile.cxx +++ b/src/ClientFile.cxx @@ -21,9 +21,10 @@ #include "ClientFile.hxx" #include "Client.hxx" #include "protocol/Ack.hxx" -#include "io_error.h" #include "fs/Path.hxx" #include "fs/FileSystem.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <sys/stat.h> #include <sys/types.h> @@ -32,14 +33,13 @@ bool client_allow_file(const Client *client, const Path &path_fs, - GError **error_r) + Error &error) { #ifdef WIN32 (void)client; (void)path_fs; - g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION, - "Access denied"); + error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied"); return false; #else const int uid = client_get_uid(client); @@ -50,21 +50,19 @@ client_allow_file(const Client *client, const Path &path_fs, if (uid <= 0) { /* unauthenticated client */ - g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION, - "Access denied"); + error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied"); return false; } struct stat st; if (!StatFile(path_fs, st)) { - set_error_errno(error_r); + error.SetErrno(); return false; } if (st.st_uid != (uid_t)uid && (st.st_mode & 0444) != 0444) { /* client is not owner */ - g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION, - "Access denied"); + error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied"); return false; } diff --git a/src/ClientFile.hxx b/src/ClientFile.hxx index 21db4d3ad..68d79ca08 100644 --- a/src/ClientFile.hxx +++ b/src/ClientFile.hxx @@ -20,10 +20,9 @@ #ifndef MPD_CLIENT_FILE_HXX #define MPD_CLIENT_FILE_HXX -#include "gerror.h" - class Client; class Path; +class Error; /** * Is this client allowed to use the specified local file? @@ -37,6 +36,6 @@ class Path; */ bool client_allow_file(const Client *client, const Path &path_fs, - GError **error_r); + Error &error); #endif diff --git a/src/ClientInternal.hxx b/src/ClientInternal.hxx index 8dd839cc2..ca2669db0 100644 --- a/src/ClientInternal.hxx +++ b/src/ClientInternal.hxx @@ -116,7 +116,7 @@ private: /* virtual methods from class BufferedSocket */ 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; /* virtual methods from class TimeoutMonitor */ diff --git a/src/ClientNew.cxx b/src/ClientNew.cxx index dd5aba318..bc12bbf6a 100644 --- a/src/ClientNew.cxx +++ b/src/ClientNew.cxx @@ -25,6 +25,7 @@ #include "system/fd_util.h" #include "system/Resolver.hxx" #include "Permission.hxx" +#include "util/Error.hxx" #include <assert.h> #include <sys/types.h> @@ -70,7 +71,8 @@ client_new(EventLoop &loop, Partition &partition, #ifdef HAVE_LIBWRAP if (sa->sa_family != AF_UNIX) { - char *hostaddr = sockaddr_to_string(sa, sa_length, NULL); + char *hostaddr = sockaddr_to_string(sa, sa_length, + IgnoreError()); const char *progname = g_get_prgname(); struct request_info req; @@ -107,7 +109,7 @@ client_new(EventLoop &loop, Partition &partition, client_list.Add(*client); - remote = sockaddr_to_string(sa, sa_length, NULL); + remote = sockaddr_to_string(sa, sa_length, IgnoreError()); g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE, "[%u] opened from %s", client->num, remote); g_free(remote); diff --git a/src/ClientProcess.cxx b/src/ClientProcess.cxx index bcd20d1b7..caaef487b 100644 --- a/src/ClientProcess.cxx +++ b/src/ClientProcess.cxx @@ -22,6 +22,8 @@ #include "protocol/Result.hxx" #include "AllCommands.hxx" +#include <glib.h> + #include <string.h> #define CLIENT_LIST_MODE_BEGIN "command_list_begin" diff --git a/src/CommandError.cxx b/src/CommandError.cxx index 7a33761ae..c9b6c2deb 100644 --- a/src/CommandError.cxx +++ b/src/CommandError.cxx @@ -20,8 +20,10 @@ #include "config.h" #include "CommandError.hxx" #include "DatabaseError.hxx" -#include "io_error.h" #include "protocol/Result.hxx" +#include "util/Error.hxx" + +#include <glib.h> #include <assert.h> #include <errno.h> @@ -85,50 +87,38 @@ print_playlist_result(Client *client, enum playlist_result result) return COMMAND_RETURN_ERROR; } -/** - * Send the GError to the client and free the GError. - */ enum command_return -print_error(Client *client, GError *error) +print_error(Client *client, const Error &error) { assert(client != NULL); - assert(error != NULL); + assert(error.IsDefined()); - g_warning("%s", error->message); + g_warning("%s", error.GetMessage()); - if (error->domain == playlist_quark()) { - enum playlist_result result = (playlist_result)error->code; - g_error_free(error); - return print_playlist_result(client, result); - } else if (error->domain == ack_quark()) { - command_error(client, (ack)error->code, "%s", error->message); - g_error_free(error); + if (error.IsDomain(playlist_domain)) { + return print_playlist_result(client, + playlist_result(error.GetCode())); + } else if (error.IsDomain(ack_domain)) { + command_error(client, (ack)error.GetCode(), + "%s", error.GetMessage()); return COMMAND_RETURN_ERROR; - } else if (error->domain == db_quark()) { - switch ((enum db_error)error->code) { + } else if (error.IsDomain(db_domain)) { + switch ((enum db_error)error.GetCode()) { case DB_DISABLED: command_error(client, ACK_ERROR_NO_EXIST, "%s", - error->message); - g_error_free(error); + error.GetMessage()); return COMMAND_RETURN_ERROR; case DB_NOT_FOUND: - g_error_free(error); command_error(client, ACK_ERROR_NO_EXIST, "Not found"); return COMMAND_RETURN_ERROR; } - } else if (error->domain == errno_quark()) { + } else if (error.IsDomain(errno_domain)) { command_error(client, ACK_ERROR_SYSTEM, "%s", - g_strerror(error->code)); - g_error_free(error); - return COMMAND_RETURN_ERROR; - } else if (error->domain == g_file_error_quark()) { - command_error(client, ACK_ERROR_SYSTEM, "%s", error->message); - g_error_free(error); + g_strerror(error.GetCode())); return COMMAND_RETURN_ERROR; } - g_error_free(error); command_error(client, ACK_ERROR_UNKNOWN, "error"); return COMMAND_RETURN_ERROR; } diff --git a/src/CommandError.hxx b/src/CommandError.hxx index 04d0aeb21..06f76390a 100644 --- a/src/CommandError.hxx +++ b/src/CommandError.hxx @@ -22,17 +22,17 @@ #include "command.h" #include "PlaylistError.hxx" -#include "gerror.h" class Client; +class Error; enum command_return print_playlist_result(Client *client, enum playlist_result result); /** - * Send the GError to the client and free the GError. + * Send the #Error to the client. */ enum command_return -print_error(Client *client, GError *error); +print_error(Client *client, const Error &error); #endif diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx index 89575a13f..71395fd0c 100644 --- a/src/CommandLine.cxx +++ b/src/CommandLine.cxx @@ -33,6 +33,8 @@ #include "mpd_error.h" #include "fs/Path.hxx" #include "fs/FileSystem.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #ifdef ENABLE_ENCODER #include "EncoderList.hxx" @@ -57,11 +59,7 @@ #define USER_CONFIG_FILE_LOCATION_XDG "mpd/mpd.conf" #endif -static GQuark -cmdline_quark(void) -{ - return g_quark_from_static_string("cmdline"); -} +static constexpr Domain cmdline_domain("cmdline"); gcc_noreturn static void version(void) @@ -147,9 +145,8 @@ PathBuildChecked(const Path &a, Path::const_pointer b) bool parse_cmdline(int argc, char **argv, struct options *options, - GError **error_r) + Error &error) { - GError *error = NULL; GOptionContext *context; bool ret; static gboolean option_version, @@ -183,11 +180,12 @@ parse_cmdline(int argc, char **argv, struct options *options, g_option_context_set_summary(context, summary); - ret = g_option_context_parse(context, &argc, &argv, &error); + GError *gerror = nullptr; + ret = g_option_context_parse(context, &argc, &argv, &gerror); g_option_context_free(context); if (!ret) - MPD_ERROR("option parsing failed: %s\n", error->message); + MPD_ERROR("option parsing failed: %s\n", gerror->message); if (option_version) version(); @@ -208,7 +206,7 @@ parse_cmdline(int argc, char **argv, struct options *options, Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()), CONFIG_FILE_LOCATION); if (!path.IsNull() && FileExists(path)) - return ReadConfigFile(path, error_r); + return ReadConfigFile(path, error); const char *const*system_config_dirs = g_get_system_config_dirs(); @@ -217,38 +215,36 @@ parse_cmdline(int argc, char **argv, struct options *options, path = PathBuildChecked(Path::FromUTF8(system_config_dirs[i]), CONFIG_FILE_LOCATION); if (!path.IsNull() && FileExists(path)) - return ReadConfigFile(path, error_r); + return ReadConfigFile(path, error); } #else /* G_OS_WIN32 */ Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()), USER_CONFIG_FILE_LOCATION_XDG); if (!path.IsNull() && FileExists(path)) - return ReadConfigFile(path, error_r); + return ReadConfigFile(path, error); path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()), USER_CONFIG_FILE_LOCATION1); if (!path.IsNull() && FileExists(path)) - return ReadConfigFile(path, error_r); + return ReadConfigFile(path, error); path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()), USER_CONFIG_FILE_LOCATION2); if (!path.IsNull() && FileExists(path)) - return ReadConfigFile(path, error_r); + return ReadConfigFile(path, error); path = Path::FromUTF8(SYSTEM_CONFIG_FILE_LOCATION); if (!path.IsNull() && FileExists(path)) - return ReadConfigFile(path, error_r); + return ReadConfigFile(path, error); #endif - g_set_error(error_r, cmdline_quark(), 0, - "No configuration file found"); + error.Set(cmdline_domain, "No configuration file found"); return false; } else if (argc == 2) { /* specified configuration file */ - return ReadConfigFile(Path::FromFS(argv[1]), error_r); + return ReadConfigFile(Path::FromFS(argv[1]), error); } else { - g_set_error(error_r, cmdline_quark(), 0, - "too many arguments"); + error.Set(cmdline_domain, "too many arguments"); return false; } } diff --git a/src/CommandLine.hxx b/src/CommandLine.hxx index 7a8731f82..214150eae 100644 --- a/src/CommandLine.hxx +++ b/src/CommandLine.hxx @@ -22,6 +22,8 @@ #include <glib.h> +class Error; + struct options { gboolean kill; gboolean daemon; @@ -31,6 +33,6 @@ struct options { bool parse_cmdline(int argc, char **argv, struct options *options, - GError **error_r); + Error &error); #endif diff --git a/src/ConfigData.cxx b/src/ConfigData.cxx index 2ed8e2f3b..84a726799 100644 --- a/src/ConfigData.cxx +++ b/src/ConfigData.cxx @@ -21,6 +21,7 @@ #include "ConfigData.hxx" #include "ConfigParser.hxx" #include "ConfigPath.hxx" +#include "util/Error.hxx" #include "fs/Path.hxx" #include "system/FatalError.hxx" #include "mpd_error.h" @@ -97,10 +98,9 @@ config_param::DupBlockString(const char *name, const char *default_value) const Path config_param::GetBlockPath(const char *name, const char *default_value, - GError **error_r) const + Error &error) const { - assert(error_r != nullptr); - assert(*error_r == nullptr); + assert(!error.IsDefined()); int line2 = line; const char *s; @@ -112,19 +112,18 @@ config_param::GetBlockPath(const char *name, const char *default_value, } else s = default_value; - Path path = ParsePath(s, error_r); + Path path = ParsePath(s, error); if (gcc_unlikely(path.IsNull())) - g_prefix_error(error_r, - "Invalid path in \"%s\" at line %i: ", - name, line2); + error.FormatPrefix("Invalid path in \"%s\" at line %i: ", + name, line2); return path; } Path -config_param::GetBlockPath(const char *name, GError **error_r) const +config_param::GetBlockPath(const char *name, Error &error) const { - return GetBlockPath(name, nullptr, error_r); + return GetBlockPath(name, nullptr, error); } unsigned diff --git a/src/ConfigData.hxx b/src/ConfigData.hxx index a7a733e4d..19613c610 100644 --- a/src/ConfigData.hxx +++ b/src/ConfigData.hxx @@ -21,7 +21,6 @@ #define MPD_CONFIG_DATA_HXX #include "ConfigOption.hxx" -#include "gerror.h" #include "gcc.h" #include <string> @@ -29,6 +28,7 @@ #include <vector> class Path; +class Error; struct block_param { std::string name; @@ -113,9 +113,9 @@ struct config_param { * specified block. */ Path GetBlockPath(const char *name, const char *default_value, - GError **error_r) const; + Error &error) const; - Path GetBlockPath(const char *name, GError **error_r) const; + Path GetBlockPath(const char *name, Error &error) const; gcc_pure unsigned GetBlockValue(const char *name, unsigned default_value) const; diff --git a/src/ConfigError.cxx b/src/ConfigError.cxx new file mode 100644 index 000000000..bd529e670 --- /dev/null +++ b/src/ConfigError.cxx @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "ConfigError.hxx" +#include "util/Domain.hxx" + +const Domain config_domain("config"); diff --git a/src/ConfigQuark.hxx b/src/ConfigError.hxx index 4d9be33b1..a8917d7d1 100644 --- a/src/ConfigQuark.hxx +++ b/src/ConfigError.hxx @@ -17,22 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_CONFIG_QUARK_HXX -#define MPD_CONFIG_QUARK_HXX +#ifndef MPD_CONFIG_ERROR_HXX +#define MPD_CONFIG_ERROR_HXX -#include "gcc.h" - -#include <glib.h> - -/** - * A GQuark for GError instances, resulting from malformed - * configuration. - */ -gcc_const -static inline GQuark -config_quark(void) -{ - return g_quark_from_static_string("config"); -} +extern const class Domain config_domain; #endif diff --git a/src/ConfigFile.cxx b/src/ConfigFile.cxx index 2573f66e5..595d6a1bf 100644 --- a/src/ConfigFile.cxx +++ b/src/ConfigFile.cxx @@ -19,12 +19,14 @@ #include "config.h" #include "ConfigFile.hxx" -#include "ConfigQuark.hxx" +#include "ConfigError.hxx" #include "ConfigData.hxx" #include "ConfigTemplates.hxx" #include "conf.h" #include "util/Tokenizer.hxx" #include "util/StringUtil.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "fs/Path.hxx" #include "fs/FileSystem.hxx" @@ -42,42 +44,41 @@ #define CONF_COMMENT '#' +static constexpr Domain config_file_domain("config_file"); + static bool config_read_name_value(struct config_param *param, char *input, unsigned line, - GError **error_r) + Error &error) { Tokenizer tokenizer(input); - const char *name = tokenizer.NextWord(error_r); + const char *name = tokenizer.NextWord(error); if (name == NULL) { assert(!tokenizer.IsEnd()); return false; } - const char *value = tokenizer.NextString(error_r); + const char *value = tokenizer.NextString(error); if (value == NULL) { if (tokenizer.IsEnd()) { - assert(error_r == NULL || *error_r == NULL); - g_set_error(error_r, config_quark(), 0, - "Value missing"); + error.Set(config_file_domain, "Value missing"); } else { - assert(error_r == NULL || *error_r != NULL); + assert(error.IsDefined()); } return false; } if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) { - g_set_error(error_r, config_quark(), 0, - "Unknown tokens after value"); + error.Set(config_file_domain, "Unknown tokens after value"); return false; } const struct block_param *bp = param->GetBlockParam(name); if (bp != NULL) { - g_set_error(error_r, config_quark(), 0, - "\"%s\" is duplicate, first defined on line %i", - name, bp->line); + error.Format(config_file_domain, + "\"%s\" is duplicate, first defined on line %i", + name, bp->line); return false; } @@ -86,10 +87,9 @@ config_read_name_value(struct config_param *param, char *input, unsigned line, } static struct config_param * -config_read_block(FILE *fp, int *count, char *string, GError **error_r) +config_read_block(FILE *fp, int *count, char *string, Error &error) { struct config_param *ret = new config_param(*count); - GError *error = NULL; while (true) { char *line; @@ -97,8 +97,8 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r) line = fgets(string, MAX_STRING_SIZE, fp); if (line == NULL) { delete ret; - g_set_error(error_r, config_quark(), 0, - "Expected '}' before end-of-file"); + error.Set(config_file_domain, + "Expected '}' before end-of-file"); return NULL; } @@ -114,9 +114,9 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r) line = strchug_fast(line + 1); if (*line != 0 && *line != CONF_COMMENT) { delete ret; - g_set_error(error_r, config_quark(), 0, - "line %i: Unknown tokens after '}'", - *count); + error.Format(config_file_domain, + "line %i: Unknown tokens after '}'", + *count); return nullptr; } @@ -125,11 +125,10 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r) /* parse name and value */ - if (!config_read_name_value(ret, line, *count, &error)) { + if (!config_read_name_value(ret, line, *count, error)) { assert(*line != 0); delete ret; - g_propagate_prefixed_error(error_r, error, - "line %i: ", *count); + error.FormatPrefix("line %i: ", *count); return NULL; } } @@ -149,7 +148,7 @@ Append(config_param *&head, config_param *p) } static bool -ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) +ReadConfigFile(ConfigData &config_data, FILE *fp, Error &error) { assert(fp != nullptr); @@ -160,7 +159,6 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) while (fgets(string, MAX_STRING_SIZE, fp)) { char *line; const char *name, *value; - GError *error = NULL; count++; @@ -172,11 +170,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) by either the value or '{' */ Tokenizer tokenizer(line); - name = tokenizer.NextWord(&error); + name = tokenizer.NextWord(error); if (name == NULL) { assert(!tokenizer.IsEnd()); - g_propagate_prefixed_error(error_r, error, - "line %i: ", count); + error.FormatPrefix("line %i: ", count); return false; } @@ -185,9 +182,9 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) const ConfigOption o = ParseConfigOptionName(name); if (o == CONF_MAX) { - g_set_error(error_r, config_quark(), 0, - "unrecognized parameter in config file at " - "line %i: %s\n", count, name); + error.Format(config_file_domain, + "unrecognized parameter in config file at " + "line %i: %s\n", count, name); return false; } @@ -197,10 +194,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) if (head != nullptr && !option.repeatable) { param = head; - g_set_error(error_r, config_quark(), 0, - "config parameter \"%s\" is first defined " - "on line %i and redefined on line %i\n", - name, param->line, count); + error.Format(config_file_domain, + "config parameter \"%s\" is first defined " + "on line %i and redefined on line %i\n", + name, param->line, count); return false; } @@ -210,47 +207,43 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) /* it's a block, call config_read_block() */ if (tokenizer.CurrentChar() != '{') { - g_set_error(error_r, config_quark(), 0, - "line %i: '{' expected", count); + error.Format(config_file_domain, + "line %i: '{' expected", count); return false; } line = strchug_fast(tokenizer.Rest() + 1); if (*line != 0 && *line != CONF_COMMENT) { - g_set_error(error_r, config_quark(), 0, - "line %i: Unknown tokens after '{'", - count); + error.Format(config_file_domain, + "line %i: Unknown tokens after '{'", + count); return false; } - param = config_read_block(fp, &count, string, error_r); + param = config_read_block(fp, &count, string, error); if (param == NULL) { return false; } } else { /* a string value */ - value = tokenizer.NextString(&error); + value = tokenizer.NextString(error); if (value == NULL) { if (tokenizer.IsEnd()) - g_set_error(error_r, config_quark(), 0, - "line %i: Value missing", - count); - else { - g_set_error(error_r, config_quark(), 0, - "line %i: %s", count, - error->message); - g_error_free(error); - } + error.Format(config_file_domain, + "line %i: Value missing", + count); + else + error.FormatPrefix("line %i: ", count); return false; } if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) { - g_set_error(error_r, config_quark(), 0, - "line %i: Unknown tokens after value", - count); + error.Format(config_file_domain, + "line %i: Unknown tokens after value", + count); return false; } @@ -264,7 +257,7 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) } bool -ReadConfigFile(ConfigData &config_data, const Path &path, GError **error_r) +ReadConfigFile(ConfigData &config_data, const Path &path, Error &error) { assert(!path.IsNull()); const std::string path_utf8 = path.ToUTF8(); @@ -273,13 +266,11 @@ ReadConfigFile(ConfigData &config_data, const Path &path, GError **error_r) FILE *fp = FOpen(path, FOpenMode::ReadText); if (fp == nullptr) { - g_set_error(error_r, config_quark(), errno, - "Failed to open %s: %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Failed to open %s", path_utf8.c_str()); return false; } - bool result = ReadConfigFile(config_data, fp, error_r); + bool result = ReadConfigFile(config_data, fp, error); fclose(fp); return result; } diff --git a/src/ConfigFile.hxx b/src/ConfigFile.hxx index 49c0d31ec..0dca65567 100644 --- a/src/ConfigFile.hxx +++ b/src/ConfigFile.hxx @@ -20,12 +20,11 @@ #ifndef MPD_CONFIG_FILE_HXX #define MPD_CONFIG_FILE_HXX -#include "gerror.h" - +class Error; class Path; struct ConfigData; bool -ReadConfigFile(ConfigData &data, const Path &path, GError **error_r); +ReadConfigFile(ConfigData &data, const Path &path, Error &error); #endif diff --git a/src/ConfigGlobal.cxx b/src/ConfigGlobal.cxx index 1f89a1283..0bf2b4433 100644 --- a/src/ConfigGlobal.cxx +++ b/src/ConfigGlobal.cxx @@ -24,6 +24,7 @@ #include "ConfigFile.hxx" #include "ConfigPath.hxx" #include "fs/Path.hxx" +#include "util/Error.hxx" #include "mpd_error.h" #include <glib.h> @@ -47,9 +48,9 @@ void config_global_init(void) } bool -ReadConfigFile(const Path &path, GError **error_r) +ReadConfigFile(const Path &path, Error &error) { - return ReadConfigFile(config_data, path, error_r); + return ReadConfigFile(config_data, path, error); } static void @@ -98,20 +99,16 @@ config_get_string(ConfigOption option, const char *default_value) } Path -config_get_path(ConfigOption option, GError **error_r) +config_get_path(ConfigOption option, Error &error) { - assert(error_r != NULL); - assert(*error_r == NULL); - const struct config_param *param = config_get_param(option); if (param == NULL) return Path::Null(); - Path path = ParsePath(param->value, error_r); + Path path = ParsePath(param->value, error); if (gcc_unlikely(path.IsNull())) - g_prefix_error(error_r, - "Invalid path at line %i: ", - param->line); + error.FormatPrefix("Invalid path at line %i: ", + param->line); return path; } diff --git a/src/ConfigGlobal.hxx b/src/ConfigGlobal.hxx index aaae82bd1..efa5e0604 100644 --- a/src/ConfigGlobal.hxx +++ b/src/ConfigGlobal.hxx @@ -21,7 +21,6 @@ #define MPD_CONFIG_GLOBAL_HXX #include "ConfigOption.hxx" -#include "gerror.h" #include "gcc.h" #include <stdbool.h> @@ -30,6 +29,7 @@ #define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16) #define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS false +class Error; class Path; void config_global_init(void); @@ -42,7 +42,7 @@ void config_global_finish(void); void config_global_check(void); bool -ReadConfigFile(const Path &path, GError **error_r); +ReadConfigFile(const Path &path, Error &error); /* don't free the returned value set _last_ to NULL to get first entry */ @@ -76,7 +76,7 @@ config_get_string(enum ConfigOption option, const char *default_value); * could not be parsed, returns Path::Null() and sets the error. */ Path -config_get_path(enum ConfigOption option, GError **error_r); +config_get_path(enum ConfigOption option, Error &error); gcc_pure unsigned diff --git a/src/ConfigPath.cxx b/src/ConfigPath.cxx index b90956a2a..9c5945a32 100644 --- a/src/ConfigPath.cxx +++ b/src/ConfigPath.cxx @@ -20,6 +20,8 @@ #include "config.h" #include "ConfigPath.hxx" #include "fs/Path.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "conf.h" #include <glib.h> @@ -46,31 +48,25 @@ #include <windows.h> #endif -gcc_const -static inline GQuark -parse_path_quark(void) -{ - return g_quark_from_static_string("path"); -} +static constexpr Domain path_domain("path"); Path -ParsePath(const char *path, GError **error_r) +ParsePath(const char *path, Error &error) { assert(path != nullptr); - assert(error_r == nullptr || *error_r == nullptr); Path path2 = Path::FromUTF8(path); if (path2.IsNull()) { - g_set_error(error_r, parse_path_quark(), 0, - "Failed to convert path to file system charset: %s", - path); + error.Format(path_domain, + "Failed to convert path to file system charset: %s", + path); return Path::Null(); } #ifndef WIN32 if (!g_path_is_absolute(path) && path[0] != '~') { - g_set_error(error_r, parse_path_quark(), 0, - "not an absolute path: %s", path); + error.Format(path_domain, + "not an absolute path: %s", path); return Path::Null(); } else if (path[0] == '~') { const char *home; @@ -80,8 +76,8 @@ ParsePath(const char *path, GError **error_r) if (user != nullptr) { struct passwd *passwd = getpwnam(user); if (!passwd) { - g_set_error(error_r, parse_path_quark(), 0, - "no such user: %s", user); + error.Format(path_domain, + "no such user: %s", user); return Path::Null(); } @@ -89,9 +85,9 @@ ParsePath(const char *path, GError **error_r) } else { home = g_get_home_dir(); if (home == nullptr) { - g_set_error_literal(error_r, parse_path_quark(), 0, - "problems getting home " - "for current user"); + error.Set(path_domain, + "problems getting home " + "for current user"); return Path::Null(); } } @@ -107,8 +103,8 @@ ParsePath(const char *path, GError **error_r) struct passwd *passwd = getpwnam(user); if (!passwd) { - g_set_error(error_r, parse_path_quark(), 0, - "no such user: %s", user); + error.Format(path_domain, + "no such user: %s", user); g_free(user); return Path::Null(); } diff --git a/src/ConfigPath.hxx b/src/ConfigPath.hxx index 79da04bb1..7bc1d732c 100644 --- a/src/ConfigPath.hxx +++ b/src/ConfigPath.hxx @@ -20,11 +20,10 @@ #ifndef MPD_CONFIG_PATH_HXX #define MPD_CONFIG_PATH_HXX -#include "gerror.h" - class Path; +class Error; Path -ParsePath(const char *path, GError **error_r); +ParsePath(const char *path, Error &error); #endif diff --git a/src/DatabaseCommands.cxx b/src/DatabaseCommands.cxx index f179713d4..abed30564 100644 --- a/src/DatabaseCommands.cxx +++ b/src/DatabaseCommands.cxx @@ -27,6 +27,7 @@ #include "ClientInternal.hxx" #include "Tag.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "SongFilter.hxx" #include "protocol/Result.hxx" @@ -46,8 +47,8 @@ handle_lsinfo2(Client *client, int argc, char *argv[]) const DatabaseSelection selection(uri, false); - GError *error = NULL; - if (!db_selection_print(client, selection, true, &error)) + Error error; + if (!db_selection_print(client, selection, true, error)) return print_error(client, error); return COMMAND_RETURN_OK; @@ -64,8 +65,8 @@ handle_match(Client *client, int argc, char *argv[], bool fold_case) const DatabaseSelection selection("", true, &filter); - GError *error = NULL; - return db_selection_print(client, selection, true, &error) + Error error; + return db_selection_print(client, selection, true, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -92,8 +93,8 @@ handle_match_add(Client *client, int argc, char *argv[], bool fold_case) } const DatabaseSelection selection("", true, &filter); - GError *error = NULL; - return AddFromDatabase(client->partition, selection, &error) + Error error; + return AddFromDatabase(client->partition, selection, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -121,8 +122,8 @@ handle_searchaddpl(Client *client, int argc, char *argv[]) return COMMAND_RETURN_ERROR; } - GError *error = NULL; - return search_add_to_playlist("", playlist, &filter, &error) + Error error; + return search_add_to_playlist("", playlist, &filter, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -136,8 +137,8 @@ handle_count(Client *client, int argc, char *argv[]) return COMMAND_RETURN_ERROR; } - GError *error = NULL; - return searchStatsForSongsIn(client, "", &filter, &error) + Error error; + return searchStatsForSongsIn(client, "", &filter, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -150,8 +151,8 @@ handle_listall(Client *client, gcc_unused int argc, char *argv[]) if (argc == 2) directory = argv[1]; - GError *error = NULL; - return printAllIn(client, directory, &error) + Error error; + return printAllIn(client, directory, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -194,9 +195,9 @@ handle_list(Client *client, int argc, char *argv[]) } else filter = nullptr; - GError *error = NULL; + Error error; enum command_return ret = - listAllUniqueTags(client, tagType, filter, &error) + listAllUniqueTags(client, tagType, filter, error) ? COMMAND_RETURN_OK : print_error(client, error); @@ -213,8 +214,8 @@ handle_listallinfo(Client *client, gcc_unused int argc, char *argv[]) if (argc == 2) directory = argv[1]; - GError *error = NULL; - return printInfoForAllIn(client, directory, &error) + Error error; + return printInfoForAllIn(client, directory, error) ? COMMAND_RETURN_OK : print_error(client, error); } diff --git a/src/DatabaseError.cxx b/src/DatabaseError.cxx new file mode 100644 index 000000000..800442b9f --- /dev/null +++ b/src/DatabaseError.cxx @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "DatabaseError.hxx" +#include "util/Domain.hxx" + +const Domain db_domain("db"); diff --git a/src/DatabaseError.hxx b/src/DatabaseError.hxx index 3827daff0..c133ee357 100644 --- a/src/DatabaseError.hxx +++ b/src/DatabaseError.hxx @@ -20,9 +20,7 @@ #ifndef MPD_DB_ERROR_HXX #define MPD_DB_ERROR_HXX -#include "gcc.h" - -#include <glib.h> +class Domain; enum db_error { /** @@ -34,14 +32,6 @@ enum db_error { DB_NOT_FOUND, }; -/** - * Quark for GError.domain; the code is an enum #db_error. - */ -gcc_const -static inline GQuark -db_quark(void) -{ - return g_quark_from_static_string("db"); -} +extern const Domain db_domain; #endif diff --git a/src/DatabaseGlue.cxx b/src/DatabaseGlue.cxx index 70b7acc9e..fb944dacc 100644 --- a/src/DatabaseGlue.cxx +++ b/src/DatabaseGlue.cxx @@ -24,6 +24,7 @@ #include "DatabaseSave.hxx" #include "DatabaseError.hxx" #include "Directory.hxx" +#include "util/Error.hxx" #include "conf.h" extern "C" { @@ -50,7 +51,7 @@ static bool db_is_open; static bool is_simple; bool -DatabaseGlobalInit(const config_param ¶m, GError **error_r) +DatabaseGlobalInit(const config_param ¶m, Error &error) { assert(db == NULL); assert(!db_is_open); @@ -61,12 +62,12 @@ DatabaseGlobalInit(const config_param ¶m, GError **error_r) const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name); if (plugin == NULL) { - g_set_error(error_r, db_quark(), 0, - "No such database plugin: %s", plugin_name); + error.Format(db_domain, + "No such database plugin: %s", plugin_name); return false; } - db = plugin->create(param, error_r); + db = plugin->create(param, error); return db != NULL; } @@ -89,13 +90,12 @@ GetDatabase() } const Database * -GetDatabase(GError **error_r) +GetDatabase(Error &error) { assert(db == nullptr || db_is_open); if (db == nullptr) - g_set_error_literal(error_r, db_quark(), DB_DISABLED, - "No database"); + error.Set(db_domain, DB_DISABLED, "No database"); return db; } @@ -131,17 +131,17 @@ db_get_directory(const char *name) } bool -db_save(GError **error_r) +db_save(Error &error) { assert(db != NULL); assert(db_is_open); assert(db_is_simple()); - return ((SimpleDatabase *)db)->Save(error_r); + return ((SimpleDatabase *)db)->Save(error); } bool -DatabaseGlobalOpen(GError **error) +DatabaseGlobalOpen(Error &error) { assert(db != NULL); assert(!db_is_open); diff --git a/src/DatabaseGlue.hxx b/src/DatabaseGlue.hxx index e321e0ba8..5e23a8c35 100644 --- a/src/DatabaseGlue.hxx +++ b/src/DatabaseGlue.hxx @@ -21,10 +21,10 @@ #define MPD_DATABASE_GLUE_HXX #include "gcc.h" -#include "gerror.h" struct config_param; class Database; +class Error; /** * Initialize the database library. @@ -32,13 +32,13 @@ class Database; * @param param the database configuration block */ bool -DatabaseGlobalInit(const config_param ¶m, GError **error_r); +DatabaseGlobalInit(const config_param ¶m, Error &error); void DatabaseGlobalDeinit(void); bool -DatabaseGlobalOpen(GError **error); +DatabaseGlobalOpen(Error &error); /** * Returns the global #Database instance. May return NULL if this MPD @@ -54,6 +54,6 @@ GetDatabase(); */ gcc_pure const Database * -GetDatabase(GError **error_r); +GetDatabase(Error &error); #endif diff --git a/src/DatabaseHelpers.cxx b/src/DatabaseHelpers.cxx index ecaf44915..f2086e5d2 100644 --- a/src/DatabaseHelpers.cxx +++ b/src/DatabaseHelpers.cxx @@ -61,17 +61,17 @@ bool VisitUniqueTags(const Database &db, const DatabaseSelection &selection, enum tag_type tag_type, VisitString visit_string, - GError **error_r) + Error &error) { StringSet set; using namespace std::placeholders; const auto f = std::bind(CollectTags, std::ref(set), tag_type, _1); - if (!db.Visit(selection, f, error_r)) + if (!db.Visit(selection, f, error)) return false; for (auto value : set) - if (!visit_string(value, error_r)) + if (!visit_string(value, error)) return false; return true; @@ -116,7 +116,7 @@ StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums, bool GetStats(const Database &db, const DatabaseSelection &selection, - DatabaseStats &stats, GError **error_r) + DatabaseStats &stats, Error &error) { stats.Clear(); @@ -125,7 +125,7 @@ GetStats(const Database &db, const DatabaseSelection &selection, const auto f = std::bind(StatsVisitSong, std::ref(stats), std::ref(artists), std::ref(albums), _1); - if (!db.Visit(selection, f, error_r)) + if (!db.Visit(selection, f, error)) return false; stats.artist_count = artists.size(); diff --git a/src/DatabaseHelpers.hxx b/src/DatabaseHelpers.hxx index 5b71fd2fb..479cc37c1 100644 --- a/src/DatabaseHelpers.hxx +++ b/src/DatabaseHelpers.hxx @@ -24,6 +24,7 @@ #include "TagType.h" #include "gcc.h" +class Error; class Database; struct DatabaseSelection; struct DatabaseStats; @@ -32,10 +33,10 @@ bool VisitUniqueTags(const Database &db, const DatabaseSelection &selection, enum tag_type tag_type, VisitString visit_string, - GError **error_r); + Error &error); bool GetStats(const Database &db, const DatabaseSelection &selection, - DatabaseStats &stats, GError **error_r); + DatabaseStats &stats, Error &error); #endif diff --git a/src/DatabasePlaylist.cxx b/src/DatabasePlaylist.cxx index 04d1a490d..8404a39c9 100644 --- a/src/DatabasePlaylist.cxx +++ b/src/DatabasePlaylist.cxx @@ -28,17 +28,17 @@ static bool AddSong(const char *playlist_path_utf8, - Song &song, GError **error_r) + Song &song, Error &error) { - return spl_append_song(playlist_path_utf8, &song, error_r); + return spl_append_song(playlist_path_utf8, &song, error); } bool search_add_to_playlist(const char *uri, const char *playlist_path_utf8, const SongFilter *filter, - GError **error_r) + Error &error) { - const Database *db = GetDatabase(error_r); + const Database *db = GetDatabase(error); if (db == nullptr) return false; @@ -46,5 +46,5 @@ search_add_to_playlist(const char *uri, const char *playlist_path_utf8, using namespace std::placeholders; const auto f = std::bind(AddSong, playlist_path_utf8, _1, _2); - return db->Visit(selection, f, error_r); + return db->Visit(selection, f, error); } diff --git a/src/DatabasePlaylist.hxx b/src/DatabasePlaylist.hxx index 7c6952ffa..d91fe13be 100644 --- a/src/DatabasePlaylist.hxx +++ b/src/DatabasePlaylist.hxx @@ -21,14 +21,14 @@ #define MPD_DATABASE_PLAYLIST_HXX #include "gcc.h" -#include "gerror.h" class SongFilter; +class Error; gcc_nonnull(1,2) bool search_add_to_playlist(const char *uri, const char *path_utf8, const SongFilter *filter, - GError **error_r); + Error &error); #endif diff --git a/src/DatabasePlugin.hxx b/src/DatabasePlugin.hxx index 835244020..c17bff63c 100644 --- a/src/DatabasePlugin.hxx +++ b/src/DatabasePlugin.hxx @@ -34,6 +34,7 @@ struct config_param; struct DatabaseSelection; struct db_visitor; struct Song; +class Error; struct DatabaseStats { /** @@ -73,7 +74,7 @@ public: /** * Open the database. Read it into memory if applicable. */ - virtual bool Open(gcc_unused GError **error_r) { + virtual bool Open(gcc_unused Error &error) { return true; } @@ -90,7 +91,7 @@ public: * directory (UTF-8) */ virtual Song *GetSong(const char *uri_utf8, - GError **error_r) const = 0; + Error &error) const = 0; /** * Mark the song object as "unused". Call this on objects @@ -105,19 +106,19 @@ public: VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, - GError **error_r) const = 0; + Error &error) const = 0; bool Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, - GError **error_r) const { + Error &error) const { return Visit(selection, visit_directory, visit_song, - VisitPlaylist(), error_r); + VisitPlaylist(), error); } bool Visit(const DatabaseSelection &selection, VisitSong visit_song, - GError **error_r) const { - return Visit(selection, VisitDirectory(), visit_song, error_r); + Error &error) const { + return Visit(selection, VisitDirectory(), visit_song, error); } /** @@ -126,11 +127,11 @@ public: virtual bool VisitUniqueTags(const DatabaseSelection &selection, enum tag_type tag_type, VisitString visit_string, - GError **error_r) const = 0; + Error &error) const = 0; virtual bool GetStats(const DatabaseSelection &selection, DatabaseStats &stats, - GError **error_r) const = 0; + Error &error) const = 0; }; struct DatabasePlugin { @@ -140,7 +141,7 @@ struct DatabasePlugin { * Allocates and configures a database. */ Database *(*create)(const config_param ¶m, - GError **error_r); + Error &error); }; #endif diff --git a/src/DatabasePrint.cxx b/src/DatabasePrint.cxx index 1f8999dc3..cc7bee9e2 100644 --- a/src/DatabasePrint.cxx +++ b/src/DatabasePrint.cxx @@ -118,9 +118,9 @@ PrintPlaylistFull(Client *client, bool db_selection_print(Client *client, const DatabaseSelection &selection, - bool full, GError **error_r) + bool full, Error &error) { - const Database *db = GetDatabase(error_r); + const Database *db = GetDatabase(error); if (db == nullptr) return false; @@ -136,7 +136,7 @@ db_selection_print(Client *client, const DatabaseSelection &selection, client, _1, _2) : VisitPlaylist(); - return db->Visit(selection, d, s, p, error_r); + return db->Visit(selection, d, s, p, error); } struct SearchStats { @@ -162,9 +162,9 @@ stats_visitor_song(SearchStats &stats, Song &song) bool searchStatsForSongsIn(Client *client, const char *name, const SongFilter *filter, - GError **error_r) + Error &error) { - const Database *db = GetDatabase(error_r); + const Database *db = GetDatabase(error); if (db == nullptr) return false; @@ -177,7 +177,7 @@ searchStatsForSongsIn(Client *client, const char *name, using namespace std::placeholders; const auto f = std::bind(stats_visitor_song, std::ref(stats), _1); - if (!db->Visit(selection, f, error_r)) + if (!db->Visit(selection, f, error)) return false; printSearchStats(client, &stats); @@ -185,18 +185,18 @@ searchStatsForSongsIn(Client *client, const char *name, } bool -printAllIn(Client *client, const char *uri_utf8, GError **error_r) +printAllIn(Client *client, const char *uri_utf8, Error &error) { const DatabaseSelection selection(uri_utf8, true); - return db_selection_print(client, selection, false, error_r); + return db_selection_print(client, selection, false, error); } bool printInfoForAllIn(Client *client, const char *uri_utf8, - GError **error_r) + Error &error) { const DatabaseSelection selection(uri_utf8, true); - return db_selection_print(client, selection, true, error_r); + return db_selection_print(client, selection, true, error); } static bool @@ -218,9 +218,9 @@ PrintUniqueTag(Client *client, enum tag_type tag_type, bool listAllUniqueTags(Client *client, int type, const SongFilter *filter, - GError **error_r) + Error &error) { - const Database *db = GetDatabase(error_r); + const Database *db = GetDatabase(error); if (db == nullptr) return false; @@ -229,12 +229,12 @@ listAllUniqueTags(Client *client, int type, if (type == LOCATE_TAG_FILE_TYPE) { using namespace std::placeholders; const auto f = std::bind(PrintSongURIVisitor, client, _1); - return db->Visit(selection, f, error_r); + return db->Visit(selection, f, error); } else { using namespace std::placeholders; const auto f = std::bind(PrintUniqueTag, client, (enum tag_type)type, _1); return db->VisitUniqueTags(selection, (enum tag_type)type, - f, error_r); + f, error); } } diff --git a/src/DatabasePrint.hxx b/src/DatabasePrint.hxx index 68551b63c..042d0458e 100644 --- a/src/DatabasePrint.hxx +++ b/src/DatabasePrint.hxx @@ -21,37 +21,37 @@ #define MPD_DB_PRINT_H #include "gcc.h" -#include "gerror.h" class SongFilter; struct DatabaseSelection; struct db_visitor; class Client; +class Error; gcc_nonnull(1) bool db_selection_print(Client *client, const DatabaseSelection &selection, - bool full, GError **error_r); + bool full, Error &error); gcc_nonnull(1,2) bool -printAllIn(Client *client, const char *uri_utf8, GError **error_r); +printAllIn(Client *client, const char *uri_utf8, Error &error); gcc_nonnull(1,2) bool printInfoForAllIn(Client *client, const char *uri_utf8, - GError **error_r); + Error &error); gcc_nonnull(1,2) bool searchStatsForSongsIn(Client *client, const char *name, const SongFilter *filter, - GError **error_r); + Error &error); gcc_nonnull(1) bool listAllUniqueTags(Client *client, int type, const SongFilter *filter, - GError **error_r); + Error &error); #endif diff --git a/src/DatabaseQueue.cxx b/src/DatabaseQueue.cxx index 67031b730..79ff004a7 100644 --- a/src/DatabaseQueue.cxx +++ b/src/DatabaseQueue.cxx @@ -23,17 +23,17 @@ #include "DatabaseGlue.hxx" #include "DatabasePlugin.hxx" #include "Partition.hxx" +#include "util/Error.hxx" #include <functional> static bool -AddToQueue(Partition &partition, Song &song, GError **error_r) +AddToQueue(Partition &partition, Song &song, Error &error) { enum playlist_result result = partition.playlist.AppendSong(partition.pc, &song, NULL); if (result != PLAYLIST_RESULT_SUCCESS) { - g_set_error(error_r, playlist_quark(), result, - "Playlist error"); + error.Set(playlist_domain, result, "Playlist error"); return false; } @@ -42,13 +42,13 @@ AddToQueue(Partition &partition, Song &song, GError **error_r) bool AddFromDatabase(Partition &partition, const DatabaseSelection &selection, - GError **error_r) + Error &error) { - const Database *db = GetDatabase(error_r); + const Database *db = GetDatabase(error); if (db == nullptr) return false; using namespace std::placeholders; const auto f = std::bind(AddToQueue, std::ref(partition), _1, _2); - return db->Visit(selection, f, error_r); + return db->Visit(selection, f, error); } diff --git a/src/DatabaseQueue.hxx b/src/DatabaseQueue.hxx index bae5b1f05..86e75a39b 100644 --- a/src/DatabaseQueue.hxx +++ b/src/DatabaseQueue.hxx @@ -20,13 +20,12 @@ #ifndef MPD_DATABASE_QUEUE_HXX #define MPD_DATABASE_QUEUE_HXX -#include "gerror.h" - struct Partition; struct DatabaseSelection; +class Error; bool AddFromDatabase(Partition &partition, const DatabaseSelection &selection, - GError **error_r); + Error &error); #endif diff --git a/src/DatabaseSave.cxx b/src/DatabaseSave.cxx index ff95cf788..4213fb9a0 100644 --- a/src/DatabaseSave.cxx +++ b/src/DatabaseSave.cxx @@ -28,6 +28,7 @@ #include "TagInternal.hxx" #include "Tag.hxx" #include "fs/Path.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -69,7 +70,7 @@ db_save_internal(FILE *fp, const Directory *music_root) } bool -db_load_internal(TextFile &file, Directory *music_root, GError **error) +db_load_internal(TextFile &file, Directory *music_root, Error &error) { char *line; int format = 0; @@ -82,7 +83,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) /* get initial info */ line = file.ReadLine(); if (line == NULL || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) { - g_set_error(error, db_quark(), 0, "Database corrupted"); + error.Set(db_domain, "Database corrupted"); return false; } @@ -94,8 +95,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1); } else if (g_str_has_prefix(line, DIRECTORY_MPD_VERSION)) { if (found_version) { - g_set_error(error, db_quark(), 0, - "Duplicate version line"); + error.Set(db_domain, "Duplicate version line"); return false; } @@ -104,8 +104,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) const char *new_charset; if (found_charset) { - g_set_error(error, db_quark(), 0, - "Duplicate charset line"); + error.Set(db_domain, "Duplicate charset line"); return false; } @@ -115,44 +114,43 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) const std::string &old_charset = Path::GetFSCharset(); if (!old_charset.empty() && strcmp(new_charset, old_charset.c_str())) { - g_set_error(error, db_quark(), 0, - "Existing database has charset " - "\"%s\" instead of \"%s\"; " - "discarding database file", - new_charset, old_charset.c_str()); + error.Format(db_domain, + "Existing database has charset " + "\"%s\" instead of \"%s\"; " + "discarding database file", + new_charset, old_charset.c_str()); return false; } } else if (g_str_has_prefix(line, DB_TAG_PREFIX)) { const char *name = line + sizeof(DB_TAG_PREFIX) - 1; enum tag_type tag = tag_name_parse(name); if (tag == TAG_NUM_OF_ITEM_TYPES) { - g_set_error(error, db_quark(), 0, - "Unrecognized tag '%s', " - "discarding database file", - name); + error.Format(db_domain, + "Unrecognized tag '%s', " + "discarding database file", + name); return false; } tags[tag] = true; } else { - g_set_error(error, db_quark(), 0, - "Malformed line: %s", line); + error.Format(db_domain, "Malformed line: %s", line); return false; } } if (format != DB_FORMAT) { - g_set_error(error, db_quark(), 0, - "Database format mismatch, " - "discarding database file"); + error.Set(db_domain, + "Database format mismatch, " + "discarding database file"); return false; } for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) { if (!ignore_tag_items[i] && !tags[i]) { - g_set_error(error, db_quark(), 0, - "Tag list mismatch, " - "discarding database file"); + error.Set(db_domain, + "Tag list mismatch, " + "discarding database file"); return false; } } diff --git a/src/DatabaseSave.hxx b/src/DatabaseSave.hxx index 40048f261..2410b0a71 100644 --- a/src/DatabaseSave.hxx +++ b/src/DatabaseSave.hxx @@ -20,17 +20,16 @@ #ifndef MPD_DATABASE_SAVE_HXX #define MPD_DATABASE_SAVE_HXX -#include "gerror.h" - #include <stdio.h> struct Directory; class TextFile; +class Error; void db_save_internal(FILE *file, const Directory *root); bool -db_load_internal(TextFile &file, Directory *root, GError **error); +db_load_internal(TextFile &file, Directory *root, Error &error); #endif diff --git a/src/DatabaseSimple.hxx b/src/DatabaseSimple.hxx index c387a64f9..f0223bce2 100644 --- a/src/DatabaseSimple.hxx +++ b/src/DatabaseSimple.hxx @@ -21,7 +21,6 @@ #define MPD_DATABASE_SIMPLE_HXX #include "gcc.h" -#include "gerror.h" #include <sys/time.h> @@ -29,6 +28,7 @@ struct config_param; struct Directory; struct db_selection; struct db_visitor; +class Error; /** * Check whether the default #SimpleDatabasePlugin is used. This @@ -60,7 +60,7 @@ db_get_directory(const char *name); * May only be used if db_is_simple() returns true. */ bool -db_save(GError **error_r); +db_save(Error &error); /** * May only be used if db_is_simple() returns true. diff --git a/src/DatabaseVisitor.hxx b/src/DatabaseVisitor.hxx index e36933d7a..cd6a7c94d 100644 --- a/src/DatabaseVisitor.hxx +++ b/src/DatabaseVisitor.hxx @@ -20,19 +20,18 @@ #ifndef MPD_DATABASE_VISITOR_HXX #define MPD_DATABASE_VISITOR_HXX -#include "gerror.h" - #include <functional> struct Directory; struct Song; struct PlaylistInfo; +class Error; -typedef std::function<bool(const Directory &, GError **)> VisitDirectory; -typedef std::function<bool(struct Song &, GError **)> VisitSong; +typedef std::function<bool(const Directory &, Error &)> VisitDirectory; +typedef std::function<bool(struct Song &, Error &)> VisitSong; typedef std::function<bool(const PlaylistInfo &, const Directory &, - GError **)> VisitPlaylist; + Error &)> VisitPlaylist; -typedef std::function<bool(const char *, GError **)> VisitString; +typedef std::function<bool(const char *, Error &)> VisitString; #endif diff --git a/src/DecoderAPI.cxx b/src/DecoderAPI.cxx index 7286bb52f..d364a3aaa 100644 --- a/src/DecoderAPI.cxx +++ b/src/DecoderAPI.cxx @@ -28,6 +28,7 @@ #include "DecoderInternal.hxx" #include "Song.hxx" #include "InputStream.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -257,8 +258,6 @@ size_t decoder_read(struct decoder *decoder, void *buffer, size_t length) { /* XXX don't allow decoder==NULL */ - GError *error = NULL; - size_t nbytes; assert(decoder == NULL || decoder->dc->state == DECODE_STATE_START || @@ -283,14 +282,13 @@ size_t decoder_read(struct decoder *decoder, is->cond.wait(is->mutex); } - nbytes = input_stream_read(is, buffer, length, &error); - assert(nbytes == 0 || error == NULL); - assert(nbytes > 0 || error != NULL || input_stream_eof(is)); + Error error; + size_t nbytes = input_stream_read(is, buffer, length, error); + assert(nbytes == 0 || !error.IsDefined()); + assert(nbytes > 0 || error.IsDefined() || input_stream_eof(is)); - if (gcc_unlikely(nbytes == 0 && error != nullptr)) { - g_warning("%s", error->message); - g_error_free(error); - } + if (gcc_unlikely(nbytes == 0 && error.IsDefined())) + g_warning("%s", error.GetMessage()); input_stream_unlock(is); @@ -364,7 +362,6 @@ decoder_data(struct decoder *decoder, uint16_t kbit_rate) { struct decoder_control *dc = decoder->dc; - GError *error = NULL; enum decoder_command cmd; assert(dc->state == DECODE_STATE_DECODE); @@ -397,16 +394,17 @@ decoder_data(struct decoder *decoder, } if (dc->in_audio_format != dc->out_audio_format) { + Error error; data = decoder->conv_state.Convert(dc->in_audio_format, data, length, dc->out_audio_format, &length, - &error); + error); if (data == NULL) { /* the PCM conversion has failed - stop playback, since we have no better way to bail out */ - g_warning("%s", error->message); + g_warning("%s", error.GetMessage()); return DECODE_COMMAND_STOP; } } diff --git a/src/DecoderControl.hxx b/src/DecoderControl.hxx index 31c72657b..98492c450 100644 --- a/src/DecoderControl.hxx +++ b/src/DecoderControl.hxx @@ -24,6 +24,7 @@ #include "AudioFormat.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -77,7 +78,7 @@ struct decoder_control { * The object must be freed when this object transitions to * any other state (usually #DECODE_STATE_START). */ - GError *error; + Error error; bool quit; bool seek_error; @@ -218,38 +219,41 @@ struct decoder_control { } /** - * Checks whether an error has occurred, and if so, returns a newly - * allocated copy of the #GError object. + * Checks whether an error has occurred, and if so, returns a + * copy of the #Error object. * * Caller must lock the object. */ - GError *GetError() const { + gcc_pure + Error GetError() const { assert(command == DECODE_COMMAND_NONE); - assert(state != DECODE_STATE_ERROR || error != nullptr); + assert(state != DECODE_STATE_ERROR || error.IsDefined()); - return state == DECODE_STATE_ERROR - ? g_error_copy(error) - : nullptr; + Error result; + if (state == DECODE_STATE_ERROR) + result.Set(error); + return result; } /** * Like dc_get_error(), but locks and unlocks the object. */ - GError *LockGetError() const { + gcc_pure + Error LockGetError() const { Lock(); - GError *result = GetError(); + Error result = GetError(); Unlock(); return result; } /** - * Clear the error condition and free the #GError object (if any). + * Clear the error condition and free the #Error object (if any). * * Caller must lock the object. */ void ClearError() { if (state == DECODE_STATE_ERROR) { - g_error_free(error); + error.Clear(); state = DECODE_STATE_STOP; } } diff --git a/src/DecoderError.cxx b/src/DecoderError.cxx new file mode 100644 index 000000000..a8d3f548d --- /dev/null +++ b/src/DecoderError.cxx @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "DecoderError.hxx" +#include "util/Domain.hxx" + +const Domain decoder_domain("decoder"); diff --git a/src/DecoderError.hxx b/src/DecoderError.hxx index 94b5a964b..9ea74167f 100644 --- a/src/DecoderError.hxx +++ b/src/DecoderError.hxx @@ -20,18 +20,6 @@ #ifndef MPD_DECODER_ERROR_HXX #define MPD_DECODER_ERROR_HXX -#include "gcc.h" - -#include <glib.h> - -/** - * Quark for GError.domain. - */ -gcc_pure -static inline GQuark -decoder_quark(void) -{ - return g_quark_from_static_string("decoder"); -} +extern const class Domain decoder_domain; #endif diff --git a/src/DecoderThread.cxx b/src/DecoderThread.cxx index 8c196cdae..5a44f0453 100644 --- a/src/DecoderThread.cxx +++ b/src/DecoderThread.cxx @@ -32,6 +32,7 @@ #include "InputStream.hxx" #include "DecoderList.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "ApeReplayGain.hxx" #include <glib.h> @@ -72,15 +73,12 @@ decoder_command_finished_locked(struct decoder_control *dc) static struct input_stream * decoder_input_stream_open(struct decoder_control *dc, const char *uri) { - GError *error = NULL; - struct input_stream *is; + Error error; - is = input_stream_open(uri, dc->mutex, dc->cond, &error); + input_stream *is = input_stream_open(uri, dc->mutex, dc->cond, error); if (is == NULL) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } + if (error.IsDefined()) + g_warning("%s", error.GetMessage()); return NULL; } @@ -98,12 +96,10 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri) input_stream_update(is); } - if (!input_stream_check(is, &error)) { + if (!input_stream_check(is, error)) { dc->Unlock(); - g_warning("%s", error->message); - g_error_free(error); - + g_warning("%s", error.GetMessage()); return NULL; } @@ -132,7 +128,10 @@ decoder_stream_decode(const struct decoder_plugin *plugin, return true; /* rewind the stream, so each plugin gets a fresh start */ - input_stream_seek(input_stream, 0, SEEK_SET, NULL); + { + Error error; + input_stream_seek(input_stream, 0, SEEK_SET, error); + } decoder->dc->Unlock(); @@ -411,8 +410,8 @@ decoder_run_song(struct decoder_control *dc, if (allocated != NULL) error_uri = allocated; - dc->error = g_error_new(decoder_quark(), 0, - "Failed to decode %s", error_uri); + dc->error.Format(decoder_domain, + "Failed to decode %s", error_uri); g_free(allocated); } @@ -436,8 +435,7 @@ decoder_run(struct decoder_control *dc) if (uri == NULL) { dc->state = DECODE_STATE_ERROR; - dc->error = g_error_new(decoder_quark(), 0, - "Failed to map song"); + dc->error.Set(decoder_domain, "Failed to map song"); decoder_command_finished_locked(dc); return; diff --git a/src/Directory.cxx b/src/Directory.cxx index 6a0da2597..261d16385 100644 --- a/src/Directory.cxx +++ b/src/Directory.cxx @@ -24,6 +24,7 @@ #include "DatabaseLock.hxx" #include "SongSort.hxx" #include "Song.hxx" +#include "util/Error.hxx" extern "C" { #include "util/list_sort.h" @@ -300,34 +301,34 @@ bool Directory::Walk(bool recursive, const SongFilter *filter, VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, - GError **error_r) const + Error &error) const { - assert(error_r == NULL || *error_r == NULL); + assert(!error.IsDefined()); if (visit_song) { Song *song; directory_for_each_song(song, this) if ((filter == nullptr || filter->Match(*song)) && - !visit_song(*song, error_r)) + !visit_song(*song, error)) return false; } if (visit_playlist) { for (const PlaylistInfo &p : playlists) - if (!visit_playlist(p, *this, error_r)) + if (!visit_playlist(p, *this, error)) return false; } Directory *child; directory_for_each_child(child, this) { if (visit_directory && - !visit_directory(*child, error_r)) + !visit_directory(*child, error)) return false; if (recursive && !child->Walk(recursive, filter, visit_directory, visit_song, visit_playlist, - error_r)) + error)) return false; } diff --git a/src/Directory.hxx b/src/Directory.hxx index 97a16f085..928f04163 100644 --- a/src/Directory.hxx +++ b/src/Directory.hxx @@ -25,7 +25,6 @@ #include "gcc.h" #include "DatabaseVisitor.hxx" #include "PlaylistVector.hxx" -#include "gerror.h" #include <sys/types.h> @@ -47,6 +46,7 @@ struct Song; struct db_visitor; class SongFilter; +class Error; struct Directory { /** @@ -251,7 +251,7 @@ public: bool Walk(bool recursive, const SongFilter *match, VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, - GError **error_r) const; + Error &error) const; }; static inline bool diff --git a/src/DirectorySave.cxx b/src/DirectorySave.cxx index 1dcc36dbf..c00338182 100644 --- a/src/DirectorySave.cxx +++ b/src/DirectorySave.cxx @@ -24,6 +24,8 @@ #include "SongSave.hxx" #include "PlaylistDatabase.hxx" #include "TextFile.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <assert.h> #include <string.h> @@ -33,14 +35,7 @@ #define DIRECTORY_BEGIN "begin: " #define DIRECTORY_END "end: " -/** - * The quark used for GError.domain. - */ -static inline GQuark -directory_quark(void) -{ - return g_quark_from_static_string("directory"); -} +static constexpr Domain directory_domain("directory"); void directory_save(FILE *fp, const Directory *directory) @@ -77,13 +72,13 @@ directory_save(FILE *fp, const Directory *directory) static Directory * directory_load_subdir(TextFile &file, Directory *parent, const char *name, - GError **error_r) + Error &error) { bool success; if (parent->FindChild(name) != nullptr) { - g_set_error(error_r, directory_quark(), 0, - "Duplicate subdirectory '%s'", name); + error.Format(directory_domain, + "Duplicate subdirectory '%s'", name); return NULL; } @@ -91,8 +86,7 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name, const char *line = file.ReadLine(); if (line == NULL) { - g_set_error(error_r, directory_quark(), 0, - "Unexpected end of file"); + error.Set(directory_domain, "Unexpected end of file"); directory->Delete(); return NULL; } @@ -104,21 +98,19 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name, line = file.ReadLine(); if (line == NULL) { - g_set_error(error_r, directory_quark(), 0, - "Unexpected end of file"); + error.Set(directory_domain, "Unexpected end of file"); directory->Delete(); return NULL; } } if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) { - g_set_error(error_r, directory_quark(), 0, - "Malformed line: %s", line); + error.Format(directory_domain, "Malformed line: %s", line); directory->Delete(); return NULL; } - success = directory_load(file, directory, error_r); + success = directory_load(file, directory, error); if (!success) { directory->Delete(); return NULL; @@ -128,7 +120,7 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name, } bool -directory_load(TextFile &file, Directory *directory, GError **error) +directory_load(TextFile &file, Directory *directory, Error &error) { const char *line; @@ -146,8 +138,8 @@ directory_load(TextFile &file, Directory *directory, GError **error) Song *song; if (directory->FindSong(name) != nullptr) { - g_set_error(error, directory_quark(), 0, - "Duplicate song '%s'", name); + error.Format(directory_domain, + "Duplicate song '%s'", name); return false; } @@ -170,8 +162,8 @@ directory_load(TextFile &file, Directory *directory, GError **error) g_free(name); } else { - g_set_error(error, directory_quark(), 0, - "Malformed line: %s", line); + error.Format(directory_domain, + "Malformed line: %s", line); return false; } } diff --git a/src/DirectorySave.hxx b/src/DirectorySave.hxx index f4b4816f7..46a3b4462 100644 --- a/src/DirectorySave.hxx +++ b/src/DirectorySave.hxx @@ -20,17 +20,16 @@ #ifndef MPD_DIRECTORY_SAVE_HXX #define MPD_DIRECTORY_SAVE_HXX -#include "gerror.h" - #include <stdio.h> struct Directory; class TextFile; +class Error; void directory_save(FILE *fp, const Directory *directory); bool -directory_load(TextFile &file, Directory *directory, GError **error); +directory_load(TextFile &file, Directory *directory, Error &error); #endif diff --git a/src/EncoderPlugin.hxx b/src/EncoderPlugin.hxx index 6bb2e1583..1bca66e0a 100644 --- a/src/EncoderPlugin.hxx +++ b/src/EncoderPlugin.hxx @@ -20,8 +20,6 @@ #ifndef MPD_ENCODER_PLUGIN_HXX #define MPD_ENCODER_PLUGIN_HXX -#include "gerror.h" - #include <assert.h> #include <stdbool.h> #include <stddef.h> @@ -30,6 +28,7 @@ struct EncoderPlugin; struct AudioFormat; struct config_param; struct Tag; +class Error; struct Encoder { const EncoderPlugin &plugin; @@ -50,28 +49,28 @@ struct EncoderPlugin { const char *name; Encoder *(*init)(const config_param ¶m, - GError **error); + Error &error); void (*finish)(Encoder *encoder); bool (*open)(Encoder *encoder, AudioFormat &audio_format, - GError **error); + Error &error); void (*close)(Encoder *encoder); - bool (*end)(Encoder *encoder, GError **error); + bool (*end)(Encoder *encoder, Error &error); - bool (*flush)(Encoder *encoder, GError **error); + bool (*flush)(Encoder *encoder, Error &error); - bool (*pre_tag)(Encoder *encoder, GError **error); + bool (*pre_tag)(Encoder *encoder, Error &error); bool (*tag)(Encoder *encoder, const Tag *tag, - GError **error); + Error &error); bool (*write)(Encoder *encoder, const void *data, size_t length, - GError **error); + Error &error); size_t (*read)(Encoder *encoder, void *dest, size_t length); @@ -88,7 +87,7 @@ struct EncoderPlugin { */ static inline Encoder * encoder_init(const EncoderPlugin &plugin, const config_param ¶m, - GError **error_r) + Error &error_r) { return plugin.init(param, error_r); } @@ -123,7 +122,7 @@ encoder_finish(Encoder *encoder) */ static inline bool encoder_open(Encoder *encoder, AudioFormat &audio_format, - GError **error) + Error &error) { assert(!encoder->open); @@ -168,7 +167,7 @@ encoder_close(Encoder *encoder) * @return true on success */ static inline bool -encoder_end(Encoder *encoder, GError **error) +encoder_end(Encoder *encoder, Error &error) { assert(encoder->open); assert(!encoder->end); @@ -192,7 +191,7 @@ encoder_end(Encoder *encoder, GError **error) * @return true on success */ static inline bool -encoder_flush(Encoder *encoder, GError **error) +encoder_flush(Encoder *encoder, Error &error) { assert(encoder->open); assert(!encoder->pre_tag); @@ -216,7 +215,7 @@ encoder_flush(Encoder *encoder, GError **error) * @return true on success */ static inline bool -encoder_pre_tag(Encoder *encoder, GError **error) +encoder_pre_tag(Encoder *encoder, Error &error) { assert(encoder->open); assert(!encoder->pre_tag); @@ -246,7 +245,7 @@ encoder_pre_tag(Encoder *encoder, GError **error) * @return true on success */ static inline bool -encoder_tag(Encoder *encoder, const Tag *tag, GError **error) +encoder_tag(Encoder *encoder, const Tag *tag, Error &error) { assert(encoder->open); assert(!encoder->pre_tag); @@ -274,7 +273,7 @@ encoder_tag(Encoder *encoder, const Tag *tag, GError **error) */ static inline bool encoder_write(Encoder *encoder, const void *data, size_t length, - GError **error) + Error &error) { assert(encoder->open); assert(!encoder->pre_tag); diff --git a/src/FilterConfig.cxx b/src/FilterConfig.cxx index 389afa99d..8a3377c7d 100644 --- a/src/FilterConfig.cxx +++ b/src/FilterConfig.cxx @@ -24,35 +24,31 @@ #include "FilterPlugin.hxx" #include "FilterInternal.hxx" #include "FilterRegistry.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" #include <glib.h> #include <string.h> -static GQuark -filter_quark(void) -{ - return g_quark_from_static_string("filter"); -} - /** * Find the "filter" configuration block for the specified name. * * @param filter_template_name the name of the filter template - * @param error_r space to return an error description + * @param error space to return an error description * @return the configuration block, or NULL if none was configured */ static const struct config_param * -filter_plugin_config(const char *filter_template_name, GError **error_r) +filter_plugin_config(const char *filter_template_name, Error &error) { const struct config_param *param = NULL; while ((param = config_get_next_param(CONF_AUDIO_FILTER, param)) != NULL) { const char *name = param->GetBlockValue("name"); if (name == NULL) { - g_set_error(error_r, filter_quark(), 1, - "filter configuration without 'name' name in line %d", - param->line); + error.Format(config_domain, + "filter configuration without 'name' name in line %d", + param->line); return NULL; } @@ -60,10 +56,9 @@ filter_plugin_config(const char *filter_template_name, GError **error_r) return param; } - g_set_error(error_r, filter_quark(), 1, - "filter template not found: %s", - filter_template_name); - + error.Format(config_domain, + "filter template not found: %s", + filter_template_name); return NULL; } @@ -73,11 +68,11 @@ filter_plugin_config(const char *filter_template_name, GError **error_r) * configured filter sections. * @param chain the chain to append filters on * @param spec the filter chain specification - * @param error_r space to return an error description + * @param error space to return an error description * @return the number of filters which were successfully added */ unsigned int -filter_chain_parse(Filter &chain, const char *spec, GError **error_r) +filter_chain_parse(Filter &chain, const char *spec, Error &error) { // Split on comma @@ -92,14 +87,14 @@ filter_chain_parse(Filter &chain, const char *spec, GError **error_r) g_strstrip(*template_names); const struct config_param *cfg = - filter_plugin_config(*template_names, error_r); + filter_plugin_config(*template_names, error); if (cfg == NULL) { // The error has already been set, just stop. break; } // Instantiate one of those filter plugins with the template name as a hint - Filter *f = filter_configured_new(*cfg, error_r); + Filter *f = filter_configured_new(*cfg, error); if (f == NULL) { // The error has already been set, just stop. break; diff --git a/src/FilterConfig.hxx b/src/FilterConfig.hxx index bad186354..3e6553b8d 100644 --- a/src/FilterConfig.hxx +++ b/src/FilterConfig.hxx @@ -25,9 +25,8 @@ #ifndef MPD_FILTER_CONFIG_HXX #define MPD_FILTER_CONFIG_HXX -#include "gerror.h" - class Filter; +class Error; /** * Builds a filter chain from a configuration string on the form @@ -39,6 +38,6 @@ class Filter; * @return the number of filters which were successfully added */ unsigned int -filter_chain_parse(Filter &chain, const char *spec, GError **error_r); +filter_chain_parse(Filter &chain, const char *spec, Error &error); #endif diff --git a/src/FilterInternal.hxx b/src/FilterInternal.hxx index 103687b61..ab648af1e 100644 --- a/src/FilterInternal.hxx +++ b/src/FilterInternal.hxx @@ -25,7 +25,10 @@ #ifndef MPD_FILTER_INTERNAL_HXX #define MPD_FILTER_INTERNAL_HXX +#include <stddef.h> + struct AudioFormat; +class Error; class Filter { public: @@ -43,7 +46,7 @@ public: * @return the format of outgoing data or * AudioFormat::Undefined() on error */ - virtual AudioFormat Open(AudioFormat &af, GError **error_r) = 0; + virtual AudioFormat Open(AudioFormat &af, Error &error) = 0; /** * Closes the filter. After that, you may call Open() again. @@ -65,7 +68,7 @@ public: */ virtual const void *FilterPCM(const void *src, size_t src_size, size_t *dest_size_r, - GError **error_r) = 0; + Error &error) = 0; }; #endif diff --git a/src/FilterPlugin.cxx b/src/FilterPlugin.cxx index 076056fbe..e9f256090 100644 --- a/src/FilterPlugin.cxx +++ b/src/FilterPlugin.cxx @@ -22,40 +22,38 @@ #include "FilterInternal.hxx" #include "FilterRegistry.hxx" #include "conf.h" -#include "ConfigQuark.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" #include <assert.h> Filter * filter_new(const struct filter_plugin *plugin, - const config_param ¶m, GError **error_r) + const config_param ¶m, Error &error) { assert(plugin != NULL); - assert(error_r == NULL || *error_r == NULL); + assert(!error.IsDefined()); - return plugin->init(param, error_r); + return plugin->init(param, error); } Filter * -filter_configured_new(const config_param ¶m, GError **error_r) +filter_configured_new(const config_param ¶m, Error &error) { - const struct filter_plugin *plugin; - - assert(error_r == NULL || *error_r == NULL); + assert(!error.IsDefined()); const char *plugin_name = param.GetBlockValue("plugin"); if (plugin_name == NULL) { - g_set_error(error_r, config_quark(), 0, - "No filter plugin specified"); + error.Set(config_domain, "No filter plugin specified"); return NULL; } - plugin = filter_plugin_by_name(plugin_name); + const filter_plugin *plugin = filter_plugin_by_name(plugin_name); if (plugin == NULL) { - g_set_error(error_r, config_quark(), 0, - "No such filter plugin: %s", plugin_name); + error.Format(config_domain, + "No such filter plugin: %s", plugin_name); return NULL; } - return filter_new(plugin, param, error_r); + return filter_new(plugin, param, error); } diff --git a/src/FilterPlugin.hxx b/src/FilterPlugin.hxx index af1e2f699..88c786120 100644 --- a/src/FilterPlugin.hxx +++ b/src/FilterPlugin.hxx @@ -26,12 +26,9 @@ #ifndef MPD_FILTER_PLUGIN_HXX #define MPD_FILTER_PLUGIN_HXX -#include "gerror.h" - -#include <stddef.h> - struct config_param; class Filter; +class Error; struct filter_plugin { const char *name; @@ -39,7 +36,7 @@ struct filter_plugin { /** * Allocates and configures a filter. */ - Filter *(*init)(const config_param ¶m, GError **error_r); + Filter *(*init)(const config_param ¶m, Error &error); }; /** @@ -53,7 +50,7 @@ struct filter_plugin { */ Filter * filter_new(const struct filter_plugin *plugin, - const config_param ¶m, GError **error_r); + const config_param ¶m, Error &error); /** * Creates a new filter, loads configuration and the plugin name from @@ -65,6 +62,6 @@ filter_new(const struct filter_plugin *plugin, * @return a new filter object, or NULL on error */ Filter * -filter_configured_new(const config_param ¶m, GError **error_r); +filter_configured_new(const config_param ¶m, Error &error); #endif diff --git a/src/InotifySource.cxx b/src/InotifySource.cxx index 9a2d4d46d..c6f0ae4db 100644 --- a/src/InotifySource.cxx +++ b/src/InotifySource.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "InotifySource.hxx" #include "util/fifo_buffer.h" +#include "util/Error.hxx" #include "system/fd_util.h" #include "system/FatalError.hxx" @@ -32,15 +33,6 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "inotify" -/** - * A GQuark for GError instances. - */ -static inline GQuark -mpd_inotify_quark(void) -{ - return g_quark_from_static_string("inotify"); -} - bool InotifySource::OnSocketReady(gcc_unused unsigned flags) { @@ -97,13 +89,11 @@ InotifySource::InotifySource(EventLoop &_loop, InotifySource * InotifySource::Create(EventLoop &loop, mpd_inotify_callback_t callback, void *callback_ctx, - GError **error_r) + Error &error) { int fd = inotify_init_cloexec(); if (fd < 0) { - g_set_error(error_r, mpd_inotify_quark(), errno, - "inotify_init() has failed: %s", - g_strerror(errno)); + error.SetErrno("inotify_init() has failed"); return NULL; } @@ -116,13 +106,11 @@ InotifySource::~InotifySource() } int -InotifySource::Add(const char *path_fs, unsigned mask, GError **error_r) +InotifySource::Add(const char *path_fs, unsigned mask, Error &error) { int wd = inotify_add_watch(Get(), path_fs, mask); if (wd < 0) - g_set_error(error_r, mpd_inotify_quark(), errno, - "inotify_add_watch() has failed: %s", - g_strerror(errno)); + error.SetErrno("inotify_add_watch() has failed"); return wd; } diff --git a/src/InotifySource.hxx b/src/InotifySource.hxx index e8f9ff03c..2f686d3b1 100644 --- a/src/InotifySource.hxx +++ b/src/InotifySource.hxx @@ -21,9 +21,10 @@ #define MPD_INOTIFY_SOURCE_HXX #include "event/SocketMonitor.hxx" -#include "gerror.h" #include "gcc.h" +class Error; + typedef void (*mpd_inotify_callback_t)(int wd, unsigned mask, const char *name, void *ctx); @@ -46,7 +47,7 @@ public: static InotifySource *Create(EventLoop &_loop, mpd_inotify_callback_t callback, void *ctx, - GError **error_r); + Error &error); ~InotifySource(); @@ -56,7 +57,7 @@ public: * * @return a watch descriptor or -1 on error */ - int Add(const char *path_fs, unsigned mask, GError **error_r); + int Add(const char *path_fs, unsigned mask, Error &error); /** * Removes a path from the notify list. diff --git a/src/InotifyUpdate.cxx b/src/InotifyUpdate.cxx index 95c8317c8..cccb9650c 100644 --- a/src/InotifyUpdate.cxx +++ b/src/InotifyUpdate.cxx @@ -24,6 +24,7 @@ #include "Mapper.hxx" #include "Main.hxx" #include "fs/Path.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -162,7 +163,7 @@ static void recursive_watch_subdirectories(WatchDirectory *directory, const char *path_fs, unsigned depth) { - GError *error = NULL; + Error error; DIR *dir; struct dirent *ent; @@ -204,12 +205,11 @@ recursive_watch_subdirectories(WatchDirectory *directory, continue; } - ret = inotify_source->Add(child_path_fs, IN_MASK, &error); + ret = inotify_source->Add(child_path_fs, IN_MASK, error); if (ret < 0) { g_warning("Failed to register %s: %s", - child_path_fs, error->message); - g_error_free(error); - error = NULL; + child_path_fs, error.GetMessage()); + error.Clear(); g_free(child_path_fs); continue; } @@ -309,8 +309,6 @@ mpd_inotify_callback(int wd, unsigned mask, void mpd_inotify_init(unsigned max_depth) { - GError *error = NULL; - g_debug("initializing inotify"); const Path &path = mapper_get_music_directory_fs(); @@ -319,21 +317,20 @@ mpd_inotify_init(unsigned max_depth) return; } + Error error; inotify_source = InotifySource::Create(*main_loop, mpd_inotify_callback, nullptr, - &error); + error); if (inotify_source == NULL) { - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); return; } inotify_max_depth = max_depth; - int descriptor = inotify_source->Add(path.c_str(), IN_MASK, &error); + int descriptor = inotify_source->Add(path.c_str(), IN_MASK, error); if (descriptor < 0) { - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); delete inotify_source; inotify_source = NULL; return; diff --git a/src/InputInit.cxx b/src/InputInit.cxx index f6e40a6f9..01ed57d5a 100644 --- a/src/InputInit.cxx +++ b/src/InputInit.cxx @@ -21,16 +21,14 @@ #include "InputInit.hxx" #include "InputRegistry.hxx" #include "InputPlugin.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "conf.h" #include <assert.h> #include <string.h> -static inline GQuark -input_quark(void) -{ - return g_quark_from_static_string("input"); -} +extern constexpr Domain input_domain("input"); /** * Find the "input" configuration block for the specified plugin. @@ -39,16 +37,16 @@ input_quark(void) * @return the configuration block, or NULL if none was configured */ static const struct config_param * -input_plugin_config(const char *plugin_name, GError **error_r) +input_plugin_config(const char *plugin_name, Error &error) { const struct config_param *param = NULL; while ((param = config_get_next_param(CONF_INPUT, param)) != NULL) { const char *name = param->GetBlockValue("plugin"); if (name == NULL) { - g_set_error(error_r, input_quark(), 0, - "input configuration without 'plugin' name in line %d", - param->line); + error.Format(input_domain, + "input configuration without 'plugin' name in line %d", + param->line); return NULL; } @@ -60,12 +58,10 @@ input_plugin_config(const char *plugin_name, GError **error_r) } bool -input_stream_global_init(GError **error_r) +input_stream_global_init(Error &error) { const config_param empty; - GError *error = NULL; - for (unsigned i = 0; input_plugins[i] != NULL; ++i) { const struct input_plugin *plugin = input_plugins[i]; @@ -74,24 +70,21 @@ input_stream_global_init(GError **error_r) assert(plugin->open != NULL); const struct config_param *param = - input_plugin_config(plugin->name, &error); + input_plugin_config(plugin->name, error); if (param == nullptr) { - if (error != nullptr) { - g_propagate_error(error_r, error); + if (error.IsDefined()) return false; - } param = ∅ } else if (!param->GetBlockValue("enabled", true)) /* the plugin is disabled in mpd.conf */ continue; - if (plugin->init == NULL || plugin->init(*param, &error)) + if (plugin->init == NULL || plugin->init(*param, error)) input_plugins_enabled[i] = true; else { - g_propagate_prefixed_error(error_r, error, - "Failed to initialize input plugin '%s': ", - plugin->name); + error.FormatPrefix("Failed to initialize input plugin '%s': ", + plugin->name); return false; } } diff --git a/src/InputInit.hxx b/src/InputInit.hxx index 9d503e5a8..9aa2de41a 100644 --- a/src/InputInit.hxx +++ b/src/InputInit.hxx @@ -20,7 +20,7 @@ #ifndef MPD_INPUT_INIT_HXX #define MPD_INPUT_INIT_HXX -#include "gerror.h" +class Error; /** * Initializes this library and all input_stream implementations. @@ -29,7 +29,7 @@ * ignore errors */ bool -input_stream_global_init(GError **error_r); +input_stream_global_init(Error &error); /** * Deinitializes this library and all input_stream implementations. diff --git a/src/InputLegacy.hxx b/src/InputLegacy.hxx index 53fab3aae..79cb1527a 100644 --- a/src/InputLegacy.hxx +++ b/src/InputLegacy.hxx @@ -31,6 +31,7 @@ struct Tag; struct input_stream; +class Error; /** * Opens a new input stream. You may not access it until the "ready" @@ -48,7 +49,7 @@ gcc_malloc struct input_stream * input_stream_open(const char *uri, Mutex &mutex, Cond &cond, - GError **error_r); + Error &error); /** * Close the input stream and free resources. @@ -66,7 +67,7 @@ input_stream_close(struct input_stream *is); */ gcc_nonnull(1) bool -input_stream_check(struct input_stream *is, GError **error_r); +input_stream_check(struct input_stream *is, Error &error); /** * Update the public attributes. Call before accessing attributes @@ -133,7 +134,7 @@ input_stream_cheap_seeking(const struct input_stream *is); gcc_nonnull(1) bool input_stream_seek(struct input_stream *is, goffset offset, int whence, - GError **error_r); + Error &error); /** * Wrapper for input_stream_seek() which locks and unlocks the @@ -142,7 +143,7 @@ input_stream_seek(struct input_stream *is, goffset offset, int whence, gcc_nonnull(1) bool input_stream_lock_seek(struct input_stream *is, goffset offset, int whence, - GError **error_r); + Error &error); /** * Returns true if the stream has reached end-of-file. @@ -210,7 +211,7 @@ input_stream_available(struct input_stream *is); gcc_nonnull(1, 2) size_t input_stream_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r); + Error &error); /** * Wrapper for input_stream_tag() which locks and unlocks the @@ -219,6 +220,6 @@ input_stream_read(struct input_stream *is, void *ptr, size_t size, gcc_nonnull(1, 2) size_t input_stream_lock_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r); + Error &error); #endif diff --git a/src/InputPlugin.hxx b/src/InputPlugin.hxx index 0b3207c17..df6196f85 100644 --- a/src/InputPlugin.hxx +++ b/src/InputPlugin.hxx @@ -23,10 +23,10 @@ #include "InputLegacy.hxx" #include <stddef.h> -#include <sys/types.h> struct config_param; struct input_stream; +class Error; struct input_plugin { const char *name; @@ -39,7 +39,7 @@ struct input_plugin { * @return true on success, false if the plugin should be * disabled */ - bool (*init)(const config_param ¶m, GError **error_r); + bool (*init)(const config_param ¶m, Error &error); /** * Global deinitialization. Called once before MPD shuts @@ -49,7 +49,7 @@ struct input_plugin { struct input_stream *(*open)(const char *uri, Mutex &mutex, Cond &cond, - GError **error_r); + Error &error); void (*close)(struct input_stream *is); /** @@ -58,7 +58,7 @@ struct input_plugin { * * @return false on error */ - bool (*check)(struct input_stream *is, GError **error_r); + bool (*check)(struct input_stream *is, Error &error); /** * Update the public attributes. Call before access. Can be @@ -79,10 +79,10 @@ struct input_plugin { bool (*available)(struct input_stream *is); size_t (*read)(struct input_stream *is, void *ptr, size_t size, - GError **error_r); + Error &error); bool (*eof)(struct input_stream *is); bool (*seek)(struct input_stream *is, goffset offset, int whence, - GError **error_r); + Error &error); }; #endif diff --git a/src/InputStream.cxx b/src/InputStream.cxx index 872d54fb7..c98797c89 100644 --- a/src/InputStream.cxx +++ b/src/InputStream.cxx @@ -23,29 +23,22 @@ #include "InputPlugin.hxx" #include "input/RewindInputPlugin.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" -#include <glib.h> #include <assert.h> -static inline GQuark -input_quark(void) -{ - return g_quark_from_static_string("input"); -} +static constexpr Domain input_domain("input"); struct input_stream * input_stream_open(const char *url, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { - GError *error = NULL; - - assert(error_r == NULL || *error_r == NULL); - input_plugins_for_each_enabled(plugin) { struct input_stream *is; - is = plugin->open(url, mutex, cond, &error); + is = plugin->open(url, mutex, cond, error); if (is != NULL) { assert(is->plugin.close != NULL); assert(is->plugin.read != NULL); @@ -55,23 +48,21 @@ input_stream_open(const char *url, is = input_rewind_open(is); return is; - } else if (error != NULL) { - g_propagate_error(error_r, error); + } else if (error.IsDefined()) return NULL; - } } - g_set_error(error_r, input_quark(), 0, "Unrecognized URI"); + error.Set(input_domain, "Unrecognized URI"); return NULL; } bool -input_stream_check(struct input_stream *is, GError **error_r) +input_stream_check(struct input_stream *is, Error &error) { assert(is != NULL); return is->plugin.check == NULL || - is->plugin.check(is, error_r); + is->plugin.check(is, error); } void @@ -159,19 +150,19 @@ input_stream_cheap_seeking(const struct input_stream *is) bool input_stream_seek(struct input_stream *is, goffset offset, int whence, - GError **error_r) + Error &error) { assert(is != NULL); if (is->plugin.seek == NULL) return false; - return is->plugin.seek(is, offset, whence, error_r); + return is->plugin.seek(is, offset, whence, error); } bool input_stream_lock_seek(struct input_stream *is, goffset offset, int whence, - GError **error_r) + Error &error) { assert(is != NULL); @@ -179,7 +170,7 @@ input_stream_lock_seek(struct input_stream *is, goffset offset, int whence, return false; const ScopeLock protect(is->mutex); - return input_stream_seek(is, offset, whence, error_r); + return input_stream_seek(is, offset, whence, error); } Tag * @@ -216,23 +207,23 @@ input_stream_available(struct input_stream *is) size_t input_stream_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r) + Error &error) { assert(ptr != NULL); assert(size > 0); - return is->plugin.read(is, ptr, size, error_r); + return is->plugin.read(is, ptr, size, error); } size_t input_stream_lock_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r) + Error &error) { assert(ptr != NULL); assert(size > 0); const ScopeLock protect(is->mutex); - return input_stream_read(is, ptr, size, error_r); + return input_stream_read(is, ptr, size, error); } void input_stream_close(struct input_stream *is) diff --git a/src/Listen.cxx b/src/Listen.cxx index 659ed6bdf..6f6ff3f33 100644 --- a/src/Listen.cxx +++ b/src/Listen.cxx @@ -24,6 +24,7 @@ #include "Client.hxx" #include "conf.h" #include "event/ServerSocket.hxx" +#include "util/Error.hxx" #include <string.h> #include <assert.h> @@ -55,7 +56,7 @@ int listen_port; static bool listen_add_config_param(unsigned int port, const struct config_param *param, - GError **error_r) + Error &error_r) { assert(param != NULL); @@ -69,7 +70,7 @@ listen_add_config_param(unsigned int port, } static bool -listen_systemd_activation(GError **error_r) +listen_systemd_activation(Error &error_r) { #ifdef ENABLE_SYSTEMD_DAEMON int n = sd_listen_fds(true); @@ -93,7 +94,7 @@ listen_systemd_activation(GError **error_r) } bool -listen_global_init(GError **error_r) +listen_global_init(Error &error) { assert(main_loop != nullptr); @@ -101,29 +102,24 @@ listen_global_init(GError **error_r) const struct config_param *param = config_get_next_param(CONF_BIND_TO_ADDRESS, NULL); bool success; - GError *error = NULL; listen_socket = new ClientListener(); - if (listen_systemd_activation(&error)) + if (listen_systemd_activation(error)) return true; - if (error != NULL) { - g_propagate_error(error_r, error); + if (error.IsDefined()) return false; - } if (param != NULL) { /* "bind_to_address" is configured, create listeners for all values */ do { - success = listen_add_config_param(port, param, &error); - if (!success) { + if (!listen_add_config_param(port, param, error)) { delete listen_socket; - g_propagate_prefixed_error(error_r, error, - "Failed to listen on %s (line %i): ", - param->value, param->line); + error.FormatPrefix("Failed to listen on %s (line %i): ", + param->value, param->line); return false; } @@ -134,17 +130,15 @@ listen_global_init(GError **error_r) /* no "bind_to_address" configured, bind the configured port on all interfaces */ - success = listen_socket->AddPort(port, error_r); + success = listen_socket->AddPort(port, error); if (!success) { delete listen_socket; - g_propagate_prefixed_error(error_r, error, - "Failed to listen on *:%d: ", - port); + error.FormatPrefix("Failed to listen on *:%d: ", port); return false; } } - if (!listen_socket->Open(error_r)) { + if (!listen_socket->Open(error)) { delete listen_socket; return false; } diff --git a/src/Listen.hxx b/src/Listen.hxx index 3e2be9e63..a6fdb2f1c 100644 --- a/src/Listen.hxx +++ b/src/Listen.hxx @@ -20,12 +20,12 @@ #ifndef MPD_LISTEN_HXX #define MPD_LISTEN_HXX -#include "gerror.h" +class Error; extern int listen_port; bool -listen_global_init(GError **error_r); +listen_global_init(Error &error); void listen_global_finish(void); diff --git a/src/Log.cxx b/src/Log.cxx index fac5d95f1..667480ce2 100644 --- a/src/Log.cxx +++ b/src/Log.cxx @@ -25,6 +25,8 @@ #include "fs/Path.hxx" #include "fs/FileSystem.hxx" #include "mpd_error.h" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <assert.h> #include <sys/types.h> @@ -51,6 +53,8 @@ #define LOG_DATE_BUF_SIZE 16 #define LOG_DATE_LEN (LOG_DATE_BUF_SIZE - 1) +static constexpr Domain log_domain("log"); + static GLogLevelFlags log_threshold = G_LOG_LEVEL_MESSAGE; static const char *log_charset; @@ -92,7 +96,7 @@ chomp_length(const char *p) } static void -file_log_func(const gchar *log_domain, +file_log_func(const gchar *domain, GLogLevelFlags log_level, const gchar *message, gcc_unused gpointer user_data) { @@ -110,12 +114,12 @@ file_log_func(const gchar *log_domain, } else converted = NULL; - if (log_domain == NULL) - log_domain = ""; + if (domain == nullptr) + domain = ""; fprintf(stderr, "%s%s%s%.*s\n", stdout_mode ? "" : log_date(), - log_domain, *log_domain == 0 ? "" : ": ", + domain, *domain == 0 ? "" : ": ", chomp_length(message), message); g_free(converted); @@ -136,16 +140,15 @@ open_log_file(void) } static bool -log_init_file(unsigned line, GError **error_r) +log_init_file(unsigned line, Error &error) { assert(!out_path.IsNull()); out_fd = open_log_file(); if (out_fd < 0) { const std::string out_path_utf8 = out_path.ToUTF8(); - g_set_error(error_r, log_quark(), errno, - "failed to open log file \"%s\" (config line %u): %s", - out_path_utf8.c_str(), line, g_strerror(errno)); + error.FormatErrno("failed to open log file \"%s\" (config line %u)", + out_path_utf8.c_str(), line); return false; } @@ -181,14 +184,14 @@ glib_to_syslog_level(GLogLevelFlags log_level) } static void -syslog_log_func(const gchar *log_domain, +syslog_log_func(const gchar *domain, GLogLevelFlags log_level, const gchar *message, gcc_unused gpointer user_data) { if (stdout_mode) { /* fall back to the file log function during startup */ - file_log_func(log_domain, log_level, + file_log_func(domain, log_level, message, user_data); return; } @@ -196,11 +199,11 @@ syslog_log_func(const gchar *log_domain, if (log_level > log_threshold) return; - if (log_domain == NULL) - log_domain = ""; + if (domain == nullptr) + domain = ""; syslog(glib_to_syslog_level(log_level), "%s%s%.*s", - log_domain, *log_domain == 0 ? "" : ": ", + domain, *domain == 0 ? "" : ": ", chomp_length(message), message); } @@ -241,7 +244,7 @@ log_early_init(bool verbose) } bool -log_init(bool verbose, bool use_stdout, GError **error_r) +log_init(bool verbose, bool use_stdout, Error &error) { const struct config_param *param; @@ -264,8 +267,8 @@ log_init(bool verbose, bool use_stdout, GError **error_r) log_init_syslog(); return true; #else - g_set_error(error_r, log_quark(), 0, - "config parameter 'log_file' not found"); + error.Set(log_domain, + "config parameter 'log_file' not found"); return false; #endif #ifdef HAVE_SYSLOG @@ -274,9 +277,9 @@ log_init(bool verbose, bool use_stdout, GError **error_r) return true; #endif } else { - out_path = config_get_path(CONF_LOG_FILE, error_r); + out_path = config_get_path(CONF_LOG_FILE, error); return !out_path.IsNull() && - log_init_file(param->line, error_r); + log_init_file(param->line, error); } } } diff --git a/src/Log.hxx b/src/Log.hxx index 55a6a7a31..24cbe5c8d 100644 --- a/src/Log.hxx +++ b/src/Log.hxx @@ -20,16 +20,7 @@ #ifndef MPD_LOG_HXX #define MPD_LOG_HXX -#include "gcc.h" - -#include <glib.h> - -gcc_const -static inline GQuark -log_quark(void) -{ - return g_quark_from_static_string("log"); -} +class Error; /** * Configure a logging destination for daemon startup, before the @@ -43,7 +34,7 @@ void log_early_init(bool verbose); bool -log_init(bool verbose, bool use_stdout, GError **error_r); +log_init(bool verbose, bool use_stdout, Error &error); void log_deinit(void); diff --git a/src/Main.cxx b/src/Main.cxx index e724ebdb5..df06fd45a 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -56,6 +56,7 @@ #include "pcm/PcmResample.hxx" #include "Daemon.hxx" #include "system/FatalError.hxx" +#include "util/Error.hxx" extern "C" { #include "stats.h" @@ -107,15 +108,11 @@ static inline GQuark main_quark() } static bool -glue_daemonize_init(const struct options *options, GError **error_r) +glue_daemonize_init(const struct options *options, Error &error) { - GError *error = NULL; - - Path pid_file = config_get_path(CONF_PID_FILE, &error); - if (pid_file.IsNull() && error != NULL) { - g_propagate_error(error_r, error); + Path pid_file = config_get_path(CONF_PID_FILE, error); + if (pid_file.IsNull() && error.IsDefined()) return false; - } daemonize_init(config_get_string(CONF_USER, NULL), config_get_string(CONF_GROUP, NULL), @@ -128,20 +125,15 @@ glue_daemonize_init(const struct options *options, GError **error_r) } static bool -glue_mapper_init(GError **error_r) +glue_mapper_init(Error &error) { - GError *error = NULL; - Path music_dir = config_get_path(CONF_MUSIC_DIR, &error); - if (music_dir.IsNull() && error != NULL) { - g_propagate_error(error_r, error); + Path music_dir = config_get_path(CONF_MUSIC_DIR, error); + if (music_dir.IsNull() && error.IsDefined()) return false; - } - Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, &error); - if (playlist_dir.IsNull() && error != NULL) { - g_propagate_error(error_r, error); + Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, error); + if (playlist_dir.IsNull() && error.IsDefined()) return false; - } if (music_dir.IsNull()) music_dir = Path::FromUTF8(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC)); @@ -164,9 +156,6 @@ glue_db_init_and_load(void) if (param != NULL && path != NULL) g_message("Found both 'database' and 'db_file' setting - ignoring the latter"); - GError *error = NULL; - bool ret; - if (!mapper_has_music_directory()) { if (param != NULL) g_message("Found database setting without " @@ -185,13 +174,13 @@ glue_db_init_and_load(void) param = allocated; } - if (!DatabaseGlobalInit(*param, &error)) + Error error; + if (!DatabaseGlobalInit(*param, error)) FatalError(error); delete allocated; - ret = DatabaseGlobalOpen(&error); - if (!ret) + if (!DatabaseGlobalOpen(error)) FatalError(error); /* run database update after daemonization? */ @@ -205,36 +194,22 @@ static void glue_sticker_init(void) { #ifdef ENABLE_SQLITE - GError *error = NULL; - Path sticker_file = config_get_path(CONF_STICKER_FILE, &error); - if (sticker_file.IsNull() && error != NULL) + Error error; + Path sticker_file = config_get_path(CONF_STICKER_FILE, error); + if (sticker_file.IsNull() && error.IsDefined()) FatalError(error); - if (!sticker_global_init(std::move(sticker_file), &error)) + if (!sticker_global_init(std::move(sticker_file), error)) FatalError(error); #endif } static bool -glue_state_file_init(GError **error_r) +glue_state_file_init(Error &error) { - GError *error = NULL; - - Path path_fs = config_get_path(CONF_STATE_FILE, &error); - if (path_fs.IsNull()) { - if (error != nullptr) { - g_propagate_error(error_r, error); - return false; - } - - return true; - } - - if (path_fs.IsNull()) { - g_set_error(error_r, main_quark(), 0, - "Failed to convert state file path to FS encoding"); - return false; - } + Path path_fs = config_get_path(CONF_STATE_FILE, error); + if (path_fs.IsNull()) + return !error.IsDefined(); state_file = new StateFile(std::move(path_fs), *instance->partition, *main_loop); @@ -364,7 +339,7 @@ int mpd_main(int argc, char *argv[]) struct options options; clock_t start; bool create_db; - GError *error = NULL; + Error error; bool success; daemonize_close_stdin(); @@ -385,25 +360,22 @@ int mpd_main(int argc, char *argv[]) winsock_init(); config_global_init(); - success = parse_cmdline(argc, argv, &options, &error); + success = parse_cmdline(argc, argv, &options, error); if (!success) { - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); return EXIT_FAILURE; } - if (!glue_daemonize_init(&options, &error)) { - g_warning("%s", error->message); - g_error_free(error); + if (!glue_daemonize_init(&options, error)) { + g_printerr("%s\n", error.GetMessage()); return EXIT_FAILURE; } stats_global_init(); tag_lib_init(); - if (!log_init(options.verbose, options.log_stderr, &error)) { - g_warning("%s", error->message); - g_error_free(error); + if (!log_init(options.verbose, options.log_stderr, error)) { + g_warning("%s", error.GetMessage()); return EXIT_FAILURE; } @@ -415,10 +387,9 @@ int mpd_main(int argc, char *argv[]) const unsigned max_clients = config_get_positive(CONF_MAX_CONN, 10); instance->client_list = new ClientList(max_clients); - success = listen_global_init(&error); + success = listen_global_init(error); if (!success) { - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); return EXIT_FAILURE; } @@ -432,9 +403,8 @@ int mpd_main(int argc, char *argv[]) Path::GlobalInit(); - if (!glue_mapper_init(&error)) { - g_warning("%s", error->message); - g_error_free(error); + if (!glue_mapper_init(error)) { + g_printerr("%s\n", error.GetMessage()); return EXIT_FAILURE; } @@ -445,9 +415,8 @@ int mpd_main(int argc, char *argv[]) archive_plugin_init_all(); #endif - if (!pcm_resample_global_init(&error)) { - g_warning("%s", error->message); - g_error_free(error); + if (!pcm_resample_global_init(error)) { + g_warning("%s", error.GetMessage()); return EXIT_FAILURE; } @@ -466,9 +435,8 @@ int mpd_main(int argc, char *argv[]) client_manager_init(); replay_gain_global_init(); - if (!input_stream_global_init(&error)) { - g_warning("%s", error->message); - g_error_free(error); + if (!input_stream_global_init(error)) { + g_warning("%s", error.GetMessage()); return EXIT_FAILURE; } @@ -494,9 +462,8 @@ int mpd_main(int argc, char *argv[]) FatalError("directory update failed"); } - if (!glue_state_file_init(&error)) { - g_warning("%s", error->message); - g_error_free(error); + if (!glue_state_file_init(error)) { + g_printerr("%s\n", error.GetMessage()); return EXIT_FAILURE; } diff --git a/src/Mapper.hxx b/src/Mapper.hxx index 1d3da3c00..a224b8051 100644 --- a/src/Mapper.hxx +++ b/src/Mapper.hxx @@ -25,7 +25,6 @@ #define MPD_MAPPER_HXX #include "gcc.h" -#include "gerror.h" #define PLAYLIST_FILE_SUFFIX ".m3u" diff --git a/src/MixerAll.cxx b/src/MixerAll.cxx index 5a6235de4..8005655e5 100644 --- a/src/MixerAll.cxx +++ b/src/MixerAll.cxx @@ -25,6 +25,7 @@ #include "OutputAll.hxx" #include "pcm/PcmVolume.hxx" #include "OutputInternal.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -38,7 +39,6 @@ output_mixer_get_volume(unsigned i) { struct audio_output *output; int volume; - GError *error = NULL; assert(i < audio_output_count()); @@ -50,12 +50,11 @@ output_mixer_get_volume(unsigned i) if (mixer == NULL) return -1; - volume = mixer_get_volume(mixer, &error); - if (volume < 0 && error != NULL) { + Error error; + volume = mixer_get_volume(mixer, error); + if (volume < 0 && error.IsDefined()) g_warning("Failed to read mixer for '%s': %s", - output->name, error->message); - g_error_free(error); - } + output->name, error.GetMessage()); return volume; } @@ -85,7 +84,6 @@ output_mixer_set_volume(unsigned i, unsigned volume) { struct audio_output *output; bool success; - GError *error = NULL; assert(i < audio_output_count()); assert(volume <= 100); @@ -98,12 +96,11 @@ output_mixer_set_volume(unsigned i, unsigned volume) if (mixer == NULL) return false; - success = mixer_set_volume(mixer, volume, &error); - if (!success && error != NULL) { + Error error; + success = mixer_set_volume(mixer, volume, error); + if (!success && error.IsDefined()) g_warning("Failed to set mixer for '%s': %s", - output->name, error->message); - g_error_free(error); - } + output->name, error.GetMessage()); return success; } @@ -138,7 +135,7 @@ output_mixer_get_software_volume(unsigned i) if (mixer == NULL || !mixer->IsPlugin(software_mixer_plugin)) return -1; - return mixer_get_volume(mixer, NULL); + return mixer_get_volume(mixer, IgnoreError()); } int @@ -172,6 +169,6 @@ mixer_all_set_software_volume(unsigned volume) struct audio_output *output = audio_output_get(i); if (output->mixer != NULL && output->mixer->plugin == &software_mixer_plugin) - mixer_set_volume(output->mixer, volume, NULL); + mixer_set_volume(output->mixer, volume, IgnoreError()); } } diff --git a/src/MixerControl.cxx b/src/MixerControl.cxx index bbb3ede2c..86db5dde4 100644 --- a/src/MixerControl.cxx +++ b/src/MixerControl.cxx @@ -20,8 +20,7 @@ #include "config.h" #include "MixerControl.hxx" #include "MixerInternal.hxx" - -#include <glib.h> +#include "util/Error.hxx" #include <assert.h> #include <stddef.h> @@ -32,13 +31,13 @@ Mixer * mixer_new(const struct mixer_plugin *plugin, void *ao, const config_param ¶m, - GError **error_r) + Error &error) { Mixer *mixer; assert(plugin != NULL); - mixer = plugin->init(ao, param, error_r); + mixer = plugin->init(ao, param, error); assert(mixer == NULL || mixer->IsPlugin(*plugin)); @@ -59,7 +58,7 @@ mixer_free(Mixer *mixer) } bool -mixer_open(Mixer *mixer, GError **error_r) +mixer_open(Mixer *mixer, Error &error) { bool success; @@ -73,7 +72,7 @@ mixer_open(Mixer *mixer, GError **error_r) else if (mixer->plugin->open == NULL) success = mixer->open = true; else - success = mixer->open = mixer->plugin->open(mixer, error_r); + success = mixer->open = mixer->plugin->open(mixer, error); mixer->failed = !success; @@ -127,26 +126,22 @@ mixer_failed(Mixer *mixer) } int -mixer_get_volume(Mixer *mixer, GError **error_r) +mixer_get_volume(Mixer *mixer, Error &error) { int volume; assert(mixer != NULL); if (mixer->plugin->global && !mixer->failed && - !mixer_open(mixer, error_r)) + !mixer_open(mixer, error)) return -1; const ScopeLock protect(mixer->mutex); if (mixer->open) { - GError *error = NULL; - - volume = mixer->plugin->get_volume(mixer, &error); - if (volume < 0 && error != NULL) { - g_propagate_error(error_r, error); + volume = mixer->plugin->get_volume(mixer, error); + if (volume < 0 && error.IsDefined()) mixer_failed(mixer); - } } else volume = -1; @@ -154,17 +149,17 @@ mixer_get_volume(Mixer *mixer, GError **error_r) } bool -mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) +mixer_set_volume(Mixer *mixer, unsigned volume, Error &error) { assert(mixer != NULL); assert(volume <= 100); if (mixer->plugin->global && !mixer->failed && - !mixer_open(mixer, error_r)) + !mixer_open(mixer, error)) return false; const ScopeLock protect(mixer->mutex); return mixer->open && - mixer->plugin->set_volume(mixer, volume, error_r); + mixer->plugin->set_volume(mixer, volume, error); } diff --git a/src/MixerControl.hxx b/src/MixerControl.hxx index cf609e817..c1ee01eec 100644 --- a/src/MixerControl.hxx +++ b/src/MixerControl.hxx @@ -25,8 +25,7 @@ #ifndef MPD_MIXER_CONTROL_HXX #define MPD_MIXER_CONTROL_HXX -#include "gerror.h" - +class Error; class Mixer; struct mixer_plugin; struct config_param; @@ -34,13 +33,13 @@ struct config_param; Mixer * mixer_new(const struct mixer_plugin *plugin, void *ao, const config_param ¶m, - GError **error_r); + Error &error); void mixer_free(Mixer *mixer); bool -mixer_open(Mixer *mixer, GError **error_r); +mixer_open(Mixer *mixer, Error &error); void mixer_close(Mixer *mixer); @@ -53,9 +52,9 @@ void mixer_auto_close(Mixer *mixer); int -mixer_get_volume(Mixer *mixer, GError **error_r); +mixer_get_volume(Mixer *mixer, Error &error); bool -mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r); +mixer_set_volume(Mixer *mixer, unsigned volume, Error &error); #endif diff --git a/src/MixerPlugin.hxx b/src/MixerPlugin.hxx index e80ae094e..4dd8969b9 100644 --- a/src/MixerPlugin.hxx +++ b/src/MixerPlugin.hxx @@ -27,10 +27,9 @@ #ifndef MPD_MIXER_PLUGIN_HXX #define MPD_MIXER_PLUGIN_HXX -#include "gerror.h" - struct config_param; class Mixer; +class Error; struct mixer_plugin { /** @@ -43,7 +42,7 @@ struct mixer_plugin { * @return a mixer object, or NULL on error */ Mixer *(*init)(void *ao, const config_param ¶m, - GError **error_r); + Error &error); /** * Finish and free mixer data @@ -57,7 +56,7 @@ struct mixer_plugin { * NULL to ignore errors * @return true on success, false on error */ - bool (*open)(Mixer *data, GError **error_r); + bool (*open)(Mixer *data, Error &error); /** * Close mixer device @@ -70,9 +69,9 @@ struct mixer_plugin { * @param error_r location to store the error occurring, or * NULL to ignore errors * @return the current volume (0..100 including) or -1 if - * unavailable or on error (error_r set, mixer will be closed) + * unavailable or on error (error set, mixer will be closed) */ - int (*get_volume)(Mixer *mixer, GError **error_r); + int (*get_volume)(Mixer *mixer, Error &error); /** * Sets the volume. @@ -83,7 +82,7 @@ struct mixer_plugin { * @return true on success, false on error */ bool (*set_volume)(Mixer *mixer, unsigned volume, - GError **error_r); + Error &error); /** * If true, then the mixer is automatically opened, even if diff --git a/src/OtherCommands.cxx b/src/OtherCommands.cxx index 547946e3e..04ccf6d54 100644 --- a/src/OtherCommands.cxx +++ b/src/OtherCommands.cxx @@ -34,6 +34,7 @@ #include "ls.hxx" #include "Volume.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "fs/Path.hxx" extern "C" { @@ -126,8 +127,8 @@ handle_lsinfo(Client *client, int argc, char *argv[]) return COMMAND_RETURN_ERROR; } - GError *error = NULL; - if (!client_allow_file(client, path_fs, &error)) + Error error; + if (!client_allow_file(client, path_fs, error)) return print_error(client, error); Song *song = Song::LoadFile(path_utf8, nullptr); @@ -147,7 +148,8 @@ handle_lsinfo(Client *client, int argc, char *argv[]) return result; if (isRootDirectory(uri)) { - const auto &list = ListPlaylistFiles(NULL); + Error error; + const auto &list = ListPlaylistFiles(error); print_spl_list(client, list); } diff --git a/src/OutputAll.cxx b/src/OutputAll.cxx index 575eb0c70..27a4e42f5 100644 --- a/src/OutputAll.cxx +++ b/src/OutputAll.cxx @@ -27,6 +27,7 @@ #include "MusicPipe.hxx" #include "MusicChunk.hxx" #include "system/FatalError.hxx" +#include "util/Error.hxx" #include "conf.h" #include "notify.hxx" @@ -104,7 +105,7 @@ audio_output_all_init(struct player_control *pc) { const struct config_param *param = NULL; unsigned int i; - GError *error = NULL; + Error error; num_audio_outputs = audio_output_config_count(); audio_outputs = g_new(struct audio_output *, num_audio_outputs); @@ -125,11 +126,12 @@ audio_output_all_init(struct player_control *pc) param = ∅ } - struct audio_output *output = audio_output_new(*param, pc, &error); + audio_output *output = audio_output_new(*param, pc, error); if (output == NULL) { if (param != NULL) FormatFatalError("line %i: %s", - param->line, error->message); + param->line, + error.GetMessage()); else FatalError(error); } @@ -271,7 +273,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode) } bool -audio_output_all_play(struct music_chunk *chunk, GError **error_r) +audio_output_all_play(struct music_chunk *chunk, Error &error) { bool ret; unsigned int i; @@ -284,8 +286,7 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r) ret = audio_output_all_update(); if (!ret) { /* TODO: obtain real error */ - g_set_error(error_r, output_quark(), 0, - "Failed to open audio output"); + error.Set(output_domain, "Failed to open audio output"); return false; } @@ -300,7 +301,7 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r) bool audio_output_all_open(const AudioFormat audio_format, struct music_buffer *buffer, - GError **error_r) + Error &error) { bool ret = false, enabled = false; unsigned int i; @@ -338,12 +339,10 @@ audio_output_all_open(const AudioFormat audio_format, } if (!enabled) - g_set_error(error_r, output_quark(), 0, - "All audio outputs are disabled"); + error.Set(output_domain, "All audio outputs are disabled"); else if (!ret) /* TODO: obtain real error */ - g_set_error(error_r, output_quark(), 0, - "Failed to open audio output"); + error.Set(output_domain, "Failed to open audio output"); if (!ret) /* close all devices if there was an error */ diff --git a/src/OutputAll.hxx b/src/OutputAll.hxx index 10f8196aa..fc27a4c6e 100644 --- a/src/OutputAll.hxx +++ b/src/OutputAll.hxx @@ -27,12 +27,12 @@ #define OUTPUT_ALL_H #include "replay_gain_info.h" -#include "gerror.h" struct AudioFormat; struct music_buffer; struct music_chunk; struct player_control; +class Error; /** * Global initialization: load audio outputs from the configuration @@ -84,7 +84,7 @@ audio_output_all_enable_disable(void); bool audio_output_all_open(AudioFormat audio_format, struct music_buffer *buffer, - GError **error_r); + Error &error); /** * Closes all audio outputs. @@ -111,7 +111,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode); * (all closed then) */ bool -audio_output_all_play(struct music_chunk *chunk, GError **error_r); +audio_output_all_play(struct music_chunk *chunk, Error &error); /** * Checks if the output devices have drained their music pipe, and diff --git a/src/OutputControl.cxx b/src/OutputControl.cxx index b8f3a3ea4..820713593 100644 --- a/src/OutputControl.cxx +++ b/src/OutputControl.cxx @@ -27,6 +27,7 @@ #include "notify.hxx" #include "filter/ReplayGainFilterPlugin.hxx" #include "FilterPlugin.hxx" +#include "util/Error.hxx" #include <assert.h> #include <stdlib.h> @@ -187,13 +188,10 @@ audio_output_open(struct audio_output *ao, open = ao->open; if (open && ao->mixer != NULL) { - GError *error = NULL; - - if (!mixer_open(ao->mixer, &error)) { + Error error; + if (!mixer_open(ao->mixer, error)) g_warning("Failed to open mixer for '%s': %s", - ao->name, error->message); - g_error_free(error); - } + ao->name, error.GetMessage()); } return open; diff --git a/src/OutputError.cxx b/src/OutputError.cxx new file mode 100644 index 000000000..a18bfff23 --- /dev/null +++ b/src/OutputError.cxx @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "OutputError.hxx" +#include "util/Domain.hxx" + +const Domain output_domain("output"); diff --git a/src/OutputError.hxx b/src/OutputError.hxx index e1f91e196..22a11fdbd 100644 --- a/src/OutputError.hxx +++ b/src/OutputError.hxx @@ -20,18 +20,6 @@ #ifndef MPD_OUTPUT_ERROR_HXX #define MPD_OUTPUT_ERROR_HXX -#include "gcc.h" - -#include <glib.h> - -/** - * Quark for GError.domain. - */ -gcc_const -static inline GQuark -output_quark(void) -{ - return g_quark_from_static_string("output"); -} +extern const class Domain output_domain; #endif diff --git a/src/OutputInit.cxx b/src/OutputInit.cxx index 2e50515c8..17fff933a 100644 --- a/src/OutputInit.cxx +++ b/src/OutputInit.cxx @@ -34,6 +34,8 @@ #include "filter/AutoConvertFilterPlugin.hxx" #include "filter/ReplayGainFilterPlugin.hxx" #include "filter/ChainFilterPlugin.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -49,7 +51,7 @@ #define AUDIO_FILTERS "filters" static const struct audio_output_plugin * -audio_output_detect(GError **error) +audio_output_detect(Error &error) { g_warning("Attempt to detect audio output device"); @@ -63,8 +65,7 @@ audio_output_detect(GError **error) return plugin; } - g_set_error(error, output_quark(), 0, - "Unable to detect an audio device"); + error.Set(output_domain, "Unable to detect an audio device"); return NULL; } @@ -99,7 +100,7 @@ audio_output_load_mixer(struct audio_output *ao, const config_param ¶m, const struct mixer_plugin *plugin, Filter &filter_chain, - GError **error_r) + Error &error) { Mixer *mixer; @@ -112,12 +113,12 @@ audio_output_load_mixer(struct audio_output *ao, if (plugin == NULL) return NULL; - return mixer_new(plugin, ao, param, error_r); + return mixer_new(plugin, ao, param, error); case MIXER_TYPE_SOFTWARE: mixer = mixer_new(&software_mixer_plugin, nullptr, config_param(), - nullptr); + IgnoreError()); assert(mixer != NULL); filter_chain_append(filter_chain, "software_mixer", @@ -132,7 +133,7 @@ audio_output_load_mixer(struct audio_output *ao, bool ao_base_init(struct audio_output *ao, const struct audio_output_plugin *plugin, - const config_param ¶m, GError **error_r) + const config_param ¶m, Error &error) { assert(ao != NULL); assert(plugin != NULL); @@ -141,13 +142,11 @@ ao_base_init(struct audio_output *ao, assert(plugin->close != NULL); assert(plugin->play != NULL); - GError *error = NULL; - if (!param.IsNull()) { ao->name = param.GetBlockValue(AUDIO_OUTPUT_NAME); if (ao->name == NULL) { - g_set_error(error_r, output_quark(), 0, - "Missing \"name\" configuration"); + error.Set(config_domain, + "Missing \"name\" configuration"); return false; } @@ -155,7 +154,7 @@ ao_base_init(struct audio_output *ao, if (p != NULL) { bool success = audio_format_parse(ao->config_audio_format, - p, true, error_r); + p, true, error); if (!success) return false; } else @@ -186,25 +185,23 @@ ao_base_init(struct audio_output *ao, if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) { Filter *normalize_filter = filter_new(&normalize_filter_plugin, config_param(), - nullptr); + IgnoreError()); assert(normalize_filter != NULL); filter_chain_append(*ao->filter, "normalize", autoconvert_filter_new(normalize_filter)); } + Error filter_error; filter_chain_parse(*ao->filter, param.GetBlockValue(AUDIO_FILTERS, ""), - &error - ); + filter_error); // It's not really fatal - Part of the filter chain has been set up already // and even an empty one will work (if only with unexpected behaviour) - if (error != NULL) { + if (filter_error.IsDefined()) g_warning("Failed to initialize filter chain for '%s': %s", - ao->name, error->message); - g_error_free(error); - } + ao->name, filter_error.GetMessage()); ao->thread = NULL; ao->command = AO_COMMAND_NONE; @@ -220,7 +217,7 @@ ao_base_init(struct audio_output *ao, static bool audio_output_setup(struct audio_output *ao, const config_param ¶m, - GError **error_r) + Error &error) { /* create the replay_gain filter */ @@ -230,13 +227,14 @@ audio_output_setup(struct audio_output *ao, const config_param ¶m, if (strcmp(replay_gain_handler, "none") != 0) { ao->replay_gain_filter = filter_new(&replay_gain_filter_plugin, - param, NULL); + param, IgnoreError()); assert(ao->replay_gain_filter != NULL); ao->replay_gain_serial = 0; ao->other_replay_gain_filter = filter_new(&replay_gain_filter_plugin, - param, NULL); + param, + IgnoreError()); assert(ao->other_replay_gain_filter != NULL); ao->other_replay_gain_serial = 0; @@ -247,15 +245,13 @@ audio_output_setup(struct audio_output *ao, const config_param ¶m, /* set up the mixer */ - GError *error = NULL; + Error mixer_error; ao->mixer = audio_output_load_mixer(ao, param, ao->plugin->mixer_plugin, - *ao->filter, &error); - if (ao->mixer == NULL && error != NULL) { + *ao->filter, mixer_error); + if (ao->mixer == NULL && mixer_error.IsDefined()) g_warning("Failed to initialize hardware mixer for '%s': %s", - ao->name, error->message); - g_error_free(error); - } + ao->name, mixer_error.GetMessage()); /* use the hardware mixer for replay gain? */ @@ -267,15 +263,15 @@ audio_output_setup(struct audio_output *ao, const config_param ¶m, g_warning("No such mixer for output '%s'", ao->name); } else if (strcmp(replay_gain_handler, "software") != 0 && ao->replay_gain_filter != NULL) { - g_set_error(error_r, output_quark(), 0, - "Invalid \"replay_gain_handler\" value"); + error.Set(config_domain, + "Invalid \"replay_gain_handler\" value"); return false; } /* the "convert" filter must be the last one in the chain */ ao->convert_filter = filter_new(&convert_filter_plugin, config_param(), - nullptr); + IgnoreError()); assert(ao->convert_filter != NULL); filter_chain_append(*ao->filter, "convert", ao->convert_filter); @@ -286,7 +282,7 @@ audio_output_setup(struct audio_output *ao, const config_param ¶m, struct audio_output * audio_output_new(const config_param ¶m, struct player_control *pc, - GError **error_r) + Error &error) { const struct audio_output_plugin *plugin; @@ -295,21 +291,21 @@ audio_output_new(const config_param ¶m, p = param.GetBlockValue(AUDIO_OUTPUT_TYPE); if (p == NULL) { - g_set_error(error_r, output_quark(), 0, - "Missing \"type\" configuration"); + error.Set(config_domain, + "Missing \"type\" configuration"); return nullptr; } plugin = audio_output_plugin_get(p); if (plugin == NULL) { - g_set_error(error_r, output_quark(), 0, - "No such audio output plugin: %s", p); + error.Format(config_domain, + "No such audio output plugin: %s", p); return nullptr; } } else { g_warning("No 'audio_output' defined in config file\n"); - plugin = audio_output_detect(error_r); + plugin = audio_output_detect(error); if (plugin == NULL) return nullptr; @@ -317,11 +313,11 @@ audio_output_new(const config_param ¶m, plugin->name); } - struct audio_output *ao = ao_plugin_init(plugin, param, error_r); + struct audio_output *ao = ao_plugin_init(plugin, param, error); if (ao == NULL) return NULL; - if (!audio_output_setup(ao, param, error_r)) { + if (!audio_output_setup(ao, param, error)) { ao_plugin_finish(ao); return NULL; } diff --git a/src/OutputInternal.hxx b/src/OutputInternal.hxx index 20e48279f..188a56723 100644 --- a/src/OutputInternal.hxx +++ b/src/OutputInternal.hxx @@ -29,6 +29,7 @@ #include <time.h> +class Error; class Filter; struct config_param; @@ -263,12 +264,12 @@ audio_output_command_is_finished(const struct audio_output *ao) struct audio_output * audio_output_new(const config_param ¶m, struct player_control *pc, - GError **error_r); + Error &error); bool ao_base_init(struct audio_output *ao, const struct audio_output_plugin *plugin, - const config_param ¶m, GError **error_r); + const config_param ¶m, Error &error); void ao_base_finish(struct audio_output *ao); diff --git a/src/OutputPlugin.cxx b/src/OutputPlugin.cxx index 7ac97cab9..038523ad9 100644 --- a/src/OutputPlugin.cxx +++ b/src/OutputPlugin.cxx @@ -24,7 +24,7 @@ struct audio_output * ao_plugin_init(const struct audio_output_plugin *plugin, const config_param ¶m, - GError **error) + Error &error) { assert(plugin != NULL); assert(plugin->init != NULL); @@ -39,7 +39,7 @@ ao_plugin_finish(struct audio_output *ao) } bool -ao_plugin_enable(struct audio_output *ao, GError **error_r) +ao_plugin_enable(struct audio_output *ao, Error &error_r) { return ao->plugin->enable != NULL ? ao->plugin->enable(ao, error_r) @@ -55,7 +55,7 @@ ao_plugin_disable(struct audio_output *ao) bool ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error) + Error &error) { return ao->plugin->open(ao, audio_format, error); } @@ -83,7 +83,7 @@ ao_plugin_send_tag(struct audio_output *ao, const Tag *tag) size_t ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error) + Error &error) { return ao->plugin->play(ao, chunk, size, error); } diff --git a/src/OutputPlugin.hxx b/src/OutputPlugin.hxx index 5be476b68..20fd74453 100644 --- a/src/OutputPlugin.hxx +++ b/src/OutputPlugin.hxx @@ -21,13 +21,13 @@ #define MPD_OUTPUT_PLUGIN_HXX #include "gcc.h" -#include "gerror.h" #include <stddef.h> struct config_param; struct AudioFormat; struct Tag; +class Error; /** * A plugin which controls an audio output device. @@ -56,7 +56,7 @@ struct audio_output_plugin { * data */ struct audio_output *(*init)(const config_param ¶m, - GError **error); + Error &error); /** * Free resources allocated by this device. @@ -73,7 +73,7 @@ struct audio_output_plugin { * NULL to ignore errors * @return true on success, false on error */ - bool (*enable)(struct audio_output *data, GError **error_r); + bool (*enable)(struct audio_output *data, Error &error); /** * Disables the device. It is closed before this method is @@ -90,7 +90,7 @@ struct audio_output_plugin { * to ignore errors */ bool (*open)(struct audio_output *data, AudioFormat &audio_format, - GError **error); + Error &error); /** * Close the device. @@ -122,7 +122,7 @@ struct audio_output_plugin { */ size_t (*play)(struct audio_output *data, const void *chunk, size_t size, - GError **error); + Error &error); /** * Wait until the device has finished playing. @@ -169,20 +169,20 @@ gcc_malloc struct audio_output * ao_plugin_init(const struct audio_output_plugin *plugin, const config_param ¶m, - GError **error); + Error &error); void ao_plugin_finish(struct audio_output *ao); bool -ao_plugin_enable(struct audio_output *ao, GError **error_r); +ao_plugin_enable(struct audio_output *ao, Error &error); void ao_plugin_disable(struct audio_output *ao); bool ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format, - GError **error); + Error &error); void ao_plugin_close(struct audio_output *ao); @@ -196,7 +196,7 @@ ao_plugin_send_tag(struct audio_output *ao, const Tag *tag); size_t ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size, - GError **error); + Error &error); void ao_plugin_drain(struct audio_output *ao); diff --git a/src/OutputThread.cxx b/src/OutputThread.cxx index 68c5c2c7b..fb73e158d 100644 --- a/src/OutputThread.cxx +++ b/src/OutputThread.cxx @@ -30,6 +30,7 @@ #include "MusicPipe.hxx" #include "MusicChunk.hxx" #include "system/FatalError.hxx" +#include "util/Error.hxx" #include "gcc.h" #include <glib.h> @@ -55,19 +56,18 @@ static void ao_command_finished(struct audio_output *ao) static bool ao_enable(struct audio_output *ao) { - GError *error = NULL; + Error error; bool success; if (ao->really_enabled) return true; ao->mutex.unlock(); - success = ao_plugin_enable(ao, &error); + success = ao_plugin_enable(ao, error); ao->mutex.lock(); if (!success) { g_warning("Failed to enable \"%s\" [%s]: %s\n", - ao->name, ao->plugin->name, error->message); - g_error_free(error); + ao->name, ao->plugin->name, error.GetMessage()); return false; } @@ -95,7 +95,7 @@ ao_disable(struct audio_output *ao) static AudioFormat ao_filter_open(struct audio_output *ao, AudioFormat &format, - GError **error_r) + Error &error_r) { assert(format.IsValid()); @@ -131,7 +131,7 @@ static void ao_open(struct audio_output *ao) { bool success; - GError *error = NULL; + Error error; struct audio_format_string af_string; assert(!ao->open); @@ -157,11 +157,10 @@ ao_open(struct audio_output *ao) /* open the filter */ const AudioFormat filter_audio_format = - ao_filter_open(ao, ao->in_audio_format, &error); + ao_filter_open(ao, ao->in_audio_format, error); if (!filter_audio_format.IsDefined()) { g_warning("Failed to open filter for \"%s\" [%s]: %s", - ao->name, ao->plugin->name, error->message); - g_error_free(error); + ao->name, ao->plugin->name, error.GetMessage()); ao->fail_timer = g_timer_new(); return; @@ -173,15 +172,14 @@ ao_open(struct audio_output *ao) ao->out_audio_format.ApplyMask(ao->config_audio_format); ao->mutex.unlock(); - success = ao_plugin_open(ao, ao->out_audio_format, &error); + success = ao_plugin_open(ao, ao->out_audio_format, error); ao->mutex.lock(); assert(!ao->open); if (!success) { g_warning("Failed to open \"%s\" [%s]: %s", - ao->name, ao->plugin->name, error->message); - g_error_free(error); + ao->name, ao->plugin->name, error.GetMessage()); ao_filter_close(ao); ao->fail_timer = g_timer_new(); @@ -231,15 +229,14 @@ ao_close(struct audio_output *ao, bool drain) static void ao_reopen_filter(struct audio_output *ao) { - GError *error = NULL; + Error error; ao_filter_close(ao); const AudioFormat filter_audio_format = - ao_filter_open(ao, ao->in_audio_format, &error); + ao_filter_open(ao, ao->in_audio_format, error); if (!filter_audio_format.IsDefined()) { g_warning("Failed to open filter for \"%s\" [%s]: %s", - ao->name, ao->plugin->name, error->message); - g_error_free(error); + ao->name, ao->plugin->name, error.GetMessage()); /* this is a little code duplication fro ao_close(), but we cannot call this function because we must @@ -333,13 +330,12 @@ ao_chunk_data(struct audio_output *ao, const struct music_chunk *chunk, *replay_gain_serial_p = chunk->replay_gain_serial; } - GError *error = NULL; + Error error; data = replay_gain_filter->FilterPCM(data, length, - &length, &error); + &length, error); if (data == NULL) { g_warning("\"%s\" [%s] failed to filter: %s", - ao->name, ao->plugin->name, error->message); - g_error_free(error); + ao->name, ao->plugin->name, error.GetMessage()); return NULL; } } @@ -352,8 +348,6 @@ static const void * ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk, size_t *length_r) { - GError *error = NULL; - size_t length; const void *data = ao_chunk_data(ao, chunk, ao->replay_gain_filter, &ao->replay_gain_serial, &length); @@ -407,11 +401,11 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk, /* apply filter chain */ - data = ao->filter->FilterPCM(data, length, &length, &error); + Error error; + data = ao->filter->FilterPCM(data, length, &length, error); if (data == NULL) { g_warning("\"%s\" [%s] failed to filter: %s", - ao->name, ao->plugin->name, error->message); - g_error_free(error); + ao->name, ao->plugin->name, error.GetMessage()); return NULL; } @@ -422,8 +416,6 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk, static bool ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) { - GError *error = NULL; - assert(ao != NULL); assert(ao->filter != NULL); @@ -448,6 +440,8 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) return false; } + Error error; + while (size > 0 && ao->command == AO_COMMAND_NONE) { size_t nbytes; @@ -455,13 +449,13 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) break; ao->mutex.unlock(); - nbytes = ao_plugin_play(ao, data, size, &error); + nbytes = ao_plugin_play(ao, data, size, error); ao->mutex.lock(); if (nbytes == 0) { /* play()==0 means failure */ g_warning("\"%s\" [%s] failed to play: %s", - ao->name, ao->plugin->name, error->message); - g_error_free(error); + ao->name, ao->plugin->name, + error.GetMessage()); ao_close(ao, false); diff --git a/src/PlayerControl.cxx b/src/PlayerControl.cxx index 357cdfc17..3fd09a8d1 100644 --- a/src/PlayerControl.cxx +++ b/src/PlayerControl.cxx @@ -40,7 +40,6 @@ player_control::player_control(unsigned _buffer_chunks, command(PLAYER_COMMAND_NONE), state(PLAYER_STATE_STOP), error_type(PLAYER_ERROR_NONE), - error(nullptr), next_song(nullptr), cross_fade_seconds(0), mixramp_db(0), @@ -216,16 +215,13 @@ player_control::GetStatus() } void -player_control::SetError(player_error type, GError *_error) +player_control::SetError(player_error type, Error &&_error) { assert(type != PLAYER_ERROR_NONE); - assert(_error != NULL); - - if (error_type != PLAYER_ERROR_NONE) - g_error_free(error); + assert(_error.IsDefined()); error_type = type; - error = _error; + error = std::move(_error); } void @@ -235,7 +231,7 @@ player_control::ClearError() if (error_type != PLAYER_ERROR_NONE) { error_type = PLAYER_ERROR_NONE; - g_error_free(error); + error.Clear(); } Unlock(); @@ -246,7 +242,7 @@ player_control::GetErrorMessage() const { Lock(); char *message = error_type != PLAYER_ERROR_NONE - ? g_strdup(error->message) + ? g_strdup(error.GetMessage()) : NULL; Unlock(); return message; diff --git a/src/PlayerControl.hxx b/src/PlayerControl.hxx index bea2e05eb..498f91143 100644 --- a/src/PlayerControl.hxx +++ b/src/PlayerControl.hxx @@ -23,6 +23,7 @@ #include "AudioFormat.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -127,7 +128,7 @@ struct player_control { * #PLAYER_ERROR_NONE. The object must be freed when this * object transitions back to #PLAYER_ERROR_NONE. */ - GError *error; + Error error; uint16_t bit_rate; AudioFormat audio_format; @@ -262,10 +263,9 @@ struct player_control { * Caller must lock the object. * * @param type the error type; must not be #PLAYER_ERROR_NONE - * @param error detailed error information; must not be NULL; the - * #player_control takes over ownership of this #GError instance + * @param error detailed error information; must be defined. */ - void SetError(player_error type, GError *error); + void SetError(player_error type, Error &&error); void ClearError(); diff --git a/src/PlayerThread.cxx b/src/PlayerThread.cxx index 87b173245..7d8c2b563 100644 --- a/src/PlayerThread.cxx +++ b/src/PlayerThread.cxx @@ -251,10 +251,10 @@ player_wait_for_decoder(struct player *player) player->queued = false; - GError *error = dc->LockGetError(); - if (error != NULL) { + Error error = dc->LockGetError(); + if (error.IsDefined()) { pc->Lock(); - pc->SetError(PLAYER_ERROR_DECODER, error); + pc->SetError(PLAYER_ERROR_DECODER, std::move(error)); pc->next_song->Free(); pc->next_song = NULL; @@ -327,9 +327,9 @@ player_open_output(struct player *player) assert(pc->state == PLAYER_STATE_PLAY || pc->state == PLAYER_STATE_PAUSE); - GError *error = NULL; + Error error; if (audio_output_all_open(player->play_audio_format, player_buffer, - &error)) { + error)) { player->output_open = true; player->paused = false; @@ -341,7 +341,7 @@ player_open_output(struct player *player) return true; } else { - g_warning("%s", error->message); + g_warning("%s", error.GetMessage()); player->output_open = false; @@ -350,7 +350,7 @@ player_open_output(struct player *player) player->paused = true; pc->Lock(); - pc->SetError(PLAYER_ERROR_OUTPUT, error); + pc->SetError(PLAYER_ERROR_OUTPUT, std::move(error)); pc->state = PLAYER_STATE_PAUSE; pc->Unlock(); @@ -377,13 +377,13 @@ player_check_decoder_startup(struct player *player) dc->Lock(); - GError *error = dc->GetError(); - if (error != NULL) { + Error error = dc->GetError(); + if (error.IsDefined()) { /* the decoder failed */ dc->Unlock(); pc->Lock(); - pc->SetError(PLAYER_ERROR_DECODER, error); + pc->SetError(PLAYER_ERROR_DECODER, std::move(error)); pc->Unlock(); return false; @@ -460,11 +460,9 @@ player_send_silence(struct player *player) chunk->length = num_frames * frame_size; memset(chunk->data, 0, chunk->length); - GError *error = NULL; - if (!audio_output_all_play(chunk, &error)) { - g_warning("%s", error->message); - g_error_free(error); - + Error error; + if (!audio_output_all_play(chunk, error)) { + g_warning("%s", error.GetMessage()); music_buffer_return(player_buffer, chunk); return false; } @@ -689,7 +687,7 @@ static bool play_chunk(struct player_control *pc, Song *song, struct music_chunk *chunk, const AudioFormat format, - GError **error_r) + Error &error) { assert(chunk->CheckFormat(format)); @@ -707,7 +705,7 @@ play_chunk(struct player_control *pc, /* send the chunk to the audio outputs */ - if (!audio_output_all_play(chunk, error_r)) + if (!audio_output_all_play(chunk, error)) return false; pc->total_play_time += (double)chunk->length / @@ -822,16 +820,16 @@ play_next_chunk(struct player *player) /* play the current chunk */ - GError *error = NULL; + Error error; if (!play_chunk(player->pc, player->song, chunk, - player->play_audio_format, &error)) { - g_warning("%s", error->message); + player->play_audio_format, error)) { + g_warning("%s", error.GetMessage()); music_buffer_return(player_buffer, chunk); pc->Lock(); - pc->SetError(PLAYER_ERROR_OUTPUT, error); + pc->SetError(PLAYER_ERROR_OUTPUT, std::move(error)); /* pause: the user may resume playback as soon as an audio output becomes available */ diff --git a/src/PlaylistAny.cxx b/src/PlaylistAny.cxx index e77b01467..9070f12a6 100644 --- a/src/PlaylistAny.cxx +++ b/src/PlaylistAny.cxx @@ -22,6 +22,7 @@ #include "PlaylistMapper.hxx" #include "PlaylistRegistry.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "InputLegacy.hxx" #include <assert.h> @@ -39,14 +40,12 @@ playlist_open_remote(const char *uri, Mutex &mutex, Cond &cond, return playlist; } - GError *error = NULL; - struct input_stream *is = input_stream_open(uri, mutex, cond, &error); + Error error; + input_stream *is = input_stream_open(uri, mutex, cond, error); if (is == NULL) { - if (error != NULL) { + if (error.IsDefined()) g_warning("Failed to open %s: %s", - uri, error->message); - g_error_free(error); - } + uri, error.GetMessage()); return NULL; } diff --git a/src/PlaylistCommands.cxx b/src/PlaylistCommands.cxx index faa8b72bb..785267c1d 100644 --- a/src/PlaylistCommands.cxx +++ b/src/PlaylistCommands.cxx @@ -33,6 +33,7 @@ #include "ls.hxx" #include "Playlist.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include <assert.h> #include <stdlib.h> @@ -64,7 +65,7 @@ handle_load(Client *client, int argc, char *argv[]) if (argc < 3) { start_index = 0; - end_index = G_MAXUINT; + end_index = unsigned(-1); } else if (!check_range(client, &start_index, &end_index, argv[2])) return COMMAND_RETURN_ERROR; @@ -77,19 +78,22 @@ handle_load(Client *client, int argc, char *argv[]) if (result != PLAYLIST_RESULT_NO_SUCH_LIST) return print_playlist_result(client, result); - GError *error = NULL; + Error error; if (playlist_load_spl(&client->playlist, client->player_control, argv[1], start_index, end_index, - &error)) + error)) return COMMAND_RETURN_OK; - if (error->domain == playlist_quark() && - error->code == PLAYLIST_RESULT_BAD_NAME) + if (error.IsDomain(playlist_domain) && + error.GetCode() == PLAYLIST_RESULT_BAD_NAME) { /* the message for BAD_NAME is confusing when the client wants to load a playlist file from the music - directory; patch the GError object to show "no such + directory; patch the Error object to show "no such playlist" instead */ - error->code = PLAYLIST_RESULT_NO_SUCH_LIST; + Error error2(playlist_domain, PLAYLIST_RESULT_NO_SUCH_LIST, + error.GetMessage()); + error = std::move(error2); + } return print_error(client, error); } @@ -100,8 +104,8 @@ handle_listplaylist(Client *client, gcc_unused int argc, char *argv[]) if (playlist_file_print(client, argv[1], false)) return COMMAND_RETURN_OK; - GError *error = NULL; - return spl_print(client, argv[1], false, &error) + Error error; + return spl_print(client, argv[1], false, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -113,8 +117,8 @@ handle_listplaylistinfo(Client *client, if (playlist_file_print(client, argv[1], true)) return COMMAND_RETURN_OK; - GError *error = NULL; - return spl_print(client, argv[1], true, &error) + Error error; + return spl_print(client, argv[1], true, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -122,8 +126,8 @@ handle_listplaylistinfo(Client *client, enum command_return handle_rm(Client *client, gcc_unused int argc, char *argv[]) { - GError *error = NULL; - return spl_delete(argv[1], &error) + Error error; + return spl_delete(argv[1], error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -131,8 +135,8 @@ handle_rm(Client *client, gcc_unused int argc, char *argv[]) enum command_return handle_rename(Client *client, gcc_unused int argc, char *argv[]) { - GError *error = NULL; - return spl_rename(argv[1], argv[2], &error) + Error error; + return spl_rename(argv[1], argv[2], error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -146,8 +150,8 @@ handle_playlistdelete(Client *client, if (!check_unsigned(client, &from, argv[2])) return COMMAND_RETURN_ERROR; - GError *error = NULL; - return spl_remove_index(playlist, from, &error) + Error error; + return spl_remove_index(playlist, from, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -163,8 +167,8 @@ handle_playlistmove(Client *client, gcc_unused int argc, char *argv[]) if (!check_unsigned(client, &to, argv[3])) return COMMAND_RETURN_ERROR; - GError *error = NULL; - return spl_move_index(playlist, from, to, &error) + Error error; + return spl_move_index(playlist, from, to, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -172,8 +176,8 @@ handle_playlistmove(Client *client, gcc_unused int argc, char *argv[]) enum command_return handle_playlistclear(Client *client, gcc_unused int argc, char *argv[]) { - GError *error = NULL; - return spl_clear(argv[1], &error) + Error error; + return spl_clear(argv[1], error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -185,7 +189,7 @@ handle_playlistadd(Client *client, gcc_unused int argc, char *argv[]) char *uri = argv[2]; bool success; - GError *error = NULL; + Error error; if (uri_has_scheme(uri)) { if (!uri_supported_scheme(uri)) { command_error(client, ACK_ERROR_NO_EXIST, @@ -193,12 +197,12 @@ handle_playlistadd(Client *client, gcc_unused int argc, char *argv[]) return COMMAND_RETURN_ERROR; } - success = spl_append_uri(uri, playlist, &error); + success = spl_append_uri(uri, playlist, error); } else success = search_add_to_playlist(uri, playlist, nullptr, - &error); + error); - if (!success && error == NULL) { + if (!success && !error.IsDefined()) { command_error(client, ACK_ERROR_NO_EXIST, "directory or file not found"); return COMMAND_RETURN_ERROR; @@ -211,9 +215,9 @@ enum command_return handle_listplaylists(Client *client, gcc_unused int argc, gcc_unused char *argv[]) { - GError *error = NULL; - const auto list = ListPlaylistFiles(&error); - if (list.empty() && error != NULL) + Error error; + const auto list = ListPlaylistFiles(error); + if (list.empty() && error.IsDefined()) return print_error(client, error); print_spl_list(client, list); diff --git a/src/PlaylistDatabase.cxx b/src/PlaylistDatabase.cxx index c5cfc8397..690845a68 100644 --- a/src/PlaylistDatabase.cxx +++ b/src/PlaylistDatabase.cxx @@ -22,15 +22,13 @@ #include "PlaylistVector.hxx" #include "TextFile.hxx" #include "util/StringUtil.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <string.h> #include <stdlib.h> -static GQuark -playlist_database_quark(void) -{ - return g_quark_from_static_string("playlist_database"); -} +static constexpr Domain playlist_database_domain("playlist_database"); void playlist_vector_save(FILE *fp, const PlaylistVector &pv) @@ -44,7 +42,7 @@ playlist_vector_save(FILE *fp, const PlaylistVector &pv) bool playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, - GError **error_r) + Error &error) { PlaylistInfo pm(name, 0); @@ -55,8 +53,8 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, strcmp(line, "playlist_end") != 0) { colon = strchr(line, ':'); if (colon == NULL || colon == line) { - g_set_error(error_r, playlist_database_quark(), 0, - "unknown line in db: %s", line); + error.Format(playlist_database_domain, + "unknown line in db: %s", line); return false; } @@ -66,8 +64,8 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, if (strcmp(line, "mtime") == 0) pm.mtime = strtol(value, NULL, 10); else { - g_set_error(error_r, playlist_database_quark(), 0, - "unknown line in db: %s", line); + error.Format(playlist_database_domain, + "unknown line in db: %s", line); return false; } } diff --git a/src/PlaylistDatabase.hxx b/src/PlaylistDatabase.hxx index a08d623fb..1481f621f 100644 --- a/src/PlaylistDatabase.hxx +++ b/src/PlaylistDatabase.hxx @@ -21,7 +21,6 @@ #define MPD_PLAYLIST_DATABASE_HXX #include "check.h" -#include "gerror.h" #include <stdio.h> @@ -29,12 +28,13 @@ class PlaylistVector; class TextFile; +class Error; void playlist_vector_save(FILE *fp, const PlaylistVector &pv); bool playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, - GError **error_r); + Error &error); #endif diff --git a/src/PlaylistEdit.cxx b/src/PlaylistEdit.cxx index 0d46f66aa..4cb6e4bf3 100644 --- a/src/PlaylistEdit.cxx +++ b/src/PlaylistEdit.cxx @@ -27,6 +27,7 @@ #include "Playlist.hxx" #include "PlayerControl.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "Song.hxx" #include "Idle.hxx" #include "DatabaseGlue.hxx" @@ -110,11 +111,11 @@ playlist::AppendURI(struct player_control &pc, if (uri_has_scheme(uri)) { song = Song::NewRemote(uri); } else { - db = GetDatabase(nullptr); + db = GetDatabase(IgnoreError()); if (db == nullptr) return PLAYLIST_RESULT_NO_SUCH_SONG; - song = db->GetSong(uri, nullptr); + song = db->GetSong(uri, IgnoreError()); if (song == nullptr) return PLAYLIST_RESULT_NO_SUCH_SONG; } diff --git a/src/PlaylistError.cxx b/src/PlaylistError.cxx new file mode 100644 index 000000000..91291f551 --- /dev/null +++ b/src/PlaylistError.cxx @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "PlaylistError.hxx" +#include "util/Domain.hxx" + +const Domain playlist_domain("playlist"); diff --git a/src/PlaylistError.hxx b/src/PlaylistError.hxx index 2750b82ba..7a3dad749 100644 --- a/src/PlaylistError.hxx +++ b/src/PlaylistError.hxx @@ -20,9 +20,7 @@ #ifndef MPD_PLAYLIST_ERROR_HXX #define MPD_PLAYLIST_ERROR_HXX -#include "gcc.h" - -#include <glib.h> +class Domain; enum playlist_result { PLAYLIST_RESULT_SUCCESS, @@ -38,14 +36,6 @@ enum playlist_result { PLAYLIST_RESULT_DISABLED, }; -/** - * Quark for GError.domain; the code is an enum #playlist_result. - */ -gcc_const -static inline GQuark -playlist_quark(void) -{ - return g_quark_from_static_string("playlist"); -} +extern const Domain playlist_domain; #endif diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx index 6541e6598..c05558fe3 100644 --- a/src/PlaylistFile.cxx +++ b/src/PlaylistFile.cxx @@ -25,7 +25,6 @@ #include "DatabasePlugin.hxx" #include "DatabaseGlue.hxx" #include "Song.hxx" -#include "io_error.h" #include "Mapper.hxx" #include "TextFile.hxx" #include "conf.h" @@ -34,6 +33,7 @@ #include "fs/FileSystem.hxx" #include "fs/DirectoryReader.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include <assert.h> #include <sys/types.h> @@ -79,22 +79,20 @@ spl_valid_name(const char *name_utf8) } static const Path & -spl_map(GError **error_r) +spl_map(Error &error) { const Path &path_fs = map_spl_path(); if (path_fs.IsNull()) - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_DISABLED, - "Stored playlists are disabled"); + error.Set(playlist_domain, PLAYLIST_RESULT_DISABLED, + "Stored playlists are disabled"); return path_fs; } static bool -spl_check_name(const char *name_utf8, GError **error_r) +spl_check_name(const char *name_utf8, Error &error) { if (!spl_valid_name(name_utf8)) { - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_BAD_NAME, + error.Set(playlist_domain, PLAYLIST_RESULT_BAD_NAME, "Bad playlist name"); return false; } @@ -103,35 +101,33 @@ spl_check_name(const char *name_utf8, GError **error_r) } static Path -spl_map_to_fs(const char *name_utf8, GError **error_r) +spl_map_to_fs(const char *name_utf8, Error &error) { - if (spl_map(error_r).IsNull() || !spl_check_name(name_utf8, error_r)) + if (spl_map(error).IsNull() || !spl_check_name(name_utf8, error)) return Path::Null(); Path path_fs = map_spl_utf8_to_fs(name_utf8); if (path_fs.IsNull()) - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_BAD_NAME, - "Bad playlist name"); + error.Set(playlist_domain, PLAYLIST_RESULT_BAD_NAME, + "Bad playlist name"); return path_fs; } /** - * Create a GError for the current errno. + * Create an #Error for the current errno. */ static void -playlist_errno(GError **error_r) +playlist_errno(Error &error) { switch (errno) { case ENOENT: - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_NO_SUCH_LIST, - "No such playlist"); + error.Set(playlist_domain, PLAYLIST_RESULT_NO_SUCH_LIST, + "No such playlist"); break; default: - set_error_errno(error_r); + error.SetErrno(); break; } } @@ -168,17 +164,17 @@ LoadPlaylistFileInfo(PlaylistInfo &info, } PlaylistVector -ListPlaylistFiles(GError **error_r) +ListPlaylistFiles(Error &error) { PlaylistVector list; - const Path &parent_path_fs = spl_map(error_r); + const Path &parent_path_fs = spl_map(error); if (parent_path_fs.IsNull()) return list; DirectoryReader reader(parent_path_fs); if (reader.HasFailed()) { - set_error_errno(error_r); + error.SetErrno(); return list; } @@ -194,20 +190,20 @@ ListPlaylistFiles(GError **error_r) static bool SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path, - GError **error_r) + Error &error) { assert(utf8path != NULL); - if (spl_map(error_r).IsNull()) + if (spl_map(error).IsNull()) return false; - const Path path_fs = spl_map_to_fs(utf8path, error_r); + const Path path_fs = spl_map_to_fs(utf8path, error); if (path_fs.IsNull()) return false; FILE *file = FOpen(path_fs, FOpenMode::WriteText); if (file == NULL) { - playlist_errno(error_r); + playlist_errno(error); return false; } @@ -219,20 +215,20 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path, } PlaylistFileContents -LoadPlaylistFile(const char *utf8path, GError **error_r) +LoadPlaylistFile(const char *utf8path, Error &error) { PlaylistFileContents contents; - if (spl_map(error_r).IsNull()) + if (spl_map(error).IsNull()) return contents; - const Path path_fs = spl_map_to_fs(utf8path, error_r); + const Path path_fs = spl_map_to_fs(utf8path, error); if (path_fs.IsNull()) return contents; TextFile file(path_fs); if (file.HasFailed()) { - playlist_errno(error_r); + playlist_errno(error); return contents; } @@ -262,24 +258,20 @@ LoadPlaylistFile(const char *utf8path, GError **error_r) bool spl_move_index(const char *utf8path, unsigned src, unsigned dest, - GError **error_r) + Error &error) { if (src == dest) /* this doesn't check whether the playlist exists, but what the hell.. */ return true; - GError *error = nullptr; - auto contents = LoadPlaylistFile(utf8path, &error); - if (contents.empty() && error != nullptr) { - g_propagate_error(error_r, error); + auto contents = LoadPlaylistFile(utf8path, error); + if (contents.empty() && error.IsDefined()) return false; - } if (src >= contents.size() || dest >= contents.size()) { - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_BAD_RANGE, - "Bad range"); + error.Set(playlist_domain, PLAYLIST_RESULT_BAD_RANGE, + "Bad range"); return false; } @@ -290,25 +282,25 @@ spl_move_index(const char *utf8path, unsigned src, unsigned dest, const auto dest_i = std::next(contents.begin(), dest); contents.insert(dest_i, std::move(value)); - bool result = SavePlaylistFile(contents, utf8path, error_r); + bool result = SavePlaylistFile(contents, utf8path, error); idle_add(IDLE_STORED_PLAYLIST); return result; } bool -spl_clear(const char *utf8path, GError **error_r) +spl_clear(const char *utf8path, Error &error) { - if (spl_map(error_r).IsNull()) + if (spl_map(error).IsNull()) return false; - const Path path_fs = spl_map_to_fs(utf8path, error_r); + const Path path_fs = spl_map_to_fs(utf8path, error); if (path_fs.IsNull()) return false; FILE *file = FOpen(path_fs, FOpenMode::WriteText); if (file == NULL) { - playlist_errno(error_r); + playlist_errno(error); return false; } @@ -319,14 +311,14 @@ spl_clear(const char *utf8path, GError **error_r) } bool -spl_delete(const char *name_utf8, GError **error_r) +spl_delete(const char *name_utf8, Error &error) { - const Path path_fs = spl_map_to_fs(name_utf8, error_r); + const Path path_fs = spl_map_to_fs(name_utf8, error); if (path_fs.IsNull()) return false; if (!RemoveFile(path_fs)) { - playlist_errno(error_r); + playlist_errno(error); return false; } @@ -335,58 +327,53 @@ spl_delete(const char *name_utf8, GError **error_r) } bool -spl_remove_index(const char *utf8path, unsigned pos, GError **error_r) +spl_remove_index(const char *utf8path, unsigned pos, Error &error) { - GError *error = nullptr; - auto contents = LoadPlaylistFile(utf8path, &error); - if (contents.empty() && error != nullptr) { - g_propagate_error(error_r, error); + auto contents = LoadPlaylistFile(utf8path, error); + if (contents.empty() && error.IsDefined()) return false; - } if (pos >= contents.size()) { - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_BAD_RANGE, - "Bad range"); + error.Set(playlist_domain, PLAYLIST_RESULT_BAD_RANGE, + "Bad range"); return false; } contents.erase(std::next(contents.begin(), pos)); - bool result = SavePlaylistFile(contents, utf8path, error_r); + bool result = SavePlaylistFile(contents, utf8path, error); idle_add(IDLE_STORED_PLAYLIST); return result; } bool -spl_append_song(const char *utf8path, Song *song, GError **error_r) +spl_append_song(const char *utf8path, Song *song, Error &error) { - if (spl_map(error_r).IsNull()) + if (spl_map(error).IsNull()) return false; - const Path path_fs = spl_map_to_fs(utf8path, error_r); + const Path path_fs = spl_map_to_fs(utf8path, error); if (path_fs.IsNull()) return false; FILE *file = FOpen(path_fs, FOpenMode::AppendText); if (file == NULL) { - playlist_errno(error_r); + playlist_errno(error); return false; } struct stat st; if (fstat(fileno(file), &st) < 0) { - playlist_errno(error_r); + playlist_errno(error); fclose(file); return false; } if (st.st_size / (MPD_PATH_MAX + 1) >= (off_t)playlist_max_length) { fclose(file); - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_TOO_LARGE, - "Stored playlist is too large"); + error.Set(playlist_domain, PLAYLIST_RESULT_TOO_LARGE, + "Stored playlist is too large"); return false; } @@ -399,23 +386,23 @@ spl_append_song(const char *utf8path, Song *song, GError **error_r) } bool -spl_append_uri(const char *url, const char *utf8file, GError **error_r) +spl_append_uri(const char *url, const char *utf8file, Error &error) { if (uri_has_scheme(url)) { Song *song = Song::NewRemote(url); - bool success = spl_append_song(utf8file, song, error_r); + bool success = spl_append_song(utf8file, song, error); song->Free(); return success; } else { - const Database *db = GetDatabase(error_r); + const Database *db = GetDatabase(error); if (db == nullptr) return false; - Song *song = db->GetSong(url, error_r); + Song *song = db->GetSong(url, error); if (song == nullptr) return false; - bool success = spl_append_song(utf8file, song, error_r); + bool success = spl_append_song(utf8file, song, error); db->ReturnSong(song); return success; } @@ -423,24 +410,22 @@ spl_append_uri(const char *url, const char *utf8file, GError **error_r) static bool spl_rename_internal(const Path &from_path_fs, const Path &to_path_fs, - GError **error_r) + Error &error) { if (!FileExists(from_path_fs)) { - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_NO_SUCH_LIST, - "No such playlist"); + error.Set(playlist_domain, PLAYLIST_RESULT_NO_SUCH_LIST, + "No such playlist"); return false; } if (FileExists(to_path_fs)) { - g_set_error_literal(error_r, playlist_quark(), - PLAYLIST_RESULT_LIST_EXISTS, - "Playlist exists already"); + error.Set(playlist_domain, PLAYLIST_RESULT_LIST_EXISTS, + "Playlist exists already"); return false; } if (!RenameFile(from_path_fs, to_path_fs)) { - playlist_errno(error_r); + playlist_errno(error); return false; } @@ -449,18 +434,18 @@ spl_rename_internal(const Path &from_path_fs, const Path &to_path_fs, } bool -spl_rename(const char *utf8from, const char *utf8to, GError **error_r) +spl_rename(const char *utf8from, const char *utf8to, Error &error) { - if (spl_map(error_r).IsNull()) + if (spl_map(error).IsNull()) return false; - Path from_path_fs = spl_map_to_fs(utf8from, error_r); + Path from_path_fs = spl_map_to_fs(utf8from, error); if (from_path_fs.IsNull()) return false; - Path to_path_fs = spl_map_to_fs(utf8to, error_r); + Path to_path_fs = spl_map_to_fs(utf8to, error); if (to_path_fs.IsNull()) return false; - return spl_rename_internal(from_path_fs, to_path_fs, error_r); + return spl_rename_internal(from_path_fs, to_path_fs, error); } diff --git a/src/PlaylistFile.hxx b/src/PlaylistFile.hxx index 15dfd480d..5040d7406 100644 --- a/src/PlaylistFile.hxx +++ b/src/PlaylistFile.hxx @@ -20,14 +20,13 @@ #ifndef MPD_PLAYLIST_FILE_HXX #define MPD_PLAYLIST_FILE_HXX -#include "gerror.h" - #include <vector> #include <string> struct Song; struct PlaylistInfo; class PlaylistVector; +class Error; typedef std::vector<std::string> PlaylistFileContents; @@ -51,31 +50,31 @@ spl_valid_name(const char *name_utf8); * NULL if an error occurred. */ PlaylistVector -ListPlaylistFiles(GError **error_r); +ListPlaylistFiles(Error &error); PlaylistFileContents -LoadPlaylistFile(const char *utf8path, GError **error_r); +LoadPlaylistFile(const char *utf8path, Error &error); bool spl_move_index(const char *utf8path, unsigned src, unsigned dest, - GError **error_r); + Error &error); bool -spl_clear(const char *utf8path, GError **error_r); +spl_clear(const char *utf8path, Error &error); bool -spl_delete(const char *name_utf8, GError **error_r); +spl_delete(const char *name_utf8, Error &error); bool -spl_remove_index(const char *utf8path, unsigned pos, GError **error_r); +spl_remove_index(const char *utf8path, unsigned pos, Error &error); bool -spl_append_song(const char *utf8path, Song *song, GError **error_r); +spl_append_song(const char *utf8path, Song *song, Error &error); bool -spl_append_uri(const char *file, const char *utf8file, GError **error_r); +spl_append_uri(const char *file, const char *utf8file, Error &error); bool -spl_rename(const char *utf8from, const char *utf8to, GError **error_r); +spl_rename(const char *utf8from, const char *utf8to, Error &error); #endif diff --git a/src/PlaylistPrint.cxx b/src/PlaylistPrint.cxx index 6eb6bf76e..99f882f91 100644 --- a/src/PlaylistPrint.cxx +++ b/src/PlaylistPrint.cxx @@ -32,6 +32,7 @@ #include "Client.hxx" #include "InputLegacy.hxx" #include "Song.hxx" +#include "util/Error.hxx" void playlist_print_uris(Client *client, const struct playlist *playlist) @@ -112,11 +113,11 @@ playlist_print_changes_position(Client *client, static bool PrintSongDetails(Client *client, const char *uri_utf8) { - const Database *db = GetDatabase(nullptr); + const Database *db = GetDatabase(IgnoreError()); if (db == nullptr) return false; - Song *song = db->GetSong(uri_utf8, nullptr); + Song *song = db->GetSong(uri_utf8, IgnoreError()); if (song == nullptr) return false; @@ -127,14 +128,11 @@ PrintSongDetails(Client *client, const char *uri_utf8) bool spl_print(Client *client, const char *name_utf8, bool detail, - GError **error_r) + Error &error) { - GError *error = NULL; - PlaylistFileContents contents = LoadPlaylistFile(name_utf8, &error); - if (contents.empty() && error != nullptr) { - g_propagate_error(error_r, error); + PlaylistFileContents contents = LoadPlaylistFile(name_utf8, error); + if (contents.empty() && error.IsDefined()) return false; - } for (const auto &uri_utf8 : contents) { if (!detail || !PrintSongDetails(client, uri_utf8.c_str())) diff --git a/src/PlaylistPrint.hxx b/src/PlaylistPrint.hxx index 16bee9b85..c8c353d0c 100644 --- a/src/PlaylistPrint.hxx +++ b/src/PlaylistPrint.hxx @@ -20,13 +20,12 @@ #ifndef MPD_PLAYLIST_PRINT_HXX #define MPD_PLAYLIST_PRINT_HXX -#include "gerror.h" - #include <stdint.h> struct playlist; class SongFilter; class Client; +class Error; /** * Sends the whole playlist to the client, song URIs only. @@ -94,7 +93,7 @@ playlist_print_changes_position(Client *client, */ bool spl_print(Client *client, const char *name_utf8, bool detail, - GError **error_r); + Error &error); /** * Send the playlist file to the client. diff --git a/src/PlaylistRegistry.cxx b/src/PlaylistRegistry.cxx index 79fec4bd9..6f3c9aded 100644 --- a/src/PlaylistRegistry.cxx +++ b/src/PlaylistRegistry.cxx @@ -34,6 +34,7 @@ #include "InputLegacy.hxx" #include "util/UriUtil.hxx" #include "util/StringUtil.hxx" +#include "util/Error.hxx" #include "conf.h" #include "mpd_error.h" @@ -219,7 +220,8 @@ playlist_list_open_stream_mime2(struct input_stream *is, const char *mime) string_array_contains(plugin->mime_types, mime)) { /* rewind the stream, so each plugin gets a fresh start */ - input_stream_seek(is, 0, SEEK_SET, NULL); + Error error; + input_stream_seek(is, 0, SEEK_SET, error); playlist = playlist_plugin_open_stream(plugin, is); if (playlist != NULL) @@ -264,7 +266,8 @@ playlist_list_open_stream_suffix(struct input_stream *is, const char *suffix) string_array_contains(plugin->suffixes, suffix)) { /* rewind the stream, so each plugin gets a fresh start */ - input_stream_seek(is, 0, SEEK_SET, NULL); + Error error; + input_stream_seek(is, 0, SEEK_SET, error); playlist = playlist_plugin_open_stream(plugin, is); if (playlist != NULL) @@ -318,9 +321,7 @@ struct playlist_provider * playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, struct input_stream **is_r) { - GError *error = NULL; const char *suffix; - struct input_stream *is; struct playlist_provider *playlist; assert(path_fs != NULL); @@ -329,12 +330,11 @@ playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, if (suffix == NULL || !playlist_suffix_supported(suffix)) return NULL; - is = input_stream_open(path_fs, mutex, cond, &error); + Error error; + input_stream *is = input_stream_open(path_fs, mutex, cond, error); if (is == NULL) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } + if (error.IsDefined()) + g_warning("%s", error.GetMessage()); return NULL; } diff --git a/src/PlaylistSave.cxx b/src/PlaylistSave.cxx index b259b1f3d..efcf03402 100644 --- a/src/PlaylistSave.cxx +++ b/src/PlaylistSave.cxx @@ -27,6 +27,7 @@ #include "fs/Path.hxx" #include "fs/FileSystem.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -99,14 +100,11 @@ bool playlist_load_spl(struct playlist *playlist, struct player_control *pc, const char *name_utf8, unsigned start_index, unsigned end_index, - GError **error_r) + Error &error) { - GError *error = NULL; - PlaylistFileContents contents = LoadPlaylistFile(name_utf8, &error); - if (contents.empty() && error != nullptr) { - g_propagate_error(error_r, error); + PlaylistFileContents contents = LoadPlaylistFile(name_utf8, error); + if (contents.empty() && error.IsDefined()) return false; - } if (end_index > contents.size()) end_index = contents.size(); diff --git a/src/PlaylistSave.hxx b/src/PlaylistSave.hxx index 075ef2ea1..f85558755 100644 --- a/src/PlaylistSave.hxx +++ b/src/PlaylistSave.hxx @@ -28,6 +28,7 @@ struct Song; struct queue; struct playlist; struct player_control; +class Error; void playlist_print_song(FILE *fp, const Song *song); @@ -55,6 +56,6 @@ bool playlist_load_spl(struct playlist *playlist, struct player_control *pc, const char *name_utf8, unsigned start_index, unsigned end_index, - GError **error_r); + Error &error); #endif diff --git a/src/PlaylistSong.cxx b/src/PlaylistSong.cxx index 5de1f5c8c..f4c5b7478 100644 --- a/src/PlaylistSong.cxx +++ b/src/PlaylistSong.cxx @@ -26,6 +26,7 @@ #include "Tag.hxx" #include "fs/Path.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "Song.hxx" #include <glib.h> @@ -102,11 +103,11 @@ playlist_check_load_song(const Song *song, const char *uri, bool secure) if (dest == NULL) return NULL; } else { - const Database *db = GetDatabase(nullptr); + const Database *db = GetDatabase(IgnoreError()); if (db == nullptr) return nullptr; - Song *tmp = db->GetSong(uri, nullptr); + Song *tmp = db->GetSong(uri, IgnoreError()); if (tmp == NULL) /* not found in database */ return NULL; diff --git a/src/QueueCommands.cxx b/src/QueueCommands.cxx index 683a88e50..a70a5f250 100644 --- a/src/QueueCommands.cxx +++ b/src/QueueCommands.cxx @@ -32,6 +32,7 @@ #include "protocol/Result.hxx" #include "ls.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "fs/Path.hxx" #include <string.h> @@ -52,8 +53,8 @@ handle_add(Client *client, gcc_unused int argc, char *argv[]) return COMMAND_RETURN_ERROR; } - GError *error = NULL; - if (!client_allow_file(client, path_fs, &error)) + Error error; + if (!client_allow_file(client, path_fs, error)) return print_error(client, error); result = client->partition.AppendFile(path_utf8); @@ -72,8 +73,8 @@ handle_add(Client *client, gcc_unused int argc, char *argv[]) } const DatabaseSelection selection(uri, true); - GError *error = NULL; - return AddFromDatabase(client->partition, selection, &error) + Error error; + return AddFromDatabase(client->partition, selection, error) ? COMMAND_RETURN_OK : print_error(client, error); } @@ -95,8 +96,8 @@ handle_addid(Client *client, int argc, char *argv[]) return COMMAND_RETURN_ERROR; } - GError *error = NULL; - if (!client_allow_file(client, path_fs, &error)) + Error error; + if (!client_allow_file(client, path_fs, error)) return print_error(client, error); result = client->partition.AppendFile(path_utf8, &added_id); diff --git a/src/QueueSave.cxx b/src/QueueSave.cxx index fd00009b1..a9c4b4cff 100644 --- a/src/QueueSave.cxx +++ b/src/QueueSave.cxx @@ -26,6 +26,7 @@ #include "DatabaseGlue.hxx" #include "TextFile.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include <stdlib.h> @@ -90,11 +91,10 @@ queue_load_song(TextFile &file, const char *line, queue *queue) if (!uri_has_scheme(uri) && !g_path_is_absolute(uri)) return; - GError *error = NULL; - song = song_load(file, NULL, uri, &error); + Error error; + song = song_load(file, NULL, uri, error); if (song == NULL) { - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); return; } } else { @@ -110,11 +110,11 @@ queue_load_song(TextFile &file, const char *line, queue *queue) if (uri_has_scheme(uri)) { song = Song::NewRemote(uri); } else { - db = GetDatabase(nullptr); + db = GetDatabase(IgnoreError()); if (db == nullptr) return; - song = db->GetSong(uri, nullptr); + song = db->GetSong(uri, IgnoreError()); if (song == nullptr) return; } diff --git a/src/SongSave.cxx b/src/SongSave.cxx index fcad320df..7b89eccf4 100644 --- a/src/SongSave.cxx +++ b/src/SongSave.cxx @@ -25,6 +25,8 @@ #include "TextFile.hxx" #include "Tag.hxx" #include "util/StringUtil.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> @@ -36,11 +38,7 @@ #define SONG_MTIME "mtime" #define SONG_END "song_end" -static GQuark -song_save_quark(void) -{ - return g_quark_from_static_string("song_save"); -} +static constexpr Domain song_save_domain("song_save"); void song_save(FILE *fp, const Song *song) @@ -61,7 +59,7 @@ song_save(FILE *fp, const Song *song) Song * song_load(TextFile &file, Directory *parent, const char *uri, - GError **error_r) + Error &error) { Song *song = parent != NULL ? Song::NewFile(uri, parent) @@ -78,8 +76,8 @@ song_load(TextFile &file, Directory *parent, const char *uri, song->tag->EndAdd(); song->Free(); - g_set_error(error_r, song_save_quark(), 0, - "unknown line in db: %s", line); + error.Format(song_save_domain, + "unknown line in db: %s", line); return NULL; } @@ -120,8 +118,8 @@ song_load(TextFile &file, Directory *parent, const char *uri, song->tag->EndAdd(); song->Free(); - g_set_error(error_r, song_save_quark(), 0, - "unknown line in db: %s", line); + error.Format(song_save_domain, + "unknown line in db: %s", line); return NULL; } } diff --git a/src/SongSave.hxx b/src/SongSave.hxx index 9fd6ba86c..f18aa9660 100644 --- a/src/SongSave.hxx +++ b/src/SongSave.hxx @@ -20,8 +20,6 @@ #ifndef MPD_SONG_SAVE_HXX #define MPD_SONG_SAVE_HXX -#include "gerror.h" - #include <stdio.h> #define SONG_BEGIN "song_begin: " @@ -29,6 +27,7 @@ struct Song; struct Directory; class TextFile; +class Error; void song_save(FILE *fp, const Song *song); @@ -37,12 +36,11 @@ song_save(FILE *fp, const Song *song); * Loads a song from the input file. Reading stops after the * "song_end" line. * - * @param error_r location to store the error occurring, or NULL to - * ignore errors + * @param error location to store the error occurring * @return true on success, false on error */ Song * song_load(TextFile &file, Directory *parent, const char *uri, - GError **error_r); + Error &error); #endif diff --git a/src/SongSticker.hxx b/src/SongSticker.hxx index 385aa59dc..0f3e0bf41 100644 --- a/src/SongSticker.hxx +++ b/src/SongSticker.hxx @@ -20,8 +20,6 @@ #ifndef MPD_SONG_STICKER_HXX #define MPD_SONG_STICKER_HXX -#include "gerror.h" - struct Song; struct Directory; struct sticker; diff --git a/src/SongUpdate.cxx b/src/SongUpdate.cxx index b0d60b85a..d6f60c5cb 100644 --- a/src/SongUpdate.cxx +++ b/src/SongUpdate.cxx @@ -20,6 +20,7 @@ #include "config.h" /* must be first for large file support */ #include "Song.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "Directory.hxx" #include "Mapper.hxx" #include "fs/Path.hxx" @@ -127,9 +128,10 @@ Song::UpdateFile() /* open the input_stream (if not already open) */ if (is == NULL) { + Error error; is = input_stream_open(path_fs.c_str(), mutex, cond, - NULL); + error); } /* now try the stream_tag() method */ @@ -143,7 +145,8 @@ Song::UpdateFile() delete tag; tag = nullptr; - input_stream_lock_seek(is, 0, SEEK_SET, NULL); + Error error; + input_stream_lock_seek(is, 0, SEEK_SET, error); } } diff --git a/src/Stats.cxx b/src/Stats.cxx index 354d26c59..0f9703674 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -29,6 +29,7 @@ extern "C" { #include "DatabaseGlue.hxx" #include "DatabasePlugin.hxx" #include "DatabaseSimple.hxx" +#include "util/Error.hxx" struct stats stats; @@ -44,19 +45,18 @@ void stats_global_finish(void) void stats_update(void) { - GError *error = nullptr; + Error error; DatabaseStats stats2; const DatabaseSelection selection("", true); - if (GetDatabase()->GetStats(selection, stats2, &error)) { + if (GetDatabase()->GetStats(selection, stats2, error)) { stats.song_count = stats2.song_count; stats.song_duration = stats2.total_duration; stats.artist_count = stats2.artist_count; stats.album_count = stats2.album_count; } else { - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); stats.song_count = 0; stats.song_duration = 0; diff --git a/src/StickerCommands.cxx b/src/StickerCommands.cxx index 5cbb7e984..5fdc0ba15 100644 --- a/src/StickerCommands.cxx +++ b/src/StickerCommands.cxx @@ -29,6 +29,9 @@ #include "StickerDatabase.hxx" #include "CommandError.hxx" #include "protocol/Result.hxx" +#include "util/Error.hxx" + +#include <glib.h> #include <string.h> @@ -39,7 +42,7 @@ struct sticker_song_find_data { static void sticker_song_find_print_cb(Song *song, const char *value, - gpointer user_data) + void *user_data) { struct sticker_song_find_data *data = (struct sticker_song_find_data *)user_data; @@ -51,14 +54,14 @@ sticker_song_find_print_cb(Song *song, const char *value, static enum command_return handle_sticker_song(Client *client, int argc, char *argv[]) { - GError *error = nullptr; - const Database *db = GetDatabase(&error); + Error error; + const Database *db = GetDatabase(error); if (db == nullptr) return print_error(client, error); /* get song song_id key */ if (argc == 5 && strcmp(argv[1], "get") == 0) { - Song *song = db->GetSong(argv[3], &error); + Song *song = db->GetSong(argv[3], error); if (song == nullptr) return print_error(client, error); @@ -76,7 +79,7 @@ handle_sticker_song(Client *client, int argc, char *argv[]) return COMMAND_RETURN_OK; /* list song song_id */ } else if (argc == 4 && strcmp(argv[1], "list") == 0) { - Song *song = db->GetSong(argv[3], &error); + Song *song = db->GetSong(argv[3], error); if (song == nullptr) return print_error(client, error); @@ -90,7 +93,7 @@ handle_sticker_song(Client *client, int argc, char *argv[]) return COMMAND_RETURN_OK; /* set song song_id id key */ } else if (argc == 6 && strcmp(argv[1], "set") == 0) { - Song *song = db->GetSong(argv[3], &error); + Song *song = db->GetSong(argv[3], error); if (song == nullptr) return print_error(client, error); @@ -106,7 +109,7 @@ handle_sticker_song(Client *client, int argc, char *argv[]) /* delete song song_id [key] */ } else if ((argc == 4 || argc == 5) && strcmp(argv[1], "delete") == 0) { - Song *song = db->GetSong(argv[3], &error); + Song *song = db->GetSong(argv[3], error); if (song == nullptr) return print_error(client, error); diff --git a/src/StickerDatabase.cxx b/src/StickerDatabase.cxx index f153231de..8ed82c770 100644 --- a/src/StickerDatabase.cxx +++ b/src/StickerDatabase.cxx @@ -21,6 +21,8 @@ #include "StickerDatabase.hxx" #include "fs/Path.hxx" #include "Idle.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <string> #include <map> @@ -81,23 +83,19 @@ static const char sticker_sql_create[] = static sqlite3 *sticker_db; static sqlite3_stmt *sticker_stmt[G_N_ELEMENTS(sticker_sql)]; -static GQuark -sticker_quark(void) -{ - return g_quark_from_static_string("sticker"); -} +static constexpr Domain sticker_domain("sticker"); static sqlite3_stmt * -sticker_prepare(const char *sql, GError **error_r) +sticker_prepare(const char *sql, Error &error) { int ret; sqlite3_stmt *stmt; ret = sqlite3_prepare_v2(sticker_db, sql, -1, &stmt, NULL); if (ret != SQLITE_OK) { - g_set_error(error_r, sticker_quark(), ret, - "sqlite3_prepare_v2() failed: %s", - sqlite3_errmsg(sticker_db)); + error.Format(sticker_domain, ret, + "sqlite3_prepare_v2() failed: %s", + sqlite3_errmsg(sticker_db)); return NULL; } @@ -105,7 +103,7 @@ sticker_prepare(const char *sql, GError **error_r) } bool -sticker_global_init(Path &&path, GError **error_r) +sticker_global_init(Path &&path, Error &error) { int ret; @@ -118,7 +116,7 @@ sticker_global_init(Path &&path, GError **error_r) ret = sqlite3_open(path.c_str(), &sticker_db); if (ret != SQLITE_OK) { const std::string utf8 = path.ToUTF8(); - g_set_error(error_r, sticker_quark(), ret, + error.Format(sticker_domain, ret, "Failed to open sqlite database '%s': %s", utf8.c_str(), sqlite3_errmsg(sticker_db)); return false; @@ -128,9 +126,9 @@ sticker_global_init(Path &&path, GError **error_r) ret = sqlite3_exec(sticker_db, sticker_sql_create, NULL, NULL, NULL); if (ret != SQLITE_OK) { - g_set_error(error_r, sticker_quark(), ret, - "Failed to create sticker table: %s", - sqlite3_errmsg(sticker_db)); + error.Format(sticker_domain, ret, + "Failed to create sticker table: %s", + sqlite3_errmsg(sticker_db)); return false; } @@ -139,7 +137,7 @@ sticker_global_init(Path &&path, GError **error_r) for (unsigned i = 0; i < G_N_ELEMENTS(sticker_sql); ++i) { assert(sticker_sql[i] != NULL); - sticker_stmt[i] = sticker_prepare(sticker_sql[i], error_r); + sticker_stmt[i] = sticker_prepare(sticker_sql[i], error); if (sticker_stmt[i] == NULL) return false; } diff --git a/src/StickerDatabase.hxx b/src/StickerDatabase.hxx index 9034c8bb8..b3f4c63b8 100644 --- a/src/StickerDatabase.hxx +++ b/src/StickerDatabase.hxx @@ -42,8 +42,7 @@ #ifndef MPD_STICKER_DATABASE_HXX #define MPD_STICKER_DATABASE_HXX -#include "gerror.h" - +class Error; class Path; struct sticker; @@ -55,7 +54,7 @@ struct sticker; * @return true on success, false on error */ bool -sticker_global_init(Path &&path, GError **error_r); +sticker_global_init(Path &&path, Error &error); /** * Close the sticker database. diff --git a/src/TagFile.cxx b/src/TagFile.cxx index bd124e20d..cfb62b58e 100644 --- a/src/TagFile.cxx +++ b/src/TagFile.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "TagFile.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include "DecoderList.hxx" #include "DecoderPlugin.hxx" #include "InputLegacy.hxx" @@ -59,9 +60,11 @@ tag_file_scan(const char *path_fs, if (plugin->scan_stream != NULL) { /* open the input_stream (if not already open) */ - if (is == nullptr) + if (is == nullptr) { + Error error; is = input_stream_open(path_fs, mutex, cond, - NULL); + error); + } /* now try the stream_tag() method */ if (is != NULL) { @@ -70,7 +73,8 @@ tag_file_scan(const char *path_fs, handler_ctx)) break; - input_stream_lock_seek(is, 0, SEEK_SET, NULL); + Error error; + input_stream_lock_seek(is, 0, SEEK_SET, error); } } diff --git a/src/TagId3.cxx b/src/TagId3.cxx index 6b2174fe5..3f7605f5e 100644 --- a/src/TagId3.cxx +++ b/src/TagId3.cxx @@ -22,6 +22,7 @@ #include "TagHandler.hxx" #include "TagTable.hxx" #include "Tag.hxx" +#include "util/Error.hxx" extern "C" { #include "riff.h" @@ -29,7 +30,6 @@ extern "C" { } #include "conf.h" -#include "io_error.h" #include <glib.h> #include <id3tag.h> @@ -545,13 +545,11 @@ tag_id3_riff_aiff_load(FILE *file) } struct id3_tag * -tag_id3_load(const char *path_fs, GError **error_r) +tag_id3_load(const char *path_fs, Error &error) { FILE *file = fopen(path_fs, "rb"); if (file == nullptr) { - g_set_error(error_r, errno_quark(), errno, - "Failed to open file %s: %s", - path_fs, g_strerror(errno)); + error.FormatErrno("Failed to open file %s", path_fs); return nullptr; } @@ -570,13 +568,11 @@ bool tag_id3_scan(const char *path_fs, const struct tag_handler *handler, void *handler_ctx) { - GError *error = nullptr; - struct id3_tag *tag = tag_id3_load(path_fs, &error); + Error error; + struct id3_tag *tag = tag_id3_load(path_fs, error); if (tag == nullptr) { - if (error != nullptr) { - g_warning("%s", error->message); - g_error_free(error); - } + if (error.IsDefined()) + g_warning("%s", error.GetMessage()); return false; } diff --git a/src/TagId3.hxx b/src/TagId3.hxx index d359306e9..ca288754b 100644 --- a/src/TagId3.hxx +++ b/src/TagId3.hxx @@ -22,11 +22,11 @@ #include "check.h" #include "gcc.h" -#include "gerror.h" struct tag_handler; struct Tag; struct id3_tag; +class Error; #ifdef HAVE_ID3TAG @@ -42,10 +42,10 @@ tag_id3_import(struct id3_tag *); * return value must be freed with id3_tag_delete(). * * @return NULL on error or if no ID3 tag was found in the file (no - * GError will be set) + * Error will be set) */ struct id3_tag * -tag_id3_load(const char *path_fs, GError **error_r); +tag_id3_load(const char *path_fs, Error &error); /** * Import all tags from the provided id3_tag *tag diff --git a/src/TextInputStream.cxx b/src/TextInputStream.cxx index bb4c8b868..486400f96 100644 --- a/src/TextInputStream.cxx +++ b/src/TextInputStream.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include "TextInputStream.hxx" #include "InputLegacy.hxx" #include "util/fifo_buffer.h" +#include "util/Error.hxx" #include <glib.h> @@ -40,7 +41,6 @@ TextInputStream::~TextInputStream() bool TextInputStream::ReadLine(std::string &line) { - GError *error = nullptr; void *dest; const char *src, *p; size_t length, nbytes; @@ -53,13 +53,13 @@ bool TextInputStream::ReadLine(std::string &line) newline character */ --length; + Error error; nbytes = input_stream_lock_read(is, dest, length, - &error); + error); if (nbytes > 0) fifo_buffer_append(buffer, nbytes); - else if (error != nullptr) { - g_warning("%s", error->message); - g_error_free(error); + else if (error.IsDefined()) { + g_warning("%s", error.GetMessage()); return false; } } else diff --git a/src/UpdateArchive.cxx b/src/UpdateArchive.cxx index ab174fa53..2e0755244 100644 --- a/src/UpdateArchive.cxx +++ b/src/UpdateArchive.cxx @@ -29,6 +29,7 @@ #include "ArchivePlugin.hxx" #include "ArchiveFile.hxx" #include "ArchiveVisitor.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -101,11 +102,10 @@ update_archive_file2(Directory *parent, const char *name, const Path path_fs = map_directory_child_fs(parent, name); /* open archive */ - GError *error = NULL; - ArchiveFile *file = archive_file_open(plugin, path_fs.c_str(), &error); + Error error; + ArchiveFile *file = archive_file_open(plugin, path_fs.c_str(), error); if (file == NULL) { - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); return; } diff --git a/src/UpdateGlue.cxx b/src/UpdateGlue.cxx index da8f92739..972842bb1 100644 --- a/src/UpdateGlue.cxx +++ b/src/UpdateGlue.cxx @@ -26,6 +26,7 @@ #include "DatabaseSimple.hxx" #include "Idle.hxx" #include "GlobalEvents.hxx" +#include "util/Error.hxx" extern "C" { #include "stats.h" @@ -77,12 +78,10 @@ static void * update_task(void *_path) modified = update_walk(path, discard); if (modified || !db_exists()) { - GError *error = NULL; - if (!db_save(&error)) { + Error error; + if (!db_save(error)) g_warning("Failed to save database: %s", - error->message); - g_error_free(error); - } + error.GetMessage()); } if (path != NULL && *path != 0) diff --git a/src/archive/Bzip2ArchivePlugin.cxx b/src/archive/Bzip2ArchivePlugin.cxx index 182b9ccd1..d997158a0 100644 --- a/src/archive/Bzip2ArchivePlugin.cxx +++ b/src/archive/Bzip2ArchivePlugin.cxx @@ -30,6 +30,8 @@ #include "InputStream.hxx" #include "InputPlugin.hxx" #include "util/RefCount.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <stdint.h> #include <stddef.h> @@ -85,7 +87,7 @@ public: virtual input_stream *OpenStream(const char *path, Mutex &mutex, Cond &cond, - GError **error_r) override; + Error &error) override; }; struct Bzip2InputStream { @@ -103,12 +105,14 @@ struct Bzip2InputStream { Mutex &mutex, Cond &cond); ~Bzip2InputStream(); - bool Open(GError **error_r); + bool Open(Error &error); void Close(); }; extern const struct input_plugin bz2_inputplugin; +static constexpr Domain bz2_domain("bz2"); + static inline GQuark bz2_quark(void) { @@ -118,7 +122,7 @@ bz2_quark(void) /* single archive handling allocation helpers */ inline bool -Bzip2InputStream::Open(GError **error_r) +Bzip2InputStream::Open(Error &error) { bzstream.bzalloc = nullptr; bzstream.bzfree = nullptr; @@ -129,8 +133,8 @@ Bzip2InputStream::Open(GError **error_r) int ret = BZ2_bzDecompressInit(&bzstream, 0, 0); if (ret != BZ_OK) { - g_set_error(error_r, bz2_quark(), ret, - "BZ2_bzDecompressInit() has failed"); + error.Set(bz2_domain, ret, + "BZ2_bzDecompressInit() has failed"); return false; } @@ -147,11 +151,11 @@ Bzip2InputStream::Close() /* archive open && listing routine */ static ArchiveFile * -bz2_open(const char *pathname, GError **error_r) +bz2_open(const char *pathname, Error &error) { static Mutex mutex; static Cond cond; - input_stream *is = input_stream_open(pathname, mutex, cond, error_r); + input_stream *is = input_stream_open(pathname, mutex, cond, error); if (is == nullptr) return nullptr; @@ -176,10 +180,10 @@ Bzip2InputStream::~Bzip2InputStream() input_stream * Bzip2ArchiveFile::OpenStream(const char *path, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { Bzip2InputStream *bis = new Bzip2InputStream(*this, path, mutex, cond); - if (!bis->Open(error_r)) { + if (!bis->Open(error)) { delete bis; return NULL; } @@ -197,7 +201,7 @@ bz2_is_close(struct input_stream *is) } static bool -bz2_fillbuffer(Bzip2InputStream *bis, GError **error_r) +bz2_fillbuffer(Bzip2InputStream *bis, Error &error) { size_t count; bz_stream *bzstream; @@ -209,7 +213,7 @@ bz2_fillbuffer(Bzip2InputStream *bis, GError **error_r) count = input_stream_read(bis->archive->istream, bis->buffer, sizeof(bis->buffer), - error_r); + error); if (count == 0) return false; @@ -220,7 +224,7 @@ bz2_fillbuffer(Bzip2InputStream *bis, GError **error_r) static size_t bz2_is_read(struct input_stream *is, void *ptr, size_t length, - GError **error_r) + Error &error) { Bzip2InputStream *bis = (Bzip2InputStream *)is; bz_stream *bzstream; @@ -235,7 +239,7 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length, bzstream->avail_out = length; do { - if (!bz2_fillbuffer(bis, error_r)) + if (!bz2_fillbuffer(bis, error)) return 0; bz_result = BZ2_bzDecompress(bzstream); @@ -246,8 +250,8 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length, } if (bz_result != BZ_OK) { - g_set_error(error_r, bz2_quark(), bz_result, - "BZ2_bzDecompress() has failed"); + error.Set(bz2_domain, bz_result, + "BZ2_bzDecompress() has failed"); return 0; } } while (bzstream->avail_out == length); diff --git a/src/archive/Iso9660ArchivePlugin.cxx b/src/archive/Iso9660ArchivePlugin.cxx index 97fd8bd52..2fee25311 100644 --- a/src/archive/Iso9660ArchivePlugin.cxx +++ b/src/archive/Iso9660ArchivePlugin.cxx @@ -30,6 +30,8 @@ #include "InputStream.hxx" #include "InputPlugin.hxx" #include "util/RefCount.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <cdio/cdio.h> #include <cdio/iso9660.h> @@ -69,16 +71,12 @@ public: virtual input_stream *OpenStream(const char *path, Mutex &mutex, Cond &cond, - GError **error_r) override; + Error &error) override; }; extern const struct input_plugin iso9660_input_plugin; -static inline GQuark -iso9660_quark(void) -{ - return g_quark_from_static_string("iso9660"); -} +static constexpr Domain iso9660_domain("iso9660"); /* archive open && listing routine */ @@ -115,13 +113,13 @@ Iso9660ArchiveFile::Visit(const char *psz_path, ArchiveVisitor &visitor) } static ArchiveFile * -iso9660_archive_open(const char *pathname, GError **error_r) +iso9660_archive_open(const char *pathname, Error &error) { /* open archive */ auto iso = iso9660_open(pathname); if (iso == nullptr) { - g_set_error(error_r, iso9660_quark(), 0, - "Failed to open ISO9660 file %s", pathname); + error.Format(iso9660_domain, + "Failed to open ISO9660 file %s", pathname); return NULL; } @@ -166,12 +164,12 @@ struct Iso9660InputStream { input_stream * Iso9660ArchiveFile::OpenStream(const char *pathname, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { auto statbuf = iso9660_ifs_stat_translate(iso, pathname); if (statbuf == nullptr) { - g_set_error(error_r, iso9660_quark(), 0, - "not found in the ISO file: %s", pathname); + error.Format(iso9660_domain, + "not found in the ISO file: %s", pathname); return NULL; } @@ -191,7 +189,8 @@ iso9660_input_close(struct input_stream *is) static size_t -iso9660_input_read(struct input_stream *is, void *ptr, size_t size, GError **error_r) +iso9660_input_read(struct input_stream *is, void *ptr, size_t size, + Error &error) { Iso9660InputStream *iis = (Iso9660InputStream *)is; int toread, readed = 0; @@ -215,9 +214,9 @@ iso9660_input_read(struct input_stream *is, void *ptr, size_t size, GError **err iis->statbuf->lsn + cur_block, no_blocks); if (readed != no_blocks * ISO_BLOCKSIZE) { - g_set_error(error_r, iso9660_quark(), 0, - "error reading ISO file at lsn %lu", - (long unsigned int) cur_block); + error.Format(iso9660_domain, + "error reading ISO file at lsn %lu", + (unsigned long)cur_block); return 0; } if (left_bytes < size) { diff --git a/src/archive/ZzipArchivePlugin.cxx b/src/archive/ZzipArchivePlugin.cxx index d0db7aa37..de2c62b5b 100644 --- a/src/archive/ZzipArchivePlugin.cxx +++ b/src/archive/ZzipArchivePlugin.cxx @@ -30,9 +30,11 @@ #include "InputStream.hxx" #include "InputPlugin.hxx" #include "util/RefCount.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <zzip/zzip.h> -#include <glib.h> + #include <string.h> class ZzipArchiveFile final : public ArchiveFile { @@ -61,26 +63,22 @@ public: virtual input_stream *OpenStream(const char *path, Mutex &mutex, Cond &cond, - GError **error_r) override; + Error &error) override; }; extern const struct input_plugin zzip_input_plugin; -static inline GQuark -zzip_quark(void) -{ - return g_quark_from_static_string("zzip"); -} +static constexpr Domain zzip_domain("zzip"); /* archive open && listing routine */ static ArchiveFile * -zzip_archive_open(const char *pathname, GError **error_r) +zzip_archive_open(const char *pathname, Error &error) { ZZIP_DIR *dir = zzip_dir_open(pathname, NULL); if (dir == nullptr) { - g_set_error(error_r, zzip_quark(), 0, - "Failed to open ZIP file %s", pathname); + error.Format(zzip_domain, "Failed to open ZIP file %s", + pathname); return NULL; } @@ -133,12 +131,12 @@ struct ZzipInputStream { input_stream * ZzipArchiveFile::OpenStream(const char *pathname, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { ZZIP_FILE *_file = zzip_file_open(dir, pathname, 0); if (_file == nullptr) { - g_set_error(error_r, zzip_quark(), 0, - "not found in the ZIP file: %s", pathname); + error.Format(zzip_domain, "not found in the ZIP file: %s", + pathname); return NULL; } @@ -159,15 +157,14 @@ zzip_input_close(struct input_stream *is) static size_t zzip_input_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r) + Error &error) { ZzipInputStream *zis = (ZzipInputStream *)is; int ret; ret = zzip_file_read(zis->file, ptr, size); if (ret < 0) { - g_set_error(error_r, zzip_quark(), ret, - "zzip_file_read() has failed"); + error.Set(zzip_domain, "zzip_file_read() has failed"); return 0; } @@ -186,13 +183,12 @@ zzip_input_eof(struct input_stream *is) static bool zzip_input_seek(struct input_stream *is, - goffset offset, int whence, GError **error_r) + goffset offset, int whence, Error &error) { ZzipInputStream *zis = (ZzipInputStream *)is; zzip_off_t ofs = zzip_seek(zis->file, offset, whence); if (ofs != -1) { - g_set_error(error_r, zzip_quark(), ofs, - "zzip_seek() has failed"); + error.Set(zzip_domain, "zzip_seek() has failed"); is->offset = ofs; return true; } diff --git a/src/db/ProxyDatabasePlugin.cxx b/src/db/ProxyDatabasePlugin.cxx index 81aad0a4c..e0af53cee 100644 --- a/src/db/ProxyDatabasePlugin.cxx +++ b/src/db/ProxyDatabasePlugin.cxx @@ -28,6 +28,8 @@ #include "gcc.h" #include "conf.h" #include "Tag.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #undef MPD_DIRECTORY_H #undef MPD_SONG_H @@ -46,39 +48,34 @@ class ProxyDatabase : public Database { public: static Database *Create(const config_param ¶m, - GError **error_r); + Error &error); - virtual bool Open(GError **error_r) override; + virtual bool Open(Error &error) override; virtual void Close() override; virtual Song *GetSong(const char *uri_utf8, - GError **error_r) const override; + Error &error) const override; virtual void ReturnSong(Song *song) const; virtual bool Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, - GError **error_r) const override; + Error &error) const override; virtual bool VisitUniqueTags(const DatabaseSelection &selection, enum tag_type tag_type, VisitString visit_string, - GError **error_r) const override; + Error &error) const override; virtual bool GetStats(const DatabaseSelection &selection, DatabaseStats &stats, - GError **error_r) const override; + Error &error) const override; protected: - bool Configure(const config_param ¶m, GError **error_r); + bool Configure(const config_param ¶m, Error &error); }; -gcc_pure -static inline GQuark -libmpdclient_quark(void) -{ - return g_quark_from_static_string("libmpdclient"); -} +static constexpr Domain libmpdclient_domain("libmpdclient"); static constexpr struct { enum tag_type d; @@ -116,23 +113,23 @@ Convert(enum tag_type tag_type) } static bool -CheckError(struct mpd_connection *connection, GError **error_r) +CheckError(struct mpd_connection *connection, Error &error) { - const auto error = mpd_connection_get_error(connection); - if (error == MPD_ERROR_SUCCESS) + const auto code = mpd_connection_get_error(connection); + if (code == MPD_ERROR_SUCCESS) return true; - g_set_error_literal(error_r, libmpdclient_quark(), (int)error, - mpd_connection_get_error_message(connection)); + error.Set(libmpdclient_domain, (int)code, + mpd_connection_get_error_message(connection)); mpd_connection_clear_error(connection); return false; } Database * -ProxyDatabase::Create(const config_param ¶m, GError **error_r) +ProxyDatabase::Create(const config_param ¶m, Error &error) { ProxyDatabase *db = new ProxyDatabase(); - if (!db->Configure(param, error_r)) { + if (!db->Configure(param, error)) { delete db; db = NULL; } @@ -141,7 +138,7 @@ ProxyDatabase::Create(const config_param ¶m, GError **error_r) } bool -ProxyDatabase::Configure(const config_param ¶m, GError **) +ProxyDatabase::Configure(const config_param ¶m, gcc_unused Error &error) { host = param.GetBlockValue("host", ""); port = param.GetBlockValue("port", 0u); @@ -150,17 +147,16 @@ ProxyDatabase::Configure(const config_param ¶m, GError **) } bool -ProxyDatabase::Open(GError **error_r) +ProxyDatabase::Open(Error &error) { connection = mpd_connection_new(host.empty() ? NULL : host.c_str(), port, 0); if (connection == NULL) { - g_set_error_literal(error_r, libmpdclient_quark(), - (int)MPD_ERROR_OOM, "Out of memory"); + error.Set(libmpdclient_domain, (int)MPD_ERROR_OOM, "Out of memory"); return false; } - if (!CheckError(connection, error_r)) { + if (!CheckError(connection, error)) { mpd_connection_free(connection); return false; } @@ -183,13 +179,13 @@ static Song * Convert(const struct mpd_song *song); Song * -ProxyDatabase::GetSong(const char *uri, GError **error_r) const +ProxyDatabase::GetSong(const char *uri, Error &error) const { // TODO: implement // TODO: auto-reconnect if (!mpd_send_list_meta(connection, uri)) { - CheckError(connection, error_r); + CheckError(connection, error); return nullptr; } @@ -202,13 +198,12 @@ ProxyDatabase::GetSong(const char *uri, GError **error_r) const if (song2 != nullptr) song2->Free(); - CheckError(connection, error_r); + CheckError(connection, error); return nullptr; } if (song2 == nullptr) - g_set_error(error_r, db_quark(), DB_NOT_FOUND, - "No such song: %s", uri); + error.Format(db_domain, DB_NOT_FOUND, "No such song: %s", uri); return song2; } @@ -226,19 +221,19 @@ ProxyDatabase::ReturnSong(Song *song) const static bool Visit(struct mpd_connection *connection, const char *uri, bool recursive, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, GError **error_r); + VisitPlaylist visit_playlist, Error &error); static bool Visit(struct mpd_connection *connection, bool recursive, const struct mpd_directory *directory, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, GError **error_r) + VisitPlaylist visit_playlist, Error &error) { const char *path = mpd_directory_get_path(directory); if (visit_directory) { Directory *d = Directory::NewGeneric(path, &detached_root); - bool success = visit_directory(*d, error_r); + bool success = visit_directory(*d, error); d->Free(); if (!success) return false; @@ -246,7 +241,7 @@ Visit(struct mpd_connection *connection, if (recursive && !Visit(connection, path, recursive, - visit_directory, visit_song, visit_playlist, error_r)) + visit_directory, visit_song, visit_playlist, error)) return false; return true; @@ -290,13 +285,13 @@ Convert(const struct mpd_song *song) static bool Visit(const struct mpd_song *song, - VisitSong visit_song, GError **error_r) + VisitSong visit_song, Error &error) { if (!visit_song) return true; Song *s = Convert(song); - bool success = visit_song(*s, error_r); + bool success = visit_song(*s, error); s->Free(); return success; @@ -304,7 +299,7 @@ Visit(const struct mpd_song *song, static bool Visit(const struct mpd_playlist *playlist, - VisitPlaylist visit_playlist, GError **error_r) + VisitPlaylist visit_playlist, Error &error) { if (!visit_playlist) return true; @@ -312,7 +307,7 @@ Visit(const struct mpd_playlist *playlist, PlaylistInfo p(mpd_playlist_get_path(playlist), mpd_playlist_get_last_modified(playlist)); - return visit_playlist(p, detached_root, error_r); + return visit_playlist(p, detached_root, error); } class ProxyEntity { @@ -356,13 +351,13 @@ ReceiveEntities(struct mpd_connection *connection) static bool Visit(struct mpd_connection *connection, const char *uri, bool recursive, VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, GError **error_r) + VisitPlaylist visit_playlist, Error &error) { if (!mpd_send_list_meta(connection, uri)) - return CheckError(connection, error_r); + return CheckError(connection, error); std::list<ProxyEntity> entities(ReceiveEntities(connection)); - if (!CheckError(connection, error_r)) + if (!CheckError(connection, error)) return false; for (const auto &entity : entities) { @@ -374,25 +369,25 @@ Visit(struct mpd_connection *connection, const char *uri, if (!Visit(connection, recursive, mpd_entity_get_directory(entity), visit_directory, visit_song, visit_playlist, - error_r)) + error)) return false; break; case MPD_ENTITY_TYPE_SONG: if (!Visit(mpd_entity_get_song(entity), visit_song, - error_r)) + error)) return false; break; case MPD_ENTITY_TYPE_PLAYLIST: if (!Visit(mpd_entity_get_playlist(entity), - visit_playlist, error_r)) + visit_playlist, error)) return false; break; } } - return CheckError(connection, error_r); + return CheckError(connection, error); } bool @@ -400,55 +395,54 @@ ProxyDatabase::Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, - GError **error_r) const + Error &error) const { // TODO: match // TODO: auto-reconnect return ::Visit(connection, selection.uri, selection.recursive, visit_directory, visit_song, visit_playlist, - error_r); + error); } bool ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection, enum tag_type tag_type, VisitString visit_string, - GError **error_r) const + Error &error) const { enum mpd_tag_type tag_type2 = Convert(tag_type); if (tag_type2 == MPD_TAG_COUNT) { - g_set_error_literal(error_r, libmpdclient_quark(), 0, - "Unsupported tag"); + error.Set(libmpdclient_domain, "Unsupported tag"); return false; } if (!mpd_search_db_tags(connection, tag_type2)) - return CheckError(connection, error_r); + return CheckError(connection, error); // TODO: match (void)selection; if (!mpd_search_commit(connection)) - return CheckError(connection, error_r); + return CheckError(connection, error); bool result = true; struct mpd_pair *pair; while (result && (pair = mpd_recv_pair_tag(connection, tag_type2)) != nullptr) { - result = visit_string(pair->value, error_r); + result = visit_string(pair->value, error); mpd_return_pair(connection, pair); } return mpd_response_finish(connection) && - CheckError(connection, error_r) && + CheckError(connection, error) && result; } bool ProxyDatabase::GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, GError **error_r) const + DatabaseStats &stats, Error &error) const { // TODO: match (void)selection; @@ -456,7 +450,7 @@ ProxyDatabase::GetStats(const DatabaseSelection &selection, struct mpd_stats *stats2 = mpd_run_stats(connection); if (stats2 == nullptr) - return CheckError(connection, error_r); + return CheckError(connection, error); stats.song_count = mpd_stats_get_number_of_songs(stats2); stats.total_duration = mpd_stats_get_db_play_time(stats2); diff --git a/src/db/SimpleDatabasePlugin.cxx b/src/db/SimpleDatabasePlugin.cxx index 21eb8752d..56bdc2cb7 100644 --- a/src/db/SimpleDatabasePlugin.cxx +++ b/src/db/SimpleDatabasePlugin.cxx @@ -29,22 +29,19 @@ #include "TextFile.hxx" #include "conf.h" #include "fs/FileSystem.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <sys/types.h> #include <errno.h> -gcc_const -static inline GQuark -simple_db_quark(void) -{ - return g_quark_from_static_string("simple_db"); -} +static constexpr Domain simple_db_domain("simple_db"); Database * -SimpleDatabase::Create(const config_param ¶m, GError **error_r) +SimpleDatabase::Create(const config_param ¶m, Error &error) { SimpleDatabase *db = new SimpleDatabase(); - if (!db->Configure(param, error_r)) { + if (!db->Configure(param, error)) { delete db; db = NULL; } @@ -53,17 +50,13 @@ SimpleDatabase::Create(const config_param ¶m, GError **error_r) } bool -SimpleDatabase::Configure(const config_param ¶m, GError **error_r) +SimpleDatabase::Configure(const config_param ¶m, Error &error) { - GError *error = NULL; - - path = param.GetBlockPath("path", &error); + path = param.GetBlockPath("path", error); if (path.IsNull()) { - if (error != NULL) - g_propagate_error(error_r, error); - else - g_set_error(error_r, simple_db_quark(), 0, - "No \"path\" parameter specified"); + if (!error.IsDefined()) + error.Set(simple_db_domain, + "No \"path\" parameter specified"); return false; } @@ -73,7 +66,7 @@ SimpleDatabase::Configure(const config_param ¶m, GError **error_r) } bool -SimpleDatabase::Check(GError **error_r) const +SimpleDatabase::Check(Error &error) const { assert(!path.IsNull()); assert(!path.empty()); @@ -88,28 +81,26 @@ SimpleDatabase::Check(GError **error_r) const /* Check that the parent part of the path is a directory */ struct stat st; if (!StatFile(dirPath, st)) { - g_set_error(error_r, simple_db_quark(), errno, - "Couldn't stat parent directory of db file " - "\"%s\": %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Couldn't stat parent directory of db file " + "\"%s\"", + path_utf8.c_str()); return false; } if (!S_ISDIR(st.st_mode)) { - g_set_error(error_r, simple_db_quark(), 0, - "Couldn't create db file \"%s\" because the " - "parent path is not a directory", - path_utf8.c_str()); + error.Format(simple_db_domain, + "Couldn't create db file \"%s\" because the " + "parent path is not a directory", + path_utf8.c_str()); return false; } /* Check if we can write to the directory */ if (!CheckAccess(dirPath, X_OK | W_OK)) { - int error = errno; + const int e = errno; const std::string dirPath_utf8 = dirPath.ToUTF8(); - g_set_error(error_r, simple_db_quark(), error, - "Can't create db file in \"%s\": %s", - dirPath_utf8.c_str(), g_strerror(error)); + error.FormatErrno(e, "Can't create db file in \"%s\"", + dirPath_utf8.c_str()); return false; } @@ -119,24 +110,22 @@ SimpleDatabase::Check(GError **error_r) const /* Path exists, now check if it's a regular file */ struct stat st; if (!StatFile(path, st)) { - g_set_error(error_r, simple_db_quark(), errno, - "Couldn't stat db file \"%s\": %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Couldn't stat db file \"%s\"", + path_utf8.c_str()); return false; } if (!S_ISREG(st.st_mode)) { - g_set_error(error_r, simple_db_quark(), 0, - "db file \"%s\" is not a regular file", - path_utf8.c_str()); + error.Format(simple_db_domain, + "db file \"%s\" is not a regular file", + path_utf8.c_str()); return false; } /* And check that we can write to it */ if (!CheckAccess(path, R_OK | W_OK)) { - g_set_error(error_r, simple_db_quark(), errno, - "Can't open db file \"%s\" for reading/writing: %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Can't open db file \"%s\" for reading/writing", + path_utf8.c_str()); return false; } @@ -144,20 +133,19 @@ SimpleDatabase::Check(GError **error_r) const } bool -SimpleDatabase::Load(GError **error_r) +SimpleDatabase::Load(Error &error) { assert(!path.empty()); assert(root != NULL); TextFile file(path); if (file.HasFailed()) { - g_set_error(error_r, simple_db_quark(), errno, - "Failed to open database file \"%s\": %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("Failed to open database file \"%s\"", + path_utf8.c_str()); return false; } - if (!db_load_internal(file, root, error_r)) + if (!db_load_internal(file, root, error)) return false; struct stat st; @@ -168,7 +156,7 @@ SimpleDatabase::Load(GError **error_r) } bool -SimpleDatabase::Open(GError **error_r) +SimpleDatabase::Open(Error &error) { root = Directory::NewRoot(); mtime = 0; @@ -177,14 +165,13 @@ SimpleDatabase::Open(GError **error_r) borrowed_song_count = 0; #endif - GError *error = NULL; - if (!Load(&error)) { + if (!Load(error)) { root->Free(); - g_warning("Failed to load database: %s", error->message); - g_error_free(error); + g_warning("Failed to load database: %s", error.GetMessage()); + error.Clear(); - if (!Check(error_r)) + if (!Check(error)) return false; root = Directory::NewRoot(); @@ -203,7 +190,7 @@ SimpleDatabase::Close() } Song * -SimpleDatabase::GetSong(const char *uri, GError **error_r) const +SimpleDatabase::GetSong(const char *uri, Error &error) const { assert(root != NULL); @@ -211,8 +198,8 @@ SimpleDatabase::GetSong(const char *uri, GError **error_r) const Song *song = root->LookupSong(uri); db_unlock(); if (song == NULL) - g_set_error(error_r, db_quark(), DB_NOT_FOUND, - "No such song: %s", uri); + error.Format(db_domain, DB_NOT_FOUND, + "No such song: %s", uri); #ifndef NDEBUG else ++const_cast<unsigned &>(borrowed_song_count); @@ -248,7 +235,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, - GError **error_r) const + Error &error) const { ScopeDatabaseLock protect; @@ -258,42 +245,41 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, Song *song = root->LookupSong(selection.uri); if (song != nullptr) return !selection.Match(*song) || - visit_song(*song, error_r); + visit_song(*song, error); } - g_set_error(error_r, db_quark(), DB_NOT_FOUND, - "No such directory"); + error.Set(db_domain, DB_NOT_FOUND, "No such directory"); return false; } if (selection.recursive && visit_directory && - !visit_directory(*directory, error_r)) + !visit_directory(*directory, error)) return false; return directory->Walk(selection.recursive, selection.filter, visit_directory, visit_song, visit_playlist, - error_r); + error); } bool SimpleDatabase::VisitUniqueTags(const DatabaseSelection &selection, enum tag_type tag_type, VisitString visit_string, - GError **error_r) const + Error &error) const { return ::VisitUniqueTags(*this, selection, tag_type, visit_string, - error_r); + error); } bool SimpleDatabase::GetStats(const DatabaseSelection &selection, - DatabaseStats &stats, GError **error_r) const + DatabaseStats &stats, Error &error) const { - return ::GetStats(*this, selection, stats, error_r); + return ::GetStats(*this, selection, stats, error); } bool -SimpleDatabase::Save(GError **error_r) +SimpleDatabase::Save(Error &error) { db_lock(); @@ -309,18 +295,15 @@ SimpleDatabase::Save(GError **error_r) FILE *fp = FOpen(path, FOpenMode::WriteText); if (!fp) { - g_set_error(error_r, simple_db_quark(), errno, - "unable to write to db file \"%s\": %s", - path_utf8.c_str(), g_strerror(errno)); + error.FormatErrno("unable to write to db file \"%s\"", + path_utf8.c_str()); return false; } db_save_internal(fp, root); if (ferror(fp)) { - g_set_error(error_r, simple_db_quark(), errno, - "Failed to write to database file: %s", - g_strerror(errno)); + error.SetErrno("Failed to write to database file"); fclose(fp); return false; } diff --git a/src/db/SimpleDatabasePlugin.hxx b/src/db/SimpleDatabasePlugin.hxx index 7250ea063..5de52cdeb 100644 --- a/src/db/SimpleDatabasePlugin.hxx +++ b/src/db/SimpleDatabasePlugin.hxx @@ -53,7 +53,7 @@ public: return root; } - bool Save(GError **error_r); + bool Save(Error &error); gcc_pure time_t GetLastModified() const { @@ -61,37 +61,37 @@ public: } static Database *Create(const config_param ¶m, - GError **error_r); + Error &error); - virtual bool Open(GError **error_r) override; + virtual bool Open(Error &error) override; virtual void Close() override; virtual Song *GetSong(const char *uri_utf8, - GError **error_r) const override; + Error &error) const override; virtual void ReturnSong(Song *song) const; virtual bool Visit(const DatabaseSelection &selection, VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, - GError **error_r) const override; + Error &error) const override; virtual bool VisitUniqueTags(const DatabaseSelection &selection, enum tag_type tag_type, VisitString visit_string, - GError **error_r) const override; + Error &error) const override; virtual bool GetStats(const DatabaseSelection &selection, DatabaseStats &stats, - GError **error_r) const override; + Error &error) const override; protected: - bool Configure(const config_param ¶m, GError **error_r); + bool Configure(const config_param ¶m, Error &error); gcc_pure - bool Check(GError **error_r) const; + bool Check(Error &error) const; - bool Load(GError **error_r); + bool Load(Error &error); gcc_pure const Directory *LookupDirectory(const char *uri) const; diff --git a/src/decoder/AdPlugDecoderPlugin.cxx b/src/decoder/AdPlugDecoderPlugin.cxx index 47ab1a7f3..f3b986fc8 100644 --- a/src/decoder/AdPlugDecoderPlugin.cxx +++ b/src/decoder/AdPlugDecoderPlugin.cxx @@ -22,6 +22,7 @@ #include "TagHandler.hxx" #include "DecoderAPI.hxx" #include "CheckAudioFormat.hxx" +#include "util/Error.hxx" #include <adplug/adplug.h> #include <adplug/emuopl.h> @@ -38,12 +39,11 @@ static unsigned sample_rate; static bool adplug_init(const config_param ¶m) { - GError *error = NULL; + Error error; sample_rate = param.GetBlockValue("sample_rate", 48000u); - if (!audio_check_sample_rate(sample_rate, &error)) { - g_warning("%s\n", error->message); - g_error_free(error); + if (!audio_check_sample_rate(sample_rate, error)) { + g_warning("%s", error.GetMessage()); return false; } diff --git a/src/decoder/AudiofileDecoderPlugin.cxx b/src/decoder/AudiofileDecoderPlugin.cxx index 9c00b20ce..c146466cb 100644 --- a/src/decoder/AudiofileDecoderPlugin.cxx +++ b/src/decoder/AudiofileDecoderPlugin.cxx @@ -22,6 +22,7 @@ #include "DecoderAPI.hxx" #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" +#include "util/Error.hxx" #include <audiofile.h> #include <af_vfs.h> @@ -53,13 +54,11 @@ static ssize_t audiofile_file_read(AFvirtualfile *vfile, void *data, size_t length) { struct input_stream *is = (struct input_stream *) vfile->closure; - GError *error = nullptr; - size_t nbytes; - nbytes = input_stream_lock_read(is, data, length, &error); - if (nbytes == 0 && error != nullptr) { - g_warning("%s", error->message); - g_error_free(error); + Error error; + size_t nbytes = input_stream_lock_read(is, data, length, error); + if (nbytes == 0 && error.IsDefined()) { + g_warning("%s", error.GetMessage()); return -1; } @@ -93,7 +92,9 @@ audiofile_file_seek(AFvirtualfile *vfile, AFfileoffset offset, int is_relative) { struct input_stream *is = (struct input_stream *) vfile->closure; int whence = (is_relative ? SEEK_CUR : SEEK_SET); - if (input_stream_lock_seek(is, offset, whence, nullptr)) { + + Error error; + if (input_stream_lock_seek(is, offset, whence, error)) { return input_stream_get_offset(is); } else { return -1; @@ -156,7 +157,6 @@ audiofile_setup_sample_format(AFfilehandle af_fp) static void audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) { - GError *error = nullptr; AFvirtualfile *vf; int fs, frame_count; AFfilehandle af_fp; @@ -180,13 +180,13 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) return; } + Error error; if (!audio_format_init_checked(audio_format, afGetRate(af_fp, AF_DEFAULT_TRACK), audiofile_setup_sample_format(af_fp), afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK), - &error)) { - g_warning("%s", error->message); - g_error_free(error); + error)) { + g_warning("%s", error.GetMessage()); afCloseFile(af_fp); return; } diff --git a/src/decoder/DsdLib.cxx b/src/decoder/DsdLib.cxx index d18131184..a9cfc9147 100644 --- a/src/decoder/DsdLib.cxx +++ b/src/decoder/DsdLib.cxx @@ -29,6 +29,7 @@ #include "util/bit_reverse.h" #include "TagHandler.hxx" #include "TagId3.hxx" +#include "util/Error.hxx" #include <unistd.h> #include <string.h> @@ -64,7 +65,7 @@ dsdlib_skip_to(struct decoder *decoder, struct input_stream *is, goffset offset) { if (input_stream_is_seekable(is)) - return input_stream_seek(is, offset, SEEK_SET, nullptr); + return input_stream_seek(is, offset, SEEK_SET, IgnoreError()); if (input_stream_get_offset(is) > offset) return false; @@ -97,7 +98,7 @@ dsdlib_skip(struct decoder *decoder, struct input_stream *is, return true; if (input_stream_is_seekable(is)) - return input_stream_seek(is, delta, SEEK_CUR, nullptr); + return input_stream_seek(is, delta, SEEK_CUR, IgnoreError()); char buffer[8192]; while (delta > 0) { diff --git a/src/decoder/DsdiffDecoderPlugin.cxx b/src/decoder/DsdiffDecoderPlugin.cxx index b6d7f65cc..7c461f9c3 100644 --- a/src/decoder/DsdiffDecoderPlugin.cxx +++ b/src/decoder/DsdiffDecoderPlugin.cxx @@ -31,6 +31,7 @@ #include "DecoderAPI.hxx" #include "CheckAudioFormat.hxx" #include "util/bit_reverse.h" +#include "util/Error.hxx" #include "TagHandler.hxx" #include "DsdLib.hxx" #include "TagHandler.hxx" @@ -432,13 +433,12 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is) if (!dsdiff_read_metadata(decoder, is, &metadata, &chunk_header)) return; - GError *error = nullptr; + Error error; AudioFormat audio_format; if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, SampleFormat::DSD, - metadata.channels, &error)) { - g_warning("%s", error->message); - g_error_free(error); + metadata.channels, error)) { + g_warning("%s", error.GetMessage()); return; } @@ -490,7 +490,7 @@ dsdiff_scan_stream(struct input_stream *is, AudioFormat audio_format; if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, SampleFormat::DSD, - metadata.channels, nullptr)) + metadata.channels, IgnoreError())) /* refuse to parse files which we cannot play anyway */ return false; diff --git a/src/decoder/DsfDecoderPlugin.cxx b/src/decoder/DsfDecoderPlugin.cxx index e487879cb..26ba0e2d6 100644 --- a/src/decoder/DsfDecoderPlugin.cxx +++ b/src/decoder/DsfDecoderPlugin.cxx @@ -32,6 +32,7 @@ #include "DecoderAPI.hxx" #include "CheckAudioFormat.hxx" #include "util/bit_reverse.h" +#include "util/Error.hxx" #include "DsdLib.hxx" #include "TagHandler.hxx" @@ -284,13 +285,12 @@ dsf_stream_decode(struct decoder *decoder, struct input_stream *is) if (!dsf_read_metadata(decoder, is, &metadata)) return; - GError *error = NULL; + Error error; AudioFormat audio_format; if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, SampleFormat::DSD, - metadata.channels, &error)) { - g_warning("%s", error->message); - g_error_free(error); + metadata.channels, error)) { + g_warning("%s", error.GetMessage()); return; } /* Calculate song time from DSD chunk size and sample frequency */ @@ -320,7 +320,7 @@ dsf_scan_stream(struct input_stream *is, AudioFormat audio_format; if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, SampleFormat::DSD, - metadata.channels, NULL)) + metadata.channels, IgnoreError())) /* refuse to parse files which we cannot play anyway */ return false; diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index 547ba24e0..1387dc45c 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -23,6 +23,8 @@ #include "DecoderBuffer.hxx" #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <neaacdec.h> @@ -42,14 +44,7 @@ static const unsigned adts_sample_rates[] = 16000, 12000, 11025, 8000, 7350, 0, 0, 0 }; -/** - * The GLib quark used for errors reported by this plugin. - */ -static inline GQuark -faad_decoder_quark(void) -{ - return g_quark_from_static_string("faad"); -} +static constexpr Domain faad_decoder_domain("faad_decoder"); /** * Check whether the buffer head is an AAC frame, and return the frame @@ -211,7 +206,7 @@ faad_song_duration(DecoderBuffer *buffer, struct input_stream *is) /* obtain the duration from the ADTS header */ float song_length = adts_song_duration(buffer); - input_stream_lock_seek(is, tagsize, SEEK_SET, nullptr); + input_stream_lock_seek(is, tagsize, SEEK_SET, IgnoreError()); data = (const uint8_t *)decoder_buffer_read(buffer, &length); if (data != nullptr) @@ -248,7 +243,7 @@ faad_song_duration(DecoderBuffer *buffer, struct input_stream *is) */ static bool faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, - AudioFormat &audio_format, GError **error_r) + AudioFormat &audio_format, Error &error) { int32_t nbytes; uint32_t sample_rate; @@ -266,8 +261,7 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, const unsigned char *data = (const unsigned char *) decoder_buffer_read(buffer, &length); if (data == nullptr) { - g_set_error(error_r, faad_decoder_quark(), 0, - "Empty file"); + error.Set(faad_decoder_domain, "Empty file"); return false; } @@ -277,15 +271,14 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, length, sample_rate_p, &channels); if (nbytes < 0) { - g_set_error(error_r, faad_decoder_quark(), 0, - "Not an AAC stream"); + error.Set(faad_decoder_domain, "Not an AAC stream"); return false; } decoder_buffer_consume(buffer, nbytes); return audio_format_init_checked(audio_format, sample_rate, - SampleFormat::S16, channels, error_r); + SampleFormat::S16, channels, error); } /** @@ -336,7 +329,8 @@ faad_get_file_time_float(struct input_stream *is) decoder_buffer_fill(buffer); - ret = faad_decoder_init(decoder, buffer, audio_format, nullptr); + ret = faad_decoder_init(decoder, buffer, audio_format, + IgnoreError()); if (ret) length = 0; @@ -368,7 +362,6 @@ faad_get_file_time(struct input_stream *is) static void faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is) { - GError *error = nullptr; float total_time = 0; AudioFormat audio_format; bool ret; @@ -400,10 +393,10 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is) /* initialize it */ - ret = faad_decoder_init(decoder, buffer, audio_format, &error); + Error error; + ret = faad_decoder_init(decoder, buffer, audio_format, error); if (!ret) { - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error.GetMessage()); NeAACDecClose(decoder); return; } diff --git a/src/decoder/FfmpegDecoderPlugin.cxx b/src/decoder/FfmpegDecoderPlugin.cxx index cf162b918..305662e6c 100644 --- a/src/decoder/FfmpegDecoderPlugin.cxx +++ b/src/decoder/FfmpegDecoderPlugin.cxx @@ -27,6 +27,7 @@ #include "TagHandler.hxx" #include "InputStream.hxx" #include "CheckAudioFormat.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -124,7 +125,8 @@ mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence) if (whence == AVSEEK_SIZE) return stream->input->size; - if (!input_stream_lock_seek(stream->input, pos, whence, NULL)) + Error error; + if (!input_stream_lock_seek(stream->input, pos, whence, error)) return -1; return stream->input->offset; @@ -343,10 +345,12 @@ ffmpeg_probe(struct decoder *decoder, struct input_stream *is) PADDING = 16, }; + Error error; + unsigned char *buffer = (unsigned char *)g_malloc(BUFFER_SIZE); size_t nbytes = decoder_read(decoder, is, buffer, BUFFER_SIZE); if (nbytes <= PADDING || - !input_stream_lock_seek(is, 0, SEEK_SET, NULL)) { + !input_stream_lock_seek(is, 0, SEEK_SET, error)) { g_free(buffer); return NULL; } @@ -427,14 +431,13 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) if (sample_format == SampleFormat::UNDEFINED) return; - GError *error = NULL; + Error error; AudioFormat audio_format; if (!audio_format_init_checked(audio_format, codec_context->sample_rate, sample_format, - codec_context->channels, &error)) { - g_warning("%s", error->message); - g_error_free(error); + codec_context->channels, error)) { + g_warning("%s", error.GetMessage()); avformat_close_input(&format_context); return; } diff --git a/src/decoder/FlacCommon.cxx b/src/decoder/FlacCommon.cxx index 5bcc20b97..62409d3cc 100644 --- a/src/decoder/FlacCommon.cxx +++ b/src/decoder/FlacCommon.cxx @@ -26,6 +26,7 @@ #include "FlacMetadata.hxx" #include "FlacPcm.hxx" #include "CheckAudioFormat.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -68,13 +69,12 @@ flac_got_stream_info(struct flac_data *data, if (data->initialized || data->unsupported) return; - GError *error = nullptr; + Error error; if (!audio_format_init_checked(data->audio_format, stream_info->sample_rate, flac_sample_format(stream_info->bits_per_sample), - stream_info->channels, &error)) { - g_warning("%s", error->message); - g_error_free(error); + stream_info->channels, error)) { + g_warning("%s", error.GetMessage()); data->unsupported = true; return; } @@ -131,13 +131,12 @@ flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header) if (data->unsupported) return false; - GError *error = nullptr; + Error error; if (!audio_format_init_checked(data->audio_format, header->sample_rate, flac_sample_format(header->bits_per_sample), - header->channels, &error)) { - g_warning("%s", error->message); - g_error_free(error); + header->channels, error)) { + g_warning("%s", error.GetMessage()); data->unsupported = true; return false; } diff --git a/src/decoder/FlacDecoderPlugin.cxx b/src/decoder/FlacDecoderPlugin.cxx index 5b02c1f9e..1693e109b 100644 --- a/src/decoder/FlacDecoderPlugin.cxx +++ b/src/decoder/FlacDecoderPlugin.cxx @@ -22,6 +22,7 @@ #include "FlacCommon.hxx" #include "FlacMetadata.hxx" #include "OggCodec.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -330,7 +331,7 @@ oggflac_decode(struct decoder *decoder, struct input_stream *input_stream) /* rewind the stream, because ogg_codec_detect() has moved it */ - input_stream_lock_seek(input_stream, 0, SEEK_SET, nullptr); + input_stream_lock_seek(input_stream, 0, SEEK_SET, IgnoreError()); flac_decode_internal(decoder, input_stream, true); } diff --git a/src/decoder/FlacIOHandle.cxx b/src/decoder/FlacIOHandle.cxx index 16a07a9d1..cf877414b 100644 --- a/src/decoder/FlacIOHandle.cxx +++ b/src/decoder/FlacIOHandle.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "FlacIOHandle.hxx" -#include "io_error.h" +#include "util/Error.hxx" #include "gcc.h" #include <errno.h> @@ -35,21 +35,20 @@ FlacIORead(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle) /* libFLAC is very picky about short reads, and expects the IO callback to fill the whole buffer (undocumented!) */ - GError *error = nullptr; + Error error; while (p < end) { - size_t nbytes = input_stream_lock_read(is, p, end - p, &error); + size_t nbytes = input_stream_lock_read(is, p, end - p, error); if (nbytes == 0) { - if (error == nullptr) + if (!error.IsDefined()) /* end of file */ break; - if (error->domain == errno_quark()) - errno = error->code; + if (error.IsDomain(errno_domain)) + errno = error.GetCode(); else /* just some random non-zero errno value */ errno = EINVAL; - g_error_free(error); return 0; } @@ -67,7 +66,8 @@ FlacIOSeek(FLAC__IOHandle handle, FLAC__int64 offset, int whence) { input_stream *is = (input_stream *)handle; - return input_stream_lock_seek(is, offset, whence, nullptr) ? 0 : -1; + Error error; + return input_stream_lock_seek(is, offset, whence, error) ? 0 : -1; } static FLAC__int64 diff --git a/src/decoder/FlacInput.cxx b/src/decoder/FlacInput.cxx index 0bb5ec7d7..46f213787 100644 --- a/src/decoder/FlacInput.cxx +++ b/src/decoder/FlacInput.cxx @@ -20,8 +20,9 @@ #include "config.h" #include "FlacInput.hxx" #include "DecoderAPI.hxx" -#include "gcc.h" #include "InputStream.hxx" +#include "util/Error.hxx" +#include "gcc.h" FLAC__StreamDecoderReadStatus FlacInput::Read(FLAC__byte buffer[], size_t *bytes) @@ -47,9 +48,10 @@ FlacInput::Seek(FLAC__uint64 absolute_byte_offset) if (!input_stream->seekable) return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; + ::Error error; if (!input_stream_lock_seek(input_stream, absolute_byte_offset, SEEK_SET, - nullptr)) + error)) return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; return FLAC__STREAM_DECODER_SEEK_STATUS_OK; diff --git a/src/decoder/FluidsynthDecoderPlugin.cxx b/src/decoder/FluidsynthDecoderPlugin.cxx index 9e9c9b2ce..66345e293 100644 --- a/src/decoder/FluidsynthDecoderPlugin.cxx +++ b/src/decoder/FluidsynthDecoderPlugin.cxx @@ -21,6 +21,7 @@ #include "FluidsynthDecoderPlugin.hxx" #include "DecoderAPI.hxx" #include "CheckAudioFormat.hxx" +#include "util/Error.hxx" #include "conf.h" #include <glib.h> @@ -73,12 +74,11 @@ fluidsynth_mpd_log_function(int level, char *message, gcc_unused void *data) static bool fluidsynth_init(const config_param ¶m) { - GError *error = nullptr; + Error error; sample_rate = param.GetBlockValue("sample_rate", 48000u); - if (!audio_check_sample_rate(sample_rate, &error)) { - g_warning("%s\n", error->message); - g_error_free(error); + if (!audio_check_sample_rate(sample_rate, error)) { + g_warning("%s", error.GetMessage()); return false; } diff --git a/src/decoder/GmeDecoderPlugin.cxx b/src/decoder/GmeDecoderPlugin.cxx index d8edbe4cb..006161c78 100644 --- a/src/decoder/GmeDecoderPlugin.cxx +++ b/src/decoder/GmeDecoderPlugin.cxx @@ -23,6 +23,7 @@ #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" #include "util/UriUtil.hxx" +#include "util/Error.hxx" #include <glib.h> #include <assert.h> @@ -152,13 +153,12 @@ gme_file_decode(struct decoder *decoder, const char *path_fs) /* initialize the MPD decoder */ - GError *error = nullptr; + Error error; AudioFormat audio_format; if (!audio_format_init_checked(audio_format, GME_SAMPLE_RATE, SampleFormat::S16, GME_CHANNELS, - &error)) { - g_warning("%s", error->message); - g_error_free(error); + error)) { + g_warning("%s", error.GetMessage()); gme_free_info(ti); gme_delete(emu); return; diff --git a/src/decoder/MadDecoderPlugin.cxx b/src/decoder/MadDecoderPlugin.cxx index 29abfafbd..f77563fb2 100644 --- a/src/decoder/MadDecoderPlugin.cxx +++ b/src/decoder/MadDecoderPlugin.cxx @@ -25,6 +25,7 @@ #include "TagRva2.hxx" #include "TagHandler.hxx" #include "CheckAudioFormat.hxx" +#include "util/Error.hxx" #include <assert.h> #include <unistd.h> @@ -203,8 +204,9 @@ MadDecoder::MadDecoder(struct decoder *_decoder, inline bool MadDecoder::Seek(long offset) { + Error error; if (!input_stream_lock_seek(input_stream, offset, SEEK_SET, - nullptr)) + error)) return false; mad_stream_buffer(&stream, input_buffer, 0); @@ -1124,16 +1126,14 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) return; } + Error error; AudioFormat audio_format; - GError *error = nullptr; if (!audio_format_init_checked(audio_format, data.frame.header.samplerate, SampleFormat::S24_P32, MAD_NCHANNELS(&data.frame.header), - &error)) { - g_warning("%s", error->message); - g_error_free(error); - + error)) { + g_warning("%s", error.GetMessage()); delete tag; return; } diff --git a/src/decoder/MpcdecDecoderPlugin.cxx b/src/decoder/MpcdecDecoderPlugin.cxx index cfb9c034b..35d5ce0df 100644 --- a/src/decoder/MpcdecDecoderPlugin.cxx +++ b/src/decoder/MpcdecDecoderPlugin.cxx @@ -22,6 +22,7 @@ #include "DecoderAPI.hxx" #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" +#include "util/Error.hxx" #include <mpc/mpcdec.h> @@ -53,7 +54,8 @@ mpc_seek_cb(mpc_reader *reader, mpc_int32_t offset) struct mpc_decoder_data *data = (struct mpc_decoder_data *)reader->data; - return input_stream_lock_seek(data->is, offset, SEEK_SET, nullptr); + return input_stream_lock_seek(data->is, offset, SEEK_SET, + IgnoreError()); } static mpc_int32_t @@ -153,13 +155,12 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) mpc_streaminfo info; mpc_demux_get_info(demux, &info); - GError *error = nullptr; + Error error; AudioFormat audio_format; if (!audio_format_init_checked(audio_format, info.sample_freq, SampleFormat::S24_P32, - info.channels, &error)) { - g_warning("%s", error->message); - g_error_free(error); + info.channels, error)) { + g_warning("%s", error.GetMessage()); mpc_demux_exit(demux); return; } diff --git a/src/decoder/Mpg123DecoderPlugin.cxx b/src/decoder/Mpg123DecoderPlugin.cxx index 05fe4717c..c30455121 100644 --- a/src/decoder/Mpg123DecoderPlugin.cxx +++ b/src/decoder/Mpg123DecoderPlugin.cxx @@ -22,6 +22,7 @@ #include "DecoderAPI.hxx" #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -58,7 +59,6 @@ static bool mpd_mpg123_open(mpg123_handle *handle, const char *path_fs, AudioFormat &audio_format) { - GError *gerror = nullptr; char *path_dup; int error; int channels, encoding; @@ -90,10 +90,10 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs, return false; } + Error error2; if (!audio_format_init_checked(audio_format, rate, SampleFormat::S16, - channels, &gerror)) { - g_warning("%s", gerror->message); - g_error_free(gerror); + channels, error2)) { + g_warning("%s", error2.GetMessage()); return false; } diff --git a/src/decoder/OpusDecoderPlugin.cxx b/src/decoder/OpusDecoderPlugin.cxx index b6835f760..18da812ab 100644 --- a/src/decoder/OpusDecoderPlugin.cxx +++ b/src/decoder/OpusDecoderPlugin.cxx @@ -29,6 +29,7 @@ #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" #include "InputStream.hxx" +#include "util/Error.hxx" #include <opus.h> #include <ogg/ogg.h> @@ -271,7 +272,7 @@ mpd_opus_stream_decode(struct decoder *decoder, /* rewind the stream, because ogg_codec_detect() has moved it */ - input_stream_lock_seek(input_stream, 0, SEEK_SET, nullptr); + input_stream_lock_seek(input_stream, 0, SEEK_SET, IgnoreError()); MPDOpusDecoder d(decoder, input_stream); OggSyncState oy(*input_stream, decoder); @@ -302,7 +303,8 @@ SeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet, oy.Reset(); - return input_stream_lock_seek(is, -65536, SEEK_END, nullptr) && + Error error; + return input_stream_lock_seek(is, -65536, SEEK_END, error) && oy.ExpectPageSeekIn(os) && OggFindEOS(oy, os, packet); } diff --git a/src/decoder/PcmDecoderPlugin.cxx b/src/decoder/PcmDecoderPlugin.cxx index 8976f511f..f47b54d03 100644 --- a/src/decoder/PcmDecoderPlugin.cxx +++ b/src/decoder/PcmDecoderPlugin.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "decoder/PcmDecoderPlugin.hxx" #include "DecoderAPI.hxx" +#include "util/Error.hxx" extern "C" { #include "util/byte_reverse.h" @@ -46,7 +47,6 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is) const bool reverse_endian = mime != nullptr && strcmp(mime, "audio/x-mpd-cdda-pcm-reverse") == 0; - GError *error = nullptr; enum decoder_command cmd; const double time_to_size = audio_format.GetTimeToSize(); @@ -81,12 +81,13 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is) if (cmd == DECODE_COMMAND_SEEK) { goffset offset = (goffset)(time_to_size * decoder_seek_where(decoder)); + + Error error; if (input_stream_lock_seek(is, offset, SEEK_SET, - &error)) { + error)) { decoder_command_finished(decoder); } else { - g_warning("seeking failed: %s", error->message); - g_error_free(error); + g_warning("seeking failed: %s", error.GetMessage()); decoder_seek_error(decoder); } diff --git a/src/decoder/SndfileDecoderPlugin.cxx b/src/decoder/SndfileDecoderPlugin.cxx index 29911a04e..0b83c142a 100644 --- a/src/decoder/SndfileDecoderPlugin.cxx +++ b/src/decoder/SndfileDecoderPlugin.cxx @@ -22,6 +22,7 @@ #include "DecoderAPI.hxx" #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" +#include "util/Error.hxx" #include <sndfile.h> @@ -40,10 +41,8 @@ static sf_count_t sndfile_vio_seek(sf_count_t offset, int whence, void *user_data) { struct input_stream *is = (struct input_stream *)user_data; - bool success; - success = input_stream_lock_seek(is, offset, whence, nullptr); - if (!success) + if (!input_stream_lock_seek(is, offset, whence, IgnoreError())) return -1; return input_stream_get_offset(is); @@ -53,13 +52,11 @@ static sf_count_t sndfile_vio_read(void *ptr, sf_count_t count, void *user_data) { struct input_stream *is = (struct input_stream *)user_data; - GError *error = nullptr; - size_t nbytes; - nbytes = input_stream_lock_read(is, ptr, count, &error); - if (nbytes == 0 && error != nullptr) { - g_warning("%s", error->message); - g_error_free(error); + Error error; + size_t nbytes = input_stream_lock_read(is, ptr, count, error); + if (nbytes == 0 && error.IsDefined()) { + g_warning("%s", error.GetMessage()); return -1; } @@ -116,7 +113,6 @@ time_to_frame(float t, const AudioFormat *audio_format) static void sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) { - GError *error = nullptr; SNDFILE *sf; SF_INFO info; size_t frame_size; @@ -135,12 +131,12 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) /* for now, always read 32 bit samples. Later, we could lower MPD's CPU usage by reading 16 bit samples with sf_readf_short() on low-quality source files. */ + Error error; AudioFormat audio_format; if (!audio_format_init_checked(audio_format, info.samplerate, SampleFormat::S32, - info.channels, &error)) { - g_warning("%s", error->message); - g_error_free(error); + info.channels, error)) { + g_warning("%s", error.GetMessage()); return; } diff --git a/src/decoder/VorbisDecoderPlugin.cxx b/src/decoder/VorbisDecoderPlugin.cxx index b9181ef75..3626fe162 100644 --- a/src/decoder/VorbisDecoderPlugin.cxx +++ b/src/decoder/VorbisDecoderPlugin.cxx @@ -23,6 +23,7 @@ #include "DecoderAPI.hxx" #include "InputStream.hxx" #include "OggCodec.hxx" +#include "util/Error.hxx" #include "util/UriUtil.hxx" #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" @@ -80,9 +81,10 @@ static int ogg_seek_cb(void *data, ogg_int64_t offset, int whence) { struct vorbis_input_stream *vis = (struct vorbis_input_stream *)data; + Error error; return vis->seekable && (!vis->decoder || decoder_get_command(vis->decoder) != DECODE_COMMAND_STOP) && - input_stream_lock_seek(vis->input_stream, offset, whence, NULL) + input_stream_lock_seek(vis->input_stream, offset, whence, error) ? 0 : -1; } @@ -182,14 +184,12 @@ static void vorbis_stream_decode(struct decoder *decoder, struct input_stream *input_stream) { - GError *error = NULL; - if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS) return; /* rewind the stream, because ogg_codec_detect() has moved it */ - input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); + input_stream_lock_seek(input_stream, 0, SEEK_SET, IgnoreError()); struct vorbis_input_stream vis; OggVorbis_File vf; @@ -202,6 +202,7 @@ vorbis_stream_decode(struct decoder *decoder, return; } + Error error; AudioFormat audio_format; if (!audio_format_init_checked(audio_format, vi->rate, #ifdef HAVE_TREMOR @@ -209,9 +210,8 @@ vorbis_stream_decode(struct decoder *decoder, #else SampleFormat::FLOAT, #endif - vi->channels, &error)) { - g_warning("%s", error->message); - g_error_free(error); + vi->channels, error)) { + g_warning("%s", error.GetMessage()); return; } diff --git a/src/decoder/WavpackDecoderPlugin.cxx b/src/decoder/WavpackDecoderPlugin.cxx index 6b6c7f2ea..528ecdc3c 100644 --- a/src/decoder/WavpackDecoderPlugin.cxx +++ b/src/decoder/WavpackDecoderPlugin.cxx @@ -24,6 +24,7 @@ #include "CheckAudioFormat.hxx" #include "TagHandler.hxx" #include "ApeTag.hxx" +#include "util/Error.hxx" #include <wavpack/wavpack.h> #include <glib.h> @@ -137,7 +138,6 @@ wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample) static void wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek) { - GError *error = NULL; bool is_float; SampleFormat sample_format; AudioFormat audio_format; @@ -150,12 +150,12 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek) wavpack_bits_to_sample_format(is_float, WavpackGetBytesPerSample(wpc)); + Error error; if (!audio_format_init_checked(audio_format, WavpackGetSampleRate(wpc), sample_format, - WavpackGetNumChannels(wpc), &error)) { - g_warning("%s", error->message); - g_error_free(error); + WavpackGetNumChannels(wpc), error)) { + g_warning("%s", error.GetMessage()); return; } @@ -401,14 +401,16 @@ wavpack_input_get_pos(void *id) static int wavpack_input_set_pos_abs(void *id, uint32_t pos) { - return input_stream_lock_seek(wpin(id)->is, pos, SEEK_SET, NULL) + Error error; + return input_stream_lock_seek(wpin(id)->is, pos, SEEK_SET, error) ? 0 : -1; } static int wavpack_input_set_pos_rel(void *id, int32_t delta, int mode) { - return input_stream_lock_seek(wpin(id)->is, delta, mode, NULL) + Error error; + return input_stream_lock_seek(wpin(id)->is, delta, mode, error) ? 0 : -1; } @@ -476,7 +478,9 @@ wavpack_open_wvc(struct decoder *decoder, const char *uri, return nullptr; wvc_url = g_strconcat(uri, "c", NULL); - is_wvc = input_stream_open(wvc_url, mutex, cond, NULL); + + Error error; + is_wvc = input_stream_open(wvc_url, mutex, cond, error); g_free(wvc_url); if (is_wvc == NULL) diff --git a/src/decoder/WildmidiDecoderPlugin.cxx b/src/decoder/WildmidiDecoderPlugin.cxx index c7bd3985e..738073d52 100644 --- a/src/decoder/WildmidiDecoderPlugin.cxx +++ b/src/decoder/WildmidiDecoderPlugin.cxx @@ -21,6 +21,7 @@ #include "WildmidiDecoderPlugin.hxx" #include "DecoderAPI.hxx" #include "TagHandler.hxx" +#include "util/Error.hxx" #include "fs/Path.hxx" #include "fs/FileSystem.hxx" #include "system/FatalError.hxx" @@ -39,10 +40,10 @@ static constexpr unsigned WILDMIDI_SAMPLE_RATE = 48000; static bool wildmidi_init(const config_param ¶m) { - GError *error = nullptr; + Error error; const Path path = param.GetBlockPath("config_file", "/etc/timidity/timidity.cfg", - &error); + error); if (path.IsNull()) FatalError(error); diff --git a/src/encoder/FlacEncoderPlugin.cxx b/src/encoder/FlacEncoderPlugin.cxx index 509d9bfdd..5a77e24a7 100644 --- a/src/encoder/FlacEncoderPlugin.cxx +++ b/src/encoder/FlacEncoderPlugin.cxx @@ -22,6 +22,9 @@ #include "EncoderAPI.hxx" #include "AudioFormat.hxx" #include "pcm/PcmBuffer.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "util/fifo_buffer.h" extern "C" { @@ -58,15 +61,11 @@ struct flac_encoder { flac_encoder():encoder(flac_encoder_plugin) {} }; -static inline GQuark -flac_encoder_quark(void) -{ - return g_quark_from_static_string("flac_encoder"); -} +static constexpr Domain flac_encoder_domain("vorbis_encoder"); static bool flac_encoder_configure(struct flac_encoder *encoder, const config_param ¶m, - gcc_unused GError **error) + gcc_unused Error &error) { encoder->compression = param.GetBlockValue("compression", 5u); @@ -74,7 +73,7 @@ flac_encoder_configure(struct flac_encoder *encoder, const config_param ¶m, } static Encoder * -flac_encoder_init(const config_param ¶m, GError **error) +flac_encoder_init(const config_param ¶m, Error &error) { flac_encoder *encoder = new flac_encoder(); @@ -100,35 +99,35 @@ flac_encoder_finish(Encoder *_encoder) static bool flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample, - GError **error) + Error &error) { if ( !FLAC__stream_encoder_set_compression_level(encoder->fse, encoder->compression)) { - g_set_error(error, flac_encoder_quark(), 0, - "error setting flac compression to %d", - encoder->compression); + error.Format(config_domain, + "error setting flac compression to %d", + encoder->compression); return false; } if ( !FLAC__stream_encoder_set_channels(encoder->fse, encoder->audio_format.channels)) { - g_set_error(error, flac_encoder_quark(), 0, - "error setting flac channels num to %d", - encoder->audio_format.channels); + error.Format(config_domain, + "error setting flac channels num to %d", + encoder->audio_format.channels); return false; } if ( !FLAC__stream_encoder_set_bits_per_sample(encoder->fse, bits_per_sample)) { - g_set_error(error, flac_encoder_quark(), 0, - "error setting flac bit format to %d", - bits_per_sample); + error.Format(config_domain, + "error setting flac bit format to %d", + bits_per_sample); return false; } if ( !FLAC__stream_encoder_set_sample_rate(encoder->fse, encoder->audio_format.sample_rate)) { - g_set_error(error, flac_encoder_quark(), 0, - "error setting flac sample rate to %d", - encoder->audio_format.sample_rate); + error.Format(config_domain, + "error setting flac sample rate to %d", + encoder->audio_format.sample_rate); return false; } return true; @@ -161,8 +160,7 @@ flac_encoder_close(Encoder *_encoder) } static bool -flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, - GError **error) +flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error) { struct flac_encoder *encoder = (struct flac_encoder *)_encoder; unsigned bits_per_sample; @@ -191,8 +189,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, /* allocate the encoder */ encoder->fse = FLAC__stream_encoder_new(); if (encoder->fse == nullptr) { - g_set_error(error, flac_encoder_quark(), 0, - "flac_new() failed"); + error.Set(flac_encoder_domain, "flac_new() failed"); return false; } @@ -213,9 +210,9 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, nullptr, nullptr, nullptr, encoder); if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { - g_set_error(error, flac_encoder_quark(), 0, - "failed to initialize encoder: %s\n", - FLAC__StreamEncoderInitStatusString[init_status]); + error.Format(flac_encoder_domain, + "failed to initialize encoder: %s\n", + FLAC__StreamEncoderInitStatusString[init_status]); flac_encoder_close(_encoder); return false; } @@ -226,7 +223,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, static bool -flac_encoder_flush(Encoder *_encoder, gcc_unused GError **error) +flac_encoder_flush(Encoder *_encoder, gcc_unused Error &error) { struct flac_encoder *encoder = (struct flac_encoder *)_encoder; @@ -255,7 +252,7 @@ pcm16_to_flac(int32_t *out, const int16_t *in, unsigned num_samples) static bool flac_encoder_write(Encoder *_encoder, const void *data, size_t length, - gcc_unused GError **error) + gcc_unused Error &error) { struct flac_encoder *encoder = (struct flac_encoder *)_encoder; unsigned num_frames, num_samples; @@ -298,8 +295,7 @@ flac_encoder_write(Encoder *_encoder, if (!FLAC__stream_encoder_process_interleaved(encoder->fse, (const FLAC__int32 *)buffer, num_frames)) { - g_set_error(error, flac_encoder_quark(), 0, - "flac encoder process failed"); + error.Set(flac_encoder_domain, "flac encoder process failed"); return false; } diff --git a/src/encoder/LameEncoderPlugin.cxx b/src/encoder/LameEncoderPlugin.cxx index 36e60dc4d..d3ed49a31 100644 --- a/src/encoder/LameEncoderPlugin.cxx +++ b/src/encoder/LameEncoderPlugin.cxx @@ -21,8 +21,11 @@ #include "LameEncoderPlugin.hxx" #include "EncoderAPI.hxx" #include "AudioFormat.hxx" +#include "ConfigError.hxx" #include "util/ReusableArray.hxx" #include "util/Manual.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <lame/lame.h> @@ -45,17 +48,13 @@ struct LameEncoder final { LameEncoder():encoder(lame_encoder_plugin) {} - bool Configure(const config_param ¶m, GError **error); + bool Configure(const config_param ¶m, Error &error); }; -static inline GQuark -lame_encoder_quark(void) -{ - return g_quark_from_static_string("lame_encoder"); -} +static constexpr Domain lame_encoder_domain("lame_encoder"); bool -LameEncoder::Configure(const config_param ¶m, GError **error) +LameEncoder::Configure(const config_param ¶m, Error &error) { const char *value; char *endptr; @@ -67,18 +66,18 @@ LameEncoder::Configure(const config_param ¶m, GError **error) quality = g_ascii_strtod(value, &endptr); if (*endptr != '\0' || quality < -1.0 || quality > 10.0) { - g_set_error(error, lame_encoder_quark(), 0, - "quality \"%s\" is not a number in the " - "range -1 to 10, line %i", - value, param.line); + error.Format(config_domain, + "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, lame_encoder_quark(), 0, - "quality and bitrate are " - "both defined (line %i)", - param.line); + error.Format(config_domain, + "quality and bitrate are " + "both defined (line %i)", + param.line); return false; } } else { @@ -86,10 +85,10 @@ LameEncoder::Configure(const config_param ¶m, GError **error) value = param.GetBlockValue("bitrate"); if (value == nullptr) { - g_set_error(error, lame_encoder_quark(), 0, - "neither bitrate nor quality defined " - "at line %i", - param.line); + error.Format(config_domain, + "neither bitrate nor quality defined " + "at line %i", + param.line); return false; } @@ -97,9 +96,9 @@ LameEncoder::Configure(const config_param ¶m, GError **error) bitrate = g_ascii_strtoll(value, &endptr, 10); if (*endptr != '\0' || bitrate <= 0) { - g_set_error(error, lame_encoder_quark(), 0, - "bitrate at line %i should be a positive integer", - param.line); + error.Format(config_domain, + "bitrate at line %i should be a positive integer", + param.line); return false; } } @@ -108,12 +107,12 @@ LameEncoder::Configure(const config_param ¶m, GError **error) } static Encoder * -lame_encoder_init(const config_param ¶m, GError **error_r) +lame_encoder_init(const config_param ¶m, Error &error) { LameEncoder *encoder = new LameEncoder(); /* load configuration from "param" */ - if (!encoder->Configure(param, error_r)) { + if (!encoder->Configure(param, error)) { /* configuration has failed, roll back and return error */ delete encoder; return nullptr; @@ -133,55 +132,55 @@ lame_encoder_finish(Encoder *_encoder) } static bool -lame_encoder_setup(LameEncoder *encoder, GError **error) +lame_encoder_setup(LameEncoder *encoder, Error &error) { if (encoder->quality >= -1.0) { /* a quality was configured (VBR) */ if (0 != lame_set_VBR(encoder->gfp, vbr_rh)) { - g_set_error(error, lame_encoder_quark(), 0, - "error setting lame VBR mode"); + error.Set(lame_encoder_domain, + "error setting lame VBR mode"); return false; } if (0 != lame_set_VBR_q(encoder->gfp, encoder->quality)) { - g_set_error(error, lame_encoder_quark(), 0, - "error setting lame VBR quality"); + error.Set(lame_encoder_domain, + "error setting lame VBR quality"); return false; } } else { /* a bit rate was configured */ if (0 != lame_set_brate(encoder->gfp, encoder->bitrate)) { - g_set_error(error, lame_encoder_quark(), 0, - "error setting lame bitrate"); + error.Set(lame_encoder_domain, + "error setting lame bitrate"); return false; } } if (0 != lame_set_num_channels(encoder->gfp, encoder->audio_format.channels)) { - g_set_error(error, lame_encoder_quark(), 0, - "error setting lame num channels"); + error.Set(lame_encoder_domain, + "error setting lame num channels"); return false; } if (0 != lame_set_in_samplerate(encoder->gfp, encoder->audio_format.sample_rate)) { - g_set_error(error, lame_encoder_quark(), 0, - "error setting lame sample rate"); + error.Set(lame_encoder_domain, + "error setting lame sample rate"); return false; } if (0 != lame_set_out_samplerate(encoder->gfp, encoder->audio_format.sample_rate)) { - g_set_error(error, lame_encoder_quark(), 0, - "error setting lame out sample rate"); + error.Set(lame_encoder_domain, + "error setting lame out sample rate"); return false; } if (0 > lame_init_params(encoder->gfp)) { - g_set_error(error, lame_encoder_quark(), 0, - "error initializing lame params"); + error.Set(lame_encoder_domain, + "error initializing lame params"); return false; } @@ -189,8 +188,7 @@ lame_encoder_setup(LameEncoder *encoder, GError **error) } static bool -lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, - GError **error) +lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error) { LameEncoder *encoder = (LameEncoder *)_encoder; @@ -201,8 +199,7 @@ lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, encoder->gfp = lame_init(); if (encoder->gfp == nullptr) { - g_set_error(error, lame_encoder_quark(), 0, - "lame_init() failed"); + error.Set(lame_encoder_domain, "lame_init() failed"); return false; } @@ -229,7 +226,7 @@ lame_encoder_close(Encoder *_encoder) static bool lame_encoder_write(Encoder *_encoder, const void *data, size_t length, - gcc_unused GError **error) + gcc_unused Error &error) { LameEncoder *encoder = (LameEncoder *)_encoder; const int16_t *src = (const int16_t*)data; @@ -254,8 +251,7 @@ lame_encoder_write(Encoder *_encoder, output_buffer_size); if (bytes_out < 0) { - g_set_error(error, lame_encoder_quark(), 0, - "lame encoder failed"); + error.Set(lame_encoder_domain, "lame encoder failed"); return false; } diff --git a/src/encoder/NullEncoderPlugin.cxx b/src/encoder/NullEncoderPlugin.cxx index 5c01fbd98..38bc5cbe3 100644 --- a/src/encoder/NullEncoderPlugin.cxx +++ b/src/encoder/NullEncoderPlugin.cxx @@ -26,8 +26,6 @@ extern "C" { } #include "gcc.h" -#include <glib.h> - #include <assert.h> #include <string.h> @@ -41,7 +39,7 @@ struct NullEncoder final { static Encoder * null_encoder_init(gcc_unused const config_param ¶m, - gcc_unused GError **error) + gcc_unused Error &error) { NullEncoder *encoder = new NullEncoder(); return &encoder->encoder; @@ -67,7 +65,7 @@ null_encoder_close(Encoder *_encoder) static bool null_encoder_open(Encoder *_encoder, gcc_unused AudioFormat &audio_format, - gcc_unused GError **error) + gcc_unused Error &error) { NullEncoder *encoder = (NullEncoder *)_encoder; encoder->buffer = growing_fifo_new(); @@ -77,7 +75,7 @@ null_encoder_open(Encoder *_encoder, static bool null_encoder_write(Encoder *_encoder, const void *data, size_t length, - gcc_unused GError **error) + gcc_unused Error &error) { NullEncoder *encoder = (NullEncoder *)_encoder; diff --git a/src/encoder/OpusEncoderPlugin.cxx b/src/encoder/OpusEncoderPlugin.cxx index 9bb339312..c6e523ec4 100644 --- a/src/encoder/OpusEncoderPlugin.cxx +++ b/src/encoder/OpusEncoderPlugin.cxx @@ -22,11 +22,15 @@ #include "OggStream.hxx" #include "EncoderAPI.hxx" #include "AudioFormat.hxx" -#include "mpd_error.h" +#include "ConfigError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <opus.h> #include <ogg/ogg.h> +#include <glib.h> + #include <assert.h> #undef G_LOG_DOMAIN @@ -66,16 +70,11 @@ struct opus_encoder { opus_encoder():encoder(opus_encoder_plugin) {} }; -gcc_const -static inline GQuark -opus_encoder_quark(void) -{ - return g_quark_from_static_string("opus_encoder"); -} +static constexpr Domain opus_encoder_domain("opus_encoder"); static bool opus_encoder_configure(struct opus_encoder *encoder, - const config_param ¶m, GError **error_r) + const config_param ¶m, Error &error) { const char *value = param.GetBlockValue("bitrate", "auto"); if (strcmp(value, "auto") == 0) @@ -87,16 +86,14 @@ opus_encoder_configure(struct opus_encoder *encoder, encoder->bitrate = strtoul(value, &endptr, 10); if (endptr == value || *endptr != 0 || encoder->bitrate < 500 || encoder->bitrate > 512000) { - g_set_error(error_r, opus_encoder_quark(), 0, - "Invalid bit rate"); + error.Set(config_domain, "Invalid bit rate"); return false; } } encoder->complexity = param.GetBlockValue("complexity", 10u); if (encoder->complexity > 10) { - g_set_error(error_r, opus_encoder_quark(), 0, - "Invalid complexity"); + error.Format(config_domain, "Invalid complexity"); return false; } @@ -108,8 +105,7 @@ opus_encoder_configure(struct opus_encoder *encoder, else if (strcmp(value, "music") == 0) encoder->signal = OPUS_SIGNAL_MUSIC; else { - g_set_error(error_r, opus_encoder_quark(), 0, - "Invalid signal"); + error.Format(config_domain, "Invalid signal"); return false; } @@ -117,7 +113,7 @@ opus_encoder_configure(struct opus_encoder *encoder, } static Encoder * -opus_encoder_init(const config_param ¶m, GError **error) +opus_encoder_init(const config_param ¶m, Error &error) { opus_encoder *encoder = new opus_encoder(); @@ -144,7 +140,7 @@ opus_encoder_finish(Encoder *_encoder) static bool opus_encoder_open(Encoder *_encoder, AudioFormat &audio_format, - GError **error_r) + Error &error) { struct opus_encoder *encoder = (struct opus_encoder *)_encoder; @@ -171,14 +167,14 @@ opus_encoder_open(Encoder *_encoder, encoder->audio_format = audio_format; encoder->frame_size = audio_format.GetFrameSize(); - int error; + int error_code; encoder->enc = opus_encoder_create(audio_format.sample_rate, audio_format.channels, OPUS_APPLICATION_AUDIO, - &error); + &error_code); if (encoder->enc == nullptr) { - g_set_error_literal(error_r, opus_encoder_quark(), error, - opus_strerror(error)); + error.Set(opus_encoder_domain, error_code, + opus_strerror(error_code)); return false; } @@ -212,7 +208,7 @@ opus_encoder_close(Encoder *_encoder) static bool opus_encoder_do_encode(struct opus_encoder *encoder, bool eos, - GError **error_r) + Error &error) { assert(encoder->buffer_position == encoder->buffer_size); @@ -229,8 +225,7 @@ opus_encoder_do_encode(struct opus_encoder *encoder, bool eos, encoder->buffer2, sizeof(encoder->buffer2)); if (result < 0) { - g_set_error_literal(error_r, opus_encoder_quark(), 0, - "Opus encoder error"); + error.Set(opus_encoder_domain, "Opus encoder error"); return false; } @@ -251,7 +246,7 @@ opus_encoder_do_encode(struct opus_encoder *encoder, bool eos, } static bool -opus_encoder_end(Encoder *_encoder, GError **error_r) +opus_encoder_end(Encoder *_encoder, Error &error) { struct opus_encoder *encoder = (struct opus_encoder *)_encoder; @@ -261,11 +256,11 @@ opus_encoder_end(Encoder *_encoder, GError **error_r) encoder->buffer_size - encoder->buffer_position); encoder->buffer_position = encoder->buffer_size; - return opus_encoder_do_encode(encoder, true, error_r); + return opus_encoder_do_encode(encoder, true, error); } static bool -opus_encoder_flush(Encoder *_encoder, gcc_unused GError **error) +opus_encoder_flush(Encoder *_encoder, gcc_unused Error &error) { struct opus_encoder *encoder = (struct opus_encoder *)_encoder; @@ -275,7 +270,7 @@ opus_encoder_flush(Encoder *_encoder, gcc_unused GError **error) static bool opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames, - GError **error_r) + Error &error) { size_t fill_bytes = fill_frames * encoder->frame_size; @@ -291,7 +286,7 @@ opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames, fill_bytes -= nbytes; if (encoder->buffer_position == encoder->buffer_size && - !opus_encoder_do_encode(encoder, false, error_r)) + !opus_encoder_do_encode(encoder, false, error)) return false; } @@ -301,7 +296,7 @@ opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames, static bool opus_encoder_write(Encoder *_encoder, const void *_data, size_t length, - GError **error_r) + Error &error) { struct opus_encoder *encoder = (struct opus_encoder *)_encoder; const uint8_t *data = (const uint8_t *)_data; @@ -313,7 +308,7 @@ opus_encoder_write(Encoder *_encoder, assert(encoder->buffer_position == 0); if (!opus_encoder_write_silence(encoder, encoder->lookahead, - error_r)) + error)) return false; encoder->lookahead = 0; @@ -332,7 +327,7 @@ opus_encoder_write(Encoder *_encoder, encoder->buffer_position += nbytes; if (encoder->buffer_position == encoder->buffer_size && - !opus_encoder_do_encode(encoder, false, error_r)) + !opus_encoder_do_encode(encoder, false, error)) return false; } diff --git a/src/encoder/TwolameEncoderPlugin.cxx b/src/encoder/TwolameEncoderPlugin.cxx index 4243a579b..a04c2afe2 100644 --- a/src/encoder/TwolameEncoderPlugin.cxx +++ b/src/encoder/TwolameEncoderPlugin.cxx @@ -21,6 +21,9 @@ #include "TwolameEncoderPlugin.hxx" #include "EncoderAPI.hxx" #include "AudioFormat.hxx" +#include "ConfigError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <twolame.h> @@ -50,17 +53,13 @@ struct TwolameEncoder final { TwolameEncoder():encoder(twolame_encoder_plugin) {} - bool Configure(const config_param ¶m, GError **error); + bool Configure(const config_param ¶m, Error &error); }; -static inline GQuark -twolame_encoder_quark(void) -{ - return g_quark_from_static_string("twolame_encoder"); -} +static constexpr Domain twolame_encoder_domain("twolame_encoder"); bool -TwolameEncoder::Configure(const config_param ¶m, GError **error) +TwolameEncoder::Configure(const config_param ¶m, Error &error) { const char *value; char *endptr; @@ -72,18 +71,18 @@ TwolameEncoder::Configure(const config_param ¶m, GError **error) quality = g_ascii_strtod(value, &endptr); if (*endptr != '\0' || quality < -1.0 || quality > 10.0) { - g_set_error(error, twolame_encoder_quark(), 0, - "quality \"%s\" is not a number in the " - "range -1 to 10, line %i", - value, param.line); + error.Format(config_domain, + "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, twolame_encoder_quark(), 0, - "quality and bitrate are " - "both defined (line %i)", - param.line); + error.Format(config_domain, + "quality and bitrate are " + "both defined (line %i)", + param.line); return false; } } else { @@ -91,10 +90,10 @@ TwolameEncoder::Configure(const config_param ¶m, GError **error) value = param.GetBlockValue("bitrate"); if (value == nullptr) { - g_set_error(error, twolame_encoder_quark(), 0, - "neither bitrate nor quality defined " - "at line %i", - param.line); + error.Format(config_domain, + "neither bitrate nor quality defined " + "at line %i", + param.line); return false; } @@ -102,9 +101,9 @@ TwolameEncoder::Configure(const config_param ¶m, GError **error) bitrate = g_ascii_strtoll(value, &endptr, 10); if (*endptr != '\0' || bitrate <= 0) { - g_set_error(error, twolame_encoder_quark(), 0, - "bitrate at line %i should be a positive integer", - param.line); + error.Format(config_domain, + "bitrate at line %i should be a positive integer", + param.line); return false; } } @@ -113,7 +112,7 @@ TwolameEncoder::Configure(const config_param ¶m, GError **error) } static Encoder * -twolame_encoder_init(const config_param ¶m, GError **error_r) +twolame_encoder_init(const config_param ¶m, Error &error_r) { g_debug("libtwolame version %s", get_twolame_version()); @@ -140,48 +139,48 @@ twolame_encoder_finish(Encoder *_encoder) } static bool -twolame_encoder_setup(TwolameEncoder *encoder, GError **error) +twolame_encoder_setup(TwolameEncoder *encoder, Error &error) { if (encoder->quality >= -1.0) { /* a quality was configured (VBR) */ if (0 != twolame_set_VBR(encoder->options, true)) { - g_set_error(error, twolame_encoder_quark(), 0, - "error setting twolame VBR mode"); + error.Set(twolame_encoder_domain, + "error setting twolame VBR mode"); return false; } if (0 != twolame_set_VBR_q(encoder->options, encoder->quality)) { - g_set_error(error, twolame_encoder_quark(), 0, - "error setting twolame VBR quality"); + error.Set(twolame_encoder_domain, + "error setting twolame VBR quality"); return false; } } else { /* a bit rate was configured */ if (0 != twolame_set_brate(encoder->options, encoder->bitrate)) { - g_set_error(error, twolame_encoder_quark(), 0, - "error setting twolame bitrate"); + error.Set(twolame_encoder_domain, + "error setting twolame bitrate"); return false; } } if (0 != twolame_set_num_channels(encoder->options, encoder->audio_format.channels)) { - g_set_error(error, twolame_encoder_quark(), 0, - "error setting twolame num channels"); + error.Set(twolame_encoder_domain, + "error setting twolame num channels"); return false; } if (0 != twolame_set_in_samplerate(encoder->options, encoder->audio_format.sample_rate)) { - g_set_error(error, twolame_encoder_quark(), 0, - "error setting twolame sample rate"); + error.Set(twolame_encoder_domain, + "error setting twolame sample rate"); return false; } if (0 > twolame_init_params(encoder->options)) { - g_set_error(error, twolame_encoder_quark(), 0, - "error initializing twolame params"); + error.Set(twolame_encoder_domain, + "error initializing twolame params"); return false; } @@ -190,7 +189,7 @@ twolame_encoder_setup(TwolameEncoder *encoder, GError **error) static bool twolame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, - GError **error) + Error &error) { TwolameEncoder *encoder = (TwolameEncoder *)_encoder; @@ -201,8 +200,7 @@ twolame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, encoder->options = twolame_init(); if (encoder->options == nullptr) { - g_set_error(error, twolame_encoder_quark(), 0, - "twolame_init() failed"); + error.Set(twolame_encoder_domain, "twolame_init() failed"); return false; } @@ -227,7 +225,7 @@ twolame_encoder_close(Encoder *_encoder) } static bool -twolame_encoder_flush(Encoder *_encoder, gcc_unused GError **error) +twolame_encoder_flush(Encoder *_encoder, gcc_unused Error &error) { TwolameEncoder *encoder = (TwolameEncoder *)_encoder; @@ -238,7 +236,7 @@ twolame_encoder_flush(Encoder *_encoder, gcc_unused GError **error) static bool twolame_encoder_write(Encoder *_encoder, const void *data, size_t length, - gcc_unused GError **error) + gcc_unused Error &error) { TwolameEncoder *encoder = (TwolameEncoder *)_encoder; const int16_t *src = (const int16_t*)data; @@ -254,8 +252,7 @@ twolame_encoder_write(Encoder *_encoder, encoder->output_buffer, sizeof(encoder->output_buffer)); if (bytes_out < 0) { - g_set_error(error, twolame_encoder_quark(), 0, - "twolame encoder failed"); + error.Set(twolame_encoder_domain, "twolame encoder failed"); return false; } diff --git a/src/encoder/VorbisEncoderPlugin.cxx b/src/encoder/VorbisEncoderPlugin.cxx index 4fb6bb661..27a368766 100644 --- a/src/encoder/VorbisEncoderPlugin.cxx +++ b/src/encoder/VorbisEncoderPlugin.cxx @@ -23,10 +23,14 @@ #include "EncoderAPI.hxx" #include "Tag.hxx" #include "AudioFormat.hxx" -#include "mpd_error.h" +#include "ConfigError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <vorbis/vorbisenc.h> +#include <glib.h> + #include <assert.h> #undef G_LOG_DOMAIN @@ -54,15 +58,11 @@ struct vorbis_encoder { vorbis_encoder():encoder(vorbis_encoder_plugin) {} }; -static inline GQuark -vorbis_encoder_quark(void) -{ - return g_quark_from_static_string("vorbis_encoder"); -} +static constexpr Domain vorbis_encoder_domain("vorbis_encoder"); static bool vorbis_encoder_configure(struct vorbis_encoder *encoder, - const config_param ¶m, GError **error) + const config_param ¶m, Error &error) { const char *value = param.GetBlockValue("quality"); if (value != nullptr) { @@ -73,18 +73,18 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, if (*endptr != '\0' || encoder->quality < -1.0 || encoder->quality > 10.0) { - g_set_error(error, vorbis_encoder_quark(), 0, - "quality \"%s\" is not a number in the " - "range -1 to 10, line %i", - value, param.line); + error.Format(config_domain, + "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, vorbis_encoder_quark(), 0, - "quality and bitrate are " - "both defined (line %i)", - param.line); + error.Format(config_domain, + "quality and bitrate are " + "both defined (line %i)", + param.line); return false; } } else { @@ -92,10 +92,10 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, value = param.GetBlockValue("bitrate"); if (value == nullptr) { - g_set_error(error, vorbis_encoder_quark(), 0, - "neither bitrate nor quality defined " - "at line %i", - param.line); + error.Format(config_domain, + "neither bitrate nor quality defined " + "at line %i", + param.line); return false; } @@ -104,9 +104,9 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, char *endptr; encoder->bitrate = g_ascii_strtoll(value, &endptr, 10); if (*endptr != '\0' || encoder->bitrate <= 0) { - g_set_error(error, vorbis_encoder_quark(), 0, - "bitrate at line %i should be a positive integer", - param.line); + error.Format(config_domain, + "bitrate at line %i should be a positive integer", + param.line); return false; } } @@ -115,7 +115,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, } static Encoder * -vorbis_encoder_init(const config_param ¶m, GError **error) +vorbis_encoder_init(const config_param ¶m, Error &error) { vorbis_encoder *encoder = new vorbis_encoder(); @@ -140,7 +140,7 @@ vorbis_encoder_finish(Encoder *_encoder) } static bool -vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error) +vorbis_encoder_reinit(struct vorbis_encoder *encoder, Error &error) { vorbis_info_init(&encoder->vi); @@ -151,8 +151,8 @@ vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error) encoder->audio_format.channels, encoder->audio_format.sample_rate, encoder->quality * 0.1)) { - g_set_error(error, vorbis_encoder_quark(), 0, - "error initializing vorbis vbr"); + error.Set(vorbis_encoder_domain, + "error initializing vorbis vbr"); vorbis_info_clear(&encoder->vi); return false; } @@ -163,8 +163,8 @@ vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error) encoder->audio_format.channels, encoder->audio_format.sample_rate, -1.0, encoder->bitrate * 1000, -1.0)) { - g_set_error(error, vorbis_encoder_quark(), 0, - "error initializing vorbis encoder"); + error.Set(vorbis_encoder_domain, + "error initializing vorbis encoder"); vorbis_info_clear(&encoder->vi); return false; } @@ -203,7 +203,7 @@ vorbis_encoder_send_header(struct vorbis_encoder *encoder) static bool vorbis_encoder_open(Encoder *_encoder, AudioFormat &audio_format, - GError **error) + Error &error) { struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; @@ -250,7 +250,7 @@ vorbis_encoder_blockout(struct vorbis_encoder *encoder) } static bool -vorbis_encoder_flush(Encoder *_encoder, gcc_unused GError **error) +vorbis_encoder_flush(Encoder *_encoder, gcc_unused Error &error) { struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; @@ -259,7 +259,7 @@ vorbis_encoder_flush(Encoder *_encoder, gcc_unused GError **error) } static bool -vorbis_encoder_pre_tag(Encoder *_encoder, gcc_unused GError **error) +vorbis_encoder_pre_tag(Encoder *_encoder, gcc_unused Error &error) { struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; @@ -290,7 +290,7 @@ copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag *tag) static bool vorbis_encoder_tag(Encoder *_encoder, const Tag *tag, - gcc_unused GError **error) + gcc_unused Error &error) { struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; vorbis_comment comment; @@ -324,7 +324,7 @@ interleaved_to_vorbis_buffer(float **dest, const float *src, static bool vorbis_encoder_write(Encoder *_encoder, const void *data, size_t length, - gcc_unused GError **error) + gcc_unused Error &error) { struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; diff --git a/src/encoder/WaveEncoderPlugin.cxx b/src/encoder/WaveEncoderPlugin.cxx index 17560dfea..493b07b61 100644 --- a/src/encoder/WaveEncoderPlugin.cxx +++ b/src/encoder/WaveEncoderPlugin.cxx @@ -84,7 +84,7 @@ fill_wave_header(struct wave_header *header, int channels, int bits, static Encoder * wave_encoder_init(gcc_unused const config_param ¶m, - gcc_unused GError **error) + gcc_unused Error &error) { WaveEncoder *encoder = new WaveEncoder(); return &encoder->encoder; @@ -101,7 +101,7 @@ wave_encoder_finish(Encoder *_encoder) static bool wave_encoder_open(Encoder *_encoder, AudioFormat &audio_format, - gcc_unused GError **error) + gcc_unused Error &error) { WaveEncoder *encoder = (WaveEncoder *)_encoder; @@ -196,7 +196,7 @@ pcm24_to_wave(uint8_t *dst8, const uint32_t *src32, size_t length) static bool wave_encoder_write(Encoder *_encoder, const void *src, size_t length, - gcc_unused GError **error) + gcc_unused Error &error) { WaveEncoder *encoder = (WaveEncoder *)_encoder; diff --git a/src/event/BufferedSocket.cxx b/src/event/BufferedSocket.cxx index ac3d2cf0e..f333a5987 100644 --- a/src/event/BufferedSocket.cxx +++ b/src/event/BufferedSocket.cxx @@ -21,6 +21,8 @@ #include "BufferedSocket.hxx" #include "system/SocketError.hxx" #include "util/fifo_buffer.h" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <assert.h> #include <stdint.h> @@ -97,8 +99,11 @@ BufferedSocket::ResumeInput() case InputResult::MORE: if (fifo_buffer_is_full(input)) { // TODO - OnSocketError(g_error_new_literal(g_quark_from_static_string("buffered_socket"), - 0, "Input buffer is full")); + static constexpr Domain buffered_socket_domain("buffered_socket"); + Error error; + error.Set(buffered_socket_domain, + "Input buffer is full"); + OnSocketError(std::move(error)); return false; } diff --git a/src/event/BufferedSocket.hxx b/src/event/BufferedSocket.hxx index 07b0b903b..cc763c164 100644 --- a/src/event/BufferedSocket.hxx +++ b/src/event/BufferedSocket.hxx @@ -22,10 +22,10 @@ #include "check.h" #include "SocketMonitor.hxx" -#include "gerror.h" #include "gcc.h" struct fifo_buffer; +class Error; /** * A #SocketMonitor specialization that adds an input buffer. @@ -96,7 +96,7 @@ protected: }; virtual InputResult OnSocketInput(const void *data, size_t length) = 0; - virtual void OnSocketError(GError *error) = 0; + virtual void OnSocketError(Error &&error) = 0; virtual void OnSocketClosed() = 0; virtual bool OnSocketReady(unsigned flags) override; diff --git a/src/event/FullyBufferedSocket.cxx b/src/event/FullyBufferedSocket.cxx index f8b149500..3ffd9f416 100644 --- a/src/event/FullyBufferedSocket.cxx +++ b/src/event/FullyBufferedSocket.cxx @@ -21,6 +21,8 @@ #include "FullyBufferedSocket.hxx" #include "system/SocketError.hxx" #include "util/fifo_buffer.h" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <assert.h> #include <stdint.h> @@ -98,8 +100,10 @@ FullyBufferedSocket::Write(const void *data, size_t length) if (!output.Append(data, length)) { // TODO - OnSocketError(g_error_new_literal(g_quark_from_static_string("buffered_socket"), - 0, "Output buffer is full")); + static constexpr Domain buffered_socket_domain("buffered_socket"); + Error error; + error.Set(buffered_socket_domain, "Output buffer is full"); + OnSocketError(std::move(error)); return false; } diff --git a/src/event/ServerSocket.cxx b/src/event/ServerSocket.cxx index d22790de5..f0b02e34c 100644 --- a/src/event/ServerSocket.cxx +++ b/src/event/ServerSocket.cxx @@ -29,6 +29,8 @@ #include "event/SocketMonitor.hxx" #include "system/Resolver.hxx" #include "system/fd_util.h" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <sys/types.h> #include <sys/stat.h> @@ -96,7 +98,7 @@ public: path = g_strdup(_path); } - bool Open(GError **error_r); + bool Open(Error &error); using SocketMonitor::IsDefined; using SocketMonitor::Close; @@ -114,11 +116,7 @@ private: virtual bool OnSocketReady(unsigned flags) override; }; -static GQuark -server_socket_quark(void) -{ - return g_quark_from_static_string("server_socket"); -} +static constexpr Domain server_socket_domain("server_socket"); /** * Wraper for sockaddr_to_string() which never fails. @@ -126,7 +124,7 @@ server_socket_quark(void) char * OneServerSocket::ToString() const { - char *p = sockaddr_to_string(address, address_length, nullptr); + char *p = sockaddr_to_string(address, address_length, IgnoreError()); if (p == nullptr) p = g_strdup("[unknown]"); return p; @@ -190,14 +188,14 @@ OneServerSocket::OnSocketReady(gcc_unused unsigned flags) } inline bool -OneServerSocket::Open(GError **error_r) +OneServerSocket::Open(Error &error) { assert(!IsDefined()); int _fd = socket_bind_listen(address->sa_family, SOCK_STREAM, 0, address, address_length, 5, - error_r); + error); if (_fd < 0) return false; @@ -221,10 +219,10 @@ ServerSocket::ServerSocket(EventLoop &_loop) ServerSocket::~ServerSocket() {} bool -ServerSocket::Open(GError **error_r) +ServerSocket::Open(Error &error) { OneServerSocket *good = nullptr, *bad = nullptr; - GError *last_error = nullptr; + Error last_error; for (auto &i : sockets) { assert(i.GetSerial() > 0); @@ -232,33 +230,33 @@ ServerSocket::Open(GError **error_r) if (bad != nullptr && i.GetSerial() != bad->GetSerial()) { Close(); - g_propagate_error(error_r, last_error); + error = std::move(last_error); return false; } - GError *error = nullptr; - if (!i.Open(&error)) { + Error error2; + if (!i.Open(error2)) { if (good != nullptr && good->GetSerial() == i.GetSerial()) { char *address_string = i.ToString(); char *good_string = good->ToString(); g_warning("bind to '%s' failed: %s " "(continuing anyway, because " "binding to '%s' succeeded)", - address_string, error->message, + address_string, error2.GetMessage(), good_string); g_free(address_string); g_free(good_string); - g_error_free(error); } else if (bad == nullptr) { bad = &i; char *address_string = i.ToString(); - g_propagate_prefixed_error(&last_error, error, - "Failed to bind to '%s': ", - address_string); + error2.FormatPrefix("Failed to bind to '%s': ", + address_string); g_free(address_string); - } else - g_error_free(error); + + last_error = std::move(error2); + } + continue; } @@ -269,14 +267,13 @@ ServerSocket::Open(GError **error_r) if (bad != nullptr) { bad = nullptr; - g_error_free(last_error); - last_error = nullptr; + last_error.Clear(); } } if (bad != nullptr) { Close(); - g_propagate_error(error_r, last_error); + error = std::move(last_error); return false; } @@ -301,7 +298,7 @@ ServerSocket::AddAddress(const sockaddr &address, size_t address_length) } bool -ServerSocket::AddFD(int fd, GError **error_r) +ServerSocket::AddFD(int fd, Error &error) { assert(fd >= 0); @@ -309,8 +306,8 @@ ServerSocket::AddFD(int fd, GError **error_r) socklen_t address_length = sizeof(address); if (getsockname(fd, (struct sockaddr *)&address, &address_length) < 0) { - SetSocketError(error_r); - g_prefix_error(error_r, "Failed to get socket address"); + SetSocketError(error); + error.AddPrefix("Failed to get socket address: "); return false; } @@ -351,12 +348,11 @@ ServerSocket::AddPortIPv6(unsigned port) #endif /* HAVE_TCP */ bool -ServerSocket::AddPort(unsigned port, GError **error_r) +ServerSocket::AddPort(unsigned port, Error &error) { #ifdef HAVE_TCP if (port == 0 || port > 0xffff) { - g_set_error(error_r, server_socket_quark(), 0, - "Invalid TCP port"); + error.Set(server_socket_domain, "Invalid TCP port"); return false; } @@ -371,19 +367,18 @@ ServerSocket::AddPort(unsigned port, GError **error_r) #else /* HAVE_TCP */ (void)port; - g_set_error(error_r, server_socket_quark(), 0, - "TCP support is disabled"); + error.Set(server_socket_domain, "TCP support is disabled"); return false; #endif /* HAVE_TCP */ } bool -ServerSocket::AddHost(const char *hostname, unsigned port, GError **error_r) +ServerSocket::AddHost(const char *hostname, unsigned port, Error &error) { #ifdef HAVE_TCP struct addrinfo *ai = resolve_host_port(hostname, port, AI_PASSIVE, SOCK_STREAM, - error_r); + error); if (ai == nullptr) return false; @@ -399,22 +394,21 @@ ServerSocket::AddHost(const char *hostname, unsigned port, GError **error_r) (void)hostname; (void)port; - g_set_error(error_r, server_socket_quark(), 0, - "TCP support is disabled"); + error.Set(server_socket_domain, "TCP support is disabled"); return false; #endif /* HAVE_TCP */ } bool -ServerSocket::AddPath(const char *path, GError **error_r) +ServerSocket::AddPath(const char *path, Error &error) { #ifdef HAVE_UN struct sockaddr_un s_un; size_t path_length = strlen(path); if (path_length >= sizeof(s_un.sun_path)) { - g_set_error(error_r, server_socket_quark(), 0, - "UNIX socket path is too long"); + error.Set(server_socket_domain, + "UNIX socket path is too long"); return false; } @@ -430,8 +424,8 @@ ServerSocket::AddPath(const char *path, GError **error_r) #else /* !HAVE_UN */ (void)path; - g_set_error(error_r, server_socket_quark(), 0, - "UNIX domain socket support is disabled"); + error.Set(server_socket_domain, + "UNIX domain socket support is disabled"); return false; #endif /* !HAVE_UN */ } diff --git a/src/event/ServerSocket.hxx b/src/event/ServerSocket.hxx index 600cdf8a7..9f0745708 100644 --- a/src/event/ServerSocket.hxx +++ b/src/event/ServerSocket.hxx @@ -20,14 +20,13 @@ #ifndef MPD_SERVER_SOCKET_HXX #define MPD_SERVER_SOCKET_HXX -#include "gerror.h" - #include <forward_list> #include <stddef.h> struct sockaddr; class EventLoop; +class Error; typedef void (*server_socket_callback_t)(int fd, const struct sockaddr *address, @@ -79,7 +78,7 @@ public: * ignore errors * @return true on success */ - bool AddPort(unsigned port, GError **error_r); + bool AddPort(unsigned port, Error &error); /** * Resolves a host name, and adds listeners on all addresses in the @@ -91,7 +90,7 @@ public: * ignore errors * @return true on success */ - bool AddHost(const char *hostname, unsigned port, GError **error_r); + bool AddHost(const char *hostname, unsigned port, Error &error); /** * Add a listener on a Unix domain socket. @@ -101,16 +100,16 @@ public: * ignore errors * @return true on success */ - bool AddPath(const char *path, GError **error_r); + bool AddPath(const char *path, Error &error); /** * Add a socket descriptor that is accepting connections. After this * has been called, don't call server_socket_open(), because the * socket is already open. */ - bool AddFD(int fd, GError **error_r); + bool AddFD(int fd, Error &error); - bool Open(GError **error_r); + bool Open(Error &error); void Close(); protected: diff --git a/src/filter/AutoConvertFilterPlugin.cxx b/src/filter/AutoConvertFilterPlugin.cxx index 19495acbc..4b5ebff4d 100644 --- a/src/filter/AutoConvertFilterPlugin.cxx +++ b/src/filter/AutoConvertFilterPlugin.cxx @@ -46,21 +46,22 @@ public: delete filter; } - virtual AudioFormat Open(AudioFormat &af, GError **error_r); - virtual void Close(); + virtual AudioFormat Open(AudioFormat &af, Error &error) override; + virtual void Close() override; virtual const void *FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r); + size_t *dest_size_r, + Error &error) override; }; AudioFormat -AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r) +AutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error) { assert(in_audio_format.IsValid()); /* open the "real" filter */ const AudioFormat child_audio_format = in_audio_format; - AudioFormat out_audio_format = filter->Open(in_audio_format, error_r); + AudioFormat out_audio_format = filter->Open(in_audio_format, error); if (!out_audio_format.IsDefined()) return out_audio_format; @@ -70,7 +71,7 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r) /* yes - create a convert_filter */ const config_param empty; - convert = filter_new(&convert_filter_plugin, empty, error_r); + convert = filter_new(&convert_filter_plugin, empty, error); if (convert == nullptr) { filter->Close(); return AudioFormat::Undefined(); @@ -78,7 +79,7 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r) AudioFormat audio_format2 = in_audio_format; AudioFormat audio_format3 = - convert->Open(audio_format2, error_r); + convert->Open(audio_format2, error); if (!audio_format3.IsDefined()) { delete convert; filter->Close(); @@ -108,15 +109,15 @@ AutoConvertFilter::Close() const void * AutoConvertFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r) + size_t *dest_size_r, Error &error) { if (convert != nullptr) { - src = convert->FilterPCM(src, src_size, &src_size, error_r); + src = convert->FilterPCM(src, src_size, &src_size, error); if (src == nullptr) return nullptr; } - return filter->FilterPCM(src, src_size, dest_size_r, error_r); + return filter->FilterPCM(src, src_size, dest_size_r, error); } Filter * diff --git a/src/filter/ChainFilterPlugin.cxx b/src/filter/ChainFilterPlugin.cxx index fbb91795d..a24f533b1 100644 --- a/src/filter/ChainFilterPlugin.cxx +++ b/src/filter/ChainFilterPlugin.cxx @@ -24,6 +24,8 @@ #include "FilterInternal.hxx" #include "FilterRegistry.hxx" #include "AudioFormat.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> @@ -53,10 +55,10 @@ public: children.emplace_back(name, filter); } - virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; + virtual AudioFormat Open(AudioFormat &af, Error &error) override; virtual void Close(); virtual const void *FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r); + size_t *dest_size_r, Error &error); private: /** @@ -66,15 +68,11 @@ private: void CloseUntil(const Filter *until); }; -static inline GQuark -filter_quark(void) -{ - return g_quark_from_static_string("filter"); -} +static constexpr Domain chain_filter_domain("chain_filter"); static Filter * chain_filter_init(gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { return new ChainFilter(); } @@ -99,11 +97,11 @@ ChainFilter::CloseUntil(const Filter *until) static AudioFormat chain_open_child(const char *name, Filter *filter, const AudioFormat &prev_audio_format, - GError **error_r) + Error &error) { AudioFormat conv_audio_format = prev_audio_format; const AudioFormat next_audio_format = - filter->Open(conv_audio_format, error_r); + filter->Open(conv_audio_format, error); if (!next_audio_format.IsDefined()) return next_audio_format; @@ -111,10 +109,11 @@ chain_open_child(const char *name, Filter *filter, struct audio_format_string s; filter->Close(); - g_set_error(error_r, filter_quark(), 0, - "Audio format not supported by filter '%s': %s", - name, - audio_format_to_string(prev_audio_format, &s)); + + error.Format(chain_filter_domain, + "Audio format not supported by filter '%s': %s", + name, + audio_format_to_string(prev_audio_format, &s)); return AudioFormat::Undefined(); } @@ -122,13 +121,13 @@ chain_open_child(const char *name, Filter *filter, } AudioFormat -ChainFilter::Open(AudioFormat &in_audio_format, GError **error_r) +ChainFilter::Open(AudioFormat &in_audio_format, Error &error) { AudioFormat audio_format = in_audio_format; for (auto &child : children) { audio_format = chain_open_child(child.name, child.filter, - audio_format, error_r); + audio_format, error); if (!audio_format.IsDefined()) { /* rollback, close all children */ CloseUntil(child.filter); @@ -149,13 +148,13 @@ ChainFilter::Close() const void * ChainFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r) + size_t *dest_size_r, Error &error) { for (auto &child : children) { /* feed the output of the previous filter as input into the current one */ src = child.filter->FilterPCM(src, src_size, &src_size, - error_r); + error); if (src == NULL) return NULL; } diff --git a/src/filter/ConvertFilterPlugin.cxx b/src/filter/ConvertFilterPlugin.cxx index 4dc0d0333..3ef2be719 100644 --- a/src/filter/ConvertFilterPlugin.cxx +++ b/src/filter/ConvertFilterPlugin.cxx @@ -56,21 +56,22 @@ public: out_audio_format = _out_audio_format; } - virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; - virtual void Close(); + virtual AudioFormat Open(AudioFormat &af, Error &error) override; + virtual void Close() override; virtual const void *FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r); + size_t *dest_size_r, + Error &error) override; }; static Filter * convert_filter_init(gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { return new ConvertFilter(); } AudioFormat -ConvertFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r) +ConvertFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) { assert(audio_format.IsValid()); @@ -91,7 +92,7 @@ ConvertFilter::Close() const void * ConvertFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r) + size_t *dest_size_r, Error &error) { if (in_audio_format == out_audio_format) { /* optimized special case: no-op */ @@ -102,7 +103,7 @@ ConvertFilter::FilterPCM(const void *src, size_t src_size, return state->Convert(in_audio_format, src, src_size, out_audio_format, dest_size_r, - error_r); + error); } const struct filter_plugin convert_filter_plugin = { diff --git a/src/filter/NormalizeFilterPlugin.cxx b/src/filter/NormalizeFilterPlugin.cxx index 63b562fa0..6c4f6b0e5 100644 --- a/src/filter/NormalizeFilterPlugin.cxx +++ b/src/filter/NormalizeFilterPlugin.cxx @@ -34,21 +34,21 @@ class NormalizeFilter final : public Filter { PcmBuffer buffer; public: - virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; + virtual AudioFormat Open(AudioFormat &af, Error &error) override; virtual void Close(); virtual const void *FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r); + size_t *dest_size_r, Error &error); }; static Filter * normalize_filter_init(gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { return new NormalizeFilter(); } AudioFormat -NormalizeFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r) +NormalizeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) { audio_format.format = SampleFormat::S16; @@ -66,7 +66,7 @@ NormalizeFilter::Close() const void * NormalizeFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, gcc_unused GError **error_r) + size_t *dest_size_r, gcc_unused Error &error) { int16_t *dest = (int16_t *)buffer.Get(src_size); memcpy(dest, src, src_size); diff --git a/src/filter/NullFilterPlugin.cxx b/src/filter/NullFilterPlugin.cxx index f76c05d3f..ad585d4b6 100644 --- a/src/filter/NullFilterPlugin.cxx +++ b/src/filter/NullFilterPlugin.cxx @@ -34,15 +34,15 @@ class NullFilter final : public Filter { public: virtual AudioFormat Open(AudioFormat &af, - gcc_unused GError **error_r) { + gcc_unused Error &error) override { return af; } - virtual void Close() {} + virtual void Close() override {} virtual const void *FilterPCM(const void *src, size_t src_size, size_t *dest_size_r, - gcc_unused GError **error_r) { + gcc_unused Error &error) override { *dest_size_r = src_size; return src; } @@ -50,7 +50,7 @@ public: static Filter * null_filter_init(gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { return new NullFilter(); } diff --git a/src/filter/ReplayGainFilterPlugin.cxx b/src/filter/ReplayGainFilterPlugin.cxx index 446264c6e..0dd8905cb 100644 --- a/src/filter/ReplayGainFilterPlugin.cxx +++ b/src/filter/ReplayGainFilterPlugin.cxx @@ -28,6 +28,8 @@ #include "MixerControl.hxx" #include "pcm/PcmVolume.hxx" #include "pcm/PcmBuffer.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> @@ -114,17 +116,13 @@ public: */ void Update(); - virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; + virtual AudioFormat Open(AudioFormat &af, Error &error) override; virtual void Close(); virtual const void *FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r); + size_t *dest_size_r, Error &error); }; -static inline GQuark -replay_gain_quark(void) -{ - return g_quark_from_static_string("replay_gain"); -} +static constexpr Domain replay_gain_domain("replay_gain"); void ReplayGainFilter::Update() @@ -145,24 +143,22 @@ ReplayGainFilter::Update() if (_volume > 100) _volume = 100; - GError *error = NULL; - if (!mixer_set_volume(mixer, _volume, &error)) { + Error error; + if (!mixer_set_volume(mixer, _volume, error)) g_warning("Failed to update hardware mixer: %s", - error->message); - g_error_free(error); - } + error.GetMessage()); } } static Filter * replay_gain_filter_init(gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { return new ReplayGainFilter(); } AudioFormat -ReplayGainFilter::Open(AudioFormat &af, gcc_unused GError **error_r) +ReplayGainFilter::Open(AudioFormat &af, gcc_unused Error &error) { format = af; @@ -177,7 +173,7 @@ ReplayGainFilter::Close() const void * ReplayGainFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r) + size_t *dest_size_r, Error &error) { *dest_size_r = src_size; @@ -201,8 +197,7 @@ ReplayGainFilter::FilterPCM(const void *src, size_t src_size, format.format, volume); if (!success) { - g_set_error(error_r, replay_gain_quark(), 0, - "pcm_volume() has failed"); + error.Set(replay_gain_domain, "pcm_volume() has failed"); return NULL; } diff --git a/src/filter/RouteFilterPlugin.cxx b/src/filter/RouteFilterPlugin.cxx index 2c0d60cbe..20ef5e963 100644 --- a/src/filter/RouteFilterPlugin.cxx +++ b/src/filter/RouteFilterPlugin.cxx @@ -41,13 +41,16 @@ #include "config.h" #include "conf.h" -#include "ConfigQuark.hxx" +#include "ConfigError.hxx" #include "AudioFormat.hxx" #include "CheckAudioFormat.hxx" #include "FilterPlugin.hxx" #include "FilterInternal.hxx" #include "FilterRegistry.hxx" #include "pcm/PcmBuffer.hxx" +#include "util/Error.hxx" + +#include <glib.h> #include <assert.h> #include <string.h> @@ -118,16 +121,16 @@ public: * @param filter a route_filter whose min_channels and sources[] to set * @return true on success, false on error */ - bool Configure(const config_param ¶m, GError **error_r); + bool Configure(const config_param ¶m, Error &error); - virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; + virtual AudioFormat Open(AudioFormat &af, Error &error) override; virtual void Close(); virtual const void *FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r); + size_t *dest_size_r, Error &error); }; bool -RouteFilter::Configure(const config_param ¶m, GError **error_r) { +RouteFilter::Configure(const config_param ¶m, Error &error) { /* TODO: * With a more clever way of marking "don't copy to output N", @@ -160,9 +163,9 @@ RouteFilter::Configure(const config_param ¶m, GError **error_r) { // Split the a>b string into source and destination sd = g_strsplit(tokens[c], ">", 2); if (g_strv_length(sd) != 2) { - g_set_error(error_r, config_quark(), 1, - "Invalid copy around %d in routes spec: %s", - param.line, tokens[c]); + error.Format(config_domain, + "Invalid copy around %d in routes spec: %s", + param.line, tokens[c]); g_strfreev(sd); g_strfreev(tokens); return false; @@ -183,9 +186,9 @@ RouteFilter::Configure(const config_param ¶m, GError **error_r) { if (!audio_valid_channel_count(min_output_channels)) { g_strfreev(tokens); - g_set_error(error_r, audio_format_quark(), 0, - "Invalid number of output channels requested: %d", - min_output_channels); + error.Format(config_domain, + "Invalid number of output channels requested: %d", + min_output_channels); return false; } @@ -207,9 +210,9 @@ RouteFilter::Configure(const config_param ¶m, GError **error_r) { // Split the a>b string into source and destination sd = g_strsplit(tokens[c], ">", 2); if (g_strv_length(sd) != 2) { - g_set_error(error_r, config_quark(), 1, - "Invalid copy around %d in routes spec: %s", - param.line, tokens[c]); + error.Format(config_domain, + "Invalid copy around %d in routes spec: %s", + param.line, tokens[c]); g_strfreev(sd); g_strfreev(tokens); return false; @@ -229,10 +232,10 @@ RouteFilter::Configure(const config_param ¶m, GError **error_r) { } static Filter * -route_filter_init(const config_param ¶m, GError **error_r) +route_filter_init(const config_param ¶m, Error &error) { RouteFilter *filter = new RouteFilter(); - if (!filter->Configure(param, error_r)) { + if (!filter->Configure(param, error)) { delete filter; return nullptr; } @@ -241,7 +244,7 @@ route_filter_init(const config_param ¶m, GError **error_r) } AudioFormat -RouteFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r) +RouteFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) { // Copy the input format for later reference input_format = audio_format; @@ -266,7 +269,7 @@ RouteFilter::Close() const void * RouteFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, gcc_unused GError **error_r) + size_t *dest_size_r, gcc_unused Error &error) { size_t number_of_frames = src_size / input_frame_size; diff --git a/src/filter/VolumeFilterPlugin.cxx b/src/filter/VolumeFilterPlugin.cxx index 239f0b899..4c51ac599 100644 --- a/src/filter/VolumeFilterPlugin.cxx +++ b/src/filter/VolumeFilterPlugin.cxx @@ -26,6 +26,8 @@ #include "pcm/PcmVolume.hxx" #include "pcm/PcmBuffer.hxx" #include "AudioFormat.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> @@ -58,27 +60,23 @@ public: volume = _volume; } - virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; + virtual AudioFormat Open(AudioFormat &af, Error &error) override; virtual void Close(); virtual const void *FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r); + size_t *dest_size_r, Error &error); }; -static inline GQuark -volume_quark(void) -{ - return g_quark_from_static_string("pcm_volume"); -} +static constexpr Domain volume_domain("pcm_volume"); static Filter * volume_filter_init(gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { return new VolumeFilter(); } AudioFormat -VolumeFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r) +VolumeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) { format = audio_format; @@ -93,7 +91,7 @@ VolumeFilter::Close() const void * VolumeFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, GError **error_r) + size_t *dest_size_r, Error &error) { *dest_size_r = src_size; @@ -117,8 +115,7 @@ VolumeFilter::FilterPCM(const void *src, size_t src_size, format.format, volume); if (!success) { - g_set_error(error_r, volume_quark(), 0, - "pcm_volume() has failed"); + error.Set(volume_domain, "pcm_volume() has failed"); return NULL; } diff --git a/src/input/ArchiveInputPlugin.cxx b/src/input/ArchiveInputPlugin.cxx index 0d856527f..025b25fef 100644 --- a/src/input/ArchiveInputPlugin.cxx +++ b/src/input/ArchiveInputPlugin.cxx @@ -24,6 +24,7 @@ #include "ArchivePlugin.hxx" #include "ArchiveFile.hxx" #include "InputPlugin.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -38,7 +39,7 @@ static struct input_stream * input_archive_open(const char *pathname, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { const struct archive_plugin *arplug; char *archive, *filename, *suffix, *pname; @@ -63,14 +64,14 @@ input_archive_open(const char *pathname, return NULL; } - auto file = archive_file_open(arplug, archive, error_r); + auto file = archive_file_open(arplug, archive, error); if (file == NULL) { g_free(pname); return NULL; } //setup fileops - is = file->OpenStream(filename, mutex, cond, error_r); + is = file->OpenStream(filename, mutex, cond, error); g_free(pname); file->Close(); diff --git a/src/input/CdioParanoiaInputPlugin.cxx b/src/input/CdioParanoiaInputPlugin.cxx index f0fa835b3..660c157e8 100644 --- a/src/input/CdioParanoiaInputPlugin.cxx +++ b/src/input/CdioParanoiaInputPlugin.cxx @@ -26,6 +26,8 @@ #include "InputInternal.hxx" #include "InputStream.hxx" #include "InputPlugin.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <stdio.h> #include <stdint.h> @@ -71,11 +73,7 @@ struct CdioParanoiaInputStream { } }; -static inline GQuark -cdio_quark(void) -{ - return g_quark_from_static_string("cdio"); -} +static constexpr Domain cdio_domain("cdio"); static void input_cdio_close(struct input_stream *is) @@ -91,7 +89,7 @@ struct cdio_uri { }; static bool -parse_cdio_uri(struct cdio_uri *dest, const char *src, GError **error_r) +parse_cdio_uri(struct cdio_uri *dest, const char *src, Error &error) { if (!g_str_has_prefix(src, "cdda://")) return false; @@ -125,8 +123,7 @@ parse_cdio_uri(struct cdio_uri *dest, const char *src, GError **error_r) char *endptr; dest->track = strtoul(track, &endptr, 10); if (*endptr != 0) { - g_set_error(error_r, cdio_quark(), 0, - "Malformed track number"); + error.Set(cdio_domain, "Malformed track number"); return false; } @@ -154,10 +151,10 @@ cdio_detect_device(void) static struct input_stream * input_cdio_open(const char *uri, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { struct cdio_uri parsed_uri; - if (!parse_cdio_uri(&parsed_uri, uri, error_r)) + if (!parse_cdio_uri(&parsed_uri, uri, error)) return nullptr; CdioParanoiaInputStream *i = @@ -169,8 +166,8 @@ input_cdio_open(const char *uri, ? g_strdup(parsed_uri.device) : cdio_detect_device(); if (device == nullptr) { - g_set_error(error_r, cdio_quark(), 0, - "Unable find or access a CD-ROM drive with an audio CD in it."); + error.Set(cdio_domain, + "Unable find or access a CD-ROM drive with an audio CD in it."); delete i; return nullptr; } @@ -182,8 +179,7 @@ input_cdio_open(const char *uri, i->drv = cdio_cddap_identify_cdio(i->cdio, 1, nullptr); if ( !i->drv ) { - g_set_error(error_r, cdio_quark(), 0, - "Unable to identify audio CD disc."); + error.Set(cdio_domain, "Unable to identify audio CD disc."); delete i; return nullptr; } @@ -191,7 +187,7 @@ input_cdio_open(const char *uri, cdda_verbose_set(i->drv, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); if ( 0 != cdio_cddap_open(i->drv) ) { - g_set_error(error_r, cdio_quark(), 0, "Unable to open disc."); + error.Set(cdio_domain, "Unable to open disc."); delete i; return nullptr; } @@ -211,9 +207,8 @@ input_cdio_open(const char *uri, reverse_endian = G_BYTE_ORDER == G_LITTLE_ENDIAN; break; default: - g_set_error(error_r, cdio_quark(), 0, - "Drive returns unknown data type %d", - data_bigendianp(i->drv)); + error.Format(cdio_domain, "Drive returns unknown data type %d", + data_bigendianp(i->drv)); delete i; return nullptr; } @@ -250,7 +245,7 @@ input_cdio_open(const char *uri, static bool input_cdio_seek(struct input_stream *is, - goffset offset, int whence, GError **error_r) + goffset offset, int whence, Error &error) { CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is; @@ -267,9 +262,8 @@ input_cdio_seek(struct input_stream *is, } if (offset < 0 || offset > cis->base.size) { - g_set_error(error_r, cdio_quark(), 0, - "Invalid offset to seek %ld (%ld)", - (long int)offset, (long int)cis->base.size); + error.Format(cdio_domain, "Invalid offset to seek %ld (%ld)", + (long int)offset, (long int)cis->base.size); return false; } @@ -288,7 +282,7 @@ input_cdio_seek(struct input_stream *is, static size_t input_cdio_read(struct input_stream *is, void *ptr, size_t length, - GError **error_r) + Error &error) { CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is; size_t nbytes = 0; @@ -319,8 +313,8 @@ input_cdio_read(struct input_stream *is, void *ptr, size_t length, free(s_mess); } if (!rbuf) { - g_set_error(error_r, cdio_quark(), 0, - "paranoia read error. Stopping."); + error.Set(cdio_domain, + "paranoia read error. Stopping."); return 0; } //store current buffer diff --git a/src/input/CurlInputPlugin.cxx b/src/input/CurlInputPlugin.cxx index c5f524bc0..cbf5c6b83 100644 --- a/src/input/CurlInputPlugin.cxx +++ b/src/input/CurlInputPlugin.cxx @@ -28,6 +28,8 @@ #include "event/MultiSocketMonitor.hxx" #include "event/Call.hxx" #include "IOThread.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <assert.h> @@ -162,16 +164,14 @@ struct input_curl { input_stream_tag() */ Tag *tag; - GError *postponed_error; + Error postponed_error; input_curl(const char *url, Mutex &mutex, Cond &cond) :base(input_plugin_curl, url, mutex, cond), range(nullptr), request_headers(nullptr), paused(false), meta_name(nullptr), - tag(nullptr), - postponed_error(nullptr) { - } + tag(nullptr) {} ~input_curl(); @@ -215,12 +215,9 @@ static struct { CurlSockets *sockets; } curl; -gcc_const -static inline GQuark -curl_quark(void) -{ - return g_quark_from_static_string("curl"); -} +static constexpr Domain http_domain("http"); +static constexpr Domain curl_domain("curl"); +static constexpr Domain curlm_domain("curlm"); /** * Find a request by its CURL "easy" handle. @@ -319,7 +316,7 @@ CurlSockets::UpdateSockets() * Runs in the I/O thread. No lock needed. */ static bool -input_curl_easy_add(struct input_curl *c, GError **error_r) +input_curl_easy_add(struct input_curl *c, Error &error) { assert(io_thread_inside()); assert(c != NULL); @@ -330,9 +327,9 @@ input_curl_easy_add(struct input_curl *c, GError **error_r) CURLMcode mcode = curl_multi_add_handle(curl.multi, c->easy); if (mcode != CURLM_OK) { - g_set_error(error_r, curl_quark(), mcode, - "curl_multi_add_handle() failed: %s", - curl_multi_strerror(mcode)); + error.Format(curlm_domain, mcode, + "curl_multi_add_handle() failed: %s", + curl_multi_strerror(mcode)); return false; } @@ -346,14 +343,14 @@ input_curl_easy_add(struct input_curl *c, GError **error_r) * any thread. Caller must not hold a mutex. */ static bool -input_curl_easy_add_indirect(struct input_curl *c, GError **error_r) +input_curl_easy_add_indirect(struct input_curl *c, Error &error) { assert(c != NULL); assert(c->easy != NULL); bool result; - BlockingCall(io_thread_get(), [c, error_r, &result](){ - result = input_curl_easy_add(c, error_r); + BlockingCall(io_thread_get(), [c, &error, &result](){ + result = input_curl_easy_add(c, error); }); return result; } @@ -409,27 +406,25 @@ input_curl_easy_free_indirect(struct input_curl *c) * Runs in the I/O thread. The caller must not hold locks. */ static void -input_curl_abort_all_requests(GError *error) +input_curl_abort_all_requests(const Error &error) { assert(io_thread_inside()); - assert(error != NULL); + assert(error.IsDefined()); while (!curl.requests.empty()) { struct input_curl *c = curl.requests.front(); - assert(c->postponed_error == NULL); + assert(!c->postponed_error.IsDefined()); input_curl_easy_free(c); const ScopeLock protect(c->base.mutex); - c->postponed_error = g_error_copy(error); + c->postponed_error.Set(error); c->base.ready = true; c->base.cond.broadcast(); } - g_error_free(error); - } /** @@ -443,18 +438,17 @@ input_curl_request_done(struct input_curl *c, CURLcode result, long status) assert(io_thread_inside()); assert(c != NULL); assert(c->easy == NULL); - assert(c->postponed_error == NULL); + assert(!c->postponed_error.IsDefined()); const ScopeLock protect(c->base.mutex); if (result != CURLE_OK) { - c->postponed_error = g_error_new(curl_quark(), result, - "curl failed: %s", - c->error); + c->postponed_error.Format(curl_domain, result, + "curl failed: %s", c->error); } else if (status < 200 || status >= 300) { - c->postponed_error = g_error_new(curl_quark(), 0, - "got HTTP status %ld", - status); + c->postponed_error.Format(http_domain, status, + "got HTTP status %ld", + status); } c->base.ready = true; @@ -513,9 +507,10 @@ input_curl_perform(void) } while (mcode == CURLM_CALL_MULTI_PERFORM); if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) { - GError *error = g_error_new(curl_quark(), mcode, - "curl_multi_perform() failed: %s", - curl_multi_strerror(mcode)); + Error error; + error.Format(curlm_domain, mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); input_curl_abort_all_requests(error); return false; } @@ -559,14 +554,13 @@ CurlSockets::DispatchSockets() */ static bool -input_curl_init(const config_param ¶m, - gcc_unused GError **error_r) +input_curl_init(const config_param ¶m, Error &error) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); if (code != CURLE_OK) { - g_set_error(error_r, curl_quark(), code, - "curl_global_init() failed: %s\n", - curl_easy_strerror(code)); + error.Format(curl_domain, code, + "curl_global_init() failed: %s", + curl_easy_strerror(code)); return false; } @@ -588,8 +582,7 @@ input_curl_init(const config_param ¶m, curl.multi = curl_multi_init(); if (curl.multi == NULL) { - g_set_error(error_r, curl_quark(), 0, - "curl_multi_init() failed"); + error.Set(curl_domain, 0, "curl_multi_init() failed"); return false; } @@ -639,20 +632,17 @@ input_curl::~input_curl() g_free(meta_name); input_curl_easy_free_indirect(this); - - if (postponed_error != NULL) - g_error_free(postponed_error); } static bool -input_curl_check(struct input_stream *is, GError **error_r) +input_curl_check(struct input_stream *is, Error &error) { struct input_curl *c = (struct input_curl *)is; - bool success = c->postponed_error == NULL; + bool success = !c->postponed_error.IsDefined(); if (!success) { - g_propagate_error(error_r, c->postponed_error); - c->postponed_error = NULL; + error = std::move(c->postponed_error); + c->postponed_error.Clear(); } return success; @@ -669,14 +659,14 @@ input_curl_tag(struct input_stream *is) } static bool -fill_buffer(struct input_curl *c, GError **error_r) +fill_buffer(struct input_curl *c, Error &error) { while (c->easy != NULL && c->buffers.empty()) c->base.cond.wait(c->base.mutex); - if (c->postponed_error != NULL) { - g_propagate_error(error_r, c->postponed_error); - c->postponed_error = NULL; + if (c->postponed_error.IsDefined()) { + error = std::move(c->postponed_error); + c->postponed_error.Clear(); return false; } @@ -754,13 +744,13 @@ input_curl_available(struct input_stream *is) { struct input_curl *c = (struct input_curl *)is; - return c->postponed_error != NULL || c->easy == NULL || + return c->postponed_error.IsDefined() || c->easy == NULL || !c->buffers.empty(); } static size_t input_curl_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r) + Error &error) { struct input_curl *c = (struct input_curl *)is; bool success; @@ -770,7 +760,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size, do { /* fill the buffer */ - success = fill_buffer(c, error_r); + success = fill_buffer(c, error); if (!success) return 0; @@ -927,14 +917,13 @@ input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream) } static bool -input_curl_easy_init(struct input_curl *c, GError **error_r) +input_curl_easy_init(struct input_curl *c, Error &error) { CURLcode code; c->easy = curl_easy_init(); if (c->easy == NULL) { - g_set_error(error_r, curl_quark(), 0, - "curl_easy_init() failed"); + error.Set(curl_domain, "curl_easy_init() failed"); return false; } @@ -971,9 +960,9 @@ input_curl_easy_init(struct input_curl *c, GError **error_r) code = curl_easy_setopt(c->easy, CURLOPT_URL, c->base.uri.c_str()); if (code != CURLE_OK) { - g_set_error(error_r, curl_quark(), code, - "curl_easy_setopt() failed: %s", - curl_easy_strerror(code)); + error.Format(curl_domain, code, + "curl_easy_setopt() failed: %s", + curl_easy_strerror(code)); return false; } @@ -987,7 +976,7 @@ input_curl_easy_init(struct input_curl *c, GError **error_r) static bool input_curl_seek(struct input_stream *is, goffset offset, int whence, - GError **error_r) + Error &error) { struct input_curl *c = (struct input_curl *)is; bool ret; @@ -1059,7 +1048,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence, return true; } - ret = input_curl_easy_init(c, error_r); + ret = input_curl_easy_init(c, error); if (!ret) return false; @@ -1072,7 +1061,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence, c->base.ready = false; - if (!input_curl_easy_add_indirect(c, error_r)) + if (!input_curl_easy_add_indirect(c, error)) return false; c->base.mutex.lock(); @@ -1080,9 +1069,9 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence, while (!c->base.ready) c->base.cond.wait(c->base.mutex); - if (c->postponed_error != NULL) { - g_propagate_error(error_r, c->postponed_error); - c->postponed_error = NULL; + if (c->postponed_error.IsDefined()) { + error = std::move(c->postponed_error); + c->postponed_error.Clear(); return false; } @@ -1091,19 +1080,19 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence, static struct input_stream * input_curl_open(const char *url, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { if (strncmp(url, "http://", 7) != 0) return NULL; struct input_curl *c = new input_curl(url, mutex, cond); - if (!input_curl_easy_init(c, error_r)) { + if (!input_curl_easy_init(c, error)) { delete c; return NULL; } - if (!input_curl_easy_add_indirect(c, error_r)) { + if (!input_curl_easy_add_indirect(c, error)) { delete c; return NULL; } diff --git a/src/input/DespotifyInputPlugin.cxx b/src/input/DespotifyInputPlugin.cxx index 30ecceed7..f2b87dbcc 100644 --- a/src/input/DespotifyInputPlugin.cxx +++ b/src/input/DespotifyInputPlugin.cxx @@ -124,7 +124,7 @@ static void callback(gcc_unused struct despotify_session* ds, static struct input_stream * input_despotify_open(const char *url, Mutex &mutex, Cond &cond, - gcc_unused GError **error_r) + gcc_unused Error &error) { struct despotify_session *session; struct ds_link *ds_link; @@ -172,7 +172,7 @@ input_despotify_open(const char *url, static size_t input_despotify_read(struct input_stream *is, void *ptr, size_t size, - gcc_unused GError **error_r) + gcc_unused Error &error) { DespotifyInputStream *ctx = (DespotifyInputStream *)is; size_t to_cpy = size; diff --git a/src/input/FfmpegInputPlugin.cxx b/src/input/FfmpegInputPlugin.cxx index f27348b27..1837303bb 100644 --- a/src/input/FfmpegInputPlugin.cxx +++ b/src/input/FfmpegInputPlugin.cxx @@ -25,6 +25,8 @@ #include "InputInternal.hxx" #include "InputStream.hxx" #include "InputPlugin.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" extern "C" { #include <libavutil/avutil.h> @@ -62,11 +64,7 @@ struct FfmpegInputStream { } }; -static inline GQuark -ffmpeg_quark(void) -{ - return g_quark_from_static_string("ffmpeg"); -} +static constexpr Domain ffmpeg_domain("ffmpeg"); static inline bool input_ffmpeg_supported(void) @@ -77,14 +75,13 @@ input_ffmpeg_supported(void) static bool input_ffmpeg_init(gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + Error &error) { av_register_all(); /* disable this plugin if there's no registered protocol */ if (!input_ffmpeg_supported()) { - g_set_error(error_r, ffmpeg_quark(), 0, - "No protocol"); + error.Set(ffmpeg_domain, "No protocol"); return false; } @@ -94,7 +91,7 @@ input_ffmpeg_init(gcc_unused const config_param ¶m, static struct input_stream * input_ffmpeg_open(const char *uri, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { if (!g_str_has_prefix(uri, "gopher://") && !g_str_has_prefix(uri, "rtp://") && @@ -107,8 +104,8 @@ input_ffmpeg_open(const char *uri, AVIOContext *h; int ret = avio_open(&h, uri, AVIO_FLAG_READ); if (ret != 0) { - g_set_error(error_r, ffmpeg_quark(), ret, - "libavformat failed to open the URI"); + error.Set(ffmpeg_domain, ret, + "libavformat failed to open the URI"); return nullptr; } @@ -118,15 +115,14 @@ input_ffmpeg_open(const char *uri, static size_t input_ffmpeg_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r) + Error &error) { FfmpegInputStream *i = (FfmpegInputStream *)is; int ret = avio_read(i->h, (unsigned char *)ptr, size); if (ret <= 0) { if (ret < 0) - g_set_error(error_r, ffmpeg_quark(), 0, - "url_read() failed"); + error.Set(ffmpeg_domain, "avio_read() failed"); i->eof = true; return false; @@ -154,7 +150,7 @@ input_ffmpeg_eof(struct input_stream *is) static bool input_ffmpeg_seek(struct input_stream *is, goffset offset, int whence, - gcc_unused GError **error_r) + Error &error) { FfmpegInputStream *i = (FfmpegInputStream *)is; int64_t ret = avio_seek(i->h, offset, whence); @@ -163,7 +159,7 @@ input_ffmpeg_seek(struct input_stream *is, goffset offset, int whence, i->eof = false; return true; } else { - g_set_error(error_r, ffmpeg_quark(), 0, "url_seek() failed"); + error.Set(ffmpeg_domain, "avio_seek() failed"); return false; } } diff --git a/src/input/FileInputPlugin.cxx b/src/input/FileInputPlugin.cxx index 6fd743179..7d1fc0a7f 100644 --- a/src/input/FileInputPlugin.cxx +++ b/src/input/FileInputPlugin.cxx @@ -22,9 +22,10 @@ #include "InputInternal.hxx" #include "InputStream.hxx" #include "InputPlugin.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include "system/fd_util.h" #include "open.h" -#include "io_error.h" #include <sys/stat.h> #include <unistd.h> @@ -35,6 +36,8 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "input_file" +static constexpr Domain file_domain("file"); + struct FileInputStream { struct input_stream base; @@ -57,7 +60,7 @@ struct FileInputStream { static struct input_stream * input_file_open(const char *filename, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { int fd, ret; struct stat st; @@ -68,24 +71,20 @@ input_file_open(const char *filename, fd = open_cloexec(filename, O_RDONLY|O_BINARY, 0); if (fd < 0) { if (errno != ENOENT && errno != ENOTDIR) - g_set_error(error_r, errno_quark(), errno, - "Failed to open \"%s\": %s", - filename, g_strerror(errno)); + error.FormatErrno("Failed to open \"%s\"", + filename); return nullptr; } ret = fstat(fd, &st); if (ret < 0) { - g_set_error(error_r, errno_quark(), errno, - "Failed to stat \"%s\": %s", - filename, g_strerror(errno)); + error.FormatErrno("Failed to stat \"%s\"", filename); close(fd); return nullptr; } if (!S_ISREG(st.st_mode)) { - g_set_error(error_r, errno_quark(), 0, - "Not a regular file: %s", filename); + error.Format(file_domain, "Not a regular file: %s", filename); close(fd); return nullptr; } @@ -101,14 +100,13 @@ input_file_open(const char *filename, static bool input_file_seek(struct input_stream *is, goffset offset, int whence, - GError **error_r) + Error &error) { FileInputStream *fis = (FileInputStream *)is; offset = (goffset)lseek(fis->fd, (off_t)offset, whence); if (offset < 0) { - g_set_error(error_r, errno_quark(), errno, - "Failed to seek: %s", g_strerror(errno)); + error.SetErrno("Failed to seek"); return false; } @@ -118,15 +116,14 @@ input_file_seek(struct input_stream *is, goffset offset, int whence, static size_t input_file_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r) + Error &error) { FileInputStream *fis = (FileInputStream *)is; ssize_t nbytes; nbytes = read(fis->fd, ptr, size); if (nbytes < 0) { - g_set_error(error_r, errno_quark(), errno, - "Failed to read: %s", g_strerror(errno)); + error.SetErrno("Failed to read"); return 0; } diff --git a/src/input/MmsInputPlugin.cxx b/src/input/MmsInputPlugin.cxx index 80d479613..02810bb22 100644 --- a/src/input/MmsInputPlugin.cxx +++ b/src/input/MmsInputPlugin.cxx @@ -22,6 +22,8 @@ #include "InputInternal.hxx" #include "InputStream.hxx" #include "InputPlugin.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> #include <libmms/mmsx.h> @@ -56,16 +58,12 @@ struct MmsInputStream { } }; -static inline GQuark -mms_quark(void) -{ - return g_quark_from_static_string("mms"); -} +static constexpr Domain mms_domain("mms"); static struct input_stream * input_mms_open(const char *url, Mutex &mutex, Cond &cond, - GError **error_r) + Error &error) { if (!g_str_has_prefix(url, "mms://") && !g_str_has_prefix(url, "mmsh://") && @@ -75,7 +73,7 @@ input_mms_open(const char *url, const auto mms = mmsx_connect(nullptr, nullptr, url, 128 * 1024); if (mms == nullptr) { - g_set_error(error_r, mms_quark(), 0, "mmsx_connect() failed"); + error.Set(mms_domain, "mmsx_connect() failed"); return nullptr; } @@ -85,18 +83,15 @@ input_mms_open(const char *url, static size_t input_mms_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r) + Error &error) { MmsInputStream *m = (MmsInputStream *)is; int ret; ret = mmsx_read(nullptr, m->mms, (char *)ptr, size); if (ret <= 0) { - if (ret < 0) { - g_set_error(error_r, mms_quark(), errno, - "mmsx_read() failed: %s", - g_strerror(errno)); - } + if (ret < 0) + error.SetErrno("mmsx_read() failed"); m->eof = true; return false; diff --git a/src/input/RewindInputPlugin.cxx b/src/input/RewindInputPlugin.cxx index d68fd3d73..7a88d4f52 100644 --- a/src/input/RewindInputPlugin.cxx +++ b/src/input/RewindInputPlugin.cxx @@ -24,8 +24,6 @@ #include "InputPlugin.hxx" #include "Tag.hxx" -#include <glib.h> - #include <assert.h> #include <string.h> #include <stdio.h> @@ -112,11 +110,11 @@ input_rewind_close(struct input_stream *is) } static bool -input_rewind_check(struct input_stream *is, GError **error_r) +input_rewind_check(struct input_stream *is, Error &error) { RewindInputStream *r = (RewindInputStream *)is; - return input_stream_check(r->input, error_r); + return input_stream_check(r->input, error); } static void @@ -146,7 +144,7 @@ input_rewind_available(struct input_stream *is) static size_t input_rewind_read(struct input_stream *is, void *ptr, size_t size, - GError **error_r) + Error &error) { RewindInputStream *r = (RewindInputStream *)is; @@ -167,7 +165,7 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size, } else { /* pass method call to underlying stream */ - size_t nbytes = input_stream_read(r->input, ptr, size, error_r); + size_t nbytes = input_stream_read(r->input, ptr, size, error); if (r->input->offset > (goffset)sizeof(r->buffer)) /* disable buffering */ @@ -197,7 +195,7 @@ input_rewind_eof(struct input_stream *is) static bool input_rewind_seek(struct input_stream *is, goffset offset, int whence, - GError **error_r) + Error &error) { RewindInputStream *r = (RewindInputStream *)is; @@ -216,7 +214,7 @@ input_rewind_seek(struct input_stream *is, goffset offset, int whence, return true; } else { bool success = input_stream_seek(r->input, offset, whence, - error_r); + error); r->CopyAttributes(); /* disable the buffer, because r->input has left the diff --git a/src/mixer/AlsaMixerPlugin.cxx b/src/mixer/AlsaMixerPlugin.cxx index 587ec699e..1ea26d0c1 100644 --- a/src/mixer/AlsaMixerPlugin.cxx +++ b/src/mixer/AlsaMixerPlugin.cxx @@ -25,6 +25,8 @@ #include "event/MultiSocketMonitor.hxx" #include "event/Loop.hxx" #include "util/ReusableArray.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <algorithm> @@ -68,23 +70,15 @@ public: AlsaMixer():Mixer(alsa_mixer_plugin) {} void Configure(const config_param ¶m); - bool Setup(GError **error_r); - bool Open(GError **error_r); + bool Setup(Error &error); + bool Open(Error &error); void Close(); - int GetVolume(GError **error_r); - bool SetVolume(unsigned volume, GError **error_r); + int GetVolume(Error &error); + bool SetVolume(unsigned volume, Error &error); }; -/** - * The quark used for GError.domain. - */ -gcc_const -static inline GQuark -alsa_mixer_quark(void) -{ - return g_quark_from_static_string("alsa_mixer"); -} +static constexpr Domain alsa_mixer_domain("alsa_mixer"); int AlsaMixerMonitor::PrepareSockets() @@ -158,7 +152,7 @@ AlsaMixer::Configure(const config_param ¶m) static Mixer * alsa_mixer_init(gcc_unused void *ao, const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { AlsaMixer *am = new AlsaMixer(); am->Configure(param); @@ -194,35 +188,35 @@ alsa_mixer_lookup_elem(snd_mixer_t *handle, const char *name, unsigned idx) } inline bool -AlsaMixer::Setup(GError **error_r) +AlsaMixer::Setup(Error &error) { int err; if ((err = snd_mixer_attach(handle, device)) < 0) { - g_set_error(error_r, alsa_mixer_quark(), err, - "failed to attach to %s: %s", - device, snd_strerror(err)); + error.Format(alsa_mixer_domain, err, + "failed to attach to %s: %s", + device, snd_strerror(err)); return false; } if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { - g_set_error(error_r, alsa_mixer_quark(), err, - "snd_mixer_selem_register() failed: %s", - snd_strerror(err)); + error.Format(alsa_mixer_domain, err, + "snd_mixer_selem_register() failed: %s", + snd_strerror(err)); return false; } if ((err = snd_mixer_load(handle)) < 0) { - g_set_error(error_r, alsa_mixer_quark(), err, - "snd_mixer_load() failed: %s\n", - snd_strerror(err)); + error.Format(alsa_mixer_domain, err, + "snd_mixer_load() failed: %s\n", + snd_strerror(err)); return false; } elem = alsa_mixer_lookup_elem(handle, control, index); if (elem == NULL) { - g_set_error(error_r, alsa_mixer_quark(), 0, + error.Format(alsa_mixer_domain, 0, "no such mixer control: %s", control); return false; } @@ -238,7 +232,7 @@ AlsaMixer::Setup(GError **error_r) } inline bool -AlsaMixer::Open(GError **error_r) +AlsaMixer::Open(Error &error) { int err; @@ -246,12 +240,12 @@ AlsaMixer::Open(GError **error_r) err = snd_mixer_open(&handle, 0); if (err < 0) { - g_set_error(error_r, alsa_mixer_quark(), err, - "snd_mixer_open() failed: %s", snd_strerror(err)); + error.Format(alsa_mixer_domain, err, + "snd_mixer_open() failed: %s", snd_strerror(err)); return false; } - if (!Setup(error_r)) { + if (!Setup(error)) { snd_mixer_close(handle); return false; } @@ -260,11 +254,11 @@ AlsaMixer::Open(GError **error_r) } static bool -alsa_mixer_open(Mixer *data, GError **error_r) +alsa_mixer_open(Mixer *data, Error &error) { AlsaMixer *am = (AlsaMixer *)data; - return am->Open(error_r); + return am->Open(error); } inline void @@ -286,7 +280,7 @@ alsa_mixer_close(Mixer *data) } inline int -AlsaMixer::GetVolume(GError **error_r) +AlsaMixer::GetVolume(Error &error) { int err; int ret; @@ -296,9 +290,9 @@ AlsaMixer::GetVolume(GError **error_r) err = snd_mixer_handle_events(handle); if (err < 0) { - g_set_error(error_r, alsa_mixer_quark(), err, - "snd_mixer_handle_events() failed: %s", - snd_strerror(err)); + error.Format(alsa_mixer_domain, err, + "snd_mixer_handle_events() failed: %s", + snd_strerror(err)); return false; } @@ -306,9 +300,9 @@ AlsaMixer::GetVolume(GError **error_r) SND_MIXER_SCHN_FRONT_LEFT, &level); if (err < 0) { - g_set_error(error_r, alsa_mixer_quark(), err, - "failed to read ALSA volume: %s", - snd_strerror(err)); + error.Format(alsa_mixer_domain, err, + "failed to read ALSA volume: %s", + snd_strerror(err)); return false; } @@ -325,14 +319,14 @@ AlsaMixer::GetVolume(GError **error_r) } static int -alsa_mixer_get_volume(Mixer *mixer, GError **error_r) +alsa_mixer_get_volume(Mixer *mixer, Error &error) { AlsaMixer *am = (AlsaMixer *)mixer; - return am->GetVolume(error_r); + return am->GetVolume(error); } inline bool -AlsaMixer::SetVolume(unsigned volume, GError **error_r) +AlsaMixer::SetVolume(unsigned volume, Error &error) { float vol; long level; @@ -351,9 +345,9 @@ AlsaMixer::SetVolume(unsigned volume, GError **error_r) err = snd_mixer_selem_set_playback_volume_all(elem, level); if (err < 0) { - g_set_error(error_r, alsa_mixer_quark(), err, - "failed to set ALSA volume: %s", - snd_strerror(err)); + error.Format(alsa_mixer_domain, err, + "failed to set ALSA volume: %s", + snd_strerror(err)); return false; } @@ -361,10 +355,10 @@ AlsaMixer::SetVolume(unsigned volume, GError **error_r) } static bool -alsa_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) +alsa_mixer_set_volume(Mixer *mixer, unsigned volume, Error &error) { AlsaMixer *am = (AlsaMixer *)mixer; - return am->SetVolume(volume, error_r); + return am->SetVolume(volume, error); } const struct mixer_plugin alsa_mixer_plugin = { diff --git a/src/mixer/OssMixerPlugin.cxx b/src/mixer/OssMixerPlugin.cxx index 231f38432..84cd223e6 100644 --- a/src/mixer/OssMixerPlugin.cxx +++ b/src/mixer/OssMixerPlugin.cxx @@ -21,6 +21,8 @@ #include "MixerInternal.hxx" #include "OutputAPI.hxx" #include "system/fd_util.h" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> @@ -51,22 +53,15 @@ class OssMixer : public Mixer { public: OssMixer():Mixer(oss_mixer_plugin) {} - bool Configure(const config_param ¶m, GError **error_r); - bool Open(GError **error_r); + bool Configure(const config_param ¶m, Error &error); + bool Open(Error &error); void Close(); - int GetVolume(GError **error_r); - bool SetVolume(unsigned volume, GError **error_r); + int GetVolume(Error &error); + bool SetVolume(unsigned volume, Error &error); }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -oss_mixer_quark(void) -{ - return g_quark_from_static_string("oss_mixer"); -} +static constexpr Domain oss_mixer_domain("oss_mixer"); static int oss_find_mixer(const char *name) @@ -84,17 +79,16 @@ oss_find_mixer(const char *name) } inline bool -OssMixer::Configure(const config_param ¶m, GError **error_r) +OssMixer::Configure(const config_param ¶m, Error &error) { - device = param.GetBlockValue("mixer_device", - VOLUME_MIXER_OSS_DEFAULT); + device = param.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT); control = param.GetBlockValue("mixer_control"); if (control != NULL) { volume_control = oss_find_mixer(control); if (volume_control < 0) { - g_set_error(error_r, oss_mixer_quark(), 0, - "no such mixer control: %s", control); + error.Format(oss_mixer_domain, 0, + "no such mixer control: %s", control); return false; } } else @@ -105,11 +99,11 @@ OssMixer::Configure(const config_param ¶m, GError **error_r) static Mixer * oss_mixer_init(gcc_unused void *ao, const config_param ¶m, - GError **error_r) + Error &error) { OssMixer *om = new OssMixer(); - if (!om->Configure(param, error_r)) { + if (!om->Configure(param, error)) { delete om; return nullptr; } @@ -141,13 +135,11 @@ oss_mixer_close(Mixer *data) } inline bool -OssMixer::Open(GError **error_r) +OssMixer::Open(Error &error) { device_fd = open_cloexec(device, O_RDONLY, 0); if (device_fd < 0) { - g_set_error(error_r, oss_mixer_quark(), errno, - "failed to open %s: %s", - device, g_strerror(errno)); + error.FormatErrno("failed to open %s", device); return false; } @@ -155,17 +147,15 @@ OssMixer::Open(GError **error_r) int devmask = 0; if (ioctl(device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { - g_set_error(error_r, oss_mixer_quark(), errno, - "READ_DEVMASK failed: %s", - g_strerror(errno)); + error.SetErrno("READ_DEVMASK failed"); Close(); return false; } if (((1 << volume_control) & devmask) == 0) { - g_set_error(error_r, oss_mixer_quark(), 0, - "mixer control \"%s\" not usable", - control); + error.Format(oss_mixer_domain, 0, + "mixer control \"%s\" not usable", + control); Close(); return false; } @@ -175,15 +165,15 @@ OssMixer::Open(GError **error_r) } static bool -oss_mixer_open(Mixer *data, GError **error_r) +oss_mixer_open(Mixer *data, Error &error) { OssMixer *om = (OssMixer *) data; - return om->Open(error_r); + return om->Open(error); } inline int -OssMixer::GetVolume(GError **error_r) +OssMixer::GetVolume(Error &error) { int left, right, level; int ret; @@ -192,9 +182,7 @@ OssMixer::GetVolume(GError **error_r) ret = ioctl(device_fd, MIXER_READ(volume_control), &level); if (ret < 0) { - g_set_error(error_r, oss_mixer_quark(), errno, - "failed to read OSS volume: %s", - g_strerror(errno)); + error.SetErrno("failed to read OSS volume"); return false; } @@ -210,14 +198,14 @@ OssMixer::GetVolume(GError **error_r) } static int -oss_mixer_get_volume(Mixer *mixer, GError **error_r) +oss_mixer_get_volume(Mixer *mixer, Error &error) { OssMixer *om = (OssMixer *)mixer; - return om->GetVolume(error_r); + return om->GetVolume(error); } inline bool -OssMixer::SetVolume(unsigned volume, GError **error_r) +OssMixer::SetVolume(unsigned volume, Error &error) { int level; int ret; @@ -229,9 +217,7 @@ OssMixer::SetVolume(unsigned volume, GError **error_r) ret = ioctl(device_fd, MIXER_WRITE(volume_control), &level); if (ret < 0) { - g_set_error(error_r, oss_mixer_quark(), errno, - "failed to set OSS volume: %s", - g_strerror(errno)); + error.SetErrno("failed to set OSS volume"); return false; } @@ -239,10 +225,10 @@ OssMixer::SetVolume(unsigned volume, GError **error_r) } static bool -oss_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) +oss_mixer_set_volume(Mixer *mixer, unsigned volume, Error &error) { OssMixer *om = (OssMixer *)mixer; - return om->SetVolume(volume, error_r); + return om->SetVolume(volume, error); } const struct mixer_plugin oss_mixer_plugin = { diff --git a/src/mixer/PulseMixerPlugin.cxx b/src/mixer/PulseMixerPlugin.cxx index 1c99b2469..069f4e36f 100644 --- a/src/mixer/PulseMixerPlugin.cxx +++ b/src/mixer/PulseMixerPlugin.cxx @@ -23,6 +23,8 @@ #include "output/PulseOutputPlugin.hxx" #include "conf.h" #include "GlobalEvents.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> @@ -52,14 +54,7 @@ struct PulseMixer final : public Mixer { } }; -/** - * The quark used for GError.domain. - */ -static inline GQuark -pulse_mixer_quark(void) -{ - return g_quark_from_static_string("pulse_mixer"); -} +static constexpr Domain pulse_mixer_domain("pulse_mixer"); static void pulse_mixer_offline(PulseMixer *pm) @@ -154,13 +149,13 @@ pulse_mixer_on_change(PulseMixer *pm, static Mixer * pulse_mixer_init(void *ao, gcc_unused const config_param ¶m, - GError **error_r) + Error &error) { PulseOutput *po = (PulseOutput *)ao; if (ao == NULL) { - g_set_error(error_r, pulse_mixer_quark(), 0, - "The pulse mixer cannot work without the audio output"); + error.Set(pulse_mixer_domain, + "The pulse mixer cannot work without the audio output"); return nullptr; } @@ -182,7 +177,7 @@ pulse_mixer_finish(Mixer *data) } static int -pulse_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) +pulse_mixer_get_volume(Mixer *mixer, gcc_unused Error &error) { PulseMixer *pm = (PulseMixer *) mixer; int ret; @@ -199,7 +194,7 @@ pulse_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) } static bool -pulse_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) +pulse_mixer_set_volume(Mixer *mixer, unsigned volume, Error &error) { PulseMixer *pm = (PulseMixer *) mixer; struct pa_cvolume cvolume; @@ -209,13 +204,13 @@ pulse_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) if (!pm->online) { pulse_output_unlock(pm->output); - g_set_error(error_r, pulse_mixer_quark(), 0, "disconnected"); + error.Set(pulse_mixer_domain, "disconnected"); return false; } pa_cvolume_set(&cvolume, pm->volume.channels, (pa_volume_t)volume * PA_VOLUME_NORM / 100 + 0.5); - success = pulse_output_set_volume(pm->output, &cvolume, error_r); + success = pulse_output_set_volume(pm->output, &cvolume, error); if (success) pm->volume = cvolume; diff --git a/src/mixer/RoarMixerPlugin.cxx b/src/mixer/RoarMixerPlugin.cxx index 90d54ddaa..6bd700551 100644 --- a/src/mixer/RoarMixerPlugin.cxx +++ b/src/mixer/RoarMixerPlugin.cxx @@ -35,7 +35,7 @@ struct RoarMixer final : public Mixer { static Mixer * roar_mixer_init(void *ao, gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { return new RoarMixer((RoarOutput *)ao); } @@ -49,7 +49,7 @@ roar_mixer_finish(Mixer *data) } static int -roar_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) +roar_mixer_get_volume(Mixer *mixer, gcc_unused Error &error) { RoarMixer *self = (RoarMixer *)mixer; return roar_output_get_volume(self->self); @@ -57,7 +57,7 @@ roar_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) static bool roar_mixer_set_volume(Mixer *mixer, unsigned volume, - gcc_unused GError **error_r) + gcc_unused Error &error) { RoarMixer *self = (RoarMixer *)mixer; return roar_output_set_volume(self->self, volume); diff --git a/src/mixer/SoftwareMixerPlugin.cxx b/src/mixer/SoftwareMixerPlugin.cxx index 8a268aaf1..b7eb8ff0f 100644 --- a/src/mixer/SoftwareMixerPlugin.cxx +++ b/src/mixer/SoftwareMixerPlugin.cxx @@ -26,10 +26,18 @@ #include "filter/VolumeFilterPlugin.hxx" #include "pcm/PcmVolume.hxx" #include "ConfigData.hxx" +#include "util/Error.hxx" #include <assert.h> #include <math.h> +static Filter * +CreateVolumeFilter() +{ + Error error; + return filter_new(&volume_filter_plugin, config_param(), error); +} + struct SoftwareMixer final : public Mixer { Filter *filter; @@ -37,8 +45,7 @@ struct SoftwareMixer final : public Mixer { SoftwareMixer() :Mixer(software_mixer_plugin), - filter(filter_new(&volume_filter_plugin, config_param(), - nullptr)), + filter(CreateVolumeFilter()), volume(100) { assert(filter != nullptr); @@ -52,7 +59,7 @@ struct SoftwareMixer final : public Mixer { static Mixer * software_mixer_init(gcc_unused void *ao, gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { return new SoftwareMixer(); } @@ -66,7 +73,7 @@ software_mixer_finish(Mixer *data) } static int -software_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) +software_mixer_get_volume(Mixer *mixer, gcc_unused Error &error) { SoftwareMixer *sm = (SoftwareMixer *)mixer; @@ -75,7 +82,7 @@ software_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) static bool software_mixer_set_volume(Mixer *mixer, unsigned volume, - gcc_unused GError **error_r) + gcc_unused Error &error) { SoftwareMixer *sm = (SoftwareMixer *)mixer; diff --git a/src/mixer/WinmmMixerPlugin.cxx b/src/mixer/WinmmMixerPlugin.cxx index cbfb8f6cb..ae25b532c 100644 --- a/src/mixer/WinmmMixerPlugin.cxx +++ b/src/mixer/WinmmMixerPlugin.cxx @@ -21,6 +21,8 @@ #include "MixerInternal.hxx" #include "OutputAPI.hxx" #include "output/WinmmOutputPlugin.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <mmsystem.h> @@ -40,11 +42,7 @@ struct WinmmMixer final : public Mixer { } }; -static inline GQuark -winmm_mixer_quark(void) -{ - return g_quark_from_static_string("winmm_mixer"); -} +static constexpr Domain winmm_mixer_domain("winmm_mixer"); static inline int winmm_volume_decode(DWORD volume) @@ -61,7 +59,7 @@ winmm_volume_encode(int volume) static Mixer * winmm_mixer_init(void *ao, gcc_unused const config_param ¶m, - gcc_unused GError **error_r) + gcc_unused Error &error) { assert(ao != nullptr); @@ -77,7 +75,7 @@ winmm_mixer_finish(Mixer *data) } static int -winmm_mixer_get_volume(Mixer *mixer, GError **error_r) +winmm_mixer_get_volume(Mixer *mixer, Error &error) { WinmmMixer *wm = (WinmmMixer *) mixer; DWORD volume; @@ -85,8 +83,7 @@ winmm_mixer_get_volume(Mixer *mixer, GError **error_r) MMRESULT result = waveOutGetVolume(handle, &volume); if (result != MMSYSERR_NOERROR) { - g_set_error(error_r, 0, winmm_mixer_quark(), - "Failed to get winmm volume"); + error.Set(winmm_mixer_domain, "Failed to get winmm volume"); return -1; } @@ -94,7 +91,7 @@ winmm_mixer_get_volume(Mixer *mixer, GError **error_r) } static bool -winmm_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) +winmm_mixer_set_volume(Mixer *mixer, unsigned volume, Error &error) { WinmmMixer *wm = (WinmmMixer *) mixer; DWORD value = winmm_volume_encode(volume); @@ -102,8 +99,7 @@ winmm_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) MMRESULT result = waveOutSetVolume(handle, value); if (result != MMSYSERR_NOERROR) { - g_set_error(error_r, 0, winmm_mixer_quark(), - "Failed to set winmm volume"); + error.Set(winmm_mixer_domain, "Failed to set winmm volume"); return false; } diff --git a/src/mpd_error.h b/src/mpd_error.h index e0b7d29a4..f7af84656 100644 --- a/src/mpd_error.h +++ b/src/mpd_error.h @@ -24,7 +24,7 @@ #include <stdlib.h> /* This macro is used as an intermediate step to a proper error handling - * using GError in mpd. It is used for unrecoverable error conditions + * using #Error in mpd. It is used for unrecoverable error conditions * and exits immediately. The long-term goal is to replace this macro by * proper error handling. */ 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 <glib.h> #include <alsa/asoundlib.h> @@ -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 <ao/ao.h> #include <glib.h> @@ -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 <glib.h> @@ -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 <forward_list> 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 <assert.h> @@ -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 <assert.h> @@ -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 <glib.h> @@ -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 <glib.h> @@ -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 <stdio.h> #include <errno.h> @@ -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 <glib.h> @@ -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 <glib.h> @@ -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 <shout/shout.h> @@ -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 <glib.h> +#include "util/Error.hxx" #include <sys/stropts.h> #include <sys/types.h> @@ -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 <stdlib.h> #include <string.h> @@ -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); } diff --git a/src/pcm/PcmConvert.cxx b/src/pcm/PcmConvert.cxx index 7e71da283..38672810e 100644 --- a/src/pcm/PcmConvert.cxx +++ b/src/pcm/PcmConvert.cxx @@ -23,6 +23,8 @@ #include "PcmFormat.hxx" #include "pcm_pack.h" #include "AudioFormat.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> @@ -32,6 +34,8 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "pcm" +const Domain pcm_convert_domain("pcm_convert"); + PcmConvert::PcmConvert() { } @@ -51,7 +55,7 @@ inline const int16_t * PcmConvert::Convert16(const AudioFormat src_format, const void *src_buffer, size_t src_size, const AudioFormat dest_format, size_t *dest_size_r, - GError **error_r) + Error &error) { const int16_t *buf; size_t len; @@ -63,9 +67,9 @@ PcmConvert::Convert16(const AudioFormat src_format, src_buffer, src_size, &len); if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %s to 16 bit is not implemented", - sample_format_to_string(src_format.format)); + error.Format(pcm_convert_domain, + "Conversion from %s to 16 bit is not implemented", + sample_format_to_string(src_format.format)); return NULL; } @@ -75,11 +79,11 @@ PcmConvert::Convert16(const AudioFormat src_format, src_format.channels, buf, len, &len); if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to %u channels " - "is not implemented", - src_format.channels, - dest_format.channels); + error.Format(pcm_convert_domain, + "Conversion from %u to %u channels " + "is not implemented", + src_format.channels, + dest_format.channels); return NULL; } } @@ -88,7 +92,7 @@ PcmConvert::Convert16(const AudioFormat src_format, buf = resampler.Resample16(dest_format.channels, src_format.sample_rate, buf, len, dest_format.sample_rate, &len, - error_r); + error); if (buf == NULL) return NULL; } @@ -101,7 +105,7 @@ inline const int32_t * PcmConvert::Convert24(const AudioFormat src_format, const void *src_buffer, size_t src_size, const AudioFormat dest_format, size_t *dest_size_r, - GError **error_r) + Error &error) { const int32_t *buf; size_t len; @@ -112,9 +116,9 @@ PcmConvert::Convert24(const AudioFormat src_format, src_format.format, src_buffer, src_size, &len); if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %s to 24 bit is not implemented", - sample_format_to_string(src_format.format)); + error.Format(pcm_convert_domain, + "Conversion from %s to 24 bit is not implemented", + sample_format_to_string(src_format.format)); return NULL; } @@ -124,11 +128,11 @@ PcmConvert::Convert24(const AudioFormat src_format, src_format.channels, buf, len, &len); if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to %u channels " - "is not implemented", - src_format.channels, - dest_format.channels); + error.Format(pcm_convert_domain, + "Conversion from %u to %u channels " + "is not implemented", + src_format.channels, + dest_format.channels); return NULL; } } @@ -137,7 +141,7 @@ PcmConvert::Convert24(const AudioFormat src_format, buf = resampler.Resample24(dest_format.channels, src_format.sample_rate, buf, len, dest_format.sample_rate, &len, - error_r); + error); if (buf == NULL) return NULL; } @@ -150,7 +154,7 @@ inline const int32_t * PcmConvert::Convert32(const AudioFormat src_format, const void *src_buffer, size_t src_size, const AudioFormat dest_format, size_t *dest_size_r, - GError **error_r) + Error &error) { const int32_t *buf; size_t len; @@ -161,9 +165,9 @@ PcmConvert::Convert32(const AudioFormat src_format, src_format.format, src_buffer, src_size, &len); if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %s to 32 bit is not implemented", - sample_format_to_string(src_format.format)); + error.Format(pcm_convert_domain, + "Conversion from %s to 32 bit is not implemented", + sample_format_to_string(src_format.format)); return NULL; } @@ -173,11 +177,11 @@ PcmConvert::Convert32(const AudioFormat src_format, src_format.channels, buf, len, &len); if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to %u channels " - "is not implemented", - src_format.channels, - dest_format.channels); + error.Format(pcm_convert_domain, + "Conversion from %u to %u channels " + "is not implemented", + src_format.channels, + dest_format.channels); return NULL; } } @@ -186,7 +190,7 @@ PcmConvert::Convert32(const AudioFormat src_format, buf = resampler.Resample32(dest_format.channels, src_format.sample_rate, buf, len, dest_format.sample_rate, &len, - error_r); + error); if (buf == NULL) return buf; } @@ -199,7 +203,7 @@ inline const float * PcmConvert::ConvertFloat(const AudioFormat src_format, const void *src_buffer, size_t src_size, const AudioFormat dest_format, size_t *dest_size_r, - GError **error_r) + Error &error) { const float *buffer = (const float *)src_buffer; size_t size = src_size; @@ -212,9 +216,9 @@ PcmConvert::ConvertFloat(const AudioFormat src_format, src_format.format, buffer, size, &size); if (buffer == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %s to float is not implemented", - sample_format_to_string(src_format.format)); + error.Format(pcm_convert_domain, + "Conversion from %s to float is not implemented", + sample_format_to_string(src_format.format)); return NULL; } @@ -226,11 +230,11 @@ PcmConvert::ConvertFloat(const AudioFormat src_format, src_format.channels, buffer, size, &size); if (buffer == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to %u channels " - "is not implemented", - src_format.channels, - dest_format.channels); + error.Format(pcm_convert_domain, + "Conversion from %u to %u channels " + "is not implemented", + src_format.channels, + dest_format.channels); return NULL; } } @@ -243,7 +247,7 @@ PcmConvert::ConvertFloat(const AudioFormat src_format, src_format.sample_rate, buffer, size, dest_format.sample_rate, - &size, error_r); + &size, error); if (buffer == NULL) return NULL; } @@ -257,7 +261,7 @@ PcmConvert::Convert(AudioFormat src_format, const void *src, size_t src_size, const AudioFormat dest_format, size_t *dest_size_r, - GError **error_r) + Error &error) { AudioFormat float_format; if (src_format.format == SampleFormat::DSD) { @@ -266,8 +270,8 @@ PcmConvert::Convert(AudioFormat src_format, false, (const uint8_t *)src, src_size, &f_size); if (f == NULL) { - g_set_error_literal(error_r, pcm_convert_quark(), 0, - "DSD to PCM conversion failed"); + error.Set(pcm_convert_domain, + "DSD to PCM conversion failed"); return NULL; } @@ -283,27 +287,27 @@ PcmConvert::Convert(AudioFormat src_format, case SampleFormat::S16: return Convert16(src_format, src, src_size, dest_format, dest_size_r, - error_r); + error); case SampleFormat::S24_P32: return Convert24(src_format, src, src_size, dest_format, dest_size_r, - error_r); + error); case SampleFormat::S32: return Convert32(src_format, src, src_size, dest_format, dest_size_r, - error_r); + error); case SampleFormat::FLOAT: return ConvertFloat(src_format, src, src_size, dest_format, dest_size_r, - error_r); + error); default: - g_set_error(error_r, pcm_convert_quark(), 0, - "PCM conversion to %s is not implemented", - sample_format_to_string(dest_format.format)); + error.Format(pcm_convert_domain, + "PCM conversion to %s is not implemented", + sample_format_to_string(dest_format.format)); return NULL; } } diff --git a/src/pcm/PcmConvert.hxx b/src/pcm/PcmConvert.hxx index 42b59e407..40f785179 100644 --- a/src/pcm/PcmConvert.hxx +++ b/src/pcm/PcmConvert.hxx @@ -25,9 +25,10 @@ #include "PcmResample.hxx" #include "PcmBuffer.hxx" -#include <glib.h> +#include <stddef.h> struct AudioFormat; +class Error; /** * This object is statically allocated (within another struct), and @@ -75,38 +76,34 @@ public: const void *src, size_t src_size, AudioFormat dest_format, size_t *dest_size_r, - GError **error_r); + Error &error); private: const int16_t *Convert16(AudioFormat src_format, const void *src_buffer, size_t src_size, AudioFormat dest_format, size_t *dest_size_r, - GError **error_r); + Error &error); const int32_t *Convert24(AudioFormat src_format, const void *src_buffer, size_t src_size, AudioFormat dest_format, size_t *dest_size_r, - GError **error_r); + Error &error); const int32_t *Convert32(AudioFormat src_format, const void *src_buffer, size_t src_size, AudioFormat dest_format, size_t *dest_size_r, - GError **error_r); + Error &error); const float *ConvertFloat(AudioFormat src_format, const void *src_buffer, size_t src_size, AudioFormat dest_format, size_t *dest_size_r, - GError **error_r); + Error &error); }; -static inline GQuark -pcm_convert_quark(void) -{ - return g_quark_from_static_string("pcm_convert"); -} +extern const class Domain pcm_convert_domain; #endif diff --git a/src/pcm/PcmResample.cxx b/src/pcm/PcmResample.cxx index 423e3d442..9ade8cf5b 100644 --- a/src/pcm/PcmResample.cxx +++ b/src/pcm/PcmResample.cxx @@ -39,7 +39,7 @@ pcm_resample_lsr_enabled(void) #endif bool -pcm_resample_global_init(GError **error_r) +pcm_resample_global_init(Error &error) { #ifdef HAVE_LIBSAMPLERATE const char *converter = @@ -47,11 +47,11 @@ pcm_resample_global_init(GError **error_r) lsr_enabled = strcmp(converter, "internal") != 0; if (lsr_enabled) - return pcm_resample_lsr_global_init(converter, error_r); + return pcm_resample_lsr_global_init(converter, error); else return true; #else - (void)error_r; + (void)error; return true; #endif } @@ -84,7 +84,7 @@ const float * PcmResampler::ResampleFloat(unsigned channels, unsigned src_rate, const float *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r) + Error &error_r) { #ifdef HAVE_LIBSAMPLERATE if (pcm_resample_lsr_enabled()) @@ -110,7 +110,7 @@ const int16_t * PcmResampler::Resample16(unsigned channels, unsigned src_rate, const int16_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r) + Error &error_r) { #ifdef HAVE_LIBSAMPLERATE if (pcm_resample_lsr_enabled()) @@ -131,7 +131,7 @@ const int32_t * PcmResampler::Resample32(unsigned channels, unsigned src_rate, const int32_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r) + Error &error_r) { #ifdef HAVE_LIBSAMPLERATE if (pcm_resample_lsr_enabled()) diff --git a/src/pcm/PcmResample.hxx b/src/pcm/PcmResample.hxx index db0bbff8d..8a740744a 100644 --- a/src/pcm/PcmResample.hxx +++ b/src/pcm/PcmResample.hxx @@ -22,7 +22,6 @@ #include "check.h" #include "PcmBuffer.hxx" -#include "gerror.h" #include <stdint.h> #include <stddef.h> @@ -31,6 +30,8 @@ #include <samplerate.h> #endif +class Error; + /** * This object is statically allocated (within another struct), and * holds buffer allocations and the state for the resampler. @@ -75,7 +76,7 @@ struct PcmResampler { const float *ResampleFloat(unsigned channels, unsigned src_rate, const float *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r); + Error &error_r); /** * Resamples 16 bit PCM data. @@ -91,7 +92,7 @@ struct PcmResampler { const int16_t *Resample16(unsigned channels, unsigned src_rate, const int16_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r); + Error &error_r); /** * Resamples 32 bit PCM data. @@ -107,7 +108,7 @@ struct PcmResampler { const int32_t *Resample32(unsigned channels, unsigned src_rate, const int32_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r); + Error &error_r); /** * Resamples 24 bit PCM data. @@ -123,7 +124,7 @@ struct PcmResampler { const int32_t *Resample24(unsigned channels, unsigned src_rate, const int32_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r) + Error &error_r) { /* reuse the 32 bit code - the resampler code doesn't care if the upper 8 bits are actually used */ @@ -133,6 +134,6 @@ struct PcmResampler { }; bool -pcm_resample_global_init(GError **error_r); +pcm_resample_global_init(Error &error); #endif diff --git a/src/pcm/PcmResampleInternal.hxx b/src/pcm/PcmResampleInternal.hxx index 5275c090a..59bb2f5df 100644 --- a/src/pcm/PcmResampleInternal.hxx +++ b/src/pcm/PcmResampleInternal.hxx @@ -33,7 +33,7 @@ #ifdef HAVE_LIBSAMPLERATE bool -pcm_resample_lsr_global_init(const char *converter, GError **error_r); +pcm_resample_lsr_global_init(const char *converter, Error &error); void pcm_resample_lsr_init(PcmResampler *state); @@ -50,7 +50,7 @@ pcm_resample_lsr_float(PcmResampler *state, unsigned src_rate, const float *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r); + Error &error); const int16_t * pcm_resample_lsr_16(PcmResampler *state, @@ -58,7 +58,7 @@ pcm_resample_lsr_16(PcmResampler *state, unsigned src_rate, const int16_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r); + Error &error); const int32_t * pcm_resample_lsr_32(PcmResampler *state, @@ -67,7 +67,7 @@ pcm_resample_lsr_32(PcmResampler *state, const int32_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r); + Error &error); #endif diff --git a/src/pcm/PcmResampleLibsamplerate.cxx b/src/pcm/PcmResampleLibsamplerate.cxx index d8dde62e9..6710c2070 100644 --- a/src/pcm/PcmResampleLibsamplerate.cxx +++ b/src/pcm/PcmResampleLibsamplerate.cxx @@ -20,6 +20,8 @@ #include "config.h" #include "PcmResampleInternal.hxx" #include "conf.h" +#include "util/Error.hxx" +#include "util/Domain.hxx" #include <glib.h> @@ -32,11 +34,7 @@ static int lsr_converter = SRC_SINC_FASTEST; -static inline GQuark -libsamplerate_quark(void) -{ - return g_quark_from_static_string("libsamplerate"); -} +static constexpr Domain libsamplerate_domain("libsamplerate"); static bool lsr_parse_converter(const char *s) @@ -69,11 +67,11 @@ lsr_parse_converter(const char *s) } bool -pcm_resample_lsr_global_init(const char *converter, GError **error_r) +pcm_resample_lsr_global_init(const char *converter, Error &error) { if (!lsr_parse_converter(converter)) { - g_set_error(error_r, libsamplerate_quark(), 0, - "unknown samplerate converter '%s'", converter); + error.Format(libsamplerate_domain, + "unknown samplerate converter '%s'", converter); return false; } @@ -109,7 +107,7 @@ pcm_resample_lsr_reset(PcmResampler *state) static bool pcm_resample_set(PcmResampler *state, unsigned channels, unsigned src_rate, unsigned dest_rate, - GError **error_r) + Error &error_r) { /* (re)set the state/ratio if the in or out format changed */ if (channels == state->prev.channels && @@ -128,9 +126,9 @@ pcm_resample_set(PcmResampler *state, int error; state->state = src_new(lsr_converter, channels, &error); if (!state->state) { - g_set_error(error_r, libsamplerate_quark(), state->error, - "libsamplerate initialization has failed: %s", - src_strerror(error)); + error_r.Format(libsamplerate_domain, error, + "libsamplerate initialization has failed: %s", + src_strerror(error)); return false; } @@ -144,14 +142,14 @@ pcm_resample_set(PcmResampler *state, } static bool -lsr_process(PcmResampler *state, GError **error_r) +lsr_process(PcmResampler *state, Error &error) { if (state->error == 0) state->error = src_process(state->state, &state->data); if (state->error) { - g_set_error(error_r, libsamplerate_quark(), state->error, - "libsamplerate has failed: %s", - src_strerror(state->error)); + error.Format(libsamplerate_domain, state->error, + "libsamplerate has failed: %s", + src_strerror(state->error)); return false; } @@ -164,16 +162,15 @@ pcm_resample_lsr_float(PcmResampler *state, unsigned src_rate, const float *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r) + Error &error) { SRC_DATA *data = &state->data; assert((src_size % (sizeof(*src_buffer) * channels)) == 0); - if (!pcm_resample_set(state, channels, src_rate, dest_rate, error_r)) + if (!pcm_resample_set(state, channels, src_rate, dest_rate, error)) return nullptr; - data->input_frames = src_size / sizeof(*src_buffer) / channels; data->data_in = const_cast<float *>(src_buffer); @@ -181,7 +178,7 @@ pcm_resample_lsr_float(PcmResampler *state, size_t data_out_size = data->output_frames * sizeof(float) * channels; data->data_out = (float *)state->out.Get(data_out_size); - if (!lsr_process(state, error_r)) + if (!lsr_process(state, error)) return nullptr; *dest_size_r = data->output_frames_gen * @@ -195,14 +192,14 @@ pcm_resample_lsr_16(PcmResampler *state, unsigned src_rate, const int16_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r) + Error &error) { SRC_DATA *data = &state->data; assert((src_size % (sizeof(*src_buffer) * channels)) == 0); if (!pcm_resample_set(state, channels, src_rate, dest_rate, - error_r)) + error)) return nullptr; data->input_frames = src_size / sizeof(*src_buffer) / channels; @@ -216,7 +213,7 @@ pcm_resample_lsr_16(PcmResampler *state, src_short_to_float_array(src_buffer, data->data_in, data->input_frames * channels); - if (!lsr_process(state, error_r)) + if (!lsr_process(state, error)) return nullptr; int16_t *dest_buffer; @@ -255,14 +252,14 @@ pcm_resample_lsr_32(PcmResampler *state, unsigned src_rate, const int32_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - GError **error_r) + Error &error) { SRC_DATA *data = &state->data; assert((src_size % (sizeof(*src_buffer) * channels)) == 0); if (!pcm_resample_set(state, channels, src_rate, dest_rate, - error_r)) + error)) return nullptr; data->input_frames = src_size / sizeof(*src_buffer) / channels; @@ -276,7 +273,7 @@ pcm_resample_lsr_32(PcmResampler *state, src_int_to_float_array(src_buffer, data->data_in, data->input_frames * channels); - if (!lsr_process(state, error_r)) + if (!lsr_process(state, error)) return nullptr; int32_t *dest_buffer; diff --git a/src/playlist/AsxPlaylistPlugin.cxx b/src/playlist/AsxPlaylistPlugin.cxx index c0a47b8e3..16b187402 100644 --- a/src/playlist/AsxPlaylistPlugin.cxx +++ b/src/playlist/AsxPlaylistPlugin.cxx @@ -23,6 +23,7 @@ #include "InputLegacy.hxx" #include "Song.hxx" #include "Tag.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -208,6 +209,7 @@ asx_open_stream(struct input_stream *is) char buffer[1024]; size_t nbytes; bool success; + Error error2; GError *error = NULL; /* parse the ASX XML file */ @@ -218,12 +220,11 @@ asx_open_stream(struct input_stream *is) while (true) { nbytes = input_stream_lock_read(is, buffer, sizeof(buffer), - &error); + error2); if (nbytes == 0) { - if (error != NULL) { + if (error2.IsDefined()) { g_markup_parse_context_free(context); - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error2.GetMessage()); return NULL; } diff --git a/src/playlist/LastFMPlaylistPlugin.cxx b/src/playlist/LastFMPlaylistPlugin.cxx index a6071e092..5b168ee83 100644 --- a/src/playlist/LastFMPlaylistPlugin.cxx +++ b/src/playlist/LastFMPlaylistPlugin.cxx @@ -24,6 +24,7 @@ #include "conf.h" #include "Song.hxx" #include "InputLegacy.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -92,16 +93,14 @@ static char * lastfm_get(const char *url, Mutex &mutex, Cond &cond) { struct input_stream *input_stream; - GError *error = NULL; + Error error; char buffer[4096]; - size_t length = 0, nbytes; + size_t length = 0; - input_stream = input_stream_open(url, mutex, cond, &error); + input_stream = input_stream_open(url, mutex, cond, error); if (input_stream == NULL) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } + if (error.IsDefined()) + g_warning("%s", error.GetMessage()); return NULL; } @@ -111,13 +110,12 @@ lastfm_get(const char *url, Mutex &mutex, Cond &cond) input_stream_wait_ready(input_stream); do { - nbytes = input_stream_read(input_stream, buffer + length, - sizeof(buffer) - length, &error); + size_t nbytes = + input_stream_read(input_stream, buffer + length, + sizeof(buffer) - length, error); if (nbytes == 0) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } + if (error.IsDefined()) + g_warning("%s", error.GetMessage()); if (input_stream_eof(input_stream)) break; @@ -166,7 +164,6 @@ lastfm_find(const char *response, const char *name) static struct playlist_provider * lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond) { - GError *error = NULL; char *p, *q, *response, *session; /* handshake */ @@ -225,15 +222,15 @@ lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond) NULL); g_free(session); - const auto is = input_stream_open(p, mutex, cond, &error); + Error error; + const auto is = input_stream_open(p, mutex, cond, error); g_free(p); if (is == nullptr) { - if (error != NULL) { + if (error.IsDefined()) g_warning("Failed to load XSPF playlist: %s", - error->message); - g_error_free(error); - } else + error.GetMessage()); + else g_warning("Failed to load XSPF playlist"); return NULL; } diff --git a/src/playlist/PlsPlaylistPlugin.cxx b/src/playlist/PlsPlaylistPlugin.cxx index 9ef302388..ab8f93bef 100644 --- a/src/playlist/PlsPlaylistPlugin.cxx +++ b/src/playlist/PlsPlaylistPlugin.cxx @@ -23,6 +23,7 @@ #include "InputLegacy.hxx" #include "Song.hxx" #include "Tag.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -104,6 +105,7 @@ static struct playlist_provider * pls_open_stream(struct input_stream *is) { GError *error = NULL; + Error error2; size_t nbytes; char buffer[1024]; bool success; @@ -113,11 +115,10 @@ pls_open_stream(struct input_stream *is) do { nbytes = input_stream_lock_read(is, buffer, sizeof(buffer), - &error); + error2); if (nbytes == 0) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); + if (error2.IsDefined()) { + g_warning("%s", error2.GetMessage()); return NULL; } diff --git a/src/playlist/RssPlaylistPlugin.cxx b/src/playlist/RssPlaylistPlugin.cxx index 16dcd5fe5..98f323e66 100644 --- a/src/playlist/RssPlaylistPlugin.cxx +++ b/src/playlist/RssPlaylistPlugin.cxx @@ -23,6 +23,7 @@ #include "InputLegacy.hxx" #include "Song.hxx" #include "Tag.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -205,6 +206,7 @@ rss_open_stream(struct input_stream *is) char buffer[1024]; size_t nbytes; bool success; + Error error2; GError *error = NULL; /* parse the RSS XML file */ @@ -215,12 +217,11 @@ rss_open_stream(struct input_stream *is) while (true) { nbytes = input_stream_lock_read(is, buffer, sizeof(buffer), - &error); + error2); if (nbytes == 0) { - if (error != NULL) { + if (error2.IsDefined()) { g_markup_parse_context_free(context); - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error2.GetMessage()); return NULL; } diff --git a/src/playlist/SoundCloudPlaylistPlugin.cxx b/src/playlist/SoundCloudPlaylistPlugin.cxx index b60635049..b6be4fd30 100644 --- a/src/playlist/SoundCloudPlaylistPlugin.cxx +++ b/src/playlist/SoundCloudPlaylistPlugin.cxx @@ -24,6 +24,7 @@ #include "InputLegacy.hxx" #include "Song.hxx" #include "Tag.hxx" +#include "util/Error.hxx" #include <glib.h> #include <yajl/yajl_parse.h> @@ -244,18 +245,15 @@ static int soundcloud_parse_json(const char *url, yajl_handle hand, Mutex &mutex, Cond &cond) { - struct input_stream *input_stream; - GError *error = NULL; char buffer[4096]; unsigned char *ubuffer = (unsigned char *)buffer; - size_t nbytes; - input_stream = input_stream_open(url, mutex, cond, &error); + Error error; + input_stream *input_stream = input_stream_open(url, mutex, cond, + error); if (input_stream == NULL) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } + if (error.IsDefined()) + g_warning("%s", error.GetMessage()); return -1; } @@ -266,12 +264,13 @@ soundcloud_parse_json(const char *url, yajl_handle hand, int done = 0; while (!done) { - nbytes = input_stream_read(input_stream, buffer, sizeof(buffer), &error); + const size_t nbytes = + input_stream_read(input_stream, buffer, sizeof(buffer), + error); if (nbytes == 0) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } + if (error.IsDefined()) + g_warning("%s", error.GetMessage()); + if (input_stream_eof(input_stream)) { done = true; } else { diff --git a/src/playlist/XspfPlaylistPlugin.cxx b/src/playlist/XspfPlaylistPlugin.cxx index c8a067da4..f2412897b 100644 --- a/src/playlist/XspfPlaylistPlugin.cxx +++ b/src/playlist/XspfPlaylistPlugin.cxx @@ -22,6 +22,7 @@ #include "MemoryPlaylistProvider.hxx" #include "InputLegacy.hxx" #include "Tag.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -224,6 +225,7 @@ xspf_open_stream(struct input_stream *is) char buffer[1024]; size_t nbytes; bool success; + Error error2; GError *error = NULL; /* parse the XSPF XML file */ @@ -234,12 +236,11 @@ xspf_open_stream(struct input_stream *is) while (true) { nbytes = input_stream_lock_read(is, buffer, sizeof(buffer), - &error); + error2); if (nbytes == 0) { - if (error != NULL) { + if (error2.IsDefined()) { g_markup_parse_context_free(context); - g_warning("%s", error->message); - g_error_free(error); + g_warning("%s", error2.GetMessage()); return NULL; } diff --git a/src/protocol/Ack.cxx b/src/protocol/Ack.cxx new file mode 100644 index 000000000..3c8185afd --- /dev/null +++ b/src/protocol/Ack.cxx @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2003-2011 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Ack.hxx" +#include "util/Domain.hxx" + +const Domain ack_domain("ack"); diff --git a/src/protocol/Ack.hxx b/src/protocol/Ack.hxx index b76fae17d..a7f8e5e53 100644 --- a/src/protocol/Ack.hxx +++ b/src/protocol/Ack.hxx @@ -20,9 +20,7 @@ #ifndef MPD_ACK_H #define MPD_ACK_H -#include "gcc.h" - -#include <glib.h> +class Domain; enum ack { ACK_ERROR_NOT_LIST = 1, @@ -40,14 +38,6 @@ enum ack { ACK_ERROR_EXIST = 56, }; -/** - * Quark for GError.domain; the code is an enum #ack. - */ -gcc_const -static inline GQuark -ack_quark(void) -{ - return g_quark_from_static_string("ack"); -} +extern const Domain ack_domain; #endif diff --git a/src/protocol/Result.hxx b/src/protocol/Result.hxx index 6766da3d5..0f953c62b 100644 --- a/src/protocol/Result.hxx +++ b/src/protocol/Result.hxx @@ -24,6 +24,8 @@ #include "gcc.h" #include "Ack.hxx" +#include <stdarg.h> + class Client; extern const char *current_command; diff --git a/src/system/FatalError.cxx b/src/system/FatalError.cxx index 30ddc50ea..65cb9aa26 100644 --- a/src/system/FatalError.cxx +++ b/src/system/FatalError.cxx @@ -17,7 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "FatalError.hxx" +#include "util/Error.hxx" #include <glib.h> @@ -53,6 +55,12 @@ FormatFatalError(const char *fmt, ...) } void +FatalError(const Error &error) +{ + FatalError(error.GetMessage()); +} + +void FatalError(GError *error) { FatalError(error->message); diff --git a/src/system/FatalError.hxx b/src/system/FatalError.hxx index 3918e5fc1..be67aabbd 100644 --- a/src/system/FatalError.hxx +++ b/src/system/FatalError.hxx @@ -20,9 +20,12 @@ #ifndef MPD_FATAL_ERROR_HXX #define MPD_FATAL_ERROR_HXX +#include "check.h" #include "gerror.h" #include "gcc.h" +class Error; + /** * Log the specified message and abort the process. */ @@ -36,6 +39,10 @@ FormatFatalError(const char *fmt, ...); gcc_noreturn void +FatalError(const Error &error); + +gcc_noreturn +void FatalError(GError *error); gcc_noreturn diff --git a/src/system/Resolver.cxx b/src/system/Resolver.cxx index a574e82c1..b7fa80c38 100644 --- a/src/system/Resolver.cxx +++ b/src/system/Resolver.cxx @@ -19,6 +19,10 @@ #include "config.h" #include "Resolver.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" + +#include <glib.h> #ifndef G_OS_WIN32 #include <sys/socket.h> @@ -30,8 +34,10 @@ #include <string.h> +const Domain resolver_domain("resolver"); + char * -sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error) +sockaddr_to_string(const struct sockaddr *sa, size_t length, Error &error) { #if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)sa; @@ -59,8 +65,7 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error) ret = getnameinfo(sa, length, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV); if (ret != 0) { - g_set_error(error, g_quark_from_static_string("netdb"), ret, - "%s", gai_strerror(ret)); + error.Set(resolver_domain, ret, gai_strerror(ret)); return NULL; } @@ -82,7 +87,7 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error) struct addrinfo * resolve_host_port(const char *host_port, unsigned default_port, int flags, int socktype, - GError **error_r) + Error &error) { char *p = g_strdup(host_port); const char *host = p, *port = NULL; @@ -130,9 +135,9 @@ resolve_host_port(const char *host_port, unsigned default_port, int ret = getaddrinfo(host, port, &hints, &ai); g_free(p); if (ret != 0) { - g_set_error(error_r, resolver_quark(), ret, - "Failed to look up '%s': %s", - host_port, gai_strerror(ret)); + error.Format(resolver_domain, ret, + "Failed to look up '%s': %s", + host_port, gai_strerror(ret)); return NULL; } diff --git a/src/system/Resolver.hxx b/src/system/Resolver.hxx index a1cd00329..38803dcd1 100644 --- a/src/system/Resolver.hxx +++ b/src/system/Resolver.hxx @@ -22,17 +22,13 @@ #include "gcc.h" -#include <glib.h> +#include <stddef.h> struct sockaddr; struct addrinfo; +class Error; -gcc_const -static inline GQuark -resolver_quark(void) -{ - return g_quark_from_static_string("resolver"); -} +extern const class Domain resolver_domain; /** * Converts the specified socket address into a string in the form @@ -46,7 +42,7 @@ resolver_quark(void) */ gcc_malloc char * -sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error); +sockaddr_to_string(const struct sockaddr *sa, size_t length, Error &error); /** * Resolve a specification in the form "host", "host:port", @@ -61,6 +57,6 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error); struct addrinfo * resolve_host_port(const char *host_port, unsigned default_port, int flags, int socktype, - GError **error_r); + Error &error); #endif diff --git a/src/system/SocketError.cxx b/src/system/SocketError.cxx new file mode 100644 index 000000000..d3569c6f1 --- /dev/null +++ b/src/system/SocketError.cxx @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "SocketError.hxx" +#include "util/Domain.hxx" + +const Domain socket_domain("socket"); diff --git a/src/system/SocketError.hxx b/src/system/SocketError.hxx index 53a0c1d8f..c42e267dd 100644 --- a/src/system/SocketError.hxx +++ b/src/system/SocketError.hxx @@ -21,6 +21,7 @@ #define MPD_SOCKET_ERROR_HXX #include "gcc.h" +#include "util/Error.hxx" #include <glib.h> @@ -33,15 +34,10 @@ typedef int socket_error_t; #endif /** - * A GQuark for GError for socket I/O errors. The code is an errno + * A #Domain for #Error for socket I/O errors. The code is an errno * value (or WSAGetLastError() on Windows). */ -gcc_const -static inline GQuark -SocketErrorQuark(void) -{ - return g_quark_from_static_string("socket"); -} +extern const class Domain socket_domain; gcc_pure static inline socket_error_t @@ -121,33 +117,29 @@ public: }; static inline void -SetSocketError(GError **error_r, socket_error_t code) +SetSocketError(Error &error, socket_error_t code) { -#ifdef WIN32 - if (error_r == NULL) - return; -#endif - const SocketErrorMessage msg(code); - g_set_error_literal(error_r, SocketErrorQuark(), code, msg); + error.Set(socket_domain, code, msg); } static inline void -SetSocketError(GError **error_r) +SetSocketError(Error &error) { - SetSocketError(error_r, GetSocketError()); + SetSocketError(error, GetSocketError()); } -gcc_malloc -static inline GError * +gcc_const +static inline Error NewSocketError(socket_error_t code) { - const SocketErrorMessage msg(code); - return g_error_new_literal(SocketErrorQuark(), code, msg); + Error error; + SetSocketError(error, code); + return error; } -gcc_malloc -static inline GError * +gcc_pure +static inline Error NewSocketError() { return NewSocketError(GetSocketError()); diff --git a/src/system/SocketUtil.cxx b/src/system/SocketUtil.cxx index dd7eb7dd2..abaedb8e7 100644 --- a/src/system/SocketUtil.cxx +++ b/src/system/SocketUtil.cxx @@ -41,38 +41,38 @@ int socket_bind_listen(int domain, int type, int protocol, const struct sockaddr *address, size_t address_length, int backlog, - GError **error_r) + Error &error) { int fd, ret; const int reuse = 1; fd = socket_cloexec_nonblock(domain, type, protocol); if (fd < 0) { - SetSocketError(error_r); - g_prefix_error(error_r, "Failed to create socket: "); + SetSocketError(error); + error.AddPrefix("Failed to create socket: "); return -1; } ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse, sizeof(reuse)); if (ret < 0) { - SetSocketError(error_r); - g_prefix_error(error_r, "setsockopt() failed: "); + SetSocketError(error); + error.AddPrefix("setsockopt() failed: "); close_socket(fd); return -1; } ret = bind(fd, address, address_length); if (ret < 0) { - SetSocketError(error_r); + SetSocketError(error); close_socket(fd); return -1; } ret = listen(fd, backlog); if (ret < 0) { - SetSocketError(error_r); - g_prefix_error(error_r, "listen() failed: "); + SetSocketError(error); + error.AddPrefix("listen() failed: "); close_socket(fd); return -1; } diff --git a/src/system/SocketUtil.hxx b/src/system/SocketUtil.hxx index 3d0be78c4..5e582ec0d 100644 --- a/src/system/SocketUtil.hxx +++ b/src/system/SocketUtil.hxx @@ -26,11 +26,10 @@ #ifndef MPD_SOCKET_UTIL_HXX #define MPD_SOCKET_UTIL_HXX -#include "gerror.h" - #include <stddef.h> struct sockaddr; +class Error; /** * Creates a socket listening on the specified address. This is a @@ -50,7 +49,7 @@ int socket_bind_listen(int domain, int type, int protocol, const struct sockaddr *address, size_t address_length, int backlog, - GError **error); + Error &error); int socket_keepalive(int fd); diff --git a/src/io_error.h b/src/util/Domain.hxx index 1442a08aa..bbdbf8371 100644 --- a/src/io_error.h +++ b/src/util/Domain.hxx @@ -17,35 +17,30 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_IO_ERROR_H -#define MPD_IO_ERROR_H +#ifndef MPD_DOMAIN_HXX +#define MPD_DOMAIN_HXX -#include <glib.h> +class Domain { + const char *const name; -#include <errno.h> +public: + constexpr explicit Domain(const char *_name) + :name(_name) {} -/** - * A GQuark for GError for I/O errors. The code is an errno value. - */ -gcc_const -static inline GQuark -errno_quark(void) -{ - return g_quark_from_static_string("errno"); -} - -static inline void -set_error_errno(GError **error_r) -{ - g_set_error_literal(error_r, errno_quark(), errno, - g_strerror(errno)); -} - -static inline GError * -new_error_errno(void) -{ - return g_error_new_literal(errno_quark(), errno, - g_strerror(errno)); -} + Domain(const Domain &) = delete; + Domain &operator=(const Domain &) = delete; + + constexpr const char *GetName() const { + return name; + } + + bool operator==(const Domain &other) const { + return this == &other; + } + + bool operator!=(const Domain &other) const { + return !(*this == other); + } +}; #endif diff --git a/src/util/Error.cxx b/src/util/Error.cxx new file mode 100644 index 000000000..1e6bd9cff --- /dev/null +++ b/src/util/Error.cxx @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Error.hxx" +#include "Domain.hxx" + +#include <glib.h> + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> + +const Domain errno_domain("errno"); + +Error::~Error() {} + +void +Error::Set(const Domain &_domain, int _code, const char *_message) +{ + domain = &_domain; + code = _code; + message.assign(_message); +} + +void +Error::Format2(const Domain &_domain, int _code, const char *fmt, ...) +{ + char buffer[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + Set(_domain, _code, buffer); +} + +void +Error::FormatPrefix(const char *fmt, ...) +{ + char buffer[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + AddPrefix(buffer); +} + +void +Error::SetErrno(int e) +{ + Set(errno_domain, e, g_strerror(e)); +} + +void +Error::SetErrno() +{ + SetErrno(errno); +} + +void +Error::SetErrno(int e, const char *prefix) +{ + Format(errno_domain, e, "%s: %s", prefix, g_strerror(e)); +} + +void +Error::SetErrno(const char *prefix) +{ + SetErrno(errno, prefix); +} + +void +Error::FormatErrno(int e, const char *fmt, ...) +{ + char buffer[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + SetErrno(e, buffer); +} + +void +Error::FormatErrno(const char *fmt, ...) +{ + const int e = errno; + + char buffer[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + SetErrno(e, buffer); +} diff --git a/src/util/Error.hxx b/src/util/Error.hxx new file mode 100644 index 000000000..1fcf46061 --- /dev/null +++ b/src/util/Error.hxx @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ERROR_HXX +#define MPD_ERROR_HXX + +#include "check.h" +#include "gcc.h" + +#include <string> + +#include <assert.h> + +class Domain; + +extern const Domain errno_domain; + +#ifdef WIN32 +/* fuck WIN32! */ +#include <windows.h> +#define IgnoreError MPDIgnoreError +#undef GetMessage +#endif + +/** + * This class contains information about a runtime error. + */ +class Error { + const Domain *domain; + int code; + std::string message; + +public: + Error():domain(nullptr), code(0) {} + + Error(const Domain &_domain, int _code, const char *_message) + :domain(&_domain), code(_code), message(_message) {} + + Error(const Domain &_domain, const char *_message) + :domain(&_domain), code(0), message(_message) {} + + Error(Error &&other) + :domain(other.domain), code(other.code), + message(std::move(other.message)) {} + + ~Error(); + + Error(const Error &) = delete; + Error &operator=(const Error &) = delete; + + Error &operator=(Error &&other) { + domain = other.domain; + code = other.code; + std::swap(message, other.message); + return *this; + } + + bool IsDefined() const { + return domain != nullptr; + } + + void Clear() { + domain = nullptr; + } + + const Domain &GetDomain() const { + assert(IsDefined()); + + return *domain; + } + + bool IsDomain(const Domain &other) const { + return domain == &other; + } + + int GetCode() const { + assert(IsDefined()); + + return code; + } + + const char *GetMessage() const { + assert(IsDefined()); + + return message.c_str(); + } + + void Set(const Error &other) { + assert(!IsDefined()); + assert(other.IsDefined()); + + domain = other.domain; + code = other.code; + message = other.message; + } + + void Set(const Domain &_domain, int _code, const char *_message); + + void Set(const Domain &_domain, const char *_message) { + Set(_domain, 0, _message); + } + +private: + void Format2(const Domain &_domain, int _code, const char *fmt, ...); + +public: + template<typename... Args> + void Format(const Domain &_domain, int _code, + const char *fmt, Args&&... args) { + Format2(_domain, _code, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void Format(const Domain &_domain, const char *fmt, Args&&... args) { + Format2(_domain, 0, fmt, std::forward<Args>(args)...); + } + + void AddPrefix(const char *prefix) { + message.insert(0, prefix); + } + + void FormatPrefix(const char *fmt, ...); + + void SetErrno(int e); + void SetErrno(); + void SetErrno(int e, const char *prefix); + void SetErrno(const char *prefix); + void FormatErrno(const char *prefix, ...); + void FormatErrno(int e, const char *prefix, ...); +}; + +/** + * Pass a temporary instance of this class to ignore errors. + */ +class IgnoreError final { + Error error; + +public: + operator Error &() { + assert(!error.IsDefined()); + + return error; + } +}; + +#endif diff --git a/src/util/Tokenizer.cxx b/src/util/Tokenizer.cxx index 0bb6edd71..726da0dd6 100644 --- a/src/util/Tokenizer.cxx +++ b/src/util/Tokenizer.cxx @@ -20,18 +20,15 @@ #include "config.h" #include "Tokenizer.hxx" #include "StringUtil.hxx" +#include "Error.hxx" +#include "Domain.hxx" #include <glib.h> #include <assert.h> #include <string.h> -gcc_const -static GQuark -tokenizer_quark(void) -{ - return g_quark_from_static_string("tokenizer"); -} +static constexpr Domain tokenizer_domain("tokenizer"); static inline bool valid_word_first_char(char ch) @@ -46,7 +43,7 @@ valid_word_char(char ch) } char * -Tokenizer::NextWord(GError **error_r) +Tokenizer::NextWord(Error &error) { char *const word = input; @@ -56,8 +53,7 @@ Tokenizer::NextWord(GError **error_r) /* check the first character */ if (!valid_word_first_char(*input)) { - g_set_error(error_r, tokenizer_quark(), 0, - "Letter expected"); + error.Set(tokenizer_domain, "Letter expected"); return nullptr; } @@ -74,8 +70,7 @@ Tokenizer::NextWord(GError **error_r) } if (!valid_word_char(*input)) { - g_set_error(error_r, tokenizer_quark(), 0, - "Invalid word character"); + error.Set(tokenizer_domain, "Invalid word character"); return nullptr; } } @@ -93,7 +88,7 @@ valid_unquoted_char(char ch) } char * -Tokenizer::NextUnquoted(GError **error_r) +Tokenizer::NextUnquoted(Error &error) { char *const word = input; @@ -103,8 +98,7 @@ Tokenizer::NextUnquoted(GError **error_r) /* check the first character */ if (!valid_unquoted_char(*input)) { - g_set_error(error_r, tokenizer_quark(), 0, - "Invalid unquoted character"); + error.Set(tokenizer_domain, "Invalid unquoted character"); return nullptr; } @@ -121,8 +115,8 @@ Tokenizer::NextUnquoted(GError **error_r) } if (!valid_unquoted_char(*input)) { - g_set_error(error_r, tokenizer_quark(), 0, - "Invalid unquoted character"); + error.Set(tokenizer_domain, + "Invalid unquoted character"); return nullptr; } } @@ -134,7 +128,7 @@ Tokenizer::NextUnquoted(GError **error_r) } char * -Tokenizer::NextString(GError **error_r) +Tokenizer::NextString(Error &error) { char *const word = input, *dest = input; @@ -145,8 +139,7 @@ Tokenizer::NextString(GError **error_r) /* check for the opening " */ if (*input != '"') { - g_set_error(error_r, tokenizer_quark(), 0, - "'\"' expected"); + error.Set(tokenizer_domain, "'\"' expected"); return nullptr; } @@ -165,8 +158,7 @@ Tokenizer::NextString(GError **error_r) difference between "end of line" and "error" */ --input; - g_set_error(error_r, tokenizer_quark(), 0, - "Missing closing '\"'"); + error.Set(tokenizer_domain, "Missing closing '\"'"); return nullptr; } @@ -179,8 +171,8 @@ Tokenizer::NextString(GError **error_r) ++input; if (*input != 0 && !g_ascii_isspace(*input)) { - g_set_error(error_r, tokenizer_quark(), 0, - "Space expected after closing '\"'"); + error.Set(tokenizer_domain, + "Space expected after closing '\"'"); return nullptr; } @@ -192,10 +184,10 @@ Tokenizer::NextString(GError **error_r) } char * -Tokenizer::NextParam(GError **error_r) +Tokenizer::NextParam(Error &error) { if (*input == '"') - return NextString(error_r); + return NextString(error); else - return NextUnquoted(error_r); + return NextUnquoted(error); } diff --git a/src/util/Tokenizer.hxx b/src/util/Tokenizer.hxx index da45348d4..a689dc31d 100644 --- a/src/util/Tokenizer.hxx +++ b/src/util/Tokenizer.hxx @@ -20,7 +20,7 @@ #ifndef MPD_TOKENIZER_HXX #define MPD_TOKENIZER_HXX -#include "gerror.h" +class Error; class Tokenizer { char *input; @@ -50,23 +50,23 @@ public: /** * Reads the next word. * - * @param error_r if this function returns nullptr and - * **input_p!=0, it optionally provides a GError object in + * @param error if this function returns nullptr and + * **input_p!=0, it provides an #Error object in * this argument * @return a pointer to the null-terminated word, or nullptr * on error or end of line */ - char *NextWord(GError **error_r); + char *NextWord(Error &error); /** * Reads the next unquoted word from the input string. * * @param error_r if this function returns nullptr and **input_p!=0, it - * optionally provides a GError object in this argument + * provides an #Error object in this argument * @return a pointer to the null-terminated word, or nullptr * on error or end of line */ - char *NextUnquoted(GError **error_r); + char *NextUnquoted(Error &error); /** * Reads the next quoted string from the input string. A backslash @@ -76,11 +76,11 @@ public: * @param input_p the input string; this function returns a pointer to * the first non-whitespace character of the following token * @param error_r if this function returns nullptr and **input_p!=0, it - * optionally provides a GError object in this argument + * provides an #Error object in this argument * @return a pointer to the null-terminated string, or nullptr on error * or end of line */ - char *NextString(GError **error_r); + char *NextString(Error &error); /** * Reads the next unquoted word or quoted string from the @@ -88,12 +88,12 @@ public: * NextString(). * * @param error_r if this function returns nullptr and - * **input_p!=0, it optionally provides a GError object in + * **input_p!=0, it provides an #Error object in * this argument * @return a pointer to the null-terminated string, or nullptr * on error or end of line */ - char *NextParam(GError **error_r); + char *NextParam(Error &error); }; #endif |