Commit 29030b54 authored by Max Kellermann's avatar Max Kellermann

util/Error: new error passing library

Replaces GLib's GError.
parent c9fcc7f1
...@@ -91,7 +91,7 @@ src_mpd_SOURCES = \ ...@@ -91,7 +91,7 @@ src_mpd_SOURCES = \
src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \ src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \
src/AudioFormat.cxx src/AudioFormat.hxx \ src/AudioFormat.cxx src/AudioFormat.hxx \
src/AudioParser.cxx src/AudioParser.hxx \ src/AudioParser.cxx src/AudioParser.hxx \
src/protocol/Ack.hxx \ src/protocol/Ack.cxx src/protocol/Ack.hxx \
src/protocol/ArgParser.cxx src/protocol/ArgParser.hxx \ src/protocol/ArgParser.cxx src/protocol/ArgParser.hxx \
src/protocol/Result.cxx src/protocol/Result.hxx \ src/protocol/Result.cxx src/protocol/Result.hxx \
src/CommandError.cxx src/CommandError.hxx \ src/CommandError.cxx src/CommandError.hxx \
...@@ -107,7 +107,7 @@ src_mpd_SOURCES = \ ...@@ -107,7 +107,7 @@ src_mpd_SOURCES = \
src/CommandLine.cxx src/CommandLine.hxx \ src/CommandLine.cxx src/CommandLine.hxx \
src/CrossFade.cxx src/CrossFade.hxx \ src/CrossFade.cxx src/CrossFade.hxx \
src/cue/CueParser.cxx src/cue/CueParser.hxx \ src/cue/CueParser.cxx src/cue/CueParser.hxx \
src/DecoderError.hxx \ src/DecoderError.cxx src/DecoderError.hxx \
src/DecoderThread.cxx src/DecoderThread.hxx \ src/DecoderThread.cxx src/DecoderThread.hxx \
src/DecoderCommand.hxx \ src/DecoderCommand.hxx \
src/DecoderControl.cxx src/DecoderControl.hxx \ src/DecoderControl.cxx src/DecoderControl.hxx \
...@@ -122,7 +122,7 @@ src_mpd_SOURCES = \ ...@@ -122,7 +122,7 @@ src_mpd_SOURCES = \
src/DatabasePrint.cxx src/DatabasePrint.hxx \ src/DatabasePrint.cxx src/DatabasePrint.hxx \
src/DatabaseQueue.cxx src/DatabaseQueue.hxx \ src/DatabaseQueue.cxx src/DatabaseQueue.hxx \
src/DatabasePlaylist.cxx src/DatabasePlaylist.hxx \ src/DatabasePlaylist.cxx src/DatabasePlaylist.hxx \
src/DatabaseError.hxx \ src/DatabaseError.cxx src/DatabaseError.hxx \
src/DatabaseLock.cxx src/DatabaseLock.hxx \ src/DatabaseLock.cxx src/DatabaseLock.hxx \
src/DatabaseSave.cxx src/DatabaseSave.hxx \ src/DatabaseSave.cxx src/DatabaseSave.hxx \
src/DatabasePlugin.hxx \ src/DatabasePlugin.hxx \
...@@ -160,7 +160,6 @@ src_mpd_SOURCES = \ ...@@ -160,7 +160,6 @@ src_mpd_SOURCES = \
src/Listen.cxx src/Listen.hxx \ src/Listen.cxx src/Listen.hxx \
src/Log.cxx src/Log.hxx \ src/Log.cxx src/Log.hxx \
src/ls.cxx src/ls.hxx \ src/ls.cxx src/ls.hxx \
src/io_error.h \
src/IOThread.cxx src/IOThread.hxx \ src/IOThread.cxx src/IOThread.hxx \
src/Main.cxx src/Main.hxx \ src/Main.cxx src/Main.hxx \
src/Instance.cxx src/Instance.hxx \ src/Instance.cxx src/Instance.hxx \
...@@ -178,7 +177,7 @@ src_mpd_SOURCES = \ ...@@ -178,7 +177,7 @@ src_mpd_SOURCES = \
src/PlayerThread.cxx src/PlayerThread.hxx \ src/PlayerThread.cxx src/PlayerThread.hxx \
src/PlayerControl.cxx src/PlayerControl.hxx \ src/PlayerControl.cxx src/PlayerControl.hxx \
src/Playlist.cxx \ src/Playlist.cxx \
src/PlaylistError.hxx \ src/PlaylistError.cxx src/PlaylistError.hxx \
src/PlaylistGlobal.cxx src/PlaylistGlobal.hxx \ src/PlaylistGlobal.cxx src/PlaylistGlobal.hxx \
src/PlaylistControl.cxx \ src/PlaylistControl.cxx \
src/PlaylistEdit.cxx \ src/PlaylistEdit.cxx \
...@@ -261,6 +260,7 @@ endif ...@@ -261,6 +260,7 @@ endif
# Generic utility library # Generic utility library
libutil_a_SOURCES = \ libutil_a_SOURCES = \
src/util/Error.cxx src/util/Error.hxx \
src/util/ReusableArray.hxx \ src/util/ReusableArray.hxx \
src/util/StringUtil.cxx src/util/StringUtil.hxx \ src/util/StringUtil.cxx src/util/StringUtil.hxx \
src/util/Tokenizer.cxx src/util/Tokenizer.hxx \ src/util/Tokenizer.cxx src/util/Tokenizer.hxx \
...@@ -284,7 +284,7 @@ libsystem_a_SOURCES = \ ...@@ -284,7 +284,7 @@ libsystem_a_SOURCES = \
src/system/FatalError.cxx src/system/FatalError.hxx \ src/system/FatalError.cxx src/system/FatalError.hxx \
src/system/fd_util.c src/system/fd_util.h \ src/system/fd_util.c src/system/fd_util.h \
src/system/SocketUtil.cxx src/system/SocketUtil.hxx \ src/system/SocketUtil.cxx src/system/SocketUtil.hxx \
src/system/SocketError.hxx \ src/system/SocketError.cxx src/system/SocketError.hxx \
src/system/Resolver.cxx src/system/Resolver.hxx \ src/system/Resolver.cxx src/system/Resolver.hxx \
src/system/EventPipe.cxx src/system/EventPipe.hxx \ src/system/EventPipe.cxx src/system/EventPipe.hxx \
src/system/EventFD.cxx src/system/EventFD.hxx \ src/system/EventFD.cxx src/system/EventFD.hxx \
...@@ -420,7 +420,7 @@ libconf_a_SOURCES = \ ...@@ -420,7 +420,7 @@ libconf_a_SOURCES = \
src/ConfigGlobal.cxx src/ConfigGlobal.hxx \ src/ConfigGlobal.cxx src/ConfigGlobal.hxx \
src/ConfigFile.cxx src/ConfigFile.hxx \ src/ConfigFile.cxx src/ConfigFile.hxx \
src/ConfigTemplates.cxx src/ConfigTemplates.hxx \ src/ConfigTemplates.cxx src/ConfigTemplates.hxx \
src/ConfigQuark.hxx \ src/ConfigError.cxx src/ConfigError.hxx \
src/ConfigOption.hxx src/ConfigOption.hxx
# tag plugins # tag plugins
...@@ -793,7 +793,7 @@ OUTPUT_API_SRC = \ ...@@ -793,7 +793,7 @@ OUTPUT_API_SRC = \
src/OutputList.cxx src/OutputList.hxx \ src/OutputList.cxx src/OutputList.hxx \
src/OutputAll.cxx src/OutputAll.hxx \ src/OutputAll.cxx src/OutputAll.hxx \
src/OutputThread.cxx src/OutputThread.hxx \ src/OutputThread.cxx src/OutputThread.hxx \
src/OutputError.hxx \ src/OutputError.cxx src/OutputError.hxx \
src/OutputControl.cxx src/OutputControl.hxx \ src/OutputControl.cxx src/OutputControl.hxx \
src/OutputState.cxx src/OutputState.hxx \ src/OutputState.cxx src/OutputState.hxx \
src/OutputPrint.cxx src/OutputPrint.hxx \ src/OutputPrint.cxx src/OutputPrint.hxx \
...@@ -1071,6 +1071,7 @@ test_read_conf_SOURCES = test/read_conf.cxx ...@@ -1071,6 +1071,7 @@ test_read_conf_SOURCES = test/read_conf.cxx
test_run_resolver_LDADD = \ test_run_resolver_LDADD = \
libsystem.a \ libsystem.a \
libutil.a \
$(GLIB_LIBS) $(GLIB_LIBS)
test_run_resolver_SOURCES = test/run_resolver.cxx test_run_resolver_SOURCES = test/run_resolver.cxx
...@@ -1082,6 +1083,7 @@ test_DumpDatabase_LDADD = \ ...@@ -1082,6 +1083,7 @@ test_DumpDatabase_LDADD = \
libfs.a \ libfs.a \
$(GLIB_LIBS) $(GLIB_LIBS)
test_DumpDatabase_SOURCES = test/DumpDatabase.cxx \ test_DumpDatabase_SOURCES = test/DumpDatabase.cxx \
src/DatabaseError.cxx \
src/DatabaseRegistry.cxx \ src/DatabaseRegistry.cxx \
src/DatabaseSelection.cxx \ src/DatabaseSelection.cxx \
src/Directory.cxx src/DirectorySave.cxx \ src/Directory.cxx src/DirectorySave.cxx \
...@@ -1217,6 +1219,7 @@ test_read_tags_SOURCES = test/read_tags.cxx \ ...@@ -1217,6 +1219,7 @@ test_read_tags_SOURCES = test/read_tags.cxx \
if HAVE_ID3TAG if HAVE_ID3TAG
test_dump_rva2_LDADD = \ test_dump_rva2_LDADD = \
$(ID3TAG_LIBS) \ $(ID3TAG_LIBS) \
libutil.a \
$(GLIB_LIBS) $(GLIB_LIBS)
test_dump_rva2_SOURCES = test/dump_rva2.cxx \ test_dump_rva2_SOURCES = test/dump_rva2.cxx \
src/riff.c src/aiff.c \ src/riff.c src/aiff.c \
...@@ -1296,6 +1299,7 @@ test_software_volume_SOURCES = test/software_volume.cxx \ ...@@ -1296,6 +1299,7 @@ test_software_volume_SOURCES = test/software_volume.cxx \
src/AudioParser.cxx src/AudioParser.cxx
test_software_volume_LDADD = \ test_software_volume_LDADD = \
$(PCM_LIBS) \ $(PCM_LIBS) \
libutil.a \
$(GLIB_LIBS) $(GLIB_LIBS)
test_run_normalize_SOURCES = test/run_normalize.cxx \ test_run_normalize_SOURCES = test/run_normalize.cxx \
...@@ -1304,6 +1308,7 @@ test_run_normalize_SOURCES = test/run_normalize.cxx \ ...@@ -1304,6 +1308,7 @@ test_run_normalize_SOURCES = test/run_normalize.cxx \
src/AudioParser.cxx \ src/AudioParser.cxx \
src/AudioCompress/compress.c src/AudioCompress/compress.c
test_run_normalize_LDADD = \ test_run_normalize_LDADD = \
libutil.a \
$(GLIB_LIBS) $(GLIB_LIBS)
test_run_convert_SOURCES = test/run_convert.cxx \ test_run_convert_SOURCES = test/run_convert.cxx \
...@@ -1337,6 +1342,7 @@ test_run_output_SOURCES = test/run_output.cxx \ ...@@ -1337,6 +1342,7 @@ test_run_output_SOURCES = test/run_output.cxx \
src/Timer.cxx \ src/Timer.cxx \
src/Tag.cxx src/TagNames.c src/TagPool.cxx \ src/Tag.cxx src/TagNames.c src/TagPool.cxx \
src/Page.cxx \ src/Page.cxx \
src/OutputError.cxx \
src/OutputInit.cxx src/OutputFinish.cxx src/OutputList.cxx \ src/OutputInit.cxx src/OutputFinish.cxx src/OutputList.cxx \
src/OutputPlugin.cxx \ src/OutputPlugin.cxx \
src/MixerControl.cxx \ src/MixerControl.cxx \
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "Client.hxx" #include "Client.hxx"
#include "util/Tokenizer.hxx" #include "util/Tokenizer.hxx"
#include "util/Error.hxx"
#ifdef ENABLE_SQLITE #ifdef ENABLE_SQLITE
#include "StickerCommands.hxx" #include "StickerCommands.hxx"
...@@ -315,7 +316,7 @@ command_checked_lookup(Client *client, unsigned permission, ...@@ -315,7 +316,7 @@ command_checked_lookup(Client *client, unsigned permission,
enum command_return enum command_return
command_process(Client *client, unsigned num, char *line) command_process(Client *client, unsigned num, char *line)
{ {
GError *error = NULL; Error error;
char *argv[COMMAND_ARGV_MAX] = { NULL }; char *argv[COMMAND_ARGV_MAX] = { NULL };
const struct command *cmd; const struct command *cmd;
enum command_return ret = COMMAND_RETURN_ERROR; enum command_return ret = COMMAND_RETURN_ERROR;
...@@ -325,17 +326,16 @@ command_process(Client *client, unsigned num, char *line) ...@@ -325,17 +326,16 @@ command_process(Client *client, unsigned num, char *line)
/* get the command name (first word on the line) */ /* get the command name (first word on the line) */
Tokenizer tokenizer(line); Tokenizer tokenizer(line);
argv[0] = tokenizer.NextWord(&error); argv[0] = tokenizer.NextWord(error);
if (argv[0] == NULL) { if (argv[0] == NULL) {
current_command = ""; current_command = "";
if (tokenizer.IsEnd()) if (tokenizer.IsEnd())
command_error(client, ACK_ERROR_UNKNOWN, command_error(client, ACK_ERROR_UNKNOWN,
"No command given"); "No command given");
else { else
command_error(client, ACK_ERROR_UNKNOWN, command_error(client, ACK_ERROR_UNKNOWN,
"%s", error->message); "%s", error.GetMessage());
g_error_free(error);
}
current_command = NULL; current_command = NULL;
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
...@@ -347,7 +347,7 @@ command_process(Client *client, unsigned num, char *line) ...@@ -347,7 +347,7 @@ command_process(Client *client, unsigned num, char *line)
while (argc < COMMAND_ARGV_MAX && while (argc < COMMAND_ARGV_MAX &&
(argv[argc] = (argv[argc] =
tokenizer.NextParam(&error)) != NULL) tokenizer.NextParam(error)) != NULL)
++argc; ++argc;
/* some error checks; we have to set current_command because /* some error checks; we have to set current_command because
...@@ -362,10 +362,8 @@ command_process(Client *client, unsigned num, char *line) ...@@ -362,10 +362,8 @@ command_process(Client *client, unsigned num, char *line)
} }
if (!tokenizer.IsEnd()) { if (!tokenizer.IsEnd()) {
command_error(client, ACK_ERROR_ARG, command_error(client, ACK_ERROR_ARG, "%s", error.GetMessage());
"%s", error->message);
current_command = NULL; current_command = NULL;
g_error_free(error);
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#ifndef MPD_ARCHIVE_FILE_HXX #ifndef MPD_ARCHIVE_FILE_HXX
#define MPD_ARCHIVE_FILE_HXX #define MPD_ARCHIVE_FILE_HXX
class Error;
class ArchiveFile { class ArchiveFile {
public: public:
const struct archive_plugin &plugin; const struct archive_plugin &plugin;
...@@ -50,7 +52,7 @@ public: ...@@ -50,7 +52,7 @@ public:
*/ */
virtual input_stream *OpenStream(const char *path, virtual input_stream *OpenStream(const char *path,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) = 0; Error &error) = 0;
}; };
#endif #endif
...@@ -17,27 +17,23 @@ ...@@ -17,27 +17,23 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "config.h"
#include "ArchivePlugin.hxx" #include "ArchivePlugin.hxx"
#include "ArchiveFile.hxx" #include "ArchiveFile.hxx"
#include "util/Error.hxx"
#include <assert.h> #include <assert.h>
ArchiveFile * ArchiveFile *
archive_file_open(const struct archive_plugin *plugin, const char *path, archive_file_open(const struct archive_plugin *plugin, const char *path,
GError **error_r) Error &error)
{ {
assert(plugin != NULL); assert(plugin != NULL);
assert(plugin->open != NULL); assert(plugin->open != NULL);
assert(path != NULL); assert(path != NULL);
assert(error_r == NULL || *error_r == NULL);
ArchiveFile *file = plugin->open(path, error_r); ArchiveFile *file = plugin->open(path, error);
assert((file == nullptr) == error.IsDefined());
if (file != NULL) {
assert(error_r == NULL || *error_r == NULL);
} else {
assert(error_r == NULL || *error_r != NULL);
}
return file; return file;
} }
...@@ -22,11 +22,11 @@ ...@@ -22,11 +22,11 @@
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "thread/Cond.hxx" #include "thread/Cond.hxx"
#include "gerror.h"
struct input_stream; struct input_stream;
class ArchiveFile; class ArchiveFile;
class ArchiveVisitor; class ArchiveVisitor;
class Error;
struct archive_plugin { struct archive_plugin {
const char *name; const char *name;
...@@ -49,7 +49,7 @@ struct archive_plugin { ...@@ -49,7 +49,7 @@ struct archive_plugin {
* returns pointer to handle used is all operations with this archive * returns pointer to handle used is all operations with this archive
* or NULL when opening fails * 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. * suffixes handled by this plugin.
...@@ -60,6 +60,6 @@ struct archive_plugin { ...@@ -60,6 +60,6 @@ struct archive_plugin {
ArchiveFile * ArchiveFile *
archive_file_open(const struct archive_plugin *plugin, const char *path, archive_file_open(const struct archive_plugin *plugin, const char *path,
GError **error_r); Error &error);
#endif #endif
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "AudioParser.hxx" #include "AudioParser.hxx"
#include "conf.h" #include "conf.h"
#include "mpd_error.h" #include "mpd_error.h"
#include "util/Error.hxx"
static AudioFormat configured_audio_format; static AudioFormat configured_audio_format;
...@@ -37,15 +38,13 @@ getOutputAudioFormat(AudioFormat inAudioFormat) ...@@ -37,15 +38,13 @@ getOutputAudioFormat(AudioFormat inAudioFormat)
void initAudioConfig(void) void initAudioConfig(void)
{ {
const struct config_param *param = config_get_param(CONF_AUDIO_OUTPUT_FORMAT); const struct config_param *param = config_get_param(CONF_AUDIO_OUTPUT_FORMAT);
GError *error = NULL;
bool ret;
if (param == NULL) if (param == NULL)
return; return;
ret = audio_format_parse(configured_audio_format, param->value, Error error;
true, &error); if (!audio_format_parse(configured_audio_format, param->value,
if (!ret) true, error))
MPD_ERROR("error parsing line %i: %s", MPD_ERROR("error parsing line %i: %s",
param->line, error->message); param->line, error.GetMessage());
} }
...@@ -26,24 +26,16 @@ ...@@ -26,24 +26,16 @@
#include "AudioParser.hxx" #include "AudioParser.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include "gcc.h" #include "gcc.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.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 static bool
parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, 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; unsigned long value;
char *endptr; char *endptr;
...@@ -56,10 +48,10 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, ...@@ -56,10 +48,10 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
value = strtoul(src, &endptr, 10); value = strtoul(src, &endptr, 10);
if (endptr == src) { if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0, error.Set(audio_format_domain,
"Failed to parse the sample rate"); "Failed to parse the sample rate");
return false; return false;
} else if (!audio_check_sample_rate(value, error_r)) } else if (!audio_check_sample_rate(value, error))
return false; return false;
*sample_rate_r = value; *sample_rate_r = value;
...@@ -70,7 +62,7 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, ...@@ -70,7 +62,7 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
static bool static bool
parse_sample_format(const char *src, bool mask, parse_sample_format(const char *src, bool mask,
SampleFormat *sample_format_r, SampleFormat *sample_format_r,
const char **endptr_r, GError **error_r) const char **endptr_r, Error &error)
{ {
unsigned long value; unsigned long value;
char *endptr; char *endptr;
...@@ -96,8 +88,8 @@ parse_sample_format(const char *src, bool mask, ...@@ -96,8 +88,8 @@ parse_sample_format(const char *src, bool mask,
value = strtoul(src, &endptr, 10); value = strtoul(src, &endptr, 10);
if (endptr == src) { if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0, error.Set(audio_format_domain,
"Failed to parse the sample format"); "Failed to parse the sample format");
return false; return false;
} }
...@@ -123,8 +115,8 @@ parse_sample_format(const char *src, bool mask, ...@@ -123,8 +115,8 @@ parse_sample_format(const char *src, bool mask,
break; break;
default: default:
g_set_error(error_r, audio_parser_quark(), 0, error.Format(audio_format_domain,
"Invalid sample format: %lu", value); "Invalid sample format: %lu", value);
return false; return false;
} }
...@@ -137,7 +129,7 @@ parse_sample_format(const char *src, bool mask, ...@@ -137,7 +129,7 @@ parse_sample_format(const char *src, bool mask,
static bool static bool
parse_channel_count(const char *src, bool mask, uint8_t *channels_r, 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; unsigned long value;
char *endptr; char *endptr;
...@@ -150,10 +142,10 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r, ...@@ -150,10 +142,10 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
value = strtoul(src, &endptr, 10); value = strtoul(src, &endptr, 10);
if (endptr == src) { if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0, error.Set(audio_format_domain,
"Failed to parse the channel count"); "Failed to parse the channel count");
return false; return false;
} else if (!audio_check_channel_count(value, error_r)) } else if (!audio_check_channel_count(value, error))
return false; return false;
*channels_r = value; *channels_r = value;
...@@ -163,7 +155,7 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r, ...@@ -163,7 +155,7 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
bool bool
audio_format_parse(AudioFormat &dest, const char *src, audio_format_parse(AudioFormat &dest, const char *src,
bool mask, GError **error_r) bool mask, Error &error)
{ {
uint32_t rate; uint32_t rate;
SampleFormat sample_format; SampleFormat sample_format;
...@@ -178,12 +170,11 @@ audio_format_parse(AudioFormat &dest, const char *src, ...@@ -178,12 +170,11 @@ audio_format_parse(AudioFormat &dest, const char *src,
rate = 0; rate = 0;
#endif #endif
if (!parse_sample_rate(src, mask, &rate, &src, error_r)) if (!parse_sample_rate(src, mask, &rate, &src, error))
return false; return false;
if (*src++ != ':') { if (*src++ != ':') {
g_set_error(error_r, audio_parser_quark(), 0, error.Set(audio_format_domain, "Sample format missing");
"Sample format missing");
return false; return false;
} }
...@@ -194,22 +185,21 @@ audio_format_parse(AudioFormat &dest, const char *src, ...@@ -194,22 +185,21 @@ audio_format_parse(AudioFormat &dest, const char *src,
sample_format = SampleFormat::UNDEFINED; sample_format = SampleFormat::UNDEFINED;
#endif #endif
if (!parse_sample_format(src, mask, &sample_format, &src, error_r)) if (!parse_sample_format(src, mask, &sample_format, &src, error))
return false; return false;
if (*src++ != ':') { if (*src++ != ':') {
g_set_error(error_r, audio_parser_quark(), 0, error.Set(audio_format_domain, "Channel count missing");
"Channel count missing");
return false; return false;
} }
/* parse channel count */ /* parse channel count */
if (!parse_channel_count(src, mask, &channels, &src, error_r)) if (!parse_channel_count(src, mask, &channels, &src, error))
return false; return false;
if (*src != 0) { if (*src != 0) {
g_set_error(error_r, audio_parser_quark(), 0, error.Format(audio_format_domain,
"Extra data after channel count: %s", src); "Extra data after channel count: %s", src);
return false; return false;
} }
......
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
#ifndef MPD_AUDIO_PARSER_HXX #ifndef MPD_AUDIO_PARSER_HXX
#define MPD_AUDIO_PARSER_HXX #define MPD_AUDIO_PARSER_HXX
#include "gerror.h"
struct AudioFormat; struct AudioFormat;
class Error;
/** /**
* Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an * Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an
...@@ -42,6 +41,6 @@ struct AudioFormat; ...@@ -42,6 +41,6 @@ struct AudioFormat;
*/ */
bool bool
audio_format_parse(AudioFormat &dest, const char *src, audio_format_parse(AudioFormat &dest, const char *src,
bool mask, GError **error_r); bool mask, Error &error);
#endif #endif
...@@ -17,17 +17,22 @@ ...@@ -17,17 +17,22 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "config.h"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h> #include <assert.h>
const Domain audio_format_domain("audio_format");
bool 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)) { if (!audio_valid_sample_rate(sample_rate)) {
g_set_error(error_r, audio_format_quark(), 0, error.Format(audio_format_domain,
"Invalid sample rate: %lu", sample_rate); "Invalid sample rate: %lu", sample_rate);
return false; return false;
} }
...@@ -35,12 +40,12 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r) ...@@ -35,12 +40,12 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r)
} }
bool 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)) { if (!audio_valid_sample_format(sample_format)) {
g_set_error(error_r, audio_format_quark(), 0, error.Format(audio_format_domain,
"Invalid sample format: %u", "Invalid sample format: %u",
unsigned(sample_format)); unsigned(sample_format));
return false; return false;
} }
...@@ -48,11 +53,11 @@ audio_check_sample_format(SampleFormat sample_format, GError **error_r) ...@@ -48,11 +53,11 @@ audio_check_sample_format(SampleFormat sample_format, GError **error_r)
} }
bool bool
audio_check_channel_count(unsigned channels, GError **error_r) audio_check_channel_count(unsigned channels, Error &error)
{ {
if (!audio_valid_channel_count(channels)) { if (!audio_valid_channel_count(channels)) {
g_set_error(error_r, audio_format_quark(), 0, error.Format(audio_format_domain,
"Invalid channel count: %u", channels); "Invalid channel count: %u", channels);
return false; return false;
} }
...@@ -62,11 +67,11 @@ audio_check_channel_count(unsigned channels, GError **error_r) ...@@ -62,11 +67,11 @@ audio_check_channel_count(unsigned channels, GError **error_r)
bool bool
audio_format_init_checked(AudioFormat &af, unsigned long sample_rate, audio_format_init_checked(AudioFormat &af, unsigned long sample_rate,
SampleFormat sample_format, unsigned channels, SampleFormat sample_format, unsigned channels,
GError **error_r) Error &error)
{ {
if (audio_check_sample_rate(sample_rate, error_r) && if (audio_check_sample_rate(sample_rate, error) &&
audio_check_sample_format(sample_format, error_r) && audio_check_sample_format(sample_format, error) &&
audio_check_channel_count(channels, error_r)) { audio_check_channel_count(channels, error)) {
af = AudioFormat(sample_rate, sample_format, channels); af = AudioFormat(sample_rate, sample_format, channels);
assert(af.IsValid()); assert(af.IsValid());
return true; return true;
......
...@@ -22,26 +22,18 @@ ...@@ -22,26 +22,18 @@
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include <glib.h> class Error;
/** extern const class Domain audio_format_domain;
* 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");
}
bool bool
audio_check_sample_rate(unsigned long sample_rate, GError **error_r); audio_check_sample_rate(unsigned long sample_rate, Error &error);
bool bool
audio_check_sample_format(SampleFormat sample_format, GError **error_r); audio_check_sample_format(SampleFormat sample_format, Error &error);
bool 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. * Wrapper for audio_format_init(), which checks all attributes.
...@@ -49,6 +41,6 @@ audio_check_channel_count(unsigned sample_format, GError **error_r); ...@@ -49,6 +41,6 @@ audio_check_channel_count(unsigned sample_format, GError **error_r);
bool bool
audio_format_init_checked(AudioFormat &af, unsigned long sample_rate, audio_format_init_checked(AudioFormat &af, unsigned long sample_rate,
SampleFormat sample_format, unsigned channels, SampleFormat sample_format, unsigned channels,
GError **error_r); Error &error);
#endif #endif
...@@ -19,14 +19,14 @@ ...@@ -19,14 +19,14 @@
#include "config.h" #include "config.h"
#include "ClientInternal.hxx" #include "ClientInternal.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
void void
Client::OnSocketError(GError *error) Client::OnSocketError(Error &&error)
{ {
g_warning("error on client %d: %s", num, error->message); g_warning("error on client %d: %s", num, error.GetMessage());
g_error_free(error);
SetExpired(); SetExpired();
} }
......
...@@ -21,9 +21,10 @@ ...@@ -21,9 +21,10 @@
#include "ClientFile.hxx" #include "ClientFile.hxx"
#include "Client.hxx" #include "Client.hxx"
#include "protocol/Ack.hxx" #include "protocol/Ack.hxx"
#include "io_error.h"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -32,14 +33,13 @@ ...@@ -32,14 +33,13 @@
bool bool
client_allow_file(const Client *client, const Path &path_fs, client_allow_file(const Client *client, const Path &path_fs,
GError **error_r) Error &error)
{ {
#ifdef WIN32 #ifdef WIN32
(void)client; (void)client;
(void)path_fs; (void)path_fs;
g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION, error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied");
"Access denied");
return false; return false;
#else #else
const int uid = client_get_uid(client); const int uid = client_get_uid(client);
...@@ -50,21 +50,19 @@ client_allow_file(const Client *client, const Path &path_fs, ...@@ -50,21 +50,19 @@ client_allow_file(const Client *client, const Path &path_fs,
if (uid <= 0) { if (uid <= 0) {
/* unauthenticated client */ /* unauthenticated client */
g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION, error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied");
"Access denied");
return false; return false;
} }
struct stat st; struct stat st;
if (!StatFile(path_fs, st)) { if (!StatFile(path_fs, st)) {
set_error_errno(error_r); error.SetErrno();
return false; return false;
} }
if (st.st_uid != (uid_t)uid && (st.st_mode & 0444) != 0444) { if (st.st_uid != (uid_t)uid && (st.st_mode & 0444) != 0444) {
/* client is not owner */ /* client is not owner */
g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION, error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied");
"Access denied");
return false; return false;
} }
......
...@@ -20,10 +20,9 @@ ...@@ -20,10 +20,9 @@
#ifndef MPD_CLIENT_FILE_HXX #ifndef MPD_CLIENT_FILE_HXX
#define MPD_CLIENT_FILE_HXX #define MPD_CLIENT_FILE_HXX
#include "gerror.h"
class Client; class Client;
class Path; class Path;
class Error;
/** /**
* Is this client allowed to use the specified local file? * Is this client allowed to use the specified local file?
...@@ -37,6 +36,6 @@ class Path; ...@@ -37,6 +36,6 @@ class Path;
*/ */
bool bool
client_allow_file(const Client *client, const Path &path_fs, client_allow_file(const Client *client, const Path &path_fs,
GError **error_r); Error &error);
#endif #endif
...@@ -116,7 +116,7 @@ private: ...@@ -116,7 +116,7 @@ private:
/* virtual methods from class BufferedSocket */ /* virtual methods from class BufferedSocket */
virtual InputResult OnSocketInput(const void *data, virtual InputResult OnSocketInput(const void *data,
size_t length) override; size_t length) override;
virtual void OnSocketError(GError *error) override; virtual void OnSocketError(Error &&error) override;
virtual void OnSocketClosed() override; virtual void OnSocketClosed() override;
/* virtual methods from class TimeoutMonitor */ /* virtual methods from class TimeoutMonitor */
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "system/fd_util.h" #include "system/fd_util.h"
#include "system/Resolver.hxx" #include "system/Resolver.hxx"
#include "Permission.hxx" #include "Permission.hxx"
#include "util/Error.hxx"
#include <assert.h> #include <assert.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -70,7 +71,8 @@ client_new(EventLoop &loop, Partition &partition, ...@@ -70,7 +71,8 @@ client_new(EventLoop &loop, Partition &partition,
#ifdef HAVE_LIBWRAP #ifdef HAVE_LIBWRAP
if (sa->sa_family != AF_UNIX) { 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(); const char *progname = g_get_prgname();
struct request_info req; struct request_info req;
...@@ -107,7 +109,7 @@ client_new(EventLoop &loop, Partition &partition, ...@@ -107,7 +109,7 @@ client_new(EventLoop &loop, Partition &partition,
client_list.Add(*client); 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, g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE,
"[%u] opened from %s", client->num, remote); "[%u] opened from %s", client->num, remote);
g_free(remote); g_free(remote);
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "AllCommands.hxx" #include "AllCommands.hxx"
#include <glib.h>
#include <string.h> #include <string.h>
#define CLIENT_LIST_MODE_BEGIN "command_list_begin" #define CLIENT_LIST_MODE_BEGIN "command_list_begin"
......
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
#include "config.h" #include "config.h"
#include "CommandError.hxx" #include "CommandError.hxx"
#include "DatabaseError.hxx" #include "DatabaseError.hxx"
#include "io_error.h"
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
...@@ -85,50 +87,38 @@ print_playlist_result(Client *client, enum playlist_result result) ...@@ -85,50 +87,38 @@ print_playlist_result(Client *client, enum playlist_result result)
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
/**
* Send the GError to the client and free the GError.
*/
enum command_return enum command_return
print_error(Client *client, GError *error) print_error(Client *client, const Error &error)
{ {
assert(client != NULL); assert(client != NULL);
assert(error != NULL); assert(error.IsDefined());
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
if (error->domain == playlist_quark()) { if (error.IsDomain(playlist_domain)) {
enum playlist_result result = (playlist_result)error->code; return print_playlist_result(client,
g_error_free(error); playlist_result(error.GetCode()));
return print_playlist_result(client, result); } else if (error.IsDomain(ack_domain)) {
} else if (error->domain == ack_quark()) { command_error(client, (ack)error.GetCode(),
command_error(client, (ack)error->code, "%s", error->message); "%s", error.GetMessage());
g_error_free(error);
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} else if (error->domain == db_quark()) { } else if (error.IsDomain(db_domain)) {
switch ((enum db_error)error->code) { switch ((enum db_error)error.GetCode()) {
case DB_DISABLED: case DB_DISABLED:
command_error(client, ACK_ERROR_NO_EXIST, "%s", command_error(client, ACK_ERROR_NO_EXIST, "%s",
error->message); error.GetMessage());
g_error_free(error);
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
case DB_NOT_FOUND: case DB_NOT_FOUND:
g_error_free(error);
command_error(client, ACK_ERROR_NO_EXIST, "Not found"); command_error(client, ACK_ERROR_NO_EXIST, "Not found");
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
} else if (error->domain == errno_quark()) { } else if (error.IsDomain(errno_domain)) {
command_error(client, ACK_ERROR_SYSTEM, "%s", command_error(client, ACK_ERROR_SYSTEM, "%s",
g_strerror(error->code)); g_strerror(error.GetCode()));
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);
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
g_error_free(error);
command_error(client, ACK_ERROR_UNKNOWN, "error"); command_error(client, ACK_ERROR_UNKNOWN, "error");
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
...@@ -22,17 +22,17 @@ ...@@ -22,17 +22,17 @@
#include "command.h" #include "command.h"
#include "PlaylistError.hxx" #include "PlaylistError.hxx"
#include "gerror.h"
class Client; class Client;
class Error;
enum command_return enum command_return
print_playlist_result(Client *client, enum playlist_result result); 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 enum command_return
print_error(Client *client, GError *error); print_error(Client *client, const Error &error);
#endif #endif
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include "mpd_error.h" #include "mpd_error.h"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#ifdef ENABLE_ENCODER #ifdef ENABLE_ENCODER
#include "EncoderList.hxx" #include "EncoderList.hxx"
...@@ -57,11 +59,7 @@ ...@@ -57,11 +59,7 @@
#define USER_CONFIG_FILE_LOCATION_XDG "mpd/mpd.conf" #define USER_CONFIG_FILE_LOCATION_XDG "mpd/mpd.conf"
#endif #endif
static GQuark static constexpr Domain cmdline_domain("cmdline");
cmdline_quark(void)
{
return g_quark_from_static_string("cmdline");
}
gcc_noreturn gcc_noreturn
static void version(void) static void version(void)
...@@ -147,9 +145,8 @@ PathBuildChecked(const Path &a, Path::const_pointer b) ...@@ -147,9 +145,8 @@ PathBuildChecked(const Path &a, Path::const_pointer b)
bool bool
parse_cmdline(int argc, char **argv, struct options *options, parse_cmdline(int argc, char **argv, struct options *options,
GError **error_r) Error &error)
{ {
GError *error = NULL;
GOptionContext *context; GOptionContext *context;
bool ret; bool ret;
static gboolean option_version, static gboolean option_version,
...@@ -183,11 +180,12 @@ parse_cmdline(int argc, char **argv, struct options *options, ...@@ -183,11 +180,12 @@ parse_cmdline(int argc, char **argv, struct options *options,
g_option_context_set_summary(context, summary); 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); g_option_context_free(context);
if (!ret) if (!ret)
MPD_ERROR("option parsing failed: %s\n", error->message); MPD_ERROR("option parsing failed: %s\n", gerror->message);
if (option_version) if (option_version)
version(); version();
...@@ -208,7 +206,7 @@ parse_cmdline(int argc, char **argv, struct options *options, ...@@ -208,7 +206,7 @@ parse_cmdline(int argc, char **argv, struct options *options,
Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()), Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()),
CONFIG_FILE_LOCATION); CONFIG_FILE_LOCATION);
if (!path.IsNull() && FileExists(path)) if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r); return ReadConfigFile(path, error);
const char *const*system_config_dirs = const char *const*system_config_dirs =
g_get_system_config_dirs(); g_get_system_config_dirs();
...@@ -217,38 +215,36 @@ parse_cmdline(int argc, char **argv, struct options *options, ...@@ -217,38 +215,36 @@ parse_cmdline(int argc, char **argv, struct options *options,
path = PathBuildChecked(Path::FromUTF8(system_config_dirs[i]), path = PathBuildChecked(Path::FromUTF8(system_config_dirs[i]),
CONFIG_FILE_LOCATION); CONFIG_FILE_LOCATION);
if (!path.IsNull() && FileExists(path)) if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r); return ReadConfigFile(path, error);
} }
#else /* G_OS_WIN32 */ #else /* G_OS_WIN32 */
Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()), Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()),
USER_CONFIG_FILE_LOCATION_XDG); USER_CONFIG_FILE_LOCATION_XDG);
if (!path.IsNull() && FileExists(path)) if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r); return ReadConfigFile(path, error);
path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()), path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()),
USER_CONFIG_FILE_LOCATION1); USER_CONFIG_FILE_LOCATION1);
if (!path.IsNull() && FileExists(path)) if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r); return ReadConfigFile(path, error);
path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()), path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()),
USER_CONFIG_FILE_LOCATION2); USER_CONFIG_FILE_LOCATION2);
if (!path.IsNull() && FileExists(path)) if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r); return ReadConfigFile(path, error);
path = Path::FromUTF8(SYSTEM_CONFIG_FILE_LOCATION); path = Path::FromUTF8(SYSTEM_CONFIG_FILE_LOCATION);
if (!path.IsNull() && FileExists(path)) if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r); return ReadConfigFile(path, error);
#endif #endif
g_set_error(error_r, cmdline_quark(), 0, error.Set(cmdline_domain, "No configuration file found");
"No configuration file found");
return false; return false;
} else if (argc == 2) { } else if (argc == 2) {
/* specified configuration file */ /* specified configuration file */
return ReadConfigFile(Path::FromFS(argv[1]), error_r); return ReadConfigFile(Path::FromFS(argv[1]), error);
} else { } else {
g_set_error(error_r, cmdline_quark(), 0, error.Set(cmdline_domain, "too many arguments");
"too many arguments");
return false; return false;
} }
} }
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <glib.h> #include <glib.h>
class Error;
struct options { struct options {
gboolean kill; gboolean kill;
gboolean daemon; gboolean daemon;
...@@ -31,6 +33,6 @@ struct options { ...@@ -31,6 +33,6 @@ struct options {
bool bool
parse_cmdline(int argc, char **argv, struct options *options, parse_cmdline(int argc, char **argv, struct options *options,
GError **error_r); Error &error);
#endif #endif
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "ConfigData.hxx" #include "ConfigData.hxx"
#include "ConfigParser.hxx" #include "ConfigParser.hxx"
#include "ConfigPath.hxx" #include "ConfigPath.hxx"
#include "util/Error.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
#include "mpd_error.h" #include "mpd_error.h"
...@@ -97,10 +98,9 @@ config_param::DupBlockString(const char *name, const char *default_value) const ...@@ -97,10 +98,9 @@ config_param::DupBlockString(const char *name, const char *default_value) const
Path Path
config_param::GetBlockPath(const char *name, const char *default_value, config_param::GetBlockPath(const char *name, const char *default_value,
GError **error_r) const Error &error) const
{ {
assert(error_r != nullptr); assert(!error.IsDefined());
assert(*error_r == nullptr);
int line2 = line; int line2 = line;
const char *s; const char *s;
...@@ -112,19 +112,18 @@ config_param::GetBlockPath(const char *name, const char *default_value, ...@@ -112,19 +112,18 @@ config_param::GetBlockPath(const char *name, const char *default_value,
} else } else
s = default_value; s = default_value;
Path path = ParsePath(s, error_r); Path path = ParsePath(s, error);
if (gcc_unlikely(path.IsNull())) if (gcc_unlikely(path.IsNull()))
g_prefix_error(error_r, error.FormatPrefix("Invalid path in \"%s\" at line %i: ",
"Invalid path in \"%s\" at line %i: ", name, line2);
name, line2);
return path; return path;
} }
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 unsigned
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#define MPD_CONFIG_DATA_HXX #define MPD_CONFIG_DATA_HXX
#include "ConfigOption.hxx" #include "ConfigOption.hxx"
#include "gerror.h"
#include "gcc.h" #include "gcc.h"
#include <string> #include <string>
...@@ -29,6 +28,7 @@ ...@@ -29,6 +28,7 @@
#include <vector> #include <vector>
class Path; class Path;
class Error;
struct block_param { struct block_param {
std::string name; std::string name;
...@@ -113,9 +113,9 @@ struct config_param { ...@@ -113,9 +113,9 @@ struct config_param {
* specified block. * specified block.
*/ */
Path GetBlockPath(const char *name, const char *default_value, 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 gcc_pure
unsigned GetBlockValue(const char *name, unsigned default_value) const; unsigned GetBlockValue(const char *name, unsigned default_value) const;
......
/*
* 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");
...@@ -17,22 +17,9 @@ ...@@ -17,22 +17,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef MPD_CONFIG_QUARK_HXX #ifndef MPD_CONFIG_ERROR_HXX
#define MPD_CONFIG_QUARK_HXX #define MPD_CONFIG_ERROR_HXX
#include "gcc.h" extern const class Domain config_domain;
#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");
}
#endif #endif
...@@ -19,12 +19,14 @@ ...@@ -19,12 +19,14 @@
#include "config.h" #include "config.h"
#include "ConfigFile.hxx" #include "ConfigFile.hxx"
#include "ConfigQuark.hxx" #include "ConfigError.hxx"
#include "ConfigData.hxx" #include "ConfigData.hxx"
#include "ConfigTemplates.hxx" #include "ConfigTemplates.hxx"
#include "conf.h" #include "conf.h"
#include "util/Tokenizer.hxx" #include "util/Tokenizer.hxx"
#include "util/StringUtil.hxx" #include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
...@@ -42,42 +44,41 @@ ...@@ -42,42 +44,41 @@
#define CONF_COMMENT '#' #define CONF_COMMENT '#'
static constexpr Domain config_file_domain("config_file");
static bool static bool
config_read_name_value(struct config_param *param, char *input, unsigned line, config_read_name_value(struct config_param *param, char *input, unsigned line,
GError **error_r) Error &error)
{ {
Tokenizer tokenizer(input); Tokenizer tokenizer(input);
const char *name = tokenizer.NextWord(error_r); const char *name = tokenizer.NextWord(error);
if (name == NULL) { if (name == NULL) {
assert(!tokenizer.IsEnd()); assert(!tokenizer.IsEnd());
return false; return false;
} }
const char *value = tokenizer.NextString(error_r); const char *value = tokenizer.NextString(error);
if (value == NULL) { if (value == NULL) {
if (tokenizer.IsEnd()) { if (tokenizer.IsEnd()) {
assert(error_r == NULL || *error_r == NULL); error.Set(config_file_domain, "Value missing");
g_set_error(error_r, config_quark(), 0,
"Value missing");
} else { } else {
assert(error_r == NULL || *error_r != NULL); assert(error.IsDefined());
} }
return false; return false;
} }
if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) { if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0, error.Set(config_file_domain, "Unknown tokens after value");
"Unknown tokens after value");
return false; return false;
} }
const struct block_param *bp = param->GetBlockParam(name); const struct block_param *bp = param->GetBlockParam(name);
if (bp != NULL) { if (bp != NULL) {
g_set_error(error_r, config_quark(), 0, error.Format(config_file_domain,
"\"%s\" is duplicate, first defined on line %i", "\"%s\" is duplicate, first defined on line %i",
name, bp->line); name, bp->line);
return false; return false;
} }
...@@ -86,10 +87,9 @@ config_read_name_value(struct config_param *param, char *input, unsigned line, ...@@ -86,10 +87,9 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
} }
static struct config_param * 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); struct config_param *ret = new config_param(*count);
GError *error = NULL;
while (true) { while (true) {
char *line; char *line;
...@@ -97,8 +97,8 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r) ...@@ -97,8 +97,8 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r)
line = fgets(string, MAX_STRING_SIZE, fp); line = fgets(string, MAX_STRING_SIZE, fp);
if (line == NULL) { if (line == NULL) {
delete ret; delete ret;
g_set_error(error_r, config_quark(), 0, error.Set(config_file_domain,
"Expected '}' before end-of-file"); "Expected '}' before end-of-file");
return NULL; return NULL;
} }
...@@ -114,9 +114,9 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r) ...@@ -114,9 +114,9 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r)
line = strchug_fast(line + 1); line = strchug_fast(line + 1);
if (*line != 0 && *line != CONF_COMMENT) { if (*line != 0 && *line != CONF_COMMENT) {
delete ret; delete ret;
g_set_error(error_r, config_quark(), 0, error.Format(config_file_domain,
"line %i: Unknown tokens after '}'", "line %i: Unknown tokens after '}'",
*count); *count);
return nullptr; return nullptr;
} }
...@@ -125,11 +125,10 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r) ...@@ -125,11 +125,10 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r)
/* parse name and value */ /* 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); assert(*line != 0);
delete ret; delete ret;
g_propagate_prefixed_error(error_r, error, error.FormatPrefix("line %i: ", *count);
"line %i: ", *count);
return NULL; return NULL;
} }
} }
...@@ -149,7 +148,7 @@ Append(config_param *&head, config_param *p) ...@@ -149,7 +148,7 @@ Append(config_param *&head, config_param *p)
} }
static bool static bool
ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ReadConfigFile(ConfigData &config_data, FILE *fp, Error &error)
{ {
assert(fp != nullptr); assert(fp != nullptr);
...@@ -160,7 +159,6 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -160,7 +159,6 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
while (fgets(string, MAX_STRING_SIZE, fp)) { while (fgets(string, MAX_STRING_SIZE, fp)) {
char *line; char *line;
const char *name, *value; const char *name, *value;
GError *error = NULL;
count++; count++;
...@@ -172,11 +170,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -172,11 +170,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
by either the value or '{' */ by either the value or '{' */
Tokenizer tokenizer(line); Tokenizer tokenizer(line);
name = tokenizer.NextWord(&error); name = tokenizer.NextWord(error);
if (name == NULL) { if (name == NULL) {
assert(!tokenizer.IsEnd()); assert(!tokenizer.IsEnd());
g_propagate_prefixed_error(error_r, error, error.FormatPrefix("line %i: ", count);
"line %i: ", count);
return false; return false;
} }
...@@ -185,9 +182,9 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -185,9 +182,9 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
const ConfigOption o = ParseConfigOptionName(name); const ConfigOption o = ParseConfigOptionName(name);
if (o == CONF_MAX) { if (o == CONF_MAX) {
g_set_error(error_r, config_quark(), 0, error.Format(config_file_domain,
"unrecognized parameter in config file at " "unrecognized parameter in config file at "
"line %i: %s\n", count, name); "line %i: %s\n", count, name);
return false; return false;
} }
...@@ -197,10 +194,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -197,10 +194,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
if (head != nullptr && !option.repeatable) { if (head != nullptr && !option.repeatable) {
param = head; param = head;
g_set_error(error_r, config_quark(), 0, error.Format(config_file_domain,
"config parameter \"%s\" is first defined " "config parameter \"%s\" is first defined "
"on line %i and redefined on line %i\n", "on line %i and redefined on line %i\n",
name, param->line, count); name, param->line, count);
return false; return false;
} }
...@@ -210,47 +207,43 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -210,47 +207,43 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
/* it's a block, call config_read_block() */ /* it's a block, call config_read_block() */
if (tokenizer.CurrentChar() != '{') { if (tokenizer.CurrentChar() != '{') {
g_set_error(error_r, config_quark(), 0, error.Format(config_file_domain,
"line %i: '{' expected", count); "line %i: '{' expected", count);
return false; return false;
} }
line = strchug_fast(tokenizer.Rest() + 1); line = strchug_fast(tokenizer.Rest() + 1);
if (*line != 0 && *line != CONF_COMMENT) { if (*line != 0 && *line != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0, error.Format(config_file_domain,
"line %i: Unknown tokens after '{'", "line %i: Unknown tokens after '{'",
count); count);
return false; return false;
} }
param = config_read_block(fp, &count, string, error_r); param = config_read_block(fp, &count, string, error);
if (param == NULL) { if (param == NULL) {
return false; return false;
} }
} else { } else {
/* a string value */ /* a string value */
value = tokenizer.NextString(&error); value = tokenizer.NextString(error);
if (value == NULL) { if (value == NULL) {
if (tokenizer.IsEnd()) if (tokenizer.IsEnd())
g_set_error(error_r, config_quark(), 0, error.Format(config_file_domain,
"line %i: Value missing", "line %i: Value missing",
count); count);
else { else
g_set_error(error_r, config_quark(), 0, error.FormatPrefix("line %i: ", count);
"line %i: %s", count,
error->message);
g_error_free(error);
}
return false; return false;
} }
if (!tokenizer.IsEnd() && if (!tokenizer.IsEnd() &&
tokenizer.CurrentChar() != CONF_COMMENT) { tokenizer.CurrentChar() != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0, error.Format(config_file_domain,
"line %i: Unknown tokens after value", "line %i: Unknown tokens after value",
count); count);
return false; return false;
} }
...@@ -264,7 +257,7 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -264,7 +257,7 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
} }
bool bool
ReadConfigFile(ConfigData &config_data, const Path &path, GError **error_r) ReadConfigFile(ConfigData &config_data, const Path &path, Error &error)
{ {
assert(!path.IsNull()); assert(!path.IsNull());
const std::string path_utf8 = path.ToUTF8(); const std::string path_utf8 = path.ToUTF8();
...@@ -273,13 +266,11 @@ ReadConfigFile(ConfigData &config_data, const Path &path, GError **error_r) ...@@ -273,13 +266,11 @@ ReadConfigFile(ConfigData &config_data, const Path &path, GError **error_r)
FILE *fp = FOpen(path, FOpenMode::ReadText); FILE *fp = FOpen(path, FOpenMode::ReadText);
if (fp == nullptr) { if (fp == nullptr) {
g_set_error(error_r, config_quark(), errno, error.FormatErrno("Failed to open %s", path_utf8.c_str());
"Failed to open %s: %s",
path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
bool result = ReadConfigFile(config_data, fp, error_r); bool result = ReadConfigFile(config_data, fp, error);
fclose(fp); fclose(fp);
return result; return result;
} }
...@@ -20,12 +20,11 @@ ...@@ -20,12 +20,11 @@
#ifndef MPD_CONFIG_FILE_HXX #ifndef MPD_CONFIG_FILE_HXX
#define MPD_CONFIG_FILE_HXX #define MPD_CONFIG_FILE_HXX
#include "gerror.h" class Error;
class Path; class Path;
struct ConfigData; struct ConfigData;
bool bool
ReadConfigFile(ConfigData &data, const Path &path, GError **error_r); ReadConfigFile(ConfigData &data, const Path &path, Error &error);
#endif #endif
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "ConfigFile.hxx" #include "ConfigFile.hxx"
#include "ConfigPath.hxx" #include "ConfigPath.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/Error.hxx"
#include "mpd_error.h" #include "mpd_error.h"
#include <glib.h> #include <glib.h>
...@@ -47,9 +48,9 @@ void config_global_init(void) ...@@ -47,9 +48,9 @@ void config_global_init(void)
} }
bool 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 static void
...@@ -98,20 +99,16 @@ config_get_string(ConfigOption option, const char *default_value) ...@@ -98,20 +99,16 @@ config_get_string(ConfigOption option, const char *default_value)
} }
Path 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); const struct config_param *param = config_get_param(option);
if (param == NULL) if (param == NULL)
return Path::Null(); return Path::Null();
Path path = ParsePath(param->value, error_r); Path path = ParsePath(param->value, error);
if (gcc_unlikely(path.IsNull())) if (gcc_unlikely(path.IsNull()))
g_prefix_error(error_r, error.FormatPrefix("Invalid path at line %i: ",
"Invalid path at line %i: ", param->line);
param->line);
return path; return path;
} }
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#define MPD_CONFIG_GLOBAL_HXX #define MPD_CONFIG_GLOBAL_HXX
#include "ConfigOption.hxx" #include "ConfigOption.hxx"
#include "gerror.h"
#include "gcc.h" #include "gcc.h"
#include <stdbool.h> #include <stdbool.h>
...@@ -30,6 +29,7 @@ ...@@ -30,6 +29,7 @@
#define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16) #define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16)
#define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS false #define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS false
class Error;
class Path; class Path;
void config_global_init(void); void config_global_init(void);
...@@ -42,7 +42,7 @@ void config_global_finish(void); ...@@ -42,7 +42,7 @@ void config_global_finish(void);
void config_global_check(void); void config_global_check(void);
bool bool
ReadConfigFile(const Path &path, GError **error_r); ReadConfigFile(const Path &path, Error &error);
/* don't free the returned value /* don't free the returned value
set _last_ to NULL to get first entry */ set _last_ to NULL to get first entry */
...@@ -76,7 +76,7 @@ config_get_string(enum ConfigOption option, const char *default_value); ...@@ -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. * could not be parsed, returns Path::Null() and sets the error.
*/ */
Path Path
config_get_path(enum ConfigOption option, GError **error_r); config_get_path(enum ConfigOption option, Error &error);
gcc_pure gcc_pure
unsigned unsigned
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "config.h" #include "config.h"
#include "ConfigPath.hxx" #include "ConfigPath.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "conf.h" #include "conf.h"
#include <glib.h> #include <glib.h>
...@@ -46,31 +48,25 @@ ...@@ -46,31 +48,25 @@
#include <windows.h> #include <windows.h>
#endif #endif
gcc_const static constexpr Domain path_domain("path");
static inline GQuark
parse_path_quark(void)
{
return g_quark_from_static_string("path");
}
Path Path
ParsePath(const char *path, GError **error_r) ParsePath(const char *path, Error &error)
{ {
assert(path != nullptr); assert(path != nullptr);
assert(error_r == nullptr || *error_r == nullptr);
Path path2 = Path::FromUTF8(path); Path path2 = Path::FromUTF8(path);
if (path2.IsNull()) { if (path2.IsNull()) {
g_set_error(error_r, parse_path_quark(), 0, error.Format(path_domain,
"Failed to convert path to file system charset: %s", "Failed to convert path to file system charset: %s",
path); path);
return Path::Null(); return Path::Null();
} }
#ifndef WIN32 #ifndef WIN32
if (!g_path_is_absolute(path) && path[0] != '~') { if (!g_path_is_absolute(path) && path[0] != '~') {
g_set_error(error_r, parse_path_quark(), 0, error.Format(path_domain,
"not an absolute path: %s", path); "not an absolute path: %s", path);
return Path::Null(); return Path::Null();
} else if (path[0] == '~') { } else if (path[0] == '~') {
const char *home; const char *home;
...@@ -80,8 +76,8 @@ ParsePath(const char *path, GError **error_r) ...@@ -80,8 +76,8 @@ ParsePath(const char *path, GError **error_r)
if (user != nullptr) { if (user != nullptr) {
struct passwd *passwd = getpwnam(user); struct passwd *passwd = getpwnam(user);
if (!passwd) { if (!passwd) {
g_set_error(error_r, parse_path_quark(), 0, error.Format(path_domain,
"no such user: %s", user); "no such user: %s", user);
return Path::Null(); return Path::Null();
} }
...@@ -89,9 +85,9 @@ ParsePath(const char *path, GError **error_r) ...@@ -89,9 +85,9 @@ ParsePath(const char *path, GError **error_r)
} else { } else {
home = g_get_home_dir(); home = g_get_home_dir();
if (home == nullptr) { if (home == nullptr) {
g_set_error_literal(error_r, parse_path_quark(), 0, error.Set(path_domain,
"problems getting home " "problems getting home "
"for current user"); "for current user");
return Path::Null(); return Path::Null();
} }
} }
...@@ -107,8 +103,8 @@ ParsePath(const char *path, GError **error_r) ...@@ -107,8 +103,8 @@ ParsePath(const char *path, GError **error_r)
struct passwd *passwd = getpwnam(user); struct passwd *passwd = getpwnam(user);
if (!passwd) { if (!passwd) {
g_set_error(error_r, parse_path_quark(), 0, error.Format(path_domain,
"no such user: %s", user); "no such user: %s", user);
g_free(user); g_free(user);
return Path::Null(); return Path::Null();
} }
......
...@@ -20,11 +20,10 @@ ...@@ -20,11 +20,10 @@
#ifndef MPD_CONFIG_PATH_HXX #ifndef MPD_CONFIG_PATH_HXX
#define MPD_CONFIG_PATH_HXX #define MPD_CONFIG_PATH_HXX
#include "gerror.h"
class Path; class Path;
class Error;
Path Path
ParsePath(const char *path, GError **error_r); ParsePath(const char *path, Error &error);
#endif #endif
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "ClientInternal.hxx" #include "ClientInternal.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "SongFilter.hxx" #include "SongFilter.hxx"
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
...@@ -46,8 +47,8 @@ handle_lsinfo2(Client *client, int argc, char *argv[]) ...@@ -46,8 +47,8 @@ handle_lsinfo2(Client *client, int argc, char *argv[])
const DatabaseSelection selection(uri, false); const DatabaseSelection selection(uri, false);
GError *error = NULL; Error error;
if (!db_selection_print(client, selection, true, &error)) if (!db_selection_print(client, selection, true, error))
return print_error(client, error); return print_error(client, error);
return COMMAND_RETURN_OK; return COMMAND_RETURN_OK;
...@@ -64,8 +65,8 @@ handle_match(Client *client, int argc, char *argv[], bool fold_case) ...@@ -64,8 +65,8 @@ handle_match(Client *client, int argc, char *argv[], bool fold_case)
const DatabaseSelection selection("", true, &filter); const DatabaseSelection selection("", true, &filter);
GError *error = NULL; Error error;
return db_selection_print(client, selection, true, &error) return db_selection_print(client, selection, true, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -92,8 +93,8 @@ handle_match_add(Client *client, int argc, char *argv[], bool fold_case) ...@@ -92,8 +93,8 @@ handle_match_add(Client *client, int argc, char *argv[], bool fold_case)
} }
const DatabaseSelection selection("", true, &filter); const DatabaseSelection selection("", true, &filter);
GError *error = NULL; Error error;
return AddFromDatabase(client->partition, selection, &error) return AddFromDatabase(client->partition, selection, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -121,8 +122,8 @@ handle_searchaddpl(Client *client, int argc, char *argv[]) ...@@ -121,8 +122,8 @@ handle_searchaddpl(Client *client, int argc, char *argv[])
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
GError *error = NULL; Error error;
return search_add_to_playlist("", playlist, &filter, &error) return search_add_to_playlist("", playlist, &filter, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -136,8 +137,8 @@ handle_count(Client *client, int argc, char *argv[]) ...@@ -136,8 +137,8 @@ handle_count(Client *client, int argc, char *argv[])
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
GError *error = NULL; Error error;
return searchStatsForSongsIn(client, "", &filter, &error) return searchStatsForSongsIn(client, "", &filter, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -150,8 +151,8 @@ handle_listall(Client *client, gcc_unused int argc, char *argv[]) ...@@ -150,8 +151,8 @@ handle_listall(Client *client, gcc_unused int argc, char *argv[])
if (argc == 2) if (argc == 2)
directory = argv[1]; directory = argv[1];
GError *error = NULL; Error error;
return printAllIn(client, directory, &error) return printAllIn(client, directory, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -194,9 +195,9 @@ handle_list(Client *client, int argc, char *argv[]) ...@@ -194,9 +195,9 @@ handle_list(Client *client, int argc, char *argv[])
} else } else
filter = nullptr; filter = nullptr;
GError *error = NULL; Error error;
enum command_return ret = enum command_return ret =
listAllUniqueTags(client, tagType, filter, &error) listAllUniqueTags(client, tagType, filter, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
...@@ -213,8 +214,8 @@ handle_listallinfo(Client *client, gcc_unused int argc, char *argv[]) ...@@ -213,8 +214,8 @@ handle_listallinfo(Client *client, gcc_unused int argc, char *argv[])
if (argc == 2) if (argc == 2)
directory = argv[1]; directory = argv[1];
GError *error = NULL; Error error;
return printInfoForAllIn(client, directory, &error) return printInfoForAllIn(client, directory, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
/*
* 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");
...@@ -20,9 +20,7 @@ ...@@ -20,9 +20,7 @@
#ifndef MPD_DB_ERROR_HXX #ifndef MPD_DB_ERROR_HXX
#define MPD_DB_ERROR_HXX #define MPD_DB_ERROR_HXX
#include "gcc.h" class Domain;
#include <glib.h>
enum db_error { enum db_error {
/** /**
...@@ -34,14 +32,6 @@ enum db_error { ...@@ -34,14 +32,6 @@ enum db_error {
DB_NOT_FOUND, DB_NOT_FOUND,
}; };
/** extern const Domain db_domain;
* 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");
}
#endif #endif
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "DatabaseSave.hxx" #include "DatabaseSave.hxx"
#include "DatabaseError.hxx" #include "DatabaseError.hxx"
#include "Directory.hxx" #include "Directory.hxx"
#include "util/Error.hxx"
#include "conf.h" #include "conf.h"
extern "C" { extern "C" {
...@@ -50,7 +51,7 @@ static bool db_is_open; ...@@ -50,7 +51,7 @@ static bool db_is_open;
static bool is_simple; static bool is_simple;
bool bool
DatabaseGlobalInit(const config_param &param, GError **error_r) DatabaseGlobalInit(const config_param &param, Error &error)
{ {
assert(db == NULL); assert(db == NULL);
assert(!db_is_open); assert(!db_is_open);
...@@ -61,12 +62,12 @@ DatabaseGlobalInit(const config_param &param, GError **error_r) ...@@ -61,12 +62,12 @@ DatabaseGlobalInit(const config_param &param, GError **error_r)
const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name); const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name);
if (plugin == NULL) { if (plugin == NULL) {
g_set_error(error_r, db_quark(), 0, error.Format(db_domain,
"No such database plugin: %s", plugin_name); "No such database plugin: %s", plugin_name);
return false; return false;
} }
db = plugin->create(param, error_r); db = plugin->create(param, error);
return db != NULL; return db != NULL;
} }
...@@ -89,13 +90,12 @@ GetDatabase() ...@@ -89,13 +90,12 @@ GetDatabase()
} }
const Database * const Database *
GetDatabase(GError **error_r) GetDatabase(Error &error)
{ {
assert(db == nullptr || db_is_open); assert(db == nullptr || db_is_open);
if (db == nullptr) if (db == nullptr)
g_set_error_literal(error_r, db_quark(), DB_DISABLED, error.Set(db_domain, DB_DISABLED, "No database");
"No database");
return db; return db;
} }
...@@ -131,17 +131,17 @@ db_get_directory(const char *name) ...@@ -131,17 +131,17 @@ db_get_directory(const char *name)
} }
bool bool
db_save(GError **error_r) db_save(Error &error)
{ {
assert(db != NULL); assert(db != NULL);
assert(db_is_open); assert(db_is_open);
assert(db_is_simple()); assert(db_is_simple());
return ((SimpleDatabase *)db)->Save(error_r); return ((SimpleDatabase *)db)->Save(error);
} }
bool bool
DatabaseGlobalOpen(GError **error) DatabaseGlobalOpen(Error &error)
{ {
assert(db != NULL); assert(db != NULL);
assert(!db_is_open); assert(!db_is_open);
......
...@@ -21,10 +21,10 @@ ...@@ -21,10 +21,10 @@
#define MPD_DATABASE_GLUE_HXX #define MPD_DATABASE_GLUE_HXX
#include "gcc.h" #include "gcc.h"
#include "gerror.h"
struct config_param; struct config_param;
class Database; class Database;
class Error;
/** /**
* Initialize the database library. * Initialize the database library.
...@@ -32,13 +32,13 @@ class Database; ...@@ -32,13 +32,13 @@ class Database;
* @param param the database configuration block * @param param the database configuration block
*/ */
bool bool
DatabaseGlobalInit(const config_param &param, GError **error_r); DatabaseGlobalInit(const config_param &param, Error &error);
void void
DatabaseGlobalDeinit(void); DatabaseGlobalDeinit(void);
bool bool
DatabaseGlobalOpen(GError **error); DatabaseGlobalOpen(Error &error);
/** /**
* Returns the global #Database instance. May return NULL if this MPD * Returns the global #Database instance. May return NULL if this MPD
...@@ -54,6 +54,6 @@ GetDatabase(); ...@@ -54,6 +54,6 @@ GetDatabase();
*/ */
gcc_pure gcc_pure
const Database * const Database *
GetDatabase(GError **error_r); GetDatabase(Error &error);
#endif #endif
...@@ -61,17 +61,17 @@ bool ...@@ -61,17 +61,17 @@ bool
VisitUniqueTags(const Database &db, const DatabaseSelection &selection, VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
enum tag_type tag_type, enum tag_type tag_type,
VisitString visit_string, VisitString visit_string,
GError **error_r) Error &error)
{ {
StringSet set; StringSet set;
using namespace std::placeholders; using namespace std::placeholders;
const auto f = std::bind(CollectTags, std::ref(set), tag_type, _1); 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; return false;
for (auto value : set) for (auto value : set)
if (!visit_string(value, error_r)) if (!visit_string(value, error))
return false; return false;
return true; return true;
...@@ -116,7 +116,7 @@ StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums, ...@@ -116,7 +116,7 @@ StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
bool bool
GetStats(const Database &db, const DatabaseSelection &selection, GetStats(const Database &db, const DatabaseSelection &selection,
DatabaseStats &stats, GError **error_r) DatabaseStats &stats, Error &error)
{ {
stats.Clear(); stats.Clear();
...@@ -125,7 +125,7 @@ GetStats(const Database &db, const DatabaseSelection &selection, ...@@ -125,7 +125,7 @@ GetStats(const Database &db, const DatabaseSelection &selection,
const auto f = std::bind(StatsVisitSong, const auto f = std::bind(StatsVisitSong,
std::ref(stats), std::ref(artists), std::ref(stats), std::ref(artists),
std::ref(albums), _1); std::ref(albums), _1);
if (!db.Visit(selection, f, error_r)) if (!db.Visit(selection, f, error))
return false; return false;
stats.artist_count = artists.size(); stats.artist_count = artists.size();
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "TagType.h" #include "TagType.h"
#include "gcc.h" #include "gcc.h"
class Error;
class Database; class Database;
struct DatabaseSelection; struct DatabaseSelection;
struct DatabaseStats; struct DatabaseStats;
...@@ -32,10 +33,10 @@ bool ...@@ -32,10 +33,10 @@ bool
VisitUniqueTags(const Database &db, const DatabaseSelection &selection, VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
enum tag_type tag_type, enum tag_type tag_type,
VisitString visit_string, VisitString visit_string,
GError **error_r); Error &error);
bool bool
GetStats(const Database &db, const DatabaseSelection &selection, GetStats(const Database &db, const DatabaseSelection &selection,
DatabaseStats &stats, GError **error_r); DatabaseStats &stats, Error &error);
#endif #endif
...@@ -28,17 +28,17 @@ ...@@ -28,17 +28,17 @@
static bool static bool
AddSong(const char *playlist_path_utf8, 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 bool
search_add_to_playlist(const char *uri, const char *playlist_path_utf8, search_add_to_playlist(const char *uri, const char *playlist_path_utf8,
const SongFilter *filter, const SongFilter *filter,
GError **error_r) Error &error)
{ {
const Database *db = GetDatabase(error_r); const Database *db = GetDatabase(error);
if (db == nullptr) if (db == nullptr)
return false; return false;
...@@ -46,5 +46,5 @@ search_add_to_playlist(const char *uri, const char *playlist_path_utf8, ...@@ -46,5 +46,5 @@ search_add_to_playlist(const char *uri, const char *playlist_path_utf8,
using namespace std::placeholders; using namespace std::placeholders;
const auto f = std::bind(AddSong, playlist_path_utf8, _1, _2); const auto f = std::bind(AddSong, playlist_path_utf8, _1, _2);
return db->Visit(selection, f, error_r); return db->Visit(selection, f, error);
} }
...@@ -21,14 +21,14 @@ ...@@ -21,14 +21,14 @@
#define MPD_DATABASE_PLAYLIST_HXX #define MPD_DATABASE_PLAYLIST_HXX
#include "gcc.h" #include "gcc.h"
#include "gerror.h"
class SongFilter; class SongFilter;
class Error;
gcc_nonnull(1,2) gcc_nonnull(1,2)
bool bool
search_add_to_playlist(const char *uri, const char *path_utf8, search_add_to_playlist(const char *uri, const char *path_utf8,
const SongFilter *filter, const SongFilter *filter,
GError **error_r); Error &error);
#endif #endif
...@@ -34,6 +34,7 @@ struct config_param; ...@@ -34,6 +34,7 @@ struct config_param;
struct DatabaseSelection; struct DatabaseSelection;
struct db_visitor; struct db_visitor;
struct Song; struct Song;
class Error;
struct DatabaseStats { struct DatabaseStats {
/** /**
...@@ -73,7 +74,7 @@ public: ...@@ -73,7 +74,7 @@ public:
/** /**
* Open the database. Read it into memory if applicable. * 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; return true;
} }
...@@ -90,7 +91,7 @@ public: ...@@ -90,7 +91,7 @@ public:
* directory (UTF-8) * directory (UTF-8)
*/ */
virtual Song *GetSong(const char *uri_utf8, 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 * Mark the song object as "unused". Call this on objects
...@@ -105,19 +106,19 @@ public: ...@@ -105,19 +106,19 @@ public:
VisitDirectory visit_directory, VisitDirectory visit_directory,
VisitSong visit_song, VisitSong visit_song,
VisitPlaylist visit_playlist, VisitPlaylist visit_playlist,
GError **error_r) const = 0; Error &error) const = 0;
bool Visit(const DatabaseSelection &selection, bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory, VisitDirectory visit_directory,
VisitSong visit_song, VisitSong visit_song,
GError **error_r) const { Error &error) const {
return Visit(selection, visit_directory, visit_song, return Visit(selection, visit_directory, visit_song,
VisitPlaylist(), error_r); VisitPlaylist(), error);
} }
bool Visit(const DatabaseSelection &selection, VisitSong visit_song, bool Visit(const DatabaseSelection &selection, VisitSong visit_song,
GError **error_r) const { Error &error) const {
return Visit(selection, VisitDirectory(), visit_song, error_r); return Visit(selection, VisitDirectory(), visit_song, error);
} }
/** /**
...@@ -126,11 +127,11 @@ public: ...@@ -126,11 +127,11 @@ public:
virtual bool VisitUniqueTags(const DatabaseSelection &selection, virtual bool VisitUniqueTags(const DatabaseSelection &selection,
enum tag_type tag_type, enum tag_type tag_type,
VisitString visit_string, VisitString visit_string,
GError **error_r) const = 0; Error &error) const = 0;
virtual bool GetStats(const DatabaseSelection &selection, virtual bool GetStats(const DatabaseSelection &selection,
DatabaseStats &stats, DatabaseStats &stats,
GError **error_r) const = 0; Error &error) const = 0;
}; };
struct DatabasePlugin { struct DatabasePlugin {
...@@ -140,7 +141,7 @@ struct DatabasePlugin { ...@@ -140,7 +141,7 @@ struct DatabasePlugin {
* Allocates and configures a database. * Allocates and configures a database.
*/ */
Database *(*create)(const config_param &param, Database *(*create)(const config_param &param,
GError **error_r); Error &error);
}; };
#endif #endif
...@@ -118,9 +118,9 @@ PrintPlaylistFull(Client *client, ...@@ -118,9 +118,9 @@ PrintPlaylistFull(Client *client,
bool bool
db_selection_print(Client *client, const DatabaseSelection &selection, 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) if (db == nullptr)
return false; return false;
...@@ -136,7 +136,7 @@ db_selection_print(Client *client, const DatabaseSelection &selection, ...@@ -136,7 +136,7 @@ db_selection_print(Client *client, const DatabaseSelection &selection,
client, _1, _2) client, _1, _2)
: VisitPlaylist(); : VisitPlaylist();
return db->Visit(selection, d, s, p, error_r); return db->Visit(selection, d, s, p, error);
} }
struct SearchStats { struct SearchStats {
...@@ -162,9 +162,9 @@ stats_visitor_song(SearchStats &stats, Song &song) ...@@ -162,9 +162,9 @@ stats_visitor_song(SearchStats &stats, Song &song)
bool bool
searchStatsForSongsIn(Client *client, const char *name, searchStatsForSongsIn(Client *client, const char *name,
const SongFilter *filter, const SongFilter *filter,
GError **error_r) Error &error)
{ {
const Database *db = GetDatabase(error_r); const Database *db = GetDatabase(error);
if (db == nullptr) if (db == nullptr)
return false; return false;
...@@ -177,7 +177,7 @@ searchStatsForSongsIn(Client *client, const char *name, ...@@ -177,7 +177,7 @@ searchStatsForSongsIn(Client *client, const char *name,
using namespace std::placeholders; using namespace std::placeholders;
const auto f = std::bind(stats_visitor_song, std::ref(stats), const auto f = std::bind(stats_visitor_song, std::ref(stats),
_1); _1);
if (!db->Visit(selection, f, error_r)) if (!db->Visit(selection, f, error))
return false; return false;
printSearchStats(client, &stats); printSearchStats(client, &stats);
...@@ -185,18 +185,18 @@ searchStatsForSongsIn(Client *client, const char *name, ...@@ -185,18 +185,18 @@ searchStatsForSongsIn(Client *client, const char *name,
} }
bool 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); const DatabaseSelection selection(uri_utf8, true);
return db_selection_print(client, selection, false, error_r); return db_selection_print(client, selection, false, error);
} }
bool bool
printInfoForAllIn(Client *client, const char *uri_utf8, printInfoForAllIn(Client *client, const char *uri_utf8,
GError **error_r) Error &error)
{ {
const DatabaseSelection selection(uri_utf8, true); 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 static bool
...@@ -218,9 +218,9 @@ PrintUniqueTag(Client *client, enum tag_type tag_type, ...@@ -218,9 +218,9 @@ PrintUniqueTag(Client *client, enum tag_type tag_type,
bool bool
listAllUniqueTags(Client *client, int type, listAllUniqueTags(Client *client, int type,
const SongFilter *filter, const SongFilter *filter,
GError **error_r) Error &error)
{ {
const Database *db = GetDatabase(error_r); const Database *db = GetDatabase(error);
if (db == nullptr) if (db == nullptr)
return false; return false;
...@@ -229,12 +229,12 @@ listAllUniqueTags(Client *client, int type, ...@@ -229,12 +229,12 @@ listAllUniqueTags(Client *client, int type,
if (type == LOCATE_TAG_FILE_TYPE) { if (type == LOCATE_TAG_FILE_TYPE) {
using namespace std::placeholders; using namespace std::placeholders;
const auto f = std::bind(PrintSongURIVisitor, client, _1); const auto f = std::bind(PrintSongURIVisitor, client, _1);
return db->Visit(selection, f, error_r); return db->Visit(selection, f, error);
} else { } else {
using namespace std::placeholders; using namespace std::placeholders;
const auto f = std::bind(PrintUniqueTag, client, const auto f = std::bind(PrintUniqueTag, client,
(enum tag_type)type, _1); (enum tag_type)type, _1);
return db->VisitUniqueTags(selection, (enum tag_type)type, return db->VisitUniqueTags(selection, (enum tag_type)type,
f, error_r); f, error);
} }
} }
...@@ -21,37 +21,37 @@ ...@@ -21,37 +21,37 @@
#define MPD_DB_PRINT_H #define MPD_DB_PRINT_H
#include "gcc.h" #include "gcc.h"
#include "gerror.h"
class SongFilter; class SongFilter;
struct DatabaseSelection; struct DatabaseSelection;
struct db_visitor; struct db_visitor;
class Client; class Client;
class Error;
gcc_nonnull(1) gcc_nonnull(1)
bool bool
db_selection_print(Client *client, const DatabaseSelection &selection, db_selection_print(Client *client, const DatabaseSelection &selection,
bool full, GError **error_r); bool full, Error &error);
gcc_nonnull(1,2) gcc_nonnull(1,2)
bool bool
printAllIn(Client *client, const char *uri_utf8, GError **error_r); printAllIn(Client *client, const char *uri_utf8, Error &error);
gcc_nonnull(1,2) gcc_nonnull(1,2)
bool bool
printInfoForAllIn(Client *client, const char *uri_utf8, printInfoForAllIn(Client *client, const char *uri_utf8,
GError **error_r); Error &error);
gcc_nonnull(1,2) gcc_nonnull(1,2)
bool bool
searchStatsForSongsIn(Client *client, const char *name, searchStatsForSongsIn(Client *client, const char *name,
const SongFilter *filter, const SongFilter *filter,
GError **error_r); Error &error);
gcc_nonnull(1) gcc_nonnull(1)
bool bool
listAllUniqueTags(Client *client, int type, listAllUniqueTags(Client *client, int type,
const SongFilter *filter, const SongFilter *filter,
GError **error_r); Error &error);
#endif #endif
...@@ -23,17 +23,17 @@ ...@@ -23,17 +23,17 @@
#include "DatabaseGlue.hxx" #include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx" #include "DatabasePlugin.hxx"
#include "Partition.hxx" #include "Partition.hxx"
#include "util/Error.hxx"
#include <functional> #include <functional>
static bool static bool
AddToQueue(Partition &partition, Song &song, GError **error_r) AddToQueue(Partition &partition, Song &song, Error &error)
{ {
enum playlist_result result = enum playlist_result result =
partition.playlist.AppendSong(partition.pc, &song, NULL); partition.playlist.AppendSong(partition.pc, &song, NULL);
if (result != PLAYLIST_RESULT_SUCCESS) { if (result != PLAYLIST_RESULT_SUCCESS) {
g_set_error(error_r, playlist_quark(), result, error.Set(playlist_domain, result, "Playlist error");
"Playlist error");
return false; return false;
} }
...@@ -42,13 +42,13 @@ AddToQueue(Partition &partition, Song &song, GError **error_r) ...@@ -42,13 +42,13 @@ AddToQueue(Partition &partition, Song &song, GError **error_r)
bool bool
AddFromDatabase(Partition &partition, const DatabaseSelection &selection, 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) if (db == nullptr)
return false; return false;
using namespace std::placeholders; using namespace std::placeholders;
const auto f = std::bind(AddToQueue, std::ref(partition), _1, _2); const auto f = std::bind(AddToQueue, std::ref(partition), _1, _2);
return db->Visit(selection, f, error_r); return db->Visit(selection, f, error);
} }
...@@ -20,13 +20,12 @@ ...@@ -20,13 +20,12 @@
#ifndef MPD_DATABASE_QUEUE_HXX #ifndef MPD_DATABASE_QUEUE_HXX
#define MPD_DATABASE_QUEUE_HXX #define MPD_DATABASE_QUEUE_HXX
#include "gerror.h"
struct Partition; struct Partition;
struct DatabaseSelection; struct DatabaseSelection;
class Error;
bool bool
AddFromDatabase(Partition &partition, const DatabaseSelection &selection, AddFromDatabase(Partition &partition, const DatabaseSelection &selection,
GError **error_r); Error &error);
#endif #endif
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "TagInternal.hxx" #include "TagInternal.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -69,7 +70,7 @@ db_save_internal(FILE *fp, const Directory *music_root) ...@@ -69,7 +70,7 @@ db_save_internal(FILE *fp, const Directory *music_root)
} }
bool bool
db_load_internal(TextFile &file, Directory *music_root, GError **error) db_load_internal(TextFile &file, Directory *music_root, Error &error)
{ {
char *line; char *line;
int format = 0; int format = 0;
...@@ -82,7 +83,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) ...@@ -82,7 +83,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
/* get initial info */ /* get initial info */
line = file.ReadLine(); line = file.ReadLine();
if (line == NULL || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) { 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; return false;
} }
...@@ -94,8 +95,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) ...@@ -94,8 +95,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1); format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1);
} else if (g_str_has_prefix(line, DIRECTORY_MPD_VERSION)) { } else if (g_str_has_prefix(line, DIRECTORY_MPD_VERSION)) {
if (found_version) { if (found_version) {
g_set_error(error, db_quark(), 0, error.Set(db_domain, "Duplicate version line");
"Duplicate version line");
return false; return false;
} }
...@@ -104,8 +104,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) ...@@ -104,8 +104,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
const char *new_charset; const char *new_charset;
if (found_charset) { if (found_charset) {
g_set_error(error, db_quark(), 0, error.Set(db_domain, "Duplicate charset line");
"Duplicate charset line");
return false; return false;
} }
...@@ -115,44 +114,43 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) ...@@ -115,44 +114,43 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
const std::string &old_charset = Path::GetFSCharset(); const std::string &old_charset = Path::GetFSCharset();
if (!old_charset.empty() if (!old_charset.empty()
&& strcmp(new_charset, old_charset.c_str())) { && strcmp(new_charset, old_charset.c_str())) {
g_set_error(error, db_quark(), 0, error.Format(db_domain,
"Existing database has charset " "Existing database has charset "
"\"%s\" instead of \"%s\"; " "\"%s\" instead of \"%s\"; "
"discarding database file", "discarding database file",
new_charset, old_charset.c_str()); new_charset, old_charset.c_str());
return false; return false;
} }
} else if (g_str_has_prefix(line, DB_TAG_PREFIX)) { } else if (g_str_has_prefix(line, DB_TAG_PREFIX)) {
const char *name = line + sizeof(DB_TAG_PREFIX) - 1; const char *name = line + sizeof(DB_TAG_PREFIX) - 1;
enum tag_type tag = tag_name_parse(name); enum tag_type tag = tag_name_parse(name);
if (tag == TAG_NUM_OF_ITEM_TYPES) { if (tag == TAG_NUM_OF_ITEM_TYPES) {
g_set_error(error, db_quark(), 0, error.Format(db_domain,
"Unrecognized tag '%s', " "Unrecognized tag '%s', "
"discarding database file", "discarding database file",
name); name);
return false; return false;
} }
tags[tag] = true; tags[tag] = true;
} else { } else {
g_set_error(error, db_quark(), 0, error.Format(db_domain, "Malformed line: %s", line);
"Malformed line: %s", line);
return false; return false;
} }
} }
if (format != DB_FORMAT) { if (format != DB_FORMAT) {
g_set_error(error, db_quark(), 0, error.Set(db_domain,
"Database format mismatch, " "Database format mismatch, "
"discarding database file"); "discarding database file");
return false; return false;
} }
for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) { for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) {
if (!ignore_tag_items[i] && !tags[i]) { if (!ignore_tag_items[i] && !tags[i]) {
g_set_error(error, db_quark(), 0, error.Set(db_domain,
"Tag list mismatch, " "Tag list mismatch, "
"discarding database file"); "discarding database file");
return false; return false;
} }
} }
......
...@@ -20,17 +20,16 @@ ...@@ -20,17 +20,16 @@
#ifndef MPD_DATABASE_SAVE_HXX #ifndef MPD_DATABASE_SAVE_HXX
#define MPD_DATABASE_SAVE_HXX #define MPD_DATABASE_SAVE_HXX
#include "gerror.h"
#include <stdio.h> #include <stdio.h>
struct Directory; struct Directory;
class TextFile; class TextFile;
class Error;
void void
db_save_internal(FILE *file, const Directory *root); db_save_internal(FILE *file, const Directory *root);
bool bool
db_load_internal(TextFile &file, Directory *root, GError **error); db_load_internal(TextFile &file, Directory *root, Error &error);
#endif #endif
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#define MPD_DATABASE_SIMPLE_HXX #define MPD_DATABASE_SIMPLE_HXX
#include "gcc.h" #include "gcc.h"
#include "gerror.h"
#include <sys/time.h> #include <sys/time.h>
...@@ -29,6 +28,7 @@ struct config_param; ...@@ -29,6 +28,7 @@ struct config_param;
struct Directory; struct Directory;
struct db_selection; struct db_selection;
struct db_visitor; struct db_visitor;
class Error;
/** /**
* Check whether the default #SimpleDatabasePlugin is used. This * Check whether the default #SimpleDatabasePlugin is used. This
...@@ -60,7 +60,7 @@ db_get_directory(const char *name); ...@@ -60,7 +60,7 @@ db_get_directory(const char *name);
* May only be used if db_is_simple() returns true. * May only be used if db_is_simple() returns true.
*/ */
bool bool
db_save(GError **error_r); db_save(Error &error);
/** /**
* May only be used if db_is_simple() returns true. * May only be used if db_is_simple() returns true.
......
...@@ -20,19 +20,18 @@ ...@@ -20,19 +20,18 @@
#ifndef MPD_DATABASE_VISITOR_HXX #ifndef MPD_DATABASE_VISITOR_HXX
#define MPD_DATABASE_VISITOR_HXX #define MPD_DATABASE_VISITOR_HXX
#include "gerror.h"
#include <functional> #include <functional>
struct Directory; struct Directory;
struct Song; struct Song;
struct PlaylistInfo; struct PlaylistInfo;
class Error;
typedef std::function<bool(const Directory &, GError **)> VisitDirectory; typedef std::function<bool(const Directory &, Error &)> VisitDirectory;
typedef std::function<bool(struct Song &, GError **)> VisitSong; typedef std::function<bool(struct Song &, Error &)> VisitSong;
typedef std::function<bool(const PlaylistInfo &, const Directory &, 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 #endif
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "DecoderInternal.hxx" #include "DecoderInternal.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -257,8 +258,6 @@ size_t decoder_read(struct decoder *decoder, ...@@ -257,8 +258,6 @@ size_t decoder_read(struct decoder *decoder,
void *buffer, size_t length) void *buffer, size_t length)
{ {
/* XXX don't allow decoder==NULL */ /* XXX don't allow decoder==NULL */
GError *error = NULL;
size_t nbytes;
assert(decoder == NULL || assert(decoder == NULL ||
decoder->dc->state == DECODE_STATE_START || decoder->dc->state == DECODE_STATE_START ||
...@@ -283,14 +282,13 @@ size_t decoder_read(struct decoder *decoder, ...@@ -283,14 +282,13 @@ size_t decoder_read(struct decoder *decoder,
is->cond.wait(is->mutex); is->cond.wait(is->mutex);
} }
nbytes = input_stream_read(is, buffer, length, &error); Error error;
assert(nbytes == 0 || error == NULL); size_t nbytes = input_stream_read(is, buffer, length, error);
assert(nbytes > 0 || error != NULL || input_stream_eof(is)); assert(nbytes == 0 || !error.IsDefined());
assert(nbytes > 0 || error.IsDefined() || input_stream_eof(is));
if (gcc_unlikely(nbytes == 0 && error != nullptr)) { if (gcc_unlikely(nbytes == 0 && error.IsDefined()))
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
}
input_stream_unlock(is); input_stream_unlock(is);
...@@ -364,7 +362,6 @@ decoder_data(struct decoder *decoder, ...@@ -364,7 +362,6 @@ decoder_data(struct decoder *decoder,
uint16_t kbit_rate) uint16_t kbit_rate)
{ {
struct decoder_control *dc = decoder->dc; struct decoder_control *dc = decoder->dc;
GError *error = NULL;
enum decoder_command cmd; enum decoder_command cmd;
assert(dc->state == DECODE_STATE_DECODE); assert(dc->state == DECODE_STATE_DECODE);
...@@ -397,16 +394,17 @@ decoder_data(struct decoder *decoder, ...@@ -397,16 +394,17 @@ decoder_data(struct decoder *decoder,
} }
if (dc->in_audio_format != dc->out_audio_format) { if (dc->in_audio_format != dc->out_audio_format) {
Error error;
data = decoder->conv_state.Convert(dc->in_audio_format, data = decoder->conv_state.Convert(dc->in_audio_format,
data, length, data, length,
dc->out_audio_format, dc->out_audio_format,
&length, &length,
&error); error);
if (data == NULL) { if (data == NULL) {
/* the PCM conversion has failed - stop /* the PCM conversion has failed - stop
playback, since we have no better way to playback, since we have no better way to
bail out */ bail out */
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
return DECODE_COMMAND_STOP; return DECODE_COMMAND_STOP;
} }
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "thread/Cond.hxx" #include "thread/Cond.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -77,7 +78,7 @@ struct decoder_control { ...@@ -77,7 +78,7 @@ struct decoder_control {
* The object must be freed when this object transitions to * The object must be freed when this object transitions to
* any other state (usually #DECODE_STATE_START). * any other state (usually #DECODE_STATE_START).
*/ */
GError *error; Error error;
bool quit; bool quit;
bool seek_error; bool seek_error;
...@@ -218,38 +219,41 @@ struct decoder_control { ...@@ -218,38 +219,41 @@ struct decoder_control {
} }
/** /**
* Checks whether an error has occurred, and if so, returns a newly * Checks whether an error has occurred, and if so, returns a
* allocated copy of the #GError object. * copy of the #Error object.
* *
* Caller must lock the object. * Caller must lock the object.
*/ */
GError *GetError() const { gcc_pure
Error GetError() const {
assert(command == DECODE_COMMAND_NONE); assert(command == DECODE_COMMAND_NONE);
assert(state != DECODE_STATE_ERROR || error != nullptr); assert(state != DECODE_STATE_ERROR || error.IsDefined());
return state == DECODE_STATE_ERROR Error result;
? g_error_copy(error) if (state == DECODE_STATE_ERROR)
: nullptr; result.Set(error);
return result;
} }
/** /**
* Like dc_get_error(), but locks and unlocks the object. * Like dc_get_error(), but locks and unlocks the object.
*/ */
GError *LockGetError() const { gcc_pure
Error LockGetError() const {
Lock(); Lock();
GError *result = GetError(); Error result = GetError();
Unlock(); Unlock();
return result; 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. * Caller must lock the object.
*/ */
void ClearError() { void ClearError() {
if (state == DECODE_STATE_ERROR) { if (state == DECODE_STATE_ERROR) {
g_error_free(error); error.Clear();
state = DECODE_STATE_STOP; state = DECODE_STATE_STOP;
} }
} }
......
...@@ -17,35 +17,7 @@ ...@@ -17,35 +17,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef MPD_IO_ERROR_H #include "DecoderError.hxx"
#define MPD_IO_ERROR_H #include "util/Domain.hxx"
#include <glib.h> const Domain decoder_domain("decoder");
#include <errno.h>
/**
* 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));
}
#endif
...@@ -20,18 +20,6 @@ ...@@ -20,18 +20,6 @@
#ifndef MPD_DECODER_ERROR_HXX #ifndef MPD_DECODER_ERROR_HXX
#define MPD_DECODER_ERROR_HXX #define MPD_DECODER_ERROR_HXX
#include "gcc.h" extern const class Domain decoder_domain;
#include <glib.h>
/**
* Quark for GError.domain.
*/
gcc_pure
static inline GQuark
decoder_quark(void)
{
return g_quark_from_static_string("decoder");
}
#endif #endif
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "InputStream.hxx" #include "InputStream.hxx"
#include "DecoderList.hxx" #include "DecoderList.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "ApeReplayGain.hxx" #include "ApeReplayGain.hxx"
#include <glib.h> #include <glib.h>
...@@ -72,15 +73,12 @@ decoder_command_finished_locked(struct decoder_control *dc) ...@@ -72,15 +73,12 @@ decoder_command_finished_locked(struct decoder_control *dc)
static struct input_stream * static struct input_stream *
decoder_input_stream_open(struct decoder_control *dc, const char *uri) decoder_input_stream_open(struct decoder_control *dc, const char *uri)
{ {
GError *error = NULL; Error error;
struct input_stream *is;
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 (is == NULL) {
if (error != NULL) { if (error.IsDefined())
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
}
return NULL; return NULL;
} }
...@@ -98,12 +96,10 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri) ...@@ -98,12 +96,10 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri)
input_stream_update(is); input_stream_update(is);
} }
if (!input_stream_check(is, &error)) { if (!input_stream_check(is, error)) {
dc->Unlock(); dc->Unlock();
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return NULL; return NULL;
} }
...@@ -132,7 +128,10 @@ decoder_stream_decode(const struct decoder_plugin *plugin, ...@@ -132,7 +128,10 @@ decoder_stream_decode(const struct decoder_plugin *plugin,
return true; return true;
/* rewind the stream, so each plugin gets a fresh start */ /* 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(); decoder->dc->Unlock();
...@@ -411,8 +410,8 @@ decoder_run_song(struct decoder_control *dc, ...@@ -411,8 +410,8 @@ decoder_run_song(struct decoder_control *dc,
if (allocated != NULL) if (allocated != NULL)
error_uri = allocated; error_uri = allocated;
dc->error = g_error_new(decoder_quark(), 0, dc->error.Format(decoder_domain,
"Failed to decode %s", error_uri); "Failed to decode %s", error_uri);
g_free(allocated); g_free(allocated);
} }
...@@ -436,8 +435,7 @@ decoder_run(struct decoder_control *dc) ...@@ -436,8 +435,7 @@ decoder_run(struct decoder_control *dc)
if (uri == NULL) { if (uri == NULL) {
dc->state = DECODE_STATE_ERROR; dc->state = DECODE_STATE_ERROR;
dc->error = g_error_new(decoder_quark(), 0, dc->error.Set(decoder_domain, "Failed to map song");
"Failed to map song");
decoder_command_finished_locked(dc); decoder_command_finished_locked(dc);
return; return;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "DatabaseLock.hxx" #include "DatabaseLock.hxx"
#include "SongSort.hxx" #include "SongSort.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "util/Error.hxx"
extern "C" { extern "C" {
#include "util/list_sort.h" #include "util/list_sort.h"
...@@ -300,34 +301,34 @@ bool ...@@ -300,34 +301,34 @@ bool
Directory::Walk(bool recursive, const SongFilter *filter, Directory::Walk(bool recursive, const SongFilter *filter,
VisitDirectory visit_directory, VisitSong visit_song, VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist, VisitPlaylist visit_playlist,
GError **error_r) const Error &error) const
{ {
assert(error_r == NULL || *error_r == NULL); assert(!error.IsDefined());
if (visit_song) { if (visit_song) {
Song *song; Song *song;
directory_for_each_song(song, this) directory_for_each_song(song, this)
if ((filter == nullptr || filter->Match(*song)) && if ((filter == nullptr || filter->Match(*song)) &&
!visit_song(*song, error_r)) !visit_song(*song, error))
return false; return false;
} }
if (visit_playlist) { if (visit_playlist) {
for (const PlaylistInfo &p : playlists) for (const PlaylistInfo &p : playlists)
if (!visit_playlist(p, *this, error_r)) if (!visit_playlist(p, *this, error))
return false; return false;
} }
Directory *child; Directory *child;
directory_for_each_child(child, this) { directory_for_each_child(child, this) {
if (visit_directory && if (visit_directory &&
!visit_directory(*child, error_r)) !visit_directory(*child, error))
return false; return false;
if (recursive && if (recursive &&
!child->Walk(recursive, filter, !child->Walk(recursive, filter,
visit_directory, visit_song, visit_playlist, visit_directory, visit_song, visit_playlist,
error_r)) error))
return false; return false;
} }
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "gcc.h" #include "gcc.h"
#include "DatabaseVisitor.hxx" #include "DatabaseVisitor.hxx"
#include "PlaylistVector.hxx" #include "PlaylistVector.hxx"
#include "gerror.h"
#include <sys/types.h> #include <sys/types.h>
...@@ -47,6 +46,7 @@ ...@@ -47,6 +46,7 @@
struct Song; struct Song;
struct db_visitor; struct db_visitor;
class SongFilter; class SongFilter;
class Error;
struct Directory { struct Directory {
/** /**
...@@ -251,7 +251,7 @@ public: ...@@ -251,7 +251,7 @@ public:
bool Walk(bool recursive, const SongFilter *match, bool Walk(bool recursive, const SongFilter *match,
VisitDirectory visit_directory, VisitSong visit_song, VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist, VisitPlaylist visit_playlist,
GError **error_r) const; Error &error) const;
}; };
static inline bool static inline bool
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include "SongSave.hxx" #include "SongSave.hxx"
#include "PlaylistDatabase.hxx" #include "PlaylistDatabase.hxx"
#include "TextFile.hxx" #include "TextFile.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
...@@ -33,14 +35,7 @@ ...@@ -33,14 +35,7 @@
#define DIRECTORY_BEGIN "begin: " #define DIRECTORY_BEGIN "begin: "
#define DIRECTORY_END "end: " #define DIRECTORY_END "end: "
/** static constexpr Domain directory_domain("directory");
* The quark used for GError.domain.
*/
static inline GQuark
directory_quark(void)
{
return g_quark_from_static_string("directory");
}
void void
directory_save(FILE *fp, const Directory *directory) directory_save(FILE *fp, const Directory *directory)
...@@ -77,13 +72,13 @@ directory_save(FILE *fp, const Directory *directory) ...@@ -77,13 +72,13 @@ directory_save(FILE *fp, const Directory *directory)
static Directory * static Directory *
directory_load_subdir(TextFile &file, Directory *parent, const char *name, directory_load_subdir(TextFile &file, Directory *parent, const char *name,
GError **error_r) Error &error)
{ {
bool success; bool success;
if (parent->FindChild(name) != nullptr) { if (parent->FindChild(name) != nullptr) {
g_set_error(error_r, directory_quark(), 0, error.Format(directory_domain,
"Duplicate subdirectory '%s'", name); "Duplicate subdirectory '%s'", name);
return NULL; return NULL;
} }
...@@ -91,8 +86,7 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name, ...@@ -91,8 +86,7 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name,
const char *line = file.ReadLine(); const char *line = file.ReadLine();
if (line == NULL) { if (line == NULL) {
g_set_error(error_r, directory_quark(), 0, error.Set(directory_domain, "Unexpected end of file");
"Unexpected end of file");
directory->Delete(); directory->Delete();
return NULL; return NULL;
} }
...@@ -104,21 +98,19 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name, ...@@ -104,21 +98,19 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name,
line = file.ReadLine(); line = file.ReadLine();
if (line == NULL) { if (line == NULL) {
g_set_error(error_r, directory_quark(), 0, error.Set(directory_domain, "Unexpected end of file");
"Unexpected end of file");
directory->Delete(); directory->Delete();
return NULL; return NULL;
} }
} }
if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) { if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) {
g_set_error(error_r, directory_quark(), 0, error.Format(directory_domain, "Malformed line: %s", line);
"Malformed line: %s", line);
directory->Delete(); directory->Delete();
return NULL; return NULL;
} }
success = directory_load(file, directory, error_r); success = directory_load(file, directory, error);
if (!success) { if (!success) {
directory->Delete(); directory->Delete();
return NULL; return NULL;
...@@ -128,7 +120,7 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name, ...@@ -128,7 +120,7 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name,
} }
bool bool
directory_load(TextFile &file, Directory *directory, GError **error) directory_load(TextFile &file, Directory *directory, Error &error)
{ {
const char *line; const char *line;
...@@ -146,8 +138,8 @@ directory_load(TextFile &file, Directory *directory, GError **error) ...@@ -146,8 +138,8 @@ directory_load(TextFile &file, Directory *directory, GError **error)
Song *song; Song *song;
if (directory->FindSong(name) != nullptr) { if (directory->FindSong(name) != nullptr) {
g_set_error(error, directory_quark(), 0, error.Format(directory_domain,
"Duplicate song '%s'", name); "Duplicate song '%s'", name);
return false; return false;
} }
...@@ -170,8 +162,8 @@ directory_load(TextFile &file, Directory *directory, GError **error) ...@@ -170,8 +162,8 @@ directory_load(TextFile &file, Directory *directory, GError **error)
g_free(name); g_free(name);
} else { } else {
g_set_error(error, directory_quark(), 0, error.Format(directory_domain,
"Malformed line: %s", line); "Malformed line: %s", line);
return false; return false;
} }
} }
......
...@@ -20,17 +20,16 @@ ...@@ -20,17 +20,16 @@
#ifndef MPD_DIRECTORY_SAVE_HXX #ifndef MPD_DIRECTORY_SAVE_HXX
#define MPD_DIRECTORY_SAVE_HXX #define MPD_DIRECTORY_SAVE_HXX
#include "gerror.h"
#include <stdio.h> #include <stdio.h>
struct Directory; struct Directory;
class TextFile; class TextFile;
class Error;
void void
directory_save(FILE *fp, const Directory *directory); directory_save(FILE *fp, const Directory *directory);
bool bool
directory_load(TextFile &file, Directory *directory, GError **error); directory_load(TextFile &file, Directory *directory, Error &error);
#endif #endif
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#ifndef MPD_ENCODER_PLUGIN_HXX #ifndef MPD_ENCODER_PLUGIN_HXX
#define MPD_ENCODER_PLUGIN_HXX #define MPD_ENCODER_PLUGIN_HXX
#include "gerror.h"
#include <assert.h> #include <assert.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
...@@ -30,6 +28,7 @@ struct EncoderPlugin; ...@@ -30,6 +28,7 @@ struct EncoderPlugin;
struct AudioFormat; struct AudioFormat;
struct config_param; struct config_param;
struct Tag; struct Tag;
class Error;
struct Encoder { struct Encoder {
const EncoderPlugin &plugin; const EncoderPlugin &plugin;
...@@ -50,28 +49,28 @@ struct EncoderPlugin { ...@@ -50,28 +49,28 @@ struct EncoderPlugin {
const char *name; const char *name;
Encoder *(*init)(const config_param &param, Encoder *(*init)(const config_param &param,
GError **error); Error &error);
void (*finish)(Encoder *encoder); void (*finish)(Encoder *encoder);
bool (*open)(Encoder *encoder, bool (*open)(Encoder *encoder,
AudioFormat &audio_format, AudioFormat &audio_format,
GError **error); Error &error);
void (*close)(Encoder *encoder); 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, bool (*tag)(Encoder *encoder, const Tag *tag,
GError **error); Error &error);
bool (*write)(Encoder *encoder, bool (*write)(Encoder *encoder,
const void *data, size_t length, const void *data, size_t length,
GError **error); Error &error);
size_t (*read)(Encoder *encoder, void *dest, size_t length); size_t (*read)(Encoder *encoder, void *dest, size_t length);
...@@ -88,7 +87,7 @@ struct EncoderPlugin { ...@@ -88,7 +87,7 @@ struct EncoderPlugin {
*/ */
static inline Encoder * static inline Encoder *
encoder_init(const EncoderPlugin &plugin, const config_param &param, encoder_init(const EncoderPlugin &plugin, const config_param &param,
GError **error_r) Error &error_r)
{ {
return plugin.init(param, error_r); return plugin.init(param, error_r);
} }
...@@ -123,7 +122,7 @@ encoder_finish(Encoder *encoder) ...@@ -123,7 +122,7 @@ encoder_finish(Encoder *encoder)
*/ */
static inline bool static inline bool
encoder_open(Encoder *encoder, AudioFormat &audio_format, encoder_open(Encoder *encoder, AudioFormat &audio_format,
GError **error) Error &error)
{ {
assert(!encoder->open); assert(!encoder->open);
...@@ -168,7 +167,7 @@ encoder_close(Encoder *encoder) ...@@ -168,7 +167,7 @@ encoder_close(Encoder *encoder)
* @return true on success * @return true on success
*/ */
static inline bool static inline bool
encoder_end(Encoder *encoder, GError **error) encoder_end(Encoder *encoder, Error &error)
{ {
assert(encoder->open); assert(encoder->open);
assert(!encoder->end); assert(!encoder->end);
...@@ -192,7 +191,7 @@ encoder_end(Encoder *encoder, GError **error) ...@@ -192,7 +191,7 @@ encoder_end(Encoder *encoder, GError **error)
* @return true on success * @return true on success
*/ */
static inline bool static inline bool
encoder_flush(Encoder *encoder, GError **error) encoder_flush(Encoder *encoder, Error &error)
{ {
assert(encoder->open); assert(encoder->open);
assert(!encoder->pre_tag); assert(!encoder->pre_tag);
...@@ -216,7 +215,7 @@ encoder_flush(Encoder *encoder, GError **error) ...@@ -216,7 +215,7 @@ encoder_flush(Encoder *encoder, GError **error)
* @return true on success * @return true on success
*/ */
static inline bool static inline bool
encoder_pre_tag(Encoder *encoder, GError **error) encoder_pre_tag(Encoder *encoder, Error &error)
{ {
assert(encoder->open); assert(encoder->open);
assert(!encoder->pre_tag); assert(!encoder->pre_tag);
...@@ -246,7 +245,7 @@ encoder_pre_tag(Encoder *encoder, GError **error) ...@@ -246,7 +245,7 @@ encoder_pre_tag(Encoder *encoder, GError **error)
* @return true on success * @return true on success
*/ */
static inline bool 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->open);
assert(!encoder->pre_tag); assert(!encoder->pre_tag);
...@@ -274,7 +273,7 @@ encoder_tag(Encoder *encoder, const Tag *tag, GError **error) ...@@ -274,7 +273,7 @@ encoder_tag(Encoder *encoder, const Tag *tag, GError **error)
*/ */
static inline bool static inline bool
encoder_write(Encoder *encoder, const void *data, size_t length, encoder_write(Encoder *encoder, const void *data, size_t length,
GError **error) Error &error)
{ {
assert(encoder->open); assert(encoder->open);
assert(!encoder->pre_tag); assert(!encoder->pre_tag);
......
...@@ -24,35 +24,31 @@ ...@@ -24,35 +24,31 @@
#include "FilterPlugin.hxx" #include "FilterPlugin.hxx"
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
#include <string.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. * Find the "filter" configuration block for the specified name.
* *
* @param filter_template_name the name of the filter template * @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 * @return the configuration block, or NULL if none was configured
*/ */
static const struct config_param * 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; const struct config_param *param = NULL;
while ((param = config_get_next_param(CONF_AUDIO_FILTER, param)) != NULL) { while ((param = config_get_next_param(CONF_AUDIO_FILTER, param)) != NULL) {
const char *name = param->GetBlockValue("name"); const char *name = param->GetBlockValue("name");
if (name == NULL) { if (name == NULL) {
g_set_error(error_r, filter_quark(), 1, error.Format(config_domain,
"filter configuration without 'name' name in line %d", "filter configuration without 'name' name in line %d",
param->line); param->line);
return NULL; return NULL;
} }
...@@ -60,10 +56,9 @@ filter_plugin_config(const char *filter_template_name, GError **error_r) ...@@ -60,10 +56,9 @@ filter_plugin_config(const char *filter_template_name, GError **error_r)
return param; return param;
} }
g_set_error(error_r, filter_quark(), 1, error.Format(config_domain,
"filter template not found: %s", "filter template not found: %s",
filter_template_name); filter_template_name);
return NULL; return NULL;
} }
...@@ -73,11 +68,11 @@ filter_plugin_config(const char *filter_template_name, GError **error_r) ...@@ -73,11 +68,11 @@ filter_plugin_config(const char *filter_template_name, GError **error_r)
* configured filter sections. * configured filter sections.
* @param chain the chain to append filters on * @param chain the chain to append filters on
* @param spec the filter chain specification * @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 * @return the number of filters which were successfully added
*/ */
unsigned int 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 // Split on comma
...@@ -92,14 +87,14 @@ filter_chain_parse(Filter &chain, const char *spec, GError **error_r) ...@@ -92,14 +87,14 @@ filter_chain_parse(Filter &chain, const char *spec, GError **error_r)
g_strstrip(*template_names); g_strstrip(*template_names);
const struct config_param *cfg = const struct config_param *cfg =
filter_plugin_config(*template_names, error_r); filter_plugin_config(*template_names, error);
if (cfg == NULL) { if (cfg == NULL) {
// The error has already been set, just stop. // The error has already been set, just stop.
break; break;
} }
// Instantiate one of those filter plugins with the template name as a hint // 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) { if (f == NULL) {
// The error has already been set, just stop. // The error has already been set, just stop.
break; break;
......
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
#ifndef MPD_FILTER_CONFIG_HXX #ifndef MPD_FILTER_CONFIG_HXX
#define MPD_FILTER_CONFIG_HXX #define MPD_FILTER_CONFIG_HXX
#include "gerror.h"
class Filter; class Filter;
class Error;
/** /**
* Builds a filter chain from a configuration string on the form * Builds a filter chain from a configuration string on the form
...@@ -39,6 +38,6 @@ class Filter; ...@@ -39,6 +38,6 @@ class Filter;
* @return the number of filters which were successfully added * @return the number of filters which were successfully added
*/ */
unsigned int unsigned int
filter_chain_parse(Filter &chain, const char *spec, GError **error_r); filter_chain_parse(Filter &chain, const char *spec, Error &error);
#endif #endif
...@@ -25,7 +25,10 @@ ...@@ -25,7 +25,10 @@
#ifndef MPD_FILTER_INTERNAL_HXX #ifndef MPD_FILTER_INTERNAL_HXX
#define MPD_FILTER_INTERNAL_HXX #define MPD_FILTER_INTERNAL_HXX
#include <stddef.h>
struct AudioFormat; struct AudioFormat;
class Error;
class Filter { class Filter {
public: public:
...@@ -43,7 +46,7 @@ public: ...@@ -43,7 +46,7 @@ public:
* @return the format of outgoing data or * @return the format of outgoing data or
* AudioFormat::Undefined() on error * 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. * Closes the filter. After that, you may call Open() again.
...@@ -65,7 +68,7 @@ public: ...@@ -65,7 +68,7 @@ public:
*/ */
virtual const void *FilterPCM(const void *src, size_t src_size, virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r) = 0; Error &error) = 0;
}; };
#endif #endif
...@@ -22,40 +22,38 @@ ...@@ -22,40 +22,38 @@
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "conf.h" #include "conf.h"
#include "ConfigQuark.hxx" #include "ConfigError.hxx"
#include "util/Error.hxx"
#include <assert.h> #include <assert.h>
Filter * Filter *
filter_new(const struct filter_plugin *plugin, filter_new(const struct filter_plugin *plugin,
const config_param &param, GError **error_r) const config_param &param, Error &error)
{ {
assert(plugin != NULL); 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 *
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.IsDefined());
assert(error_r == NULL || *error_r == NULL);
const char *plugin_name = param.GetBlockValue("plugin"); const char *plugin_name = param.GetBlockValue("plugin");
if (plugin_name == NULL) { if (plugin_name == NULL) {
g_set_error(error_r, config_quark(), 0, error.Set(config_domain, "No filter plugin specified");
"No filter plugin specified");
return NULL; return NULL;
} }
plugin = filter_plugin_by_name(plugin_name); const filter_plugin *plugin = filter_plugin_by_name(plugin_name);
if (plugin == NULL) { if (plugin == NULL) {
g_set_error(error_r, config_quark(), 0, error.Format(config_domain,
"No such filter plugin: %s", plugin_name); "No such filter plugin: %s", plugin_name);
return NULL; return NULL;
} }
return filter_new(plugin, param, error_r); return filter_new(plugin, param, error);
} }
...@@ -26,12 +26,9 @@ ...@@ -26,12 +26,9 @@
#ifndef MPD_FILTER_PLUGIN_HXX #ifndef MPD_FILTER_PLUGIN_HXX
#define MPD_FILTER_PLUGIN_HXX #define MPD_FILTER_PLUGIN_HXX
#include "gerror.h"
#include <stddef.h>
struct config_param; struct config_param;
class Filter; class Filter;
class Error;
struct filter_plugin { struct filter_plugin {
const char *name; const char *name;
...@@ -39,7 +36,7 @@ struct filter_plugin { ...@@ -39,7 +36,7 @@ struct filter_plugin {
/** /**
* Allocates and configures a filter. * 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 { ...@@ -53,7 +50,7 @@ struct filter_plugin {
*/ */
Filter * Filter *
filter_new(const struct filter_plugin *plugin, 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 * Creates a new filter, loads configuration and the plugin name from
...@@ -65,6 +62,6 @@ filter_new(const struct filter_plugin *plugin, ...@@ -65,6 +62,6 @@ filter_new(const struct filter_plugin *plugin,
* @return a new filter object, or NULL on error * @return a new filter object, or NULL on error
*/ */
Filter * Filter *
filter_configured_new(const config_param &param, GError **error_r); filter_configured_new(const config_param &param, Error &error);
#endif #endif
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include "InotifySource.hxx" #include "InotifySource.hxx"
#include "util/fifo_buffer.h" #include "util/fifo_buffer.h"
#include "util/Error.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
...@@ -32,15 +33,6 @@ ...@@ -32,15 +33,6 @@
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "inotify" #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 bool
InotifySource::OnSocketReady(gcc_unused unsigned flags) InotifySource::OnSocketReady(gcc_unused unsigned flags)
{ {
...@@ -97,13 +89,11 @@ InotifySource::InotifySource(EventLoop &_loop, ...@@ -97,13 +89,11 @@ InotifySource::InotifySource(EventLoop &_loop,
InotifySource * InotifySource *
InotifySource::Create(EventLoop &loop, InotifySource::Create(EventLoop &loop,
mpd_inotify_callback_t callback, void *callback_ctx, mpd_inotify_callback_t callback, void *callback_ctx,
GError **error_r) Error &error)
{ {
int fd = inotify_init_cloexec(); int fd = inotify_init_cloexec();
if (fd < 0) { if (fd < 0) {
g_set_error(error_r, mpd_inotify_quark(), errno, error.SetErrno("inotify_init() has failed");
"inotify_init() has failed: %s",
g_strerror(errno));
return NULL; return NULL;
} }
...@@ -116,13 +106,11 @@ InotifySource::~InotifySource() ...@@ -116,13 +106,11 @@ InotifySource::~InotifySource()
} }
int 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); int wd = inotify_add_watch(Get(), path_fs, mask);
if (wd < 0) if (wd < 0)
g_set_error(error_r, mpd_inotify_quark(), errno, error.SetErrno("inotify_add_watch() has failed");
"inotify_add_watch() has failed: %s",
g_strerror(errno));
return wd; return wd;
} }
......
...@@ -21,9 +21,10 @@ ...@@ -21,9 +21,10 @@
#define MPD_INOTIFY_SOURCE_HXX #define MPD_INOTIFY_SOURCE_HXX
#include "event/SocketMonitor.hxx" #include "event/SocketMonitor.hxx"
#include "gerror.h"
#include "gcc.h" #include "gcc.h"
class Error;
typedef void (*mpd_inotify_callback_t)(int wd, unsigned mask, typedef void (*mpd_inotify_callback_t)(int wd, unsigned mask,
const char *name, void *ctx); const char *name, void *ctx);
...@@ -46,7 +47,7 @@ public: ...@@ -46,7 +47,7 @@ public:
static InotifySource *Create(EventLoop &_loop, static InotifySource *Create(EventLoop &_loop,
mpd_inotify_callback_t callback, mpd_inotify_callback_t callback,
void *ctx, void *ctx,
GError **error_r); Error &error);
~InotifySource(); ~InotifySource();
...@@ -56,7 +57,7 @@ public: ...@@ -56,7 +57,7 @@ public:
* *
* @return a watch descriptor or -1 on error * @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. * Removes a path from the notify list.
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "Mapper.hxx" #include "Mapper.hxx"
#include "Main.hxx" #include "Main.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -162,7 +163,7 @@ static void ...@@ -162,7 +163,7 @@ static void
recursive_watch_subdirectories(WatchDirectory *directory, recursive_watch_subdirectories(WatchDirectory *directory,
const char *path_fs, unsigned depth) const char *path_fs, unsigned depth)
{ {
GError *error = NULL; Error error;
DIR *dir; DIR *dir;
struct dirent *ent; struct dirent *ent;
...@@ -204,12 +205,11 @@ recursive_watch_subdirectories(WatchDirectory *directory, ...@@ -204,12 +205,11 @@ recursive_watch_subdirectories(WatchDirectory *directory,
continue; continue;
} }
ret = inotify_source->Add(child_path_fs, IN_MASK, &error); ret = inotify_source->Add(child_path_fs, IN_MASK, error);
if (ret < 0) { if (ret < 0) {
g_warning("Failed to register %s: %s", g_warning("Failed to register %s: %s",
child_path_fs, error->message); child_path_fs, error.GetMessage());
g_error_free(error); error.Clear();
error = NULL;
g_free(child_path_fs); g_free(child_path_fs);
continue; continue;
} }
...@@ -309,8 +309,6 @@ mpd_inotify_callback(int wd, unsigned mask, ...@@ -309,8 +309,6 @@ mpd_inotify_callback(int wd, unsigned mask,
void void
mpd_inotify_init(unsigned max_depth) mpd_inotify_init(unsigned max_depth)
{ {
GError *error = NULL;
g_debug("initializing inotify"); g_debug("initializing inotify");
const Path &path = mapper_get_music_directory_fs(); const Path &path = mapper_get_music_directory_fs();
...@@ -319,21 +317,20 @@ mpd_inotify_init(unsigned max_depth) ...@@ -319,21 +317,20 @@ mpd_inotify_init(unsigned max_depth)
return; return;
} }
Error error;
inotify_source = InotifySource::Create(*main_loop, inotify_source = InotifySource::Create(*main_loop,
mpd_inotify_callback, nullptr, mpd_inotify_callback, nullptr,
&error); error);
if (inotify_source == NULL) { if (inotify_source == NULL) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return; return;
} }
inotify_max_depth = max_depth; 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) { if (descriptor < 0) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
delete inotify_source; delete inotify_source;
inotify_source = NULL; inotify_source = NULL;
return; return;
......
...@@ -21,16 +21,14 @@ ...@@ -21,16 +21,14 @@
#include "InputInit.hxx" #include "InputInit.hxx"
#include "InputRegistry.hxx" #include "InputRegistry.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "conf.h" #include "conf.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
static inline GQuark extern constexpr Domain input_domain("input");
input_quark(void)
{
return g_quark_from_static_string("input");
}
/** /**
* Find the "input" configuration block for the specified plugin. * Find the "input" configuration block for the specified plugin.
...@@ -39,16 +37,16 @@ input_quark(void) ...@@ -39,16 +37,16 @@ input_quark(void)
* @return the configuration block, or NULL if none was configured * @return the configuration block, or NULL if none was configured
*/ */
static const struct config_param * 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; const struct config_param *param = NULL;
while ((param = config_get_next_param(CONF_INPUT, param)) != NULL) { while ((param = config_get_next_param(CONF_INPUT, param)) != NULL) {
const char *name = param->GetBlockValue("plugin"); const char *name = param->GetBlockValue("plugin");
if (name == NULL) { if (name == NULL) {
g_set_error(error_r, input_quark(), 0, error.Format(input_domain,
"input configuration without 'plugin' name in line %d", "input configuration without 'plugin' name in line %d",
param->line); param->line);
return NULL; return NULL;
} }
...@@ -60,12 +58,10 @@ input_plugin_config(const char *plugin_name, GError **error_r) ...@@ -60,12 +58,10 @@ input_plugin_config(const char *plugin_name, GError **error_r)
} }
bool bool
input_stream_global_init(GError **error_r) input_stream_global_init(Error &error)
{ {
const config_param empty; const config_param empty;
GError *error = NULL;
for (unsigned i = 0; input_plugins[i] != NULL; ++i) { for (unsigned i = 0; input_plugins[i] != NULL; ++i) {
const struct input_plugin *plugin = input_plugins[i]; const struct input_plugin *plugin = input_plugins[i];
...@@ -74,24 +70,21 @@ input_stream_global_init(GError **error_r) ...@@ -74,24 +70,21 @@ input_stream_global_init(GError **error_r)
assert(plugin->open != NULL); assert(plugin->open != NULL);
const struct config_param *param = const struct config_param *param =
input_plugin_config(plugin->name, &error); input_plugin_config(plugin->name, error);
if (param == nullptr) { if (param == nullptr) {
if (error != nullptr) { if (error.IsDefined())
g_propagate_error(error_r, error);
return false; return false;
}
param = &empty; param = &empty;
} else if (!param->GetBlockValue("enabled", true)) } else if (!param->GetBlockValue("enabled", true))
/* the plugin is disabled in mpd.conf */ /* the plugin is disabled in mpd.conf */
continue; continue;
if (plugin->init == NULL || plugin->init(*param, &error)) if (plugin->init == NULL || plugin->init(*param, error))
input_plugins_enabled[i] = true; input_plugins_enabled[i] = true;
else { else {
g_propagate_prefixed_error(error_r, error, error.FormatPrefix("Failed to initialize input plugin '%s': ",
"Failed to initialize input plugin '%s': ", plugin->name);
plugin->name);
return false; return false;
} }
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#ifndef MPD_INPUT_INIT_HXX #ifndef MPD_INPUT_INIT_HXX
#define MPD_INPUT_INIT_HXX #define MPD_INPUT_INIT_HXX
#include "gerror.h" class Error;
/** /**
* Initializes this library and all input_stream implementations. * Initializes this library and all input_stream implementations.
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* ignore errors * ignore errors
*/ */
bool bool
input_stream_global_init(GError **error_r); input_stream_global_init(Error &error);
/** /**
* Deinitializes this library and all input_stream implementations. * Deinitializes this library and all input_stream implementations.
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
struct Tag; struct Tag;
struct input_stream; struct input_stream;
class Error;
/** /**
* Opens a new input stream. You may not access it until the "ready" * Opens a new input stream. You may not access it until the "ready"
...@@ -48,7 +49,7 @@ gcc_malloc ...@@ -48,7 +49,7 @@ gcc_malloc
struct input_stream * struct input_stream *
input_stream_open(const char *uri, input_stream_open(const char *uri,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r); Error &error);
/** /**
* Close the input stream and free resources. * Close the input stream and free resources.
...@@ -66,7 +67,7 @@ input_stream_close(struct input_stream *is); ...@@ -66,7 +67,7 @@ input_stream_close(struct input_stream *is);
*/ */
gcc_nonnull(1) gcc_nonnull(1)
bool 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 * Update the public attributes. Call before accessing attributes
...@@ -133,7 +134,7 @@ input_stream_cheap_seeking(const struct input_stream *is); ...@@ -133,7 +134,7 @@ input_stream_cheap_seeking(const struct input_stream *is);
gcc_nonnull(1) gcc_nonnull(1)
bool bool
input_stream_seek(struct input_stream *is, goffset offset, int whence, 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 * 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, ...@@ -142,7 +143,7 @@ input_stream_seek(struct input_stream *is, goffset offset, int whence,
gcc_nonnull(1) gcc_nonnull(1)
bool bool
input_stream_lock_seek(struct input_stream *is, goffset offset, int whence, 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. * Returns true if the stream has reached end-of-file.
...@@ -210,7 +211,7 @@ input_stream_available(struct input_stream *is); ...@@ -210,7 +211,7 @@ input_stream_available(struct input_stream *is);
gcc_nonnull(1, 2) gcc_nonnull(1, 2)
size_t size_t
input_stream_read(struct input_stream *is, void *ptr, size_t size, 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 * 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, ...@@ -219,6 +220,6 @@ input_stream_read(struct input_stream *is, void *ptr, size_t size,
gcc_nonnull(1, 2) gcc_nonnull(1, 2)
size_t size_t
input_stream_lock_read(struct input_stream *is, void *ptr, size_t size, input_stream_lock_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r); Error &error);
#endif #endif
...@@ -23,10 +23,10 @@ ...@@ -23,10 +23,10 @@
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include <stddef.h> #include <stddef.h>
#include <sys/types.h>
struct config_param; struct config_param;
struct input_stream; struct input_stream;
class Error;
struct input_plugin { struct input_plugin {
const char *name; const char *name;
...@@ -39,7 +39,7 @@ struct input_plugin { ...@@ -39,7 +39,7 @@ struct input_plugin {
* @return true on success, false if the plugin should be * @return true on success, false if the plugin should be
* disabled * 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 * Global deinitialization. Called once before MPD shuts
...@@ -49,7 +49,7 @@ struct input_plugin { ...@@ -49,7 +49,7 @@ struct input_plugin {
struct input_stream *(*open)(const char *uri, struct input_stream *(*open)(const char *uri,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r); Error &error);
void (*close)(struct input_stream *is); void (*close)(struct input_stream *is);
/** /**
...@@ -58,7 +58,7 @@ struct input_plugin { ...@@ -58,7 +58,7 @@ struct input_plugin {
* *
* @return false on error * @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 * Update the public attributes. Call before access. Can be
...@@ -79,10 +79,10 @@ struct input_plugin { ...@@ -79,10 +79,10 @@ struct input_plugin {
bool (*available)(struct input_stream *is); bool (*available)(struct input_stream *is);
size_t (*read)(struct input_stream *is, void *ptr, size_t size, size_t (*read)(struct input_stream *is, void *ptr, size_t size,
GError **error_r); Error &error);
bool (*eof)(struct input_stream *is); bool (*eof)(struct input_stream *is);
bool (*seek)(struct input_stream *is, goffset offset, int whence, bool (*seek)(struct input_stream *is, goffset offset, int whence,
GError **error_r); Error &error);
}; };
#endif #endif
...@@ -23,29 +23,22 @@ ...@@ -23,29 +23,22 @@
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "input/RewindInputPlugin.hxx" #include "input/RewindInputPlugin.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h>
#include <assert.h> #include <assert.h>
static inline GQuark static constexpr Domain input_domain("input");
input_quark(void)
{
return g_quark_from_static_string("input");
}
struct input_stream * struct input_stream *
input_stream_open(const char *url, input_stream_open(const char *url,
Mutex &mutex, Cond &cond, 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) { input_plugins_for_each_enabled(plugin) {
struct input_stream *is; struct input_stream *is;
is = plugin->open(url, mutex, cond, &error); is = plugin->open(url, mutex, cond, error);
if (is != NULL) { if (is != NULL) {
assert(is->plugin.close != NULL); assert(is->plugin.close != NULL);
assert(is->plugin.read != NULL); assert(is->plugin.read != NULL);
...@@ -55,23 +48,21 @@ input_stream_open(const char *url, ...@@ -55,23 +48,21 @@ input_stream_open(const char *url,
is = input_rewind_open(is); is = input_rewind_open(is);
return is; return is;
} else if (error != NULL) { } else if (error.IsDefined())
g_propagate_error(error_r, error);
return NULL; return NULL;
}
} }
g_set_error(error_r, input_quark(), 0, "Unrecognized URI"); error.Set(input_domain, "Unrecognized URI");
return NULL; return NULL;
} }
bool bool
input_stream_check(struct input_stream *is, GError **error_r) input_stream_check(struct input_stream *is, Error &error)
{ {
assert(is != NULL); assert(is != NULL);
return is->plugin.check == NULL || return is->plugin.check == NULL ||
is->plugin.check(is, error_r); is->plugin.check(is, error);
} }
void void
...@@ -159,19 +150,19 @@ input_stream_cheap_seeking(const struct input_stream *is) ...@@ -159,19 +150,19 @@ input_stream_cheap_seeking(const struct input_stream *is)
bool bool
input_stream_seek(struct input_stream *is, goffset offset, int whence, input_stream_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r) Error &error)
{ {
assert(is != NULL); assert(is != NULL);
if (is->plugin.seek == NULL) if (is->plugin.seek == NULL)
return false; return false;
return is->plugin.seek(is, offset, whence, error_r); return is->plugin.seek(is, offset, whence, error);
} }
bool bool
input_stream_lock_seek(struct input_stream *is, goffset offset, int whence, input_stream_lock_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r) Error &error)
{ {
assert(is != NULL); assert(is != NULL);
...@@ -179,7 +170,7 @@ input_stream_lock_seek(struct input_stream *is, goffset offset, int whence, ...@@ -179,7 +170,7 @@ input_stream_lock_seek(struct input_stream *is, goffset offset, int whence,
return false; return false;
const ScopeLock protect(is->mutex); const ScopeLock protect(is->mutex);
return input_stream_seek(is, offset, whence, error_r); return input_stream_seek(is, offset, whence, error);
} }
Tag * Tag *
...@@ -216,23 +207,23 @@ input_stream_available(struct input_stream *is) ...@@ -216,23 +207,23 @@ input_stream_available(struct input_stream *is)
size_t size_t
input_stream_read(struct input_stream *is, void *ptr, size_t size, input_stream_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r) Error &error)
{ {
assert(ptr != NULL); assert(ptr != NULL);
assert(size > 0); assert(size > 0);
return is->plugin.read(is, ptr, size, error_r); return is->plugin.read(is, ptr, size, error);
} }
size_t size_t
input_stream_lock_read(struct input_stream *is, void *ptr, size_t size, input_stream_lock_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r) Error &error)
{ {
assert(ptr != NULL); assert(ptr != NULL);
assert(size > 0); assert(size > 0);
const ScopeLock protect(is->mutex); 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) void input_stream_close(struct input_stream *is)
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "Client.hxx" #include "Client.hxx"
#include "conf.h" #include "conf.h"
#include "event/ServerSocket.hxx" #include "event/ServerSocket.hxx"
#include "util/Error.hxx"
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
...@@ -55,7 +56,7 @@ int listen_port; ...@@ -55,7 +56,7 @@ int listen_port;
static bool static bool
listen_add_config_param(unsigned int port, listen_add_config_param(unsigned int port,
const struct config_param *param, const struct config_param *param,
GError **error_r) Error &error_r)
{ {
assert(param != NULL); assert(param != NULL);
...@@ -69,7 +70,7 @@ listen_add_config_param(unsigned int port, ...@@ -69,7 +70,7 @@ listen_add_config_param(unsigned int port,
} }
static bool static bool
listen_systemd_activation(GError **error_r) listen_systemd_activation(Error &error_r)
{ {
#ifdef ENABLE_SYSTEMD_DAEMON #ifdef ENABLE_SYSTEMD_DAEMON
int n = sd_listen_fds(true); int n = sd_listen_fds(true);
...@@ -93,7 +94,7 @@ listen_systemd_activation(GError **error_r) ...@@ -93,7 +94,7 @@ listen_systemd_activation(GError **error_r)
} }
bool bool
listen_global_init(GError **error_r) listen_global_init(Error &error)
{ {
assert(main_loop != nullptr); assert(main_loop != nullptr);
...@@ -101,29 +102,24 @@ listen_global_init(GError **error_r) ...@@ -101,29 +102,24 @@ listen_global_init(GError **error_r)
const struct config_param *param = const struct config_param *param =
config_get_next_param(CONF_BIND_TO_ADDRESS, NULL); config_get_next_param(CONF_BIND_TO_ADDRESS, NULL);
bool success; bool success;
GError *error = NULL;
listen_socket = new ClientListener(); listen_socket = new ClientListener();
if (listen_systemd_activation(&error)) if (listen_systemd_activation(error))
return true; return true;
if (error != NULL) { if (error.IsDefined())
g_propagate_error(error_r, error);
return false; return false;
}
if (param != NULL) { if (param != NULL) {
/* "bind_to_address" is configured, create listeners /* "bind_to_address" is configured, create listeners
for all values */ for all values */
do { do {
success = listen_add_config_param(port, param, &error); if (!listen_add_config_param(port, param, error)) {
if (!success) {
delete listen_socket; delete listen_socket;
g_propagate_prefixed_error(error_r, error, error.FormatPrefix("Failed to listen on %s (line %i): ",
"Failed to listen on %s (line %i): ", param->value, param->line);
param->value, param->line);
return false; return false;
} }
...@@ -134,17 +130,15 @@ listen_global_init(GError **error_r) ...@@ -134,17 +130,15 @@ listen_global_init(GError **error_r)
/* no "bind_to_address" configured, bind the /* no "bind_to_address" configured, bind the
configured port on all interfaces */ configured port on all interfaces */
success = listen_socket->AddPort(port, error_r); success = listen_socket->AddPort(port, error);
if (!success) { if (!success) {
delete listen_socket; delete listen_socket;
g_propagate_prefixed_error(error_r, error, error.FormatPrefix("Failed to listen on *:%d: ", port);
"Failed to listen on *:%d: ",
port);
return false; return false;
} }
} }
if (!listen_socket->Open(error_r)) { if (!listen_socket->Open(error)) {
delete listen_socket; delete listen_socket;
return false; return false;
} }
......
...@@ -20,12 +20,12 @@ ...@@ -20,12 +20,12 @@
#ifndef MPD_LISTEN_HXX #ifndef MPD_LISTEN_HXX
#define MPD_LISTEN_HXX #define MPD_LISTEN_HXX
#include "gerror.h" class Error;
extern int listen_port; extern int listen_port;
bool bool
listen_global_init(GError **error_r); listen_global_init(Error &error);
void listen_global_finish(void); void listen_global_finish(void);
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "mpd_error.h" #include "mpd_error.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h> #include <assert.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -51,6 +53,8 @@ ...@@ -51,6 +53,8 @@
#define LOG_DATE_BUF_SIZE 16 #define LOG_DATE_BUF_SIZE 16
#define LOG_DATE_LEN (LOG_DATE_BUF_SIZE - 1) #define LOG_DATE_LEN (LOG_DATE_BUF_SIZE - 1)
static constexpr Domain log_domain("log");
static GLogLevelFlags log_threshold = G_LOG_LEVEL_MESSAGE; static GLogLevelFlags log_threshold = G_LOG_LEVEL_MESSAGE;
static const char *log_charset; static const char *log_charset;
...@@ -92,7 +96,7 @@ chomp_length(const char *p) ...@@ -92,7 +96,7 @@ chomp_length(const char *p)
} }
static void static void
file_log_func(const gchar *log_domain, file_log_func(const gchar *domain,
GLogLevelFlags log_level, GLogLevelFlags log_level,
const gchar *message, gcc_unused gpointer user_data) const gchar *message, gcc_unused gpointer user_data)
{ {
...@@ -110,12 +114,12 @@ file_log_func(const gchar *log_domain, ...@@ -110,12 +114,12 @@ file_log_func(const gchar *log_domain,
} else } else
converted = NULL; converted = NULL;
if (log_domain == NULL) if (domain == nullptr)
log_domain = ""; domain = "";
fprintf(stderr, "%s%s%s%.*s\n", fprintf(stderr, "%s%s%s%.*s\n",
stdout_mode ? "" : log_date(), stdout_mode ? "" : log_date(),
log_domain, *log_domain == 0 ? "" : ": ", domain, *domain == 0 ? "" : ": ",
chomp_length(message), message); chomp_length(message), message);
g_free(converted); g_free(converted);
...@@ -136,16 +140,15 @@ open_log_file(void) ...@@ -136,16 +140,15 @@ open_log_file(void)
} }
static bool static bool
log_init_file(unsigned line, GError **error_r) log_init_file(unsigned line, Error &error)
{ {
assert(!out_path.IsNull()); assert(!out_path.IsNull());
out_fd = open_log_file(); out_fd = open_log_file();
if (out_fd < 0) { if (out_fd < 0) {
const std::string out_path_utf8 = out_path.ToUTF8(); const std::string out_path_utf8 = out_path.ToUTF8();
g_set_error(error_r, log_quark(), errno, error.FormatErrno("failed to open log file \"%s\" (config line %u)",
"failed to open log file \"%s\" (config line %u): %s", out_path_utf8.c_str(), line);
out_path_utf8.c_str(), line, g_strerror(errno));
return false; return false;
} }
...@@ -181,14 +184,14 @@ glib_to_syslog_level(GLogLevelFlags log_level) ...@@ -181,14 +184,14 @@ glib_to_syslog_level(GLogLevelFlags log_level)
} }
static void static void
syslog_log_func(const gchar *log_domain, syslog_log_func(const gchar *domain,
GLogLevelFlags log_level, const gchar *message, GLogLevelFlags log_level, const gchar *message,
gcc_unused gpointer user_data) gcc_unused gpointer user_data)
{ {
if (stdout_mode) { if (stdout_mode) {
/* fall back to the file log function during /* fall back to the file log function during
startup */ startup */
file_log_func(log_domain, log_level, file_log_func(domain, log_level,
message, user_data); message, user_data);
return; return;
} }
...@@ -196,11 +199,11 @@ syslog_log_func(const gchar *log_domain, ...@@ -196,11 +199,11 @@ syslog_log_func(const gchar *log_domain,
if (log_level > log_threshold) if (log_level > log_threshold)
return; return;
if (log_domain == NULL) if (domain == nullptr)
log_domain = ""; domain = "";
syslog(glib_to_syslog_level(log_level), "%s%s%.*s", syslog(glib_to_syslog_level(log_level), "%s%s%.*s",
log_domain, *log_domain == 0 ? "" : ": ", domain, *domain == 0 ? "" : ": ",
chomp_length(message), message); chomp_length(message), message);
} }
...@@ -241,7 +244,7 @@ log_early_init(bool verbose) ...@@ -241,7 +244,7 @@ log_early_init(bool verbose)
} }
bool 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; const struct config_param *param;
...@@ -264,8 +267,8 @@ log_init(bool verbose, bool use_stdout, GError **error_r) ...@@ -264,8 +267,8 @@ log_init(bool verbose, bool use_stdout, GError **error_r)
log_init_syslog(); log_init_syslog();
return true; return true;
#else #else
g_set_error(error_r, log_quark(), 0, error.Set(log_domain,
"config parameter 'log_file' not found"); "config parameter 'log_file' not found");
return false; return false;
#endif #endif
#ifdef HAVE_SYSLOG #ifdef HAVE_SYSLOG
...@@ -274,9 +277,9 @@ log_init(bool verbose, bool use_stdout, GError **error_r) ...@@ -274,9 +277,9 @@ log_init(bool verbose, bool use_stdout, GError **error_r)
return true; return true;
#endif #endif
} else { } else {
out_path = config_get_path(CONF_LOG_FILE, error_r); out_path = config_get_path(CONF_LOG_FILE, error);
return !out_path.IsNull() && return !out_path.IsNull() &&
log_init_file(param->line, error_r); log_init_file(param->line, error);
} }
} }
} }
......
...@@ -20,16 +20,7 @@ ...@@ -20,16 +20,7 @@
#ifndef MPD_LOG_HXX #ifndef MPD_LOG_HXX
#define MPD_LOG_HXX #define MPD_LOG_HXX
#include "gcc.h" class Error;
#include <glib.h>
gcc_const
static inline GQuark
log_quark(void)
{
return g_quark_from_static_string("log");
}
/** /**
* Configure a logging destination for daemon startup, before the * Configure a logging destination for daemon startup, before the
...@@ -43,7 +34,7 @@ void ...@@ -43,7 +34,7 @@ void
log_early_init(bool verbose); log_early_init(bool verbose);
bool bool
log_init(bool verbose, bool use_stdout, GError **error_r); log_init(bool verbose, bool use_stdout, Error &error);
void void
log_deinit(void); log_deinit(void);
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include "pcm/PcmResample.hxx" #include "pcm/PcmResample.hxx"
#include "Daemon.hxx" #include "Daemon.hxx"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
#include "util/Error.hxx"
extern "C" { extern "C" {
#include "stats.h" #include "stats.h"
...@@ -107,15 +108,11 @@ static inline GQuark main_quark() ...@@ -107,15 +108,11 @@ static inline GQuark main_quark()
} }
static bool 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.IsDefined())
Path pid_file = config_get_path(CONF_PID_FILE, &error);
if (pid_file.IsNull() && error != NULL) {
g_propagate_error(error_r, error);
return false; return false;
}
daemonize_init(config_get_string(CONF_USER, NULL), daemonize_init(config_get_string(CONF_USER, NULL),
config_get_string(CONF_GROUP, NULL), config_get_string(CONF_GROUP, NULL),
...@@ -128,20 +125,15 @@ glue_daemonize_init(const struct options *options, GError **error_r) ...@@ -128,20 +125,15 @@ glue_daemonize_init(const struct options *options, GError **error_r)
} }
static bool 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);
Path music_dir = config_get_path(CONF_MUSIC_DIR, &error); if (music_dir.IsNull() && error.IsDefined())
if (music_dir.IsNull() && error != NULL) {
g_propagate_error(error_r, error);
return false; return false;
}
Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, &error); Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, error);
if (playlist_dir.IsNull() && error != NULL) { if (playlist_dir.IsNull() && error.IsDefined())
g_propagate_error(error_r, error);
return false; return false;
}
if (music_dir.IsNull()) if (music_dir.IsNull())
music_dir = Path::FromUTF8(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC)); music_dir = Path::FromUTF8(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC));
...@@ -164,9 +156,6 @@ glue_db_init_and_load(void) ...@@ -164,9 +156,6 @@ glue_db_init_and_load(void)
if (param != NULL && path != NULL) if (param != NULL && path != NULL)
g_message("Found both 'database' and 'db_file' setting - ignoring the latter"); g_message("Found both 'database' and 'db_file' setting - ignoring the latter");
GError *error = NULL;
bool ret;
if (!mapper_has_music_directory()) { if (!mapper_has_music_directory()) {
if (param != NULL) if (param != NULL)
g_message("Found database setting without " g_message("Found database setting without "
...@@ -185,13 +174,13 @@ glue_db_init_and_load(void) ...@@ -185,13 +174,13 @@ glue_db_init_and_load(void)
param = allocated; param = allocated;
} }
if (!DatabaseGlobalInit(*param, &error)) Error error;
if (!DatabaseGlobalInit(*param, error))
FatalError(error); FatalError(error);
delete allocated; delete allocated;
ret = DatabaseGlobalOpen(&error); if (!DatabaseGlobalOpen(error))
if (!ret)
FatalError(error); FatalError(error);
/* run database update after daemonization? */ /* run database update after daemonization? */
...@@ -205,36 +194,22 @@ static void ...@@ -205,36 +194,22 @@ static void
glue_sticker_init(void) glue_sticker_init(void)
{ {
#ifdef ENABLE_SQLITE #ifdef ENABLE_SQLITE
GError *error = NULL; Error error;
Path sticker_file = config_get_path(CONF_STICKER_FILE, &error); Path sticker_file = config_get_path(CONF_STICKER_FILE, error);
if (sticker_file.IsNull() && error != NULL) if (sticker_file.IsNull() && error.IsDefined())
FatalError(error); FatalError(error);
if (!sticker_global_init(std::move(sticker_file), &error)) if (!sticker_global_init(std::move(sticker_file), error))
FatalError(error); FatalError(error);
#endif #endif
} }
static bool 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())
Path path_fs = config_get_path(CONF_STATE_FILE, &error); return !error.IsDefined();
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;
}
state_file = new StateFile(std::move(path_fs), state_file = new StateFile(std::move(path_fs),
*instance->partition, *main_loop); *instance->partition, *main_loop);
...@@ -364,7 +339,7 @@ int mpd_main(int argc, char *argv[]) ...@@ -364,7 +339,7 @@ int mpd_main(int argc, char *argv[])
struct options options; struct options options;
clock_t start; clock_t start;
bool create_db; bool create_db;
GError *error = NULL; Error error;
bool success; bool success;
daemonize_close_stdin(); daemonize_close_stdin();
...@@ -385,25 +360,22 @@ int mpd_main(int argc, char *argv[]) ...@@ -385,25 +360,22 @@ int mpd_main(int argc, char *argv[])
winsock_init(); winsock_init();
config_global_init(); config_global_init();
success = parse_cmdline(argc, argv, &options, &error); success = parse_cmdline(argc, argv, &options, error);
if (!success) { if (!success) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!glue_daemonize_init(&options, &error)) { if (!glue_daemonize_init(&options, error)) {
g_warning("%s", error->message); g_printerr("%s\n", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
stats_global_init(); stats_global_init();
tag_lib_init(); tag_lib_init();
if (!log_init(options.verbose, options.log_stderr, &error)) { if (!log_init(options.verbose, options.log_stderr, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -415,10 +387,9 @@ int mpd_main(int argc, char *argv[]) ...@@ -415,10 +387,9 @@ int mpd_main(int argc, char *argv[])
const unsigned max_clients = config_get_positive(CONF_MAX_CONN, 10); const unsigned max_clients = config_get_positive(CONF_MAX_CONN, 10);
instance->client_list = new ClientList(max_clients); instance->client_list = new ClientList(max_clients);
success = listen_global_init(&error); success = listen_global_init(error);
if (!success) { if (!success) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -432,9 +403,8 @@ int mpd_main(int argc, char *argv[]) ...@@ -432,9 +403,8 @@ int mpd_main(int argc, char *argv[])
Path::GlobalInit(); Path::GlobalInit();
if (!glue_mapper_init(&error)) { if (!glue_mapper_init(error)) {
g_warning("%s", error->message); g_printerr("%s\n", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -445,9 +415,8 @@ int mpd_main(int argc, char *argv[]) ...@@ -445,9 +415,8 @@ int mpd_main(int argc, char *argv[])
archive_plugin_init_all(); archive_plugin_init_all();
#endif #endif
if (!pcm_resample_global_init(&error)) { if (!pcm_resample_global_init(error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -466,9 +435,8 @@ int mpd_main(int argc, char *argv[]) ...@@ -466,9 +435,8 @@ int mpd_main(int argc, char *argv[])
client_manager_init(); client_manager_init();
replay_gain_global_init(); replay_gain_global_init();
if (!input_stream_global_init(&error)) { if (!input_stream_global_init(error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -494,9 +462,8 @@ int mpd_main(int argc, char *argv[]) ...@@ -494,9 +462,8 @@ int mpd_main(int argc, char *argv[])
FatalError("directory update failed"); FatalError("directory update failed");
} }
if (!glue_state_file_init(&error)) { if (!glue_state_file_init(error)) {
g_warning("%s", error->message); g_printerr("%s\n", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#define MPD_MAPPER_HXX #define MPD_MAPPER_HXX
#include "gcc.h" #include "gcc.h"
#include "gerror.h"
#define PLAYLIST_FILE_SUFFIX ".m3u" #define PLAYLIST_FILE_SUFFIX ".m3u"
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "OutputAll.hxx" #include "OutputAll.hxx"
#include "pcm/PcmVolume.hxx" #include "pcm/PcmVolume.hxx"
#include "OutputInternal.hxx" #include "OutputInternal.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -38,7 +39,6 @@ output_mixer_get_volume(unsigned i) ...@@ -38,7 +39,6 @@ output_mixer_get_volume(unsigned i)
{ {
struct audio_output *output; struct audio_output *output;
int volume; int volume;
GError *error = NULL;
assert(i < audio_output_count()); assert(i < audio_output_count());
...@@ -50,12 +50,11 @@ output_mixer_get_volume(unsigned i) ...@@ -50,12 +50,11 @@ output_mixer_get_volume(unsigned i)
if (mixer == NULL) if (mixer == NULL)
return -1; return -1;
volume = mixer_get_volume(mixer, &error); Error error;
if (volume < 0 && error != NULL) { volume = mixer_get_volume(mixer, error);
if (volume < 0 && error.IsDefined())
g_warning("Failed to read mixer for '%s': %s", g_warning("Failed to read mixer for '%s': %s",
output->name, error->message); output->name, error.GetMessage());
g_error_free(error);
}
return volume; return volume;
} }
...@@ -85,7 +84,6 @@ output_mixer_set_volume(unsigned i, unsigned volume) ...@@ -85,7 +84,6 @@ output_mixer_set_volume(unsigned i, unsigned volume)
{ {
struct audio_output *output; struct audio_output *output;
bool success; bool success;
GError *error = NULL;
assert(i < audio_output_count()); assert(i < audio_output_count());
assert(volume <= 100); assert(volume <= 100);
...@@ -98,12 +96,11 @@ output_mixer_set_volume(unsigned i, unsigned volume) ...@@ -98,12 +96,11 @@ output_mixer_set_volume(unsigned i, unsigned volume)
if (mixer == NULL) if (mixer == NULL)
return false; return false;
success = mixer_set_volume(mixer, volume, &error); Error error;
if (!success && error != NULL) { success = mixer_set_volume(mixer, volume, error);
if (!success && error.IsDefined())
g_warning("Failed to set mixer for '%s': %s", g_warning("Failed to set mixer for '%s': %s",
output->name, error->message); output->name, error.GetMessage());
g_error_free(error);
}
return success; return success;
} }
...@@ -138,7 +135,7 @@ output_mixer_get_software_volume(unsigned i) ...@@ -138,7 +135,7 @@ output_mixer_get_software_volume(unsigned i)
if (mixer == NULL || !mixer->IsPlugin(software_mixer_plugin)) if (mixer == NULL || !mixer->IsPlugin(software_mixer_plugin))
return -1; return -1;
return mixer_get_volume(mixer, NULL); return mixer_get_volume(mixer, IgnoreError());
} }
int int
...@@ -172,6 +169,6 @@ mixer_all_set_software_volume(unsigned volume) ...@@ -172,6 +169,6 @@ mixer_all_set_software_volume(unsigned volume)
struct audio_output *output = audio_output_get(i); struct audio_output *output = audio_output_get(i);
if (output->mixer != NULL && if (output->mixer != NULL &&
output->mixer->plugin == &software_mixer_plugin) output->mixer->plugin == &software_mixer_plugin)
mixer_set_volume(output->mixer, volume, NULL); mixer_set_volume(output->mixer, volume, IgnoreError());
} }
} }
...@@ -20,8 +20,7 @@ ...@@ -20,8 +20,7 @@
#include "config.h" #include "config.h"
#include "MixerControl.hxx" #include "MixerControl.hxx"
#include "MixerInternal.hxx" #include "MixerInternal.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <assert.h> #include <assert.h>
#include <stddef.h> #include <stddef.h>
...@@ -32,13 +31,13 @@ ...@@ -32,13 +31,13 @@
Mixer * Mixer *
mixer_new(const struct mixer_plugin *plugin, void *ao, mixer_new(const struct mixer_plugin *plugin, void *ao,
const config_param &param, const config_param &param,
GError **error_r) Error &error)
{ {
Mixer *mixer; Mixer *mixer;
assert(plugin != NULL); assert(plugin != NULL);
mixer = plugin->init(ao, param, error_r); mixer = plugin->init(ao, param, error);
assert(mixer == NULL || mixer->IsPlugin(*plugin)); assert(mixer == NULL || mixer->IsPlugin(*plugin));
...@@ -59,7 +58,7 @@ mixer_free(Mixer *mixer) ...@@ -59,7 +58,7 @@ mixer_free(Mixer *mixer)
} }
bool bool
mixer_open(Mixer *mixer, GError **error_r) mixer_open(Mixer *mixer, Error &error)
{ {
bool success; bool success;
...@@ -73,7 +72,7 @@ mixer_open(Mixer *mixer, GError **error_r) ...@@ -73,7 +72,7 @@ mixer_open(Mixer *mixer, GError **error_r)
else if (mixer->plugin->open == NULL) else if (mixer->plugin->open == NULL)
success = mixer->open = true; success = mixer->open = true;
else else
success = mixer->open = mixer->plugin->open(mixer, error_r); success = mixer->open = mixer->plugin->open(mixer, error);
mixer->failed = !success; mixer->failed = !success;
...@@ -127,26 +126,22 @@ mixer_failed(Mixer *mixer) ...@@ -127,26 +126,22 @@ mixer_failed(Mixer *mixer)
} }
int int
mixer_get_volume(Mixer *mixer, GError **error_r) mixer_get_volume(Mixer *mixer, Error &error)
{ {
int volume; int volume;
assert(mixer != NULL); assert(mixer != NULL);
if (mixer->plugin->global && !mixer->failed && if (mixer->plugin->global && !mixer->failed &&
!mixer_open(mixer, error_r)) !mixer_open(mixer, error))
return -1; return -1;
const ScopeLock protect(mixer->mutex); const ScopeLock protect(mixer->mutex);
if (mixer->open) { if (mixer->open) {
GError *error = NULL; volume = mixer->plugin->get_volume(mixer, error);
if (volume < 0 && error.IsDefined())
volume = mixer->plugin->get_volume(mixer, &error);
if (volume < 0 && error != NULL) {
g_propagate_error(error_r, error);
mixer_failed(mixer); mixer_failed(mixer);
}
} else } else
volume = -1; volume = -1;
...@@ -154,17 +149,17 @@ mixer_get_volume(Mixer *mixer, GError **error_r) ...@@ -154,17 +149,17 @@ mixer_get_volume(Mixer *mixer, GError **error_r)
} }
bool bool
mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) mixer_set_volume(Mixer *mixer, unsigned volume, Error &error)
{ {
assert(mixer != NULL); assert(mixer != NULL);
assert(volume <= 100); assert(volume <= 100);
if (mixer->plugin->global && !mixer->failed && if (mixer->plugin->global && !mixer->failed &&
!mixer_open(mixer, error_r)) !mixer_open(mixer, error))
return false; return false;
const ScopeLock protect(mixer->mutex); const ScopeLock protect(mixer->mutex);
return mixer->open && return mixer->open &&
mixer->plugin->set_volume(mixer, volume, error_r); mixer->plugin->set_volume(mixer, volume, error);
} }
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
#ifndef MPD_MIXER_CONTROL_HXX #ifndef MPD_MIXER_CONTROL_HXX
#define MPD_MIXER_CONTROL_HXX #define MPD_MIXER_CONTROL_HXX
#include "gerror.h" class Error;
class Mixer; class Mixer;
struct mixer_plugin; struct mixer_plugin;
struct config_param; struct config_param;
...@@ -34,13 +33,13 @@ struct config_param; ...@@ -34,13 +33,13 @@ struct config_param;
Mixer * Mixer *
mixer_new(const struct mixer_plugin *plugin, void *ao, mixer_new(const struct mixer_plugin *plugin, void *ao,
const config_param &param, const config_param &param,
GError **error_r); Error &error);
void void
mixer_free(Mixer *mixer); mixer_free(Mixer *mixer);
bool bool
mixer_open(Mixer *mixer, GError **error_r); mixer_open(Mixer *mixer, Error &error);
void void
mixer_close(Mixer *mixer); mixer_close(Mixer *mixer);
...@@ -53,9 +52,9 @@ void ...@@ -53,9 +52,9 @@ void
mixer_auto_close(Mixer *mixer); mixer_auto_close(Mixer *mixer);
int int
mixer_get_volume(Mixer *mixer, GError **error_r); mixer_get_volume(Mixer *mixer, Error &error);
bool bool
mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r); mixer_set_volume(Mixer *mixer, unsigned volume, Error &error);
#endif #endif
...@@ -27,10 +27,9 @@ ...@@ -27,10 +27,9 @@
#ifndef MPD_MIXER_PLUGIN_HXX #ifndef MPD_MIXER_PLUGIN_HXX
#define MPD_MIXER_PLUGIN_HXX #define MPD_MIXER_PLUGIN_HXX
#include "gerror.h"
struct config_param; struct config_param;
class Mixer; class Mixer;
class Error;
struct mixer_plugin { struct mixer_plugin {
/** /**
...@@ -43,7 +42,7 @@ struct mixer_plugin { ...@@ -43,7 +42,7 @@ struct mixer_plugin {
* @return a mixer object, or NULL on error * @return a mixer object, or NULL on error
*/ */
Mixer *(*init)(void *ao, const config_param &param, Mixer *(*init)(void *ao, const config_param &param,
GError **error_r); Error &error);
/** /**
* Finish and free mixer data * Finish and free mixer data
...@@ -57,7 +56,7 @@ struct mixer_plugin { ...@@ -57,7 +56,7 @@ struct mixer_plugin {
* NULL to ignore errors * NULL to ignore errors
* @return true on success, false on error * @return true on success, false on error
*/ */
bool (*open)(Mixer *data, GError **error_r); bool (*open)(Mixer *data, Error &error);
/** /**
* Close mixer device * Close mixer device
...@@ -70,9 +69,9 @@ struct mixer_plugin { ...@@ -70,9 +69,9 @@ struct mixer_plugin {
* @param error_r location to store the error occurring, or * @param error_r location to store the error occurring, or
* NULL to ignore errors * NULL to ignore errors
* @return the current volume (0..100 including) or -1 if * @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. * Sets the volume.
...@@ -83,7 +82,7 @@ struct mixer_plugin { ...@@ -83,7 +82,7 @@ struct mixer_plugin {
* @return true on success, false on error * @return true on success, false on error
*/ */
bool (*set_volume)(Mixer *mixer, unsigned volume, bool (*set_volume)(Mixer *mixer, unsigned volume,
GError **error_r); Error &error);
/** /**
* If true, then the mixer is automatically opened, even if * If true, then the mixer is automatically opened, even if
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "ls.hxx" #include "ls.hxx"
#include "Volume.hxx" #include "Volume.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
extern "C" { extern "C" {
...@@ -126,8 +127,8 @@ handle_lsinfo(Client *client, int argc, char *argv[]) ...@@ -126,8 +127,8 @@ handle_lsinfo(Client *client, int argc, char *argv[])
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
GError *error = NULL; Error error;
if (!client_allow_file(client, path_fs, &error)) if (!client_allow_file(client, path_fs, error))
return print_error(client, error); return print_error(client, error);
Song *song = Song::LoadFile(path_utf8, nullptr); Song *song = Song::LoadFile(path_utf8, nullptr);
...@@ -147,7 +148,8 @@ handle_lsinfo(Client *client, int argc, char *argv[]) ...@@ -147,7 +148,8 @@ handle_lsinfo(Client *client, int argc, char *argv[])
return result; return result;
if (isRootDirectory(uri)) { if (isRootDirectory(uri)) {
const auto &list = ListPlaylistFiles(NULL); Error error;
const auto &list = ListPlaylistFiles(error);
print_spl_list(client, list); print_spl_list(client, list);
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "MusicPipe.hxx" #include "MusicPipe.hxx"
#include "MusicChunk.hxx" #include "MusicChunk.hxx"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
#include "util/Error.hxx"
#include "conf.h" #include "conf.h"
#include "notify.hxx" #include "notify.hxx"
...@@ -104,7 +105,7 @@ audio_output_all_init(struct player_control *pc) ...@@ -104,7 +105,7 @@ audio_output_all_init(struct player_control *pc)
{ {
const struct config_param *param = NULL; const struct config_param *param = NULL;
unsigned int i; unsigned int i;
GError *error = NULL; Error error;
num_audio_outputs = audio_output_config_count(); num_audio_outputs = audio_output_config_count();
audio_outputs = g_new(struct audio_output *, num_audio_outputs); audio_outputs = g_new(struct audio_output *, num_audio_outputs);
...@@ -125,11 +126,12 @@ audio_output_all_init(struct player_control *pc) ...@@ -125,11 +126,12 @@ audio_output_all_init(struct player_control *pc)
param = &empty; 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 (output == NULL) {
if (param != NULL) if (param != NULL)
FormatFatalError("line %i: %s", FormatFatalError("line %i: %s",
param->line, error->message); param->line,
error.GetMessage());
else else
FatalError(error); FatalError(error);
} }
...@@ -271,7 +273,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode) ...@@ -271,7 +273,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode)
} }
bool bool
audio_output_all_play(struct music_chunk *chunk, GError **error_r) audio_output_all_play(struct music_chunk *chunk, Error &error)
{ {
bool ret; bool ret;
unsigned int i; unsigned int i;
...@@ -284,8 +286,7 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r) ...@@ -284,8 +286,7 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r)
ret = audio_output_all_update(); ret = audio_output_all_update();
if (!ret) { if (!ret) {
/* TODO: obtain real error */ /* TODO: obtain real error */
g_set_error(error_r, output_quark(), 0, error.Set(output_domain, "Failed to open audio output");
"Failed to open audio output");
return false; return false;
} }
...@@ -300,7 +301,7 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r) ...@@ -300,7 +301,7 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r)
bool bool
audio_output_all_open(const AudioFormat audio_format, audio_output_all_open(const AudioFormat audio_format,
struct music_buffer *buffer, struct music_buffer *buffer,
GError **error_r) Error &error)
{ {
bool ret = false, enabled = false; bool ret = false, enabled = false;
unsigned int i; unsigned int i;
...@@ -338,12 +339,10 @@ audio_output_all_open(const AudioFormat audio_format, ...@@ -338,12 +339,10 @@ audio_output_all_open(const AudioFormat audio_format,
} }
if (!enabled) if (!enabled)
g_set_error(error_r, output_quark(), 0, error.Set(output_domain, "All audio outputs are disabled");
"All audio outputs are disabled");
else if (!ret) else if (!ret)
/* TODO: obtain real error */ /* TODO: obtain real error */
g_set_error(error_r, output_quark(), 0, error.Set(output_domain, "Failed to open audio output");
"Failed to open audio output");
if (!ret) if (!ret)
/* close all devices if there was an error */ /* close all devices if there was an error */
......
...@@ -27,12 +27,12 @@ ...@@ -27,12 +27,12 @@
#define OUTPUT_ALL_H #define OUTPUT_ALL_H
#include "replay_gain_info.h" #include "replay_gain_info.h"
#include "gerror.h"
struct AudioFormat; struct AudioFormat;
struct music_buffer; struct music_buffer;
struct music_chunk; struct music_chunk;
struct player_control; struct player_control;
class Error;
/** /**
* Global initialization: load audio outputs from the configuration * Global initialization: load audio outputs from the configuration
...@@ -84,7 +84,7 @@ audio_output_all_enable_disable(void); ...@@ -84,7 +84,7 @@ audio_output_all_enable_disable(void);
bool bool
audio_output_all_open(AudioFormat audio_format, audio_output_all_open(AudioFormat audio_format,
struct music_buffer *buffer, struct music_buffer *buffer,
GError **error_r); Error &error);
/** /**
* Closes all audio outputs. * Closes all audio outputs.
...@@ -111,7 +111,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode); ...@@ -111,7 +111,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode);
* (all closed then) * (all closed then)
*/ */
bool 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 * Checks if the output devices have drained their music pipe, and
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "notify.hxx" #include "notify.hxx"
#include "filter/ReplayGainFilterPlugin.hxx" #include "filter/ReplayGainFilterPlugin.hxx"
#include "FilterPlugin.hxx" #include "FilterPlugin.hxx"
#include "util/Error.hxx"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -187,13 +188,10 @@ audio_output_open(struct audio_output *ao, ...@@ -187,13 +188,10 @@ audio_output_open(struct audio_output *ao,
open = ao->open; open = ao->open;
if (open && ao->mixer != NULL) { if (open && ao->mixer != NULL) {
GError *error = NULL; Error error;
if (!mixer_open(ao->mixer, error))
if (!mixer_open(ao->mixer, &error)) {
g_warning("Failed to open mixer for '%s': %s", g_warning("Failed to open mixer for '%s': %s",
ao->name, error->message); ao->name, error.GetMessage());
g_error_free(error);
}
} }
return open; return open;
......
/*
* 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");
...@@ -20,18 +20,6 @@ ...@@ -20,18 +20,6 @@
#ifndef MPD_OUTPUT_ERROR_HXX #ifndef MPD_OUTPUT_ERROR_HXX
#define MPD_OUTPUT_ERROR_HXX #define MPD_OUTPUT_ERROR_HXX
#include "gcc.h" extern const class Domain output_domain;
#include <glib.h>
/**
* Quark for GError.domain.
*/
gcc_const
static inline GQuark
output_quark(void)
{
return g_quark_from_static_string("output");
}
#endif #endif
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include "filter/AutoConvertFilterPlugin.hxx" #include "filter/AutoConvertFilterPlugin.hxx"
#include "filter/ReplayGainFilterPlugin.hxx" #include "filter/ReplayGainFilterPlugin.hxx"
#include "filter/ChainFilterPlugin.hxx" #include "filter/ChainFilterPlugin.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -49,7 +51,7 @@ ...@@ -49,7 +51,7 @@
#define AUDIO_FILTERS "filters" #define AUDIO_FILTERS "filters"
static const struct audio_output_plugin * static const struct audio_output_plugin *
audio_output_detect(GError **error) audio_output_detect(Error &error)
{ {
g_warning("Attempt to detect audio output device"); g_warning("Attempt to detect audio output device");
...@@ -63,8 +65,7 @@ audio_output_detect(GError **error) ...@@ -63,8 +65,7 @@ audio_output_detect(GError **error)
return plugin; return plugin;
} }
g_set_error(error, output_quark(), 0, error.Set(output_domain, "Unable to detect an audio device");
"Unable to detect an audio device");
return NULL; return NULL;
} }
...@@ -99,7 +100,7 @@ audio_output_load_mixer(struct audio_output *ao, ...@@ -99,7 +100,7 @@ audio_output_load_mixer(struct audio_output *ao,
const config_param &param, const config_param &param,
const struct mixer_plugin *plugin, const struct mixer_plugin *plugin,
Filter &filter_chain, Filter &filter_chain,
GError **error_r) Error &error)
{ {
Mixer *mixer; Mixer *mixer;
...@@ -112,12 +113,12 @@ audio_output_load_mixer(struct audio_output *ao, ...@@ -112,12 +113,12 @@ audio_output_load_mixer(struct audio_output *ao,
if (plugin == NULL) if (plugin == NULL)
return NULL; return NULL;
return mixer_new(plugin, ao, param, error_r); return mixer_new(plugin, ao, param, error);
case MIXER_TYPE_SOFTWARE: case MIXER_TYPE_SOFTWARE:
mixer = mixer_new(&software_mixer_plugin, nullptr, mixer = mixer_new(&software_mixer_plugin, nullptr,
config_param(), config_param(),
nullptr); IgnoreError());
assert(mixer != NULL); assert(mixer != NULL);
filter_chain_append(filter_chain, "software_mixer", filter_chain_append(filter_chain, "software_mixer",
...@@ -132,7 +133,7 @@ audio_output_load_mixer(struct audio_output *ao, ...@@ -132,7 +133,7 @@ audio_output_load_mixer(struct audio_output *ao,
bool bool
ao_base_init(struct audio_output *ao, ao_base_init(struct audio_output *ao,
const struct audio_output_plugin *plugin, const struct audio_output_plugin *plugin,
const config_param &param, GError **error_r) const config_param &param, Error &error)
{ {
assert(ao != NULL); assert(ao != NULL);
assert(plugin != NULL); assert(plugin != NULL);
...@@ -141,13 +142,11 @@ ao_base_init(struct audio_output *ao, ...@@ -141,13 +142,11 @@ ao_base_init(struct audio_output *ao,
assert(plugin->close != NULL); assert(plugin->close != NULL);
assert(plugin->play != NULL); assert(plugin->play != NULL);
GError *error = NULL;
if (!param.IsNull()) { if (!param.IsNull()) {
ao->name = param.GetBlockValue(AUDIO_OUTPUT_NAME); ao->name = param.GetBlockValue(AUDIO_OUTPUT_NAME);
if (ao->name == NULL) { if (ao->name == NULL) {
g_set_error(error_r, output_quark(), 0, error.Set(config_domain,
"Missing \"name\" configuration"); "Missing \"name\" configuration");
return false; return false;
} }
...@@ -155,7 +154,7 @@ ao_base_init(struct audio_output *ao, ...@@ -155,7 +154,7 @@ ao_base_init(struct audio_output *ao,
if (p != NULL) { if (p != NULL) {
bool success = bool success =
audio_format_parse(ao->config_audio_format, audio_format_parse(ao->config_audio_format,
p, true, error_r); p, true, error);
if (!success) if (!success)
return false; return false;
} else } else
...@@ -186,25 +185,23 @@ ao_base_init(struct audio_output *ao, ...@@ -186,25 +185,23 @@ ao_base_init(struct audio_output *ao,
if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) { if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) {
Filter *normalize_filter = Filter *normalize_filter =
filter_new(&normalize_filter_plugin, config_param(), filter_new(&normalize_filter_plugin, config_param(),
nullptr); IgnoreError());
assert(normalize_filter != NULL); assert(normalize_filter != NULL);
filter_chain_append(*ao->filter, "normalize", filter_chain_append(*ao->filter, "normalize",
autoconvert_filter_new(normalize_filter)); autoconvert_filter_new(normalize_filter));
} }
Error filter_error;
filter_chain_parse(*ao->filter, filter_chain_parse(*ao->filter,
param.GetBlockValue(AUDIO_FILTERS, ""), param.GetBlockValue(AUDIO_FILTERS, ""),
&error filter_error);
);
// It's not really fatal - Part of the filter chain has been set up already // 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) // 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", g_warning("Failed to initialize filter chain for '%s': %s",
ao->name, error->message); ao->name, filter_error.GetMessage());
g_error_free(error);
}
ao->thread = NULL; ao->thread = NULL;
ao->command = AO_COMMAND_NONE; ao->command = AO_COMMAND_NONE;
...@@ -220,7 +217,7 @@ ao_base_init(struct audio_output *ao, ...@@ -220,7 +217,7 @@ ao_base_init(struct audio_output *ao,
static bool static bool
audio_output_setup(struct audio_output *ao, const config_param &param, audio_output_setup(struct audio_output *ao, const config_param &param,
GError **error_r) Error &error)
{ {
/* create the replay_gain filter */ /* create the replay_gain filter */
...@@ -230,13 +227,14 @@ audio_output_setup(struct audio_output *ao, const config_param &param, ...@@ -230,13 +227,14 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
if (strcmp(replay_gain_handler, "none") != 0) { if (strcmp(replay_gain_handler, "none") != 0) {
ao->replay_gain_filter = filter_new(&replay_gain_filter_plugin, ao->replay_gain_filter = filter_new(&replay_gain_filter_plugin,
param, NULL); param, IgnoreError());
assert(ao->replay_gain_filter != NULL); assert(ao->replay_gain_filter != NULL);
ao->replay_gain_serial = 0; ao->replay_gain_serial = 0;
ao->other_replay_gain_filter = filter_new(&replay_gain_filter_plugin, ao->other_replay_gain_filter = filter_new(&replay_gain_filter_plugin,
param, NULL); param,
IgnoreError());
assert(ao->other_replay_gain_filter != NULL); assert(ao->other_replay_gain_filter != NULL);
ao->other_replay_gain_serial = 0; ao->other_replay_gain_serial = 0;
...@@ -247,15 +245,13 @@ audio_output_setup(struct audio_output *ao, const config_param &param, ...@@ -247,15 +245,13 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
/* set up the mixer */ /* set up the mixer */
GError *error = NULL; Error mixer_error;
ao->mixer = audio_output_load_mixer(ao, param, ao->mixer = audio_output_load_mixer(ao, param,
ao->plugin->mixer_plugin, ao->plugin->mixer_plugin,
*ao->filter, &error); *ao->filter, mixer_error);
if (ao->mixer == NULL && error != NULL) { if (ao->mixer == NULL && mixer_error.IsDefined())
g_warning("Failed to initialize hardware mixer for '%s': %s", g_warning("Failed to initialize hardware mixer for '%s': %s",
ao->name, error->message); ao->name, mixer_error.GetMessage());
g_error_free(error);
}
/* use the hardware mixer for replay gain? */ /* use the hardware mixer for replay gain? */
...@@ -267,15 +263,15 @@ audio_output_setup(struct audio_output *ao, const config_param &param, ...@@ -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); g_warning("No such mixer for output '%s'", ao->name);
} else if (strcmp(replay_gain_handler, "software") != 0 && } else if (strcmp(replay_gain_handler, "software") != 0 &&
ao->replay_gain_filter != NULL) { ao->replay_gain_filter != NULL) {
g_set_error(error_r, output_quark(), 0, error.Set(config_domain,
"Invalid \"replay_gain_handler\" value"); "Invalid \"replay_gain_handler\" value");
return false; return false;
} }
/* the "convert" filter must be the last one in the chain */ /* the "convert" filter must be the last one in the chain */
ao->convert_filter = filter_new(&convert_filter_plugin, config_param(), ao->convert_filter = filter_new(&convert_filter_plugin, config_param(),
nullptr); IgnoreError());
assert(ao->convert_filter != NULL); assert(ao->convert_filter != NULL);
filter_chain_append(*ao->filter, "convert", ao->convert_filter); filter_chain_append(*ao->filter, "convert", ao->convert_filter);
...@@ -286,7 +282,7 @@ audio_output_setup(struct audio_output *ao, const config_param &param, ...@@ -286,7 +282,7 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
struct audio_output * struct audio_output *
audio_output_new(const config_param &param, audio_output_new(const config_param &param,
struct player_control *pc, struct player_control *pc,
GError **error_r) Error &error)
{ {
const struct audio_output_plugin *plugin; const struct audio_output_plugin *plugin;
...@@ -295,21 +291,21 @@ audio_output_new(const config_param &param, ...@@ -295,21 +291,21 @@ audio_output_new(const config_param &param,
p = param.GetBlockValue(AUDIO_OUTPUT_TYPE); p = param.GetBlockValue(AUDIO_OUTPUT_TYPE);
if (p == NULL) { if (p == NULL) {
g_set_error(error_r, output_quark(), 0, error.Set(config_domain,
"Missing \"type\" configuration"); "Missing \"type\" configuration");
return nullptr; return nullptr;
} }
plugin = audio_output_plugin_get(p); plugin = audio_output_plugin_get(p);
if (plugin == NULL) { if (plugin == NULL) {
g_set_error(error_r, output_quark(), 0, error.Format(config_domain,
"No such audio output plugin: %s", p); "No such audio output plugin: %s", p);
return nullptr; return nullptr;
} }
} else { } else {
g_warning("No 'audio_output' defined in config file\n"); g_warning("No 'audio_output' defined in config file\n");
plugin = audio_output_detect(error_r); plugin = audio_output_detect(error);
if (plugin == NULL) if (plugin == NULL)
return nullptr; return nullptr;
...@@ -317,11 +313,11 @@ audio_output_new(const config_param &param, ...@@ -317,11 +313,11 @@ audio_output_new(const config_param &param,
plugin->name); 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) if (ao == NULL)
return NULL; return NULL;
if (!audio_output_setup(ao, param, error_r)) { if (!audio_output_setup(ao, param, error)) {
ao_plugin_finish(ao); ao_plugin_finish(ao);
return NULL; return NULL;
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <time.h> #include <time.h>
class Error;
class Filter; class Filter;
struct config_param; struct config_param;
...@@ -263,12 +264,12 @@ audio_output_command_is_finished(const struct audio_output *ao) ...@@ -263,12 +264,12 @@ audio_output_command_is_finished(const struct audio_output *ao)
struct audio_output * struct audio_output *
audio_output_new(const config_param &param, audio_output_new(const config_param &param,
struct player_control *pc, struct player_control *pc,
GError **error_r); Error &error);
bool bool
ao_base_init(struct audio_output *ao, ao_base_init(struct audio_output *ao,
const struct audio_output_plugin *plugin, const struct audio_output_plugin *plugin,
const config_param &param, GError **error_r); const config_param &param, Error &error);
void void
ao_base_finish(struct audio_output *ao); ao_base_finish(struct audio_output *ao);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment