aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-08-10 18:02:44 +0200
committerMax Kellermann <max@duempel.org>2013-09-04 18:14:22 +0200
commit29030b54c98b0aee65fbc10ebf7ba36bed98c02c (patch)
tree79766830b55ebca38ddbce84d8d548227eedb69e /src
parentc9fcc7f14860777458153eb2d13c773ccfa1daa2 (diff)
downloadmpd-29030b54c98b0aee65fbc10ebf7ba36bed98c02c.tar.gz
mpd-29030b54c98b0aee65fbc10ebf7ba36bed98c02c.tar.xz
mpd-29030b54c98b0aee65fbc10ebf7ba36bed98c02c.zip
util/Error: new error passing library
Replaces GLib's GError.
Diffstat (limited to '')
-rw-r--r--src/AllCommands.cxx18
-rw-r--r--src/ArchiveFile.hxx4
-rw-r--r--src/ArchivePlugin.cxx14
-rw-r--r--src/ArchivePlugin.hxx6
-rw-r--r--src/AudioConfig.cxx11
-rw-r--r--src/AudioParser.cxx52
-rw-r--r--src/AudioParser.hxx5
-rw-r--r--src/CheckAudioFormat.cxx33
-rw-r--r--src/CheckAudioFormat.hxx20
-rw-r--r--src/ClientEvent.cxx6
-rw-r--r--src/ClientFile.cxx16
-rw-r--r--src/ClientFile.hxx5
-rw-r--r--src/ClientInternal.hxx2
-rw-r--r--src/ClientNew.cxx6
-rw-r--r--src/ClientProcess.cxx2
-rw-r--r--src/CommandError.cxx44
-rw-r--r--src/CommandError.hxx6
-rw-r--r--src/CommandLine.cxx36
-rw-r--r--src/CommandLine.hxx4
-rw-r--r--src/ConfigData.cxx17
-rw-r--r--src/ConfigData.hxx6
-rw-r--r--src/ConfigError.cxx23
-rw-r--r--src/ConfigError.hxx (renamed from src/ConfigQuark.hxx)19
-rw-r--r--src/ConfigFile.cxx109
-rw-r--r--src/ConfigFile.hxx5
-rw-r--r--src/ConfigGlobal.cxx17
-rw-r--r--src/ConfigGlobal.hxx6
-rw-r--r--src/ConfigPath.cxx36
-rw-r--r--src/ConfigPath.hxx5
-rw-r--r--src/DatabaseCommands.cxx33
-rw-r--r--src/DatabaseError.cxx24
-rw-r--r--src/DatabaseError.hxx14
-rw-r--r--src/DatabaseGlue.cxx20
-rw-r--r--src/DatabaseGlue.hxx8
-rw-r--r--src/DatabaseHelpers.cxx10
-rw-r--r--src/DatabaseHelpers.hxx5
-rw-r--r--src/DatabasePlaylist.cxx10
-rw-r--r--src/DatabasePlaylist.hxx4
-rw-r--r--src/DatabasePlugin.hxx21
-rw-r--r--src/DatabasePrint.cxx28
-rw-r--r--src/DatabasePrint.hxx12
-rw-r--r--src/DatabaseQueue.cxx12
-rw-r--r--src/DatabaseQueue.hxx5
-rw-r--r--src/DatabaseSave.cxx44
-rw-r--r--src/DatabaseSave.hxx5
-rw-r--r--src/DatabaseSimple.hxx4
-rw-r--r--src/DatabaseVisitor.hxx11
-rw-r--r--src/DecoderAPI.cxx22
-rw-r--r--src/DecoderControl.hxx28
-rw-r--r--src/DecoderError.cxx23
-rw-r--r--src/DecoderError.hxx14
-rw-r--r--src/DecoderThread.cxx30
-rw-r--r--src/Directory.cxx13
-rw-r--r--src/Directory.hxx4
-rw-r--r--src/DirectorySave.cxx38
-rw-r--r--src/DirectorySave.hxx5
-rw-r--r--src/EncoderPlugin.hxx31
-rw-r--r--src/FilterConfig.cxx33
-rw-r--r--src/FilterConfig.hxx5
-rw-r--r--src/FilterInternal.hxx7
-rw-r--r--src/FilterPlugin.cxx26
-rw-r--r--src/FilterPlugin.hxx11
-rw-r--r--src/InotifySource.cxx22
-rw-r--r--src/InotifySource.hxx7
-rw-r--r--src/InotifyUpdate.cxx23
-rw-r--r--src/InputInit.cxx33
-rw-r--r--src/InputInit.hxx4
-rw-r--r--src/InputLegacy.hxx13
-rw-r--r--src/InputPlugin.hxx12
-rw-r--r--src/InputStream.cxx43
-rw-r--r--src/Listen.cxx30
-rw-r--r--src/Listen.hxx4
-rw-r--r--src/Log.cxx39
-rw-r--r--src/Log.hxx13
-rw-r--r--src/Main.cxx107
-rw-r--r--src/Mapper.hxx1
-rw-r--r--src/MixerAll.cxx25
-rw-r--r--src/MixerControl.cxx29
-rw-r--r--src/MixerControl.hxx11
-rw-r--r--src/MixerPlugin.hxx13
-rw-r--r--src/OtherCommands.cxx8
-rw-r--r--src/OutputAll.cxx21
-rw-r--r--src/OutputAll.hxx6
-rw-r--r--src/OutputControl.cxx10
-rw-r--r--src/OutputError.cxx23
-rw-r--r--src/OutputError.hxx14
-rw-r--r--src/OutputInit.cxx74
-rw-r--r--src/OutputInternal.hxx5
-rw-r--r--src/OutputPlugin.cxx8
-rw-r--r--src/OutputPlugin.hxx18
-rw-r--r--src/OutputThread.cxx54
-rw-r--r--src/PlayerControl.cxx14
-rw-r--r--src/PlayerControl.hxx8
-rw-r--r--src/PlayerThread.cxx40
-rw-r--r--src/PlaylistAny.cxx11
-rw-r--r--src/PlaylistCommands.cxx60
-rw-r--r--src/PlaylistDatabase.cxx18
-rw-r--r--src/PlaylistDatabase.hxx4
-rw-r--r--src/PlaylistEdit.cxx5
-rw-r--r--src/PlaylistError.cxx24
-rw-r--r--src/PlaylistError.hxx14
-rw-r--r--src/PlaylistFile.cxx151
-rw-r--r--src/PlaylistFile.hxx21
-rw-r--r--src/PlaylistPrint.cxx14
-rw-r--r--src/PlaylistPrint.hxx5
-rw-r--r--src/PlaylistRegistry.cxx18
-rw-r--r--src/PlaylistSave.cxx10
-rw-r--r--src/PlaylistSave.hxx3
-rw-r--r--src/PlaylistSong.cxx5
-rw-r--r--src/QueueCommands.cxx13
-rw-r--r--src/QueueSave.cxx12
-rw-r--r--src/SongSave.cxx18
-rw-r--r--src/SongSave.hxx8
-rw-r--r--src/SongSticker.hxx2
-rw-r--r--src/SongUpdate.cxx7
-rw-r--r--src/Stats.cxx8
-rw-r--r--src/StickerCommands.cxx17
-rw-r--r--src/StickerDatabase.cxx28
-rw-r--r--src/StickerDatabase.hxx5
-rw-r--r--src/TagFile.cxx10
-rw-r--r--src/TagId3.cxx18
-rw-r--r--src/TagId3.hxx6
-rw-r--r--src/TextInputStream.cxx12
-rw-r--r--src/UpdateArchive.cxx8
-rw-r--r--src/UpdateGlue.cxx9
-rw-r--r--src/archive/Bzip2ArchivePlugin.cxx34
-rw-r--r--src/archive/Iso9660ArchivePlugin.cxx31
-rw-r--r--src/archive/ZzipArchivePlugin.cxx34
-rw-r--r--src/db/ProxyDatabasePlugin.cxx106
-rw-r--r--src/db/SimpleDatabasePlugin.cxx123
-rw-r--r--src/db/SimpleDatabasePlugin.hxx20
-rw-r--r--src/decoder/AdPlugDecoderPlugin.cxx8
-rw-r--r--src/decoder/AudiofileDecoderPlugin.cxx22
-rw-r--r--src/decoder/DsdLib.cxx5
-rw-r--r--src/decoder/DsdiffDecoderPlugin.cxx10
-rw-r--r--src/decoder/DsfDecoderPlugin.cxx10
-rw-r--r--src/decoder/FaadDecoderPlugin.cxx33
-rw-r--r--src/decoder/FfmpegDecoderPlugin.cxx15
-rw-r--r--src/decoder/FlacCommon.cxx15
-rw-r--r--src/decoder/FlacDecoderPlugin.cxx3
-rw-r--r--src/decoder/FlacIOHandle.cxx16
-rw-r--r--src/decoder/FlacInput.cxx6
-rw-r--r--src/decoder/FluidsynthDecoderPlugin.cxx8
-rw-r--r--src/decoder/GmeDecoderPlugin.cxx8
-rw-r--r--src/decoder/MadDecoderPlugin.cxx12
-rw-r--r--src/decoder/MpcdecDecoderPlugin.cxx11
-rw-r--r--src/decoder/Mpg123DecoderPlugin.cxx8
-rw-r--r--src/decoder/OpusDecoderPlugin.cxx6
-rw-r--r--src/decoder/PcmDecoderPlugin.cxx9
-rw-r--r--src/decoder/SndfileDecoderPlugin.cxx22
-rw-r--r--src/decoder/VorbisDecoderPlugin.cxx14
-rw-r--r--src/decoder/WavpackDecoderPlugin.cxx18
-rw-r--r--src/decoder/WildmidiDecoderPlugin.cxx5
-rw-r--r--src/encoder/FlacEncoderPlugin.cxx58
-rw-r--r--src/encoder/LameEncoderPlugin.cxx88
-rw-r--r--src/encoder/NullEncoderPlugin.cxx8
-rw-r--r--src/encoder/OpusEncoderPlugin.cxx57
-rw-r--r--src/encoder/TwolameEncoderPlugin.cxx83
-rw-r--r--src/encoder/VorbisEncoderPlugin.cxx66
-rw-r--r--src/encoder/WaveEncoderPlugin.cxx6
-rw-r--r--src/event/BufferedSocket.cxx9
-rw-r--r--src/event/BufferedSocket.hxx4
-rw-r--r--src/event/FullyBufferedSocket.cxx8
-rw-r--r--src/event/ServerSocket.cxx76
-rw-r--r--src/event/ServerSocket.hxx13
-rw-r--r--src/filter/AutoConvertFilterPlugin.cxx21
-rw-r--r--src/filter/ChainFilterPlugin.cxx35
-rw-r--r--src/filter/ConvertFilterPlugin.cxx15
-rw-r--r--src/filter/NormalizeFilterPlugin.cxx10
-rw-r--r--src/filter/NullFilterPlugin.cxx8
-rw-r--r--src/filter/ReplayGainFilterPlugin.cxx29
-rw-r--r--src/filter/RouteFilterPlugin.cxx39
-rw-r--r--src/filter/VolumeFilterPlugin.cxx21
-rw-r--r--src/input/ArchiveInputPlugin.cxx7
-rw-r--r--src/input/CdioParanoiaInputPlugin.cxx44
-rw-r--r--src/input/CurlInputPlugin.cxx127
-rw-r--r--src/input/DespotifyInputPlugin.cxx4
-rw-r--r--src/input/FfmpegInputPlugin.cxx28
-rw-r--r--src/input/FileInputPlugin.cxx29
-rw-r--r--src/input/MmsInputPlugin.cxx21
-rw-r--r--src/input/RewindInputPlugin.cxx14
-rw-r--r--src/mixer/AlsaMixerPlugin.cxx86
-rw-r--r--src/mixer/OssMixerPlugin.cxx72
-rw-r--r--src/mixer/PulseMixerPlugin.cxx25
-rw-r--r--src/mixer/RoarMixerPlugin.cxx6
-rw-r--r--src/mixer/SoftwareMixerPlugin.cxx17
-rw-r--r--src/mixer/WinmmMixerPlugin.cxx20
-rw-r--r--src/mpd_error.h2
-rw-r--r--src/output/AlsaOutputPlugin.cxx78
-rw-r--r--src/output/AoOutputPlugin.cxx49
-rw-r--r--src/output/FifoOutputPlugin.cxx90
-rw-r--r--src/output/HttpdClient.cxx5
-rw-r--r--src/output/HttpdClient.hxx2
-rw-r--r--src/output/HttpdInternal.hxx12
-rw-r--r--src/output/HttpdOutputPlugin.cxx65
-rw-r--r--src/output/JackOutputPlugin.cxx88
-rw-r--r--src/output/NullOutputPlugin.cxx12
-rw-r--r--src/output/OSXOutputPlugin.cxx84
-rw-r--r--src/output/OpenALOutputPlugin.cxx40
-rw-r--r--src/output/OssOutputPlugin.cxx114
-rw-r--r--src/output/PipeOutputPlugin.cxx43
-rw-r--r--src/output/PulseOutputPlugin.cxx152
-rw-r--r--src/output/PulseOutputPlugin.hxx5
-rw-r--r--src/output/RecorderOutputPlugin.cxx71
-rw-r--r--src/output/RoarOutputPlugin.cxx30
-rw-r--r--src/output/ShoutOutputPlugin.cxx154
-rw-r--r--src/output/SolarisOutputPlugin.cxx34
-rw-r--r--src/output/WinmmOutputPlugin.cxx61
-rw-r--r--src/pcm/PcmConvert.cxx104
-rw-r--r--src/pcm/PcmConvert.hxx19
-rw-r--r--src/pcm/PcmResample.cxx12
-rw-r--r--src/pcm/PcmResample.hxx13
-rw-r--r--src/pcm/PcmResampleInternal.hxx8
-rw-r--r--src/pcm/PcmResampleLibsamplerate.cxx49
-rw-r--r--src/playlist/AsxPlaylistPlugin.cxx9
-rw-r--r--src/playlist/LastFMPlaylistPlugin.cxx35
-rw-r--r--src/playlist/PlsPlaylistPlugin.cxx9
-rw-r--r--src/playlist/RssPlaylistPlugin.cxx9
-rw-r--r--src/playlist/SoundCloudPlaylistPlugin.cxx25
-rw-r--r--src/playlist/XspfPlaylistPlugin.cxx9
-rw-r--r--src/protocol/Ack.cxx24
-rw-r--r--src/protocol/Ack.hxx14
-rw-r--r--src/protocol/Result.hxx2
-rw-r--r--src/system/FatalError.cxx8
-rw-r--r--src/system/FatalError.hxx7
-rw-r--r--src/system/Resolver.cxx19
-rw-r--r--src/system/Resolver.hxx14
-rw-r--r--src/system/SocketError.cxx24
-rw-r--r--src/system/SocketError.hxx36
-rw-r--r--src/system/SocketUtil.cxx16
-rw-r--r--src/system/SocketUtil.hxx5
-rw-r--r--src/util/Domain.hxx (renamed from src/io_error.h)49
-rw-r--r--src/util/Error.cxx114
-rw-r--r--src/util/Error.hxx162
-rw-r--r--src/util/Tokenizer.cxx44
-rw-r--r--src/util/Tokenizer.hxx20
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 &param, GError **error_r)
+DatabaseGlobalInit(const config_param &param, Error &error)
{
assert(db == NULL);
assert(!db_is_open);
@@ -61,12 +62,12 @@ DatabaseGlobalInit(const config_param &param, 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 &param, GError **error_r);
+DatabaseGlobalInit(const config_param &param, 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 &param,
- 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 &param,
- 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 &param,
- 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 &param, GError **error_r)
+ const config_param &param, 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 &param, GError **error_r)
+filter_configured_new(const config_param &param, 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 &param, GError **error_r);
+ Filter *(*init)(const config_param &param, Error &error);
};
/**
@@ -53,7 +50,7 @@ struct filter_plugin {
*/
Filter *
filter_new(const struct filter_plugin *plugin,
- const config_param &param, GError **error_r);
+ const config_param &param, 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 &param, GError **error_r);
+filter_configured_new(const config_param &param, 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 = &empty;
} 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 &param, GError **error_r);
+ bool (*init)(const config_param &param, 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 &param,
- 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 &param,
- 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 &param,
- 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 = &empty;
}
- 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 &param,
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 &param, GError **error_r)
+ const config_param &param, 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 &param,
- GError **error_r)
+ Error &error)
{
/* create the replay_gain filter */
@@ -230,13 +227,14 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
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 &param,
/* 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 &param,
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 &param,
struct audio_output *
audio_output_new(const config_param &param,
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 &param,
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 &param,
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 &param,
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 &param, GError **error_r);
+ const config_param &param, 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 &param,
- 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 &param,
- 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 &param,
- 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 &param,
- 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 &param, GError **error_r);
+ bool Configure(const config_param &param, 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 &param, GError **error_r)
+ProxyDatabase::Create(const config_param &param, 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 &param, GError **error_r)
}
bool
-ProxyDatabase::Configure(const config_param &param, GError **)
+ProxyDatabase::Configure(const config_param &param, gcc_unused Error &error)
{
host = param.GetBlockValue("host", "");
port = param.GetBlockValue("port", 0u);
@@ -150,17 +147,16 @@ ProxyDatabase::Configure(const config_param &param, 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 &param, GError **error_r)
+SimpleDatabase::Create(const config_param &param, 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 &param, GError **error_r)
}
bool
-SimpleDatabase::Configure(const config_param &param, GError **error_r)
+SimpleDatabase::Configure(const config_param &param, 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 &param, 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 &param,
- 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 &param, GError **error_r);
+ bool Configure(const config_param &param, 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 &param)
{
- 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 &param)
{
- 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 &param)
{
- 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 &param,
- 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 &param,
}
static Encoder *
-flac_encoder_init(const config_param &param, GError **error)
+flac_encoder_init(const config_param &param, 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 &param, GError **error);
+ bool Configure(const config_param &param, 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 &param, GError **error)
+LameEncoder::Configure(const config_param &param, Error &error)
{
const char *value;
char *endptr;
@@ -67,18 +66,18 @@ LameEncoder::Configure(const config_param &param, 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 &param, 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 &param, 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 &param, GError **error)
}
static Encoder *
-lame_encoder_init(const config_param &param, GError **error_r)
+lame_encoder_init(const config_param &param, 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 &param,
- 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 &param, GError **error_r)
+ const config_param &param, 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 &param, GError **error)
+opus_encoder_init(const config_param &param, 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 &param, GError **error);
+ bool Configure(const config_param &param, 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 &param, GError **error)
+TwolameEncoder::Configure(const config_param &param, Error &error)
{
const char *value;
char *endptr;
@@ -72,18 +71,18 @@ TwolameEncoder::Configure(const config_param &param, 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 &param, 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 &param, 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 &param, GError **error)
}
static Encoder *
-twolame_encoder_init(const config_param &param, GError **error_r)
+twolame_encoder_init(const config_param &param, 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 &param, GError **error)
+ const config_param &param, 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 &param, GError **error)
+vorbis_encoder_init(const config_param &param, 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 &param,
- 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 &param,
- 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 &param,
- 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 &param,
- 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 &param,
- 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 &param,
- 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 &param, GError **error_r);
+ bool Configure(const config_param &param, 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 &param, GError **error_r) {
+RouteFilter::Configure(const config_param &param, 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 &param, 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 &param, 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 &param, 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 &param, GError **error_r) {
}
static Filter *
-route_filter_init(const config_param &param, GError **error_r)
+route_filter_init(const config_param &param, 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 &param, 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 &param,
- 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 &param,
- gcc_unused GError **error_r)
+input_curl_init(const config_param &param, 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 &param,
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 &param,
- 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 &param,
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 &param);
- 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 &param)
static Mixer *
alsa_mixer_init(gcc_unused void *ao, const config_param &param,
- 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 &param, GError **error_r);
- bool Open(GError **error_r);
+ bool Configure(const config_param &param, 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 &param, GError **error_r)
+OssMixer::Configure(const config_param &param, 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 &param, GError **error_r)
static Mixer *
oss_mixer_init(gcc_unused void *ao, const config_param &param,
- 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 &param,
- 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 &param,
- 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 &param,
- 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 &param,
- 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 &param, GError **error_r) {
+ bool Init(const config_param &param, 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 &param)
}
static struct audio_output *
-alsa_init(const config_param &param, GError **error_r)
+alsa_init(const config_param &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r);
+ bool Configure(const config_param &param, 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 &param, GError **error_r)
+AoOutput::Configure(const config_param &param, Error &error)
{
const char *value;
@@ -115,16 +113,15 @@ AoOutput::Configure(const config_param &param, 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 &param, 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 &param, GError **error_r)
}
static struct audio_output *
-ao_output_init(const config_param &param, GError **error_r)
+ao_output_init(const config_param &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r)
+fifo_output_init(const config_param &param, 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 &param, GError **error_r);
+ bool Configure(const config_param &param, 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 &param, GError **error_r)
+HttpdOutput::Configure(const config_param &param, Error &error)
{
/* read configuration */
name = param.GetBlockValue("name", "Set name in config");
@@ -104,8 +99,8 @@ HttpdOutput::Configure(const config_param &param, 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 &param, 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 &param, GError **error_r)
}
static struct audio_output *
-httpd_output_init(const struct config_param &param,
- GError **error_r)
+httpd_output_init(const config_param &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r)
+mpd_jack_init(const config_param &param, 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 &param, 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 &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r)
+null_init(const config_param &param, 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 &param)
}
static struct audio_output *
-osx_output_init(const config_param &param, GError **error_r)
+osx_output_init(const config_param &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r)
+openal_init(const config_param &param, Error &error)
{
const char *device_name = param.GetBlockValue("device");
if (device_name == nullptr) {
@@ -149,7 +145,7 @@ openal_init(const config_param &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r)
+oss_output_init(const config_param &param, 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 &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r);
+ bool Configure(const config_param &param, 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 &param, GError **error_r)
+PipeOutput::Configure(const config_param &param, 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 &param, GError **error_r)
}
static struct audio_output *
-pipe_output_init(const config_param &param, GError **error_r)
+pipe_output_init(const config_param &param, 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 &param, GError **error_r)
+pulse_output_init(const config_param &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r);
+ bool Configure(const config_param &param, 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 &param, GError **error_r)
+RecorderOutput::Configure(const config_param &param, Error &error)
{
/* read configuration */
@@ -94,21 +90,20 @@ RecorderOutput::Configure(const config_param &param, 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 &param, GError **error_r)
}
static audio_output *
-recorder_output_init(const config_param &param, GError **error_r)
+recorder_output_init(const config_param &param, 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 &param)
}
static struct audio_output *
-roar_init(const config_param &param, GError **error_r)
+roar_init(const config_param &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r);
+ bool Configure(const config_param &param, 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 &param, const char *name)
}
inline bool
-ShoutOutput::Configure(const config_param &param, GError **error_r)
+ShoutOutput::Configure(const config_param &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, GError **error_r)
}
static struct audio_output *
-my_shout_init_driver(const config_param &param, GError **error_r)
+my_shout_init_driver(const config_param &param, 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 &param, 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 &param, GError **error_r) {
+ bool Initialize(const config_param &param, 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 &param, GError **error_r)
+solaris_output_init(const config_param &param, 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 &param, GError **error_r)
+winmm_output_init(const config_param &param, 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