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,7 +88,7 @@ parse_sample_format(const char *src, bool mask, ...@@ -96,7 +88,7 @@ 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,7 +115,7 @@ parse_sample_format(const char *src, bool mask, ...@@ -123,7 +115,7 @@ 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,16 +17,21 @@ ...@@ -17,16 +17,21 @@
* 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,10 +40,10 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r) ...@@ -35,10 +40,10 @@ 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,10 +53,10 @@ audio_check_sample_format(SampleFormat sample_format, GError **error_r) ...@@ -48,10 +53,10 @@ 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,40 +44,39 @@ ...@@ -42,40 +44,39 @@
#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,7 +97,7 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r) ...@@ -97,7 +97,7 @@ 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,7 +114,7 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r) ...@@ -114,7 +114,7 @@ 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,7 +182,7 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -185,7 +182,7 @@ 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,7 +194,7 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -197,7 +194,7 @@ 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);
...@@ -210,45 +207,41 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r) ...@@ -210,45 +207,41 @@ 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,19 +99,15 @@ config_get_string(ConfigOption option, const char *default_value) ...@@ -98,19 +99,15 @@ 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,22 +48,16 @@ ...@@ -46,22 +48,16 @@
#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();
...@@ -69,7 +65,7 @@ ParsePath(const char *path, GError **error_r) ...@@ -69,7 +65,7 @@ ParsePath(const char *path, GError **error_r)
#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] == '~') {
...@@ -80,7 +76,7 @@ ParsePath(const char *path, GError **error_r) ...@@ -80,7 +76,7 @@ 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,7 +85,7 @@ ParsePath(const char *path, GError **error_r) ...@@ -89,7 +85,7 @@ 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,7 +103,7 @@ ParsePath(const char *path, GError **error_r) ...@@ -107,7 +103,7 @@ 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,7 +114,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) ...@@ -115,7 +114,7 @@ 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",
...@@ -126,7 +125,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) ...@@ -126,7 +125,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
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);
...@@ -135,14 +134,13 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) ...@@ -135,14 +134,13 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
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;
...@@ -150,7 +148,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error) ...@@ -150,7 +148,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
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,7 +410,7 @@ decoder_run_song(struct decoder_control *dc, ...@@ -411,7 +410,7 @@ 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,12 +72,12 @@ directory_save(FILE *fp, const Directory *directory) ...@@ -77,12 +72,12 @@ 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,7 +138,7 @@ directory_load(TextFile &file, Directory *directory, GError **error) ...@@ -146,7 +138,7 @@ 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,7 +162,7 @@ directory_load(TextFile &file, Directory *directory, GError **error) ...@@ -170,7 +162,7 @@ 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,33 +24,29 @@ ...@@ -24,33 +24,29 @@
#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,14 +37,14 @@ input_quark(void) ...@@ -39,14 +37,14 @@ 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,23 +70,20 @@ input_stream_global_init(GError **error_r) ...@@ -74,23 +70,20 @@ 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,28 +102,23 @@ listen_global_init(GError **error_r) ...@@ -101,28 +102,23 @@ 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,7 +267,7 @@ log_init(bool verbose, bool use_stdout, GError **error_r) ...@@ -264,7 +267,7 @@ 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
...@@ -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,12 +142,10 @@ ao_base_init(struct audio_output *ao, ...@@ -141,12 +142,10 @@ 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,7 +263,7 @@ audio_output_setup(struct audio_output *ao, const config_param &param, ...@@ -267,7 +263,7 @@ 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;
} }
...@@ -275,7 +271,7 @@ audio_output_setup(struct audio_output *ao, const config_param &param, ...@@ -275,7 +271,7 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
/* 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);
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
struct audio_output * struct audio_output *
ao_plugin_init(const struct audio_output_plugin *plugin, ao_plugin_init(const struct audio_output_plugin *plugin,
const config_param &param, const config_param &param,
GError **error) Error &error)
{ {
assert(plugin != NULL); assert(plugin != NULL);
assert(plugin->init != NULL); assert(plugin->init != NULL);
...@@ -39,7 +39,7 @@ ao_plugin_finish(struct audio_output *ao) ...@@ -39,7 +39,7 @@ ao_plugin_finish(struct audio_output *ao)
} }
bool bool
ao_plugin_enable(struct audio_output *ao, GError **error_r) ao_plugin_enable(struct audio_output *ao, Error &error_r)
{ {
return ao->plugin->enable != NULL return ao->plugin->enable != NULL
? ao->plugin->enable(ao, error_r) ? ao->plugin->enable(ao, error_r)
...@@ -55,7 +55,7 @@ ao_plugin_disable(struct audio_output *ao) ...@@ -55,7 +55,7 @@ ao_plugin_disable(struct audio_output *ao)
bool bool
ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format, ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) Error &error)
{ {
return ao->plugin->open(ao, audio_format, error); return ao->plugin->open(ao, audio_format, error);
} }
...@@ -83,7 +83,7 @@ ao_plugin_send_tag(struct audio_output *ao, const Tag *tag) ...@@ -83,7 +83,7 @@ ao_plugin_send_tag(struct audio_output *ao, const Tag *tag)
size_t size_t
ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size, ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error) Error &error)
{ {
return ao->plugin->play(ao, chunk, size, error); return ao->plugin->play(ao, chunk, size, error);
} }
......
...@@ -21,13 +21,13 @@ ...@@ -21,13 +21,13 @@
#define MPD_OUTPUT_PLUGIN_HXX #define MPD_OUTPUT_PLUGIN_HXX
#include "gcc.h" #include "gcc.h"
#include "gerror.h"
#include <stddef.h> #include <stddef.h>
struct config_param; struct config_param;
struct AudioFormat; struct AudioFormat;
struct Tag; struct Tag;
class Error;
/** /**
* A plugin which controls an audio output device. * A plugin which controls an audio output device.
...@@ -56,7 +56,7 @@ struct audio_output_plugin { ...@@ -56,7 +56,7 @@ struct audio_output_plugin {
* data * data
*/ */
struct audio_output *(*init)(const config_param &param, struct audio_output *(*init)(const config_param &param,
GError **error); Error &error);
/** /**
* Free resources allocated by this device. * Free resources allocated by this device.
...@@ -73,7 +73,7 @@ struct audio_output_plugin { ...@@ -73,7 +73,7 @@ struct audio_output_plugin {
* NULL to ignore errors * NULL to ignore errors
* @return true on success, false on error * @return true on success, false on error
*/ */
bool (*enable)(struct audio_output *data, GError **error_r); bool (*enable)(struct audio_output *data, Error &error);
/** /**
* Disables the device. It is closed before this method is * Disables the device. It is closed before this method is
...@@ -90,7 +90,7 @@ struct audio_output_plugin { ...@@ -90,7 +90,7 @@ struct audio_output_plugin {
* to ignore errors * to ignore errors
*/ */
bool (*open)(struct audio_output *data, AudioFormat &audio_format, bool (*open)(struct audio_output *data, AudioFormat &audio_format,
GError **error); Error &error);
/** /**
* Close the device. * Close the device.
...@@ -122,7 +122,7 @@ struct audio_output_plugin { ...@@ -122,7 +122,7 @@ struct audio_output_plugin {
*/ */
size_t (*play)(struct audio_output *data, size_t (*play)(struct audio_output *data,
const void *chunk, size_t size, const void *chunk, size_t size,
GError **error); Error &error);
/** /**
* Wait until the device has finished playing. * Wait until the device has finished playing.
...@@ -169,20 +169,20 @@ gcc_malloc ...@@ -169,20 +169,20 @@ gcc_malloc
struct audio_output * struct audio_output *
ao_plugin_init(const struct audio_output_plugin *plugin, ao_plugin_init(const struct audio_output_plugin *plugin,
const config_param &param, const config_param &param,
GError **error); Error &error);
void void
ao_plugin_finish(struct audio_output *ao); ao_plugin_finish(struct audio_output *ao);
bool bool
ao_plugin_enable(struct audio_output *ao, GError **error_r); ao_plugin_enable(struct audio_output *ao, Error &error);
void void
ao_plugin_disable(struct audio_output *ao); ao_plugin_disable(struct audio_output *ao);
bool bool
ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format, ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error); Error &error);
void void
ao_plugin_close(struct audio_output *ao); ao_plugin_close(struct audio_output *ao);
...@@ -196,7 +196,7 @@ ao_plugin_send_tag(struct audio_output *ao, const Tag *tag); ...@@ -196,7 +196,7 @@ ao_plugin_send_tag(struct audio_output *ao, const Tag *tag);
size_t size_t
ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size, ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error); Error &error);
void void
ao_plugin_drain(struct audio_output *ao); ao_plugin_drain(struct audio_output *ao);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,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 "gcc.h" #include "gcc.h"
#include <glib.h> #include <glib.h>
...@@ -55,19 +56,18 @@ static void ao_command_finished(struct audio_output *ao) ...@@ -55,19 +56,18 @@ static void ao_command_finished(struct audio_output *ao)
static bool static bool
ao_enable(struct audio_output *ao) ao_enable(struct audio_output *ao)
{ {
GError *error = NULL; Error error;
bool success; bool success;
if (ao->really_enabled) if (ao->really_enabled)
return true; return true;
ao->mutex.unlock(); ao->mutex.unlock();
success = ao_plugin_enable(ao, &error); success = ao_plugin_enable(ao, error);
ao->mutex.lock(); ao->mutex.lock();
if (!success) { if (!success) {
g_warning("Failed to enable \"%s\" [%s]: %s\n", g_warning("Failed to enable \"%s\" [%s]: %s\n",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error.GetMessage());
g_error_free(error);
return false; return false;
} }
...@@ -95,7 +95,7 @@ ao_disable(struct audio_output *ao) ...@@ -95,7 +95,7 @@ ao_disable(struct audio_output *ao)
static AudioFormat static AudioFormat
ao_filter_open(struct audio_output *ao, AudioFormat &format, ao_filter_open(struct audio_output *ao, AudioFormat &format,
GError **error_r) Error &error_r)
{ {
assert(format.IsValid()); assert(format.IsValid());
...@@ -131,7 +131,7 @@ static void ...@@ -131,7 +131,7 @@ static void
ao_open(struct audio_output *ao) ao_open(struct audio_output *ao)
{ {
bool success; bool success;
GError *error = NULL; Error error;
struct audio_format_string af_string; struct audio_format_string af_string;
assert(!ao->open); assert(!ao->open);
...@@ -157,11 +157,10 @@ ao_open(struct audio_output *ao) ...@@ -157,11 +157,10 @@ ao_open(struct audio_output *ao)
/* open the filter */ /* open the filter */
const AudioFormat filter_audio_format = const AudioFormat filter_audio_format =
ao_filter_open(ao, ao->in_audio_format, &error); ao_filter_open(ao, ao->in_audio_format, error);
if (!filter_audio_format.IsDefined()) { if (!filter_audio_format.IsDefined()) {
g_warning("Failed to open filter for \"%s\" [%s]: %s", g_warning("Failed to open filter for \"%s\" [%s]: %s",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error.GetMessage());
g_error_free(error);
ao->fail_timer = g_timer_new(); ao->fail_timer = g_timer_new();
return; return;
...@@ -173,15 +172,14 @@ ao_open(struct audio_output *ao) ...@@ -173,15 +172,14 @@ ao_open(struct audio_output *ao)
ao->out_audio_format.ApplyMask(ao->config_audio_format); ao->out_audio_format.ApplyMask(ao->config_audio_format);
ao->mutex.unlock(); ao->mutex.unlock();
success = ao_plugin_open(ao, ao->out_audio_format, &error); success = ao_plugin_open(ao, ao->out_audio_format, error);
ao->mutex.lock(); ao->mutex.lock();
assert(!ao->open); assert(!ao->open);
if (!success) { if (!success) {
g_warning("Failed to open \"%s\" [%s]: %s", g_warning("Failed to open \"%s\" [%s]: %s",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error.GetMessage());
g_error_free(error);
ao_filter_close(ao); ao_filter_close(ao);
ao->fail_timer = g_timer_new(); ao->fail_timer = g_timer_new();
...@@ -231,15 +229,14 @@ ao_close(struct audio_output *ao, bool drain) ...@@ -231,15 +229,14 @@ ao_close(struct audio_output *ao, bool drain)
static void static void
ao_reopen_filter(struct audio_output *ao) ao_reopen_filter(struct audio_output *ao)
{ {
GError *error = NULL; Error error;
ao_filter_close(ao); ao_filter_close(ao);
const AudioFormat filter_audio_format = const AudioFormat filter_audio_format =
ao_filter_open(ao, ao->in_audio_format, &error); ao_filter_open(ao, ao->in_audio_format, error);
if (!filter_audio_format.IsDefined()) { if (!filter_audio_format.IsDefined()) {
g_warning("Failed to open filter for \"%s\" [%s]: %s", g_warning("Failed to open filter for \"%s\" [%s]: %s",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error.GetMessage());
g_error_free(error);
/* this is a little code duplication fro ao_close(), /* this is a little code duplication fro ao_close(),
but we cannot call this function because we must but we cannot call this function because we must
...@@ -333,13 +330,12 @@ ao_chunk_data(struct audio_output *ao, const struct music_chunk *chunk, ...@@ -333,13 +330,12 @@ ao_chunk_data(struct audio_output *ao, const struct music_chunk *chunk,
*replay_gain_serial_p = chunk->replay_gain_serial; *replay_gain_serial_p = chunk->replay_gain_serial;
} }
GError *error = NULL; Error error;
data = replay_gain_filter->FilterPCM(data, length, data = replay_gain_filter->FilterPCM(data, length,
&length, &error); &length, error);
if (data == NULL) { if (data == NULL) {
g_warning("\"%s\" [%s] failed to filter: %s", g_warning("\"%s\" [%s] failed to filter: %s",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error.GetMessage());
g_error_free(error);
return NULL; return NULL;
} }
} }
...@@ -352,8 +348,6 @@ static const void * ...@@ -352,8 +348,6 @@ static const void *
ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk, ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
size_t *length_r) size_t *length_r)
{ {
GError *error = NULL;
size_t length; size_t length;
const void *data = ao_chunk_data(ao, chunk, ao->replay_gain_filter, const void *data = ao_chunk_data(ao, chunk, ao->replay_gain_filter,
&ao->replay_gain_serial, &length); &ao->replay_gain_serial, &length);
...@@ -407,11 +401,11 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk, ...@@ -407,11 +401,11 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
/* apply filter chain */ /* apply filter chain */
data = ao->filter->FilterPCM(data, length, &length, &error); Error error;
data = ao->filter->FilterPCM(data, length, &length, error);
if (data == NULL) { if (data == NULL) {
g_warning("\"%s\" [%s] failed to filter: %s", g_warning("\"%s\" [%s] failed to filter: %s",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error.GetMessage());
g_error_free(error);
return NULL; return NULL;
} }
...@@ -422,8 +416,6 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk, ...@@ -422,8 +416,6 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
static bool static bool
ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
{ {
GError *error = NULL;
assert(ao != NULL); assert(ao != NULL);
assert(ao->filter != NULL); assert(ao->filter != NULL);
...@@ -448,6 +440,8 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) ...@@ -448,6 +440,8 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
return false; return false;
} }
Error error;
while (size > 0 && ao->command == AO_COMMAND_NONE) { while (size > 0 && ao->command == AO_COMMAND_NONE) {
size_t nbytes; size_t nbytes;
...@@ -455,13 +449,13 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) ...@@ -455,13 +449,13 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
break; break;
ao->mutex.unlock(); ao->mutex.unlock();
nbytes = ao_plugin_play(ao, data, size, &error); nbytes = ao_plugin_play(ao, data, size, error);
ao->mutex.lock(); ao->mutex.lock();
if (nbytes == 0) { if (nbytes == 0) {
/* play()==0 means failure */ /* play()==0 means failure */
g_warning("\"%s\" [%s] failed to play: %s", g_warning("\"%s\" [%s] failed to play: %s",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name,
g_error_free(error); error.GetMessage());
ao_close(ao, false); ao_close(ao, false);
......
...@@ -40,7 +40,6 @@ player_control::player_control(unsigned _buffer_chunks, ...@@ -40,7 +40,6 @@ player_control::player_control(unsigned _buffer_chunks,
command(PLAYER_COMMAND_NONE), command(PLAYER_COMMAND_NONE),
state(PLAYER_STATE_STOP), state(PLAYER_STATE_STOP),
error_type(PLAYER_ERROR_NONE), error_type(PLAYER_ERROR_NONE),
error(nullptr),
next_song(nullptr), next_song(nullptr),
cross_fade_seconds(0), cross_fade_seconds(0),
mixramp_db(0), mixramp_db(0),
...@@ -216,16 +215,13 @@ player_control::GetStatus() ...@@ -216,16 +215,13 @@ player_control::GetStatus()
} }
void void
player_control::SetError(player_error type, GError *_error) player_control::SetError(player_error type, Error &&_error)
{ {
assert(type != PLAYER_ERROR_NONE); assert(type != PLAYER_ERROR_NONE);
assert(_error != NULL); assert(_error.IsDefined());
if (error_type != PLAYER_ERROR_NONE)
g_error_free(error);
error_type = type; error_type = type;
error = _error; error = std::move(_error);
} }
void void
...@@ -235,7 +231,7 @@ player_control::ClearError() ...@@ -235,7 +231,7 @@ player_control::ClearError()
if (error_type != PLAYER_ERROR_NONE) { if (error_type != PLAYER_ERROR_NONE) {
error_type = PLAYER_ERROR_NONE; error_type = PLAYER_ERROR_NONE;
g_error_free(error); error.Clear();
} }
Unlock(); Unlock();
...@@ -246,7 +242,7 @@ player_control::GetErrorMessage() const ...@@ -246,7 +242,7 @@ player_control::GetErrorMessage() const
{ {
Lock(); Lock();
char *message = error_type != PLAYER_ERROR_NONE char *message = error_type != PLAYER_ERROR_NONE
? g_strdup(error->message) ? g_strdup(error.GetMessage())
: NULL; : NULL;
Unlock(); Unlock();
return message; return message;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,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>
...@@ -127,7 +128,7 @@ struct player_control { ...@@ -127,7 +128,7 @@ struct player_control {
* #PLAYER_ERROR_NONE. The object must be freed when this * #PLAYER_ERROR_NONE. The object must be freed when this
* object transitions back to #PLAYER_ERROR_NONE. * object transitions back to #PLAYER_ERROR_NONE.
*/ */
GError *error; Error error;
uint16_t bit_rate; uint16_t bit_rate;
AudioFormat audio_format; AudioFormat audio_format;
...@@ -262,10 +263,9 @@ struct player_control { ...@@ -262,10 +263,9 @@ struct player_control {
* Caller must lock the object. * Caller must lock the object.
* *
* @param type the error type; must not be #PLAYER_ERROR_NONE * @param type the error type; must not be #PLAYER_ERROR_NONE
* @param error detailed error information; must not be NULL; the * @param error detailed error information; must be defined.
* #player_control takes over ownership of this #GError instance
*/ */
void SetError(player_error type, GError *error); void SetError(player_error type, Error &&error);
void ClearError(); void ClearError();
......
...@@ -251,10 +251,10 @@ player_wait_for_decoder(struct player *player) ...@@ -251,10 +251,10 @@ player_wait_for_decoder(struct player *player)
player->queued = false; player->queued = false;
GError *error = dc->LockGetError(); Error error = dc->LockGetError();
if (error != NULL) { if (error.IsDefined()) {
pc->Lock(); pc->Lock();
pc->SetError(PLAYER_ERROR_DECODER, error); pc->SetError(PLAYER_ERROR_DECODER, std::move(error));
pc->next_song->Free(); pc->next_song->Free();
pc->next_song = NULL; pc->next_song = NULL;
...@@ -327,9 +327,9 @@ player_open_output(struct player *player) ...@@ -327,9 +327,9 @@ player_open_output(struct player *player)
assert(pc->state == PLAYER_STATE_PLAY || assert(pc->state == PLAYER_STATE_PLAY ||
pc->state == PLAYER_STATE_PAUSE); pc->state == PLAYER_STATE_PAUSE);
GError *error = NULL; Error error;
if (audio_output_all_open(player->play_audio_format, player_buffer, if (audio_output_all_open(player->play_audio_format, player_buffer,
&error)) { error)) {
player->output_open = true; player->output_open = true;
player->paused = false; player->paused = false;
...@@ -341,7 +341,7 @@ player_open_output(struct player *player) ...@@ -341,7 +341,7 @@ player_open_output(struct player *player)
return true; return true;
} else { } else {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
player->output_open = false; player->output_open = false;
...@@ -350,7 +350,7 @@ player_open_output(struct player *player) ...@@ -350,7 +350,7 @@ player_open_output(struct player *player)
player->paused = true; player->paused = true;
pc->Lock(); pc->Lock();
pc->SetError(PLAYER_ERROR_OUTPUT, error); pc->SetError(PLAYER_ERROR_OUTPUT, std::move(error));
pc->state = PLAYER_STATE_PAUSE; pc->state = PLAYER_STATE_PAUSE;
pc->Unlock(); pc->Unlock();
...@@ -377,13 +377,13 @@ player_check_decoder_startup(struct player *player) ...@@ -377,13 +377,13 @@ player_check_decoder_startup(struct player *player)
dc->Lock(); dc->Lock();
GError *error = dc->GetError(); Error error = dc->GetError();
if (error != NULL) { if (error.IsDefined()) {
/* the decoder failed */ /* the decoder failed */
dc->Unlock(); dc->Unlock();
pc->Lock(); pc->Lock();
pc->SetError(PLAYER_ERROR_DECODER, error); pc->SetError(PLAYER_ERROR_DECODER, std::move(error));
pc->Unlock(); pc->Unlock();
return false; return false;
...@@ -460,11 +460,9 @@ player_send_silence(struct player *player) ...@@ -460,11 +460,9 @@ player_send_silence(struct player *player)
chunk->length = num_frames * frame_size; chunk->length = num_frames * frame_size;
memset(chunk->data, 0, chunk->length); memset(chunk->data, 0, chunk->length);
GError *error = NULL; Error error;
if (!audio_output_all_play(chunk, &error)) { if (!audio_output_all_play(chunk, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
music_buffer_return(player_buffer, chunk); music_buffer_return(player_buffer, chunk);
return false; return false;
} }
...@@ -689,7 +687,7 @@ static bool ...@@ -689,7 +687,7 @@ static bool
play_chunk(struct player_control *pc, play_chunk(struct player_control *pc,
Song *song, struct music_chunk *chunk, Song *song, struct music_chunk *chunk,
const AudioFormat format, const AudioFormat format,
GError **error_r) Error &error)
{ {
assert(chunk->CheckFormat(format)); assert(chunk->CheckFormat(format));
...@@ -707,7 +705,7 @@ play_chunk(struct player_control *pc, ...@@ -707,7 +705,7 @@ play_chunk(struct player_control *pc,
/* send the chunk to the audio outputs */ /* send the chunk to the audio outputs */
if (!audio_output_all_play(chunk, error_r)) if (!audio_output_all_play(chunk, error))
return false; return false;
pc->total_play_time += (double)chunk->length / pc->total_play_time += (double)chunk->length /
...@@ -822,16 +820,16 @@ play_next_chunk(struct player *player) ...@@ -822,16 +820,16 @@ play_next_chunk(struct player *player)
/* play the current chunk */ /* play the current chunk */
GError *error = NULL; Error error;
if (!play_chunk(player->pc, player->song, chunk, if (!play_chunk(player->pc, player->song, chunk,
player->play_audio_format, &error)) { player->play_audio_format, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
music_buffer_return(player_buffer, chunk); music_buffer_return(player_buffer, chunk);
pc->Lock(); pc->Lock();
pc->SetError(PLAYER_ERROR_OUTPUT, error); pc->SetError(PLAYER_ERROR_OUTPUT, std::move(error));
/* pause: the user may resume playback as soon as an /* pause: the user may resume playback as soon as an
audio output becomes available */ audio output becomes available */
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "PlaylistMapper.hxx" #include "PlaylistMapper.hxx"
#include "PlaylistRegistry.hxx" #include "PlaylistRegistry.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include <assert.h> #include <assert.h>
...@@ -39,14 +40,12 @@ playlist_open_remote(const char *uri, Mutex &mutex, Cond &cond, ...@@ -39,14 +40,12 @@ playlist_open_remote(const char *uri, Mutex &mutex, Cond &cond,
return playlist; return playlist;
} }
GError *error = NULL; Error error;
struct input_stream *is = input_stream_open(uri, mutex, cond, &error); input_stream *is = input_stream_open(uri, mutex, cond, error);
if (is == NULL) { if (is == NULL) {
if (error != NULL) { if (error.IsDefined())
g_warning("Failed to open %s: %s", g_warning("Failed to open %s: %s",
uri, error->message); uri, error.GetMessage());
g_error_free(error);
}
return NULL; return NULL;
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "ls.hxx" #include "ls.hxx"
#include "Playlist.hxx" #include "Playlist.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -64,7 +65,7 @@ handle_load(Client *client, int argc, char *argv[]) ...@@ -64,7 +65,7 @@ handle_load(Client *client, int argc, char *argv[])
if (argc < 3) { if (argc < 3) {
start_index = 0; start_index = 0;
end_index = G_MAXUINT; end_index = unsigned(-1);
} else if (!check_range(client, &start_index, &end_index, argv[2])) } else if (!check_range(client, &start_index, &end_index, argv[2]))
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
...@@ -77,19 +78,22 @@ handle_load(Client *client, int argc, char *argv[]) ...@@ -77,19 +78,22 @@ handle_load(Client *client, int argc, char *argv[])
if (result != PLAYLIST_RESULT_NO_SUCH_LIST) if (result != PLAYLIST_RESULT_NO_SUCH_LIST)
return print_playlist_result(client, result); return print_playlist_result(client, result);
GError *error = NULL; Error error;
if (playlist_load_spl(&client->playlist, client->player_control, if (playlist_load_spl(&client->playlist, client->player_control,
argv[1], start_index, end_index, argv[1], start_index, end_index,
&error)) error))
return COMMAND_RETURN_OK; return COMMAND_RETURN_OK;
if (error->domain == playlist_quark() && if (error.IsDomain(playlist_domain) &&
error->code == PLAYLIST_RESULT_BAD_NAME) error.GetCode() == PLAYLIST_RESULT_BAD_NAME) {
/* the message for BAD_NAME is confusing when the /* the message for BAD_NAME is confusing when the
client wants to load a playlist file from the music client wants to load a playlist file from the music
directory; patch the GError object to show "no such directory; patch the Error object to show "no such
playlist" instead */ playlist" instead */
error->code = PLAYLIST_RESULT_NO_SUCH_LIST; Error error2(playlist_domain, PLAYLIST_RESULT_NO_SUCH_LIST,
error.GetMessage());
error = std::move(error2);
}
return print_error(client, error); return print_error(client, error);
} }
...@@ -100,8 +104,8 @@ handle_listplaylist(Client *client, gcc_unused int argc, char *argv[]) ...@@ -100,8 +104,8 @@ handle_listplaylist(Client *client, gcc_unused int argc, char *argv[])
if (playlist_file_print(client, argv[1], false)) if (playlist_file_print(client, argv[1], false))
return COMMAND_RETURN_OK; return COMMAND_RETURN_OK;
GError *error = NULL; Error error;
return spl_print(client, argv[1], false, &error) return spl_print(client, argv[1], false, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -113,8 +117,8 @@ handle_listplaylistinfo(Client *client, ...@@ -113,8 +117,8 @@ handle_listplaylistinfo(Client *client,
if (playlist_file_print(client, argv[1], true)) if (playlist_file_print(client, argv[1], true))
return COMMAND_RETURN_OK; return COMMAND_RETURN_OK;
GError *error = NULL; Error error;
return spl_print(client, argv[1], true, &error) return spl_print(client, argv[1], true, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -122,8 +126,8 @@ handle_listplaylistinfo(Client *client, ...@@ -122,8 +126,8 @@ handle_listplaylistinfo(Client *client,
enum command_return enum command_return
handle_rm(Client *client, gcc_unused int argc, char *argv[]) handle_rm(Client *client, gcc_unused int argc, char *argv[])
{ {
GError *error = NULL; Error error;
return spl_delete(argv[1], &error) return spl_delete(argv[1], error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -131,8 +135,8 @@ handle_rm(Client *client, gcc_unused int argc, char *argv[]) ...@@ -131,8 +135,8 @@ handle_rm(Client *client, gcc_unused int argc, char *argv[])
enum command_return enum command_return
handle_rename(Client *client, gcc_unused int argc, char *argv[]) handle_rename(Client *client, gcc_unused int argc, char *argv[])
{ {
GError *error = NULL; Error error;
return spl_rename(argv[1], argv[2], &error) return spl_rename(argv[1], argv[2], error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -146,8 +150,8 @@ handle_playlistdelete(Client *client, ...@@ -146,8 +150,8 @@ handle_playlistdelete(Client *client,
if (!check_unsigned(client, &from, argv[2])) if (!check_unsigned(client, &from, argv[2]))
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
GError *error = NULL; Error error;
return spl_remove_index(playlist, from, &error) return spl_remove_index(playlist, from, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -163,8 +167,8 @@ handle_playlistmove(Client *client, gcc_unused int argc, char *argv[]) ...@@ -163,8 +167,8 @@ handle_playlistmove(Client *client, gcc_unused int argc, char *argv[])
if (!check_unsigned(client, &to, argv[3])) if (!check_unsigned(client, &to, argv[3]))
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
GError *error = NULL; Error error;
return spl_move_index(playlist, from, to, &error) return spl_move_index(playlist, from, to, error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -172,8 +176,8 @@ handle_playlistmove(Client *client, gcc_unused int argc, char *argv[]) ...@@ -172,8 +176,8 @@ handle_playlistmove(Client *client, gcc_unused int argc, char *argv[])
enum command_return enum command_return
handle_playlistclear(Client *client, gcc_unused int argc, char *argv[]) handle_playlistclear(Client *client, gcc_unused int argc, char *argv[])
{ {
GError *error = NULL; Error error;
return spl_clear(argv[1], &error) return spl_clear(argv[1], error)
? COMMAND_RETURN_OK ? COMMAND_RETURN_OK
: print_error(client, error); : print_error(client, error);
} }
...@@ -185,7 +189,7 @@ handle_playlistadd(Client *client, gcc_unused int argc, char *argv[]) ...@@ -185,7 +189,7 @@ handle_playlistadd(Client *client, gcc_unused int argc, char *argv[])
char *uri = argv[2]; char *uri = argv[2];
bool success; bool success;
GError *error = NULL; Error error;
if (uri_has_scheme(uri)) { if (uri_has_scheme(uri)) {
if (!uri_supported_scheme(uri)) { if (!uri_supported_scheme(uri)) {
command_error(client, ACK_ERROR_NO_EXIST, command_error(client, ACK_ERROR_NO_EXIST,
...@@ -193,12 +197,12 @@ handle_playlistadd(Client *client, gcc_unused int argc, char *argv[]) ...@@ -193,12 +197,12 @@ handle_playlistadd(Client *client, gcc_unused int argc, char *argv[])
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
} }
success = spl_append_uri(uri, playlist, &error); success = spl_append_uri(uri, playlist, error);
} else } else
success = search_add_to_playlist(uri, playlist, nullptr, success = search_add_to_playlist(uri, playlist, nullptr,
&error); error);
if (!success && error == NULL) { if (!success && !error.IsDefined()) {
command_error(client, ACK_ERROR_NO_EXIST, command_error(client, ACK_ERROR_NO_EXIST,
"directory or file not found"); "directory or file not found");
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
...@@ -211,9 +215,9 @@ enum command_return ...@@ -211,9 +215,9 @@ enum command_return
handle_listplaylists(Client *client, handle_listplaylists(Client *client,
gcc_unused int argc, gcc_unused char *argv[]) gcc_unused int argc, gcc_unused char *argv[])
{ {
GError *error = NULL; Error error;
const auto list = ListPlaylistFiles(&error); const auto list = ListPlaylistFiles(error);
if (list.empty() && error != NULL) if (list.empty() && error.IsDefined())
return print_error(client, error); return print_error(client, error);
print_spl_list(client, list); print_spl_list(client, list);
......
...@@ -22,15 +22,13 @@ ...@@ -22,15 +22,13 @@
#include "PlaylistVector.hxx" #include "PlaylistVector.hxx"
#include "TextFile.hxx" #include "TextFile.hxx"
#include "util/StringUtil.hxx" #include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
static GQuark static constexpr Domain playlist_database_domain("playlist_database");
playlist_database_quark(void)
{
return g_quark_from_static_string("playlist_database");
}
void void
playlist_vector_save(FILE *fp, const PlaylistVector &pv) playlist_vector_save(FILE *fp, const PlaylistVector &pv)
...@@ -44,7 +42,7 @@ playlist_vector_save(FILE *fp, const PlaylistVector &pv) ...@@ -44,7 +42,7 @@ playlist_vector_save(FILE *fp, const PlaylistVector &pv)
bool bool
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
GError **error_r) Error &error)
{ {
PlaylistInfo pm(name, 0); PlaylistInfo pm(name, 0);
...@@ -55,7 +53,7 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, ...@@ -55,7 +53,7 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
strcmp(line, "playlist_end") != 0) { strcmp(line, "playlist_end") != 0) {
colon = strchr(line, ':'); colon = strchr(line, ':');
if (colon == NULL || colon == line) { if (colon == NULL || colon == line) {
g_set_error(error_r, playlist_database_quark(), 0, error.Format(playlist_database_domain,
"unknown line in db: %s", line); "unknown line in db: %s", line);
return false; return false;
} }
...@@ -66,7 +64,7 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, ...@@ -66,7 +64,7 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
if (strcmp(line, "mtime") == 0) if (strcmp(line, "mtime") == 0)
pm.mtime = strtol(value, NULL, 10); pm.mtime = strtol(value, NULL, 10);
else { else {
g_set_error(error_r, playlist_database_quark(), 0, error.Format(playlist_database_domain,
"unknown line in db: %s", line); "unknown line in db: %s", line);
return false; return false;
} }
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#define MPD_PLAYLIST_DATABASE_HXX #define MPD_PLAYLIST_DATABASE_HXX
#include "check.h" #include "check.h"
#include "gerror.h"
#include <stdio.h> #include <stdio.h>
...@@ -29,12 +28,13 @@ ...@@ -29,12 +28,13 @@
class PlaylistVector; class PlaylistVector;
class TextFile; class TextFile;
class Error;
void void
playlist_vector_save(FILE *fp, const PlaylistVector &pv); playlist_vector_save(FILE *fp, const PlaylistVector &pv);
bool bool
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name, playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
GError **error_r); Error &error);
#endif #endif
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "Playlist.hxx" #include "Playlist.hxx"
#include "PlayerControl.hxx" #include "PlayerControl.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "Idle.hxx" #include "Idle.hxx"
#include "DatabaseGlue.hxx" #include "DatabaseGlue.hxx"
...@@ -110,11 +111,11 @@ playlist::AppendURI(struct player_control &pc, ...@@ -110,11 +111,11 @@ playlist::AppendURI(struct player_control &pc,
if (uri_has_scheme(uri)) { if (uri_has_scheme(uri)) {
song = Song::NewRemote(uri); song = Song::NewRemote(uri);
} else { } else {
db = GetDatabase(nullptr); db = GetDatabase(IgnoreError());
if (db == nullptr) if (db == nullptr)
return PLAYLIST_RESULT_NO_SUCH_SONG; return PLAYLIST_RESULT_NO_SUCH_SONG;
song = db->GetSong(uri, nullptr); song = db->GetSong(uri, IgnoreError());
if (song == nullptr) if (song == nullptr)
return PLAYLIST_RESULT_NO_SUCH_SONG; return PLAYLIST_RESULT_NO_SUCH_SONG;
} }
......
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "PlaylistError.hxx"
#include "util/Domain.hxx"
const Domain playlist_domain("playlist");
...@@ -20,9 +20,7 @@ ...@@ -20,9 +20,7 @@
#ifndef MPD_PLAYLIST_ERROR_HXX #ifndef MPD_PLAYLIST_ERROR_HXX
#define MPD_PLAYLIST_ERROR_HXX #define MPD_PLAYLIST_ERROR_HXX
#include "gcc.h" class Domain;
#include <glib.h>
enum playlist_result { enum playlist_result {
PLAYLIST_RESULT_SUCCESS, PLAYLIST_RESULT_SUCCESS,
...@@ -38,14 +36,6 @@ enum playlist_result { ...@@ -38,14 +36,6 @@ enum playlist_result {
PLAYLIST_RESULT_DISABLED, PLAYLIST_RESULT_DISABLED,
}; };
/** extern const Domain playlist_domain;
* Quark for GError.domain; the code is an enum #playlist_result.
*/
gcc_const
static inline GQuark
playlist_quark(void)
{
return g_quark_from_static_string("playlist");
}
#endif #endif
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "DatabasePlugin.hxx" #include "DatabasePlugin.hxx"
#include "DatabaseGlue.hxx" #include "DatabaseGlue.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "io_error.h"
#include "Mapper.hxx" #include "Mapper.hxx"
#include "TextFile.hxx" #include "TextFile.hxx"
#include "conf.h" #include "conf.h"
...@@ -34,6 +33,7 @@ ...@@ -34,6 +33,7 @@
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "fs/DirectoryReader.hxx" #include "fs/DirectoryReader.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include <assert.h> #include <assert.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -79,22 +79,20 @@ spl_valid_name(const char *name_utf8) ...@@ -79,22 +79,20 @@ spl_valid_name(const char *name_utf8)
} }
static const Path & static const Path &
spl_map(GError **error_r) spl_map(Error &error)
{ {
const Path &path_fs = map_spl_path(); const Path &path_fs = map_spl_path();
if (path_fs.IsNull()) if (path_fs.IsNull())
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_DISABLED,
PLAYLIST_RESULT_DISABLED,
"Stored playlists are disabled"); "Stored playlists are disabled");
return path_fs; return path_fs;
} }
static bool static bool
spl_check_name(const char *name_utf8, GError **error_r) spl_check_name(const char *name_utf8, Error &error)
{ {
if (!spl_valid_name(name_utf8)) { if (!spl_valid_name(name_utf8)) {
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_BAD_NAME,
PLAYLIST_RESULT_BAD_NAME,
"Bad playlist name"); "Bad playlist name");
return false; return false;
} }
...@@ -103,35 +101,33 @@ spl_check_name(const char *name_utf8, GError **error_r) ...@@ -103,35 +101,33 @@ spl_check_name(const char *name_utf8, GError **error_r)
} }
static Path static Path
spl_map_to_fs(const char *name_utf8, GError **error_r) spl_map_to_fs(const char *name_utf8, Error &error)
{ {
if (spl_map(error_r).IsNull() || !spl_check_name(name_utf8, error_r)) if (spl_map(error).IsNull() || !spl_check_name(name_utf8, error))
return Path::Null(); return Path::Null();
Path path_fs = map_spl_utf8_to_fs(name_utf8); Path path_fs = map_spl_utf8_to_fs(name_utf8);
if (path_fs.IsNull()) if (path_fs.IsNull())
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_BAD_NAME,
PLAYLIST_RESULT_BAD_NAME,
"Bad playlist name"); "Bad playlist name");
return path_fs; return path_fs;
} }
/** /**
* Create a GError for the current errno. * Create an #Error for the current errno.
*/ */
static void static void
playlist_errno(GError **error_r) playlist_errno(Error &error)
{ {
switch (errno) { switch (errno) {
case ENOENT: case ENOENT:
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_NO_SUCH_LIST,
PLAYLIST_RESULT_NO_SUCH_LIST,
"No such playlist"); "No such playlist");
break; break;
default: default:
set_error_errno(error_r); error.SetErrno();
break; break;
} }
} }
...@@ -168,17 +164,17 @@ LoadPlaylistFileInfo(PlaylistInfo &info, ...@@ -168,17 +164,17 @@ LoadPlaylistFileInfo(PlaylistInfo &info,
} }
PlaylistVector PlaylistVector
ListPlaylistFiles(GError **error_r) ListPlaylistFiles(Error &error)
{ {
PlaylistVector list; PlaylistVector list;
const Path &parent_path_fs = spl_map(error_r); const Path &parent_path_fs = spl_map(error);
if (parent_path_fs.IsNull()) if (parent_path_fs.IsNull())
return list; return list;
DirectoryReader reader(parent_path_fs); DirectoryReader reader(parent_path_fs);
if (reader.HasFailed()) { if (reader.HasFailed()) {
set_error_errno(error_r); error.SetErrno();
return list; return list;
} }
...@@ -194,20 +190,20 @@ ListPlaylistFiles(GError **error_r) ...@@ -194,20 +190,20 @@ ListPlaylistFiles(GError **error_r)
static bool static bool
SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path, SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path,
GError **error_r) Error &error)
{ {
assert(utf8path != NULL); assert(utf8path != NULL);
if (spl_map(error_r).IsNull()) if (spl_map(error).IsNull())
return false; return false;
const Path path_fs = spl_map_to_fs(utf8path, error_r); const Path path_fs = spl_map_to_fs(utf8path, error);
if (path_fs.IsNull()) if (path_fs.IsNull())
return false; return false;
FILE *file = FOpen(path_fs, FOpenMode::WriteText); FILE *file = FOpen(path_fs, FOpenMode::WriteText);
if (file == NULL) { if (file == NULL) {
playlist_errno(error_r); playlist_errno(error);
return false; return false;
} }
...@@ -219,20 +215,20 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path, ...@@ -219,20 +215,20 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path,
} }
PlaylistFileContents PlaylistFileContents
LoadPlaylistFile(const char *utf8path, GError **error_r) LoadPlaylistFile(const char *utf8path, Error &error)
{ {
PlaylistFileContents contents; PlaylistFileContents contents;
if (spl_map(error_r).IsNull()) if (spl_map(error).IsNull())
return contents; return contents;
const Path path_fs = spl_map_to_fs(utf8path, error_r); const Path path_fs = spl_map_to_fs(utf8path, error);
if (path_fs.IsNull()) if (path_fs.IsNull())
return contents; return contents;
TextFile file(path_fs); TextFile file(path_fs);
if (file.HasFailed()) { if (file.HasFailed()) {
playlist_errno(error_r); playlist_errno(error);
return contents; return contents;
} }
...@@ -262,23 +258,19 @@ LoadPlaylistFile(const char *utf8path, GError **error_r) ...@@ -262,23 +258,19 @@ LoadPlaylistFile(const char *utf8path, GError **error_r)
bool bool
spl_move_index(const char *utf8path, unsigned src, unsigned dest, spl_move_index(const char *utf8path, unsigned src, unsigned dest,
GError **error_r) Error &error)
{ {
if (src == dest) if (src == dest)
/* this doesn't check whether the playlist exists, but /* this doesn't check whether the playlist exists, but
what the hell.. */ what the hell.. */
return true; return true;
GError *error = nullptr; auto contents = LoadPlaylistFile(utf8path, error);
auto contents = LoadPlaylistFile(utf8path, &error); if (contents.empty() && error.IsDefined())
if (contents.empty() && error != nullptr) {
g_propagate_error(error_r, error);
return false; return false;
}
if (src >= contents.size() || dest >= contents.size()) { if (src >= contents.size() || dest >= contents.size()) {
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_BAD_RANGE,
PLAYLIST_RESULT_BAD_RANGE,
"Bad range"); "Bad range");
return false; return false;
} }
...@@ -290,25 +282,25 @@ spl_move_index(const char *utf8path, unsigned src, unsigned dest, ...@@ -290,25 +282,25 @@ spl_move_index(const char *utf8path, unsigned src, unsigned dest,
const auto dest_i = std::next(contents.begin(), dest); const auto dest_i = std::next(contents.begin(), dest);
contents.insert(dest_i, std::move(value)); contents.insert(dest_i, std::move(value));
bool result = SavePlaylistFile(contents, utf8path, error_r); bool result = SavePlaylistFile(contents, utf8path, error);
idle_add(IDLE_STORED_PLAYLIST); idle_add(IDLE_STORED_PLAYLIST);
return result; return result;
} }
bool bool
spl_clear(const char *utf8path, GError **error_r) spl_clear(const char *utf8path, Error &error)
{ {
if (spl_map(error_r).IsNull()) if (spl_map(error).IsNull())
return false; return false;
const Path path_fs = spl_map_to_fs(utf8path, error_r); const Path path_fs = spl_map_to_fs(utf8path, error);
if (path_fs.IsNull()) if (path_fs.IsNull())
return false; return false;
FILE *file = FOpen(path_fs, FOpenMode::WriteText); FILE *file = FOpen(path_fs, FOpenMode::WriteText);
if (file == NULL) { if (file == NULL) {
playlist_errno(error_r); playlist_errno(error);
return false; return false;
} }
...@@ -319,14 +311,14 @@ spl_clear(const char *utf8path, GError **error_r) ...@@ -319,14 +311,14 @@ spl_clear(const char *utf8path, GError **error_r)
} }
bool bool
spl_delete(const char *name_utf8, GError **error_r) spl_delete(const char *name_utf8, Error &error)
{ {
const Path path_fs = spl_map_to_fs(name_utf8, error_r); const Path path_fs = spl_map_to_fs(name_utf8, error);
if (path_fs.IsNull()) if (path_fs.IsNull())
return false; return false;
if (!RemoveFile(path_fs)) { if (!RemoveFile(path_fs)) {
playlist_errno(error_r); playlist_errno(error);
return false; return false;
} }
...@@ -335,57 +327,52 @@ spl_delete(const char *name_utf8, GError **error_r) ...@@ -335,57 +327,52 @@ spl_delete(const char *name_utf8, GError **error_r)
} }
bool bool
spl_remove_index(const char *utf8path, unsigned pos, GError **error_r) spl_remove_index(const char *utf8path, unsigned pos, Error &error)
{ {
GError *error = nullptr; auto contents = LoadPlaylistFile(utf8path, error);
auto contents = LoadPlaylistFile(utf8path, &error); if (contents.empty() && error.IsDefined())
if (contents.empty() && error != nullptr) {
g_propagate_error(error_r, error);
return false; return false;
}
if (pos >= contents.size()) { if (pos >= contents.size()) {
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_BAD_RANGE,
PLAYLIST_RESULT_BAD_RANGE,
"Bad range"); "Bad range");
return false; return false;
} }
contents.erase(std::next(contents.begin(), pos)); contents.erase(std::next(contents.begin(), pos));
bool result = SavePlaylistFile(contents, utf8path, error_r); bool result = SavePlaylistFile(contents, utf8path, error);
idle_add(IDLE_STORED_PLAYLIST); idle_add(IDLE_STORED_PLAYLIST);
return result; return result;
} }
bool bool
spl_append_song(const char *utf8path, Song *song, GError **error_r) spl_append_song(const char *utf8path, Song *song, Error &error)
{ {
if (spl_map(error_r).IsNull()) if (spl_map(error).IsNull())
return false; return false;
const Path path_fs = spl_map_to_fs(utf8path, error_r); const Path path_fs = spl_map_to_fs(utf8path, error);
if (path_fs.IsNull()) if (path_fs.IsNull())
return false; return false;
FILE *file = FOpen(path_fs, FOpenMode::AppendText); FILE *file = FOpen(path_fs, FOpenMode::AppendText);
if (file == NULL) { if (file == NULL) {
playlist_errno(error_r); playlist_errno(error);
return false; return false;
} }
struct stat st; struct stat st;
if (fstat(fileno(file), &st) < 0) { if (fstat(fileno(file), &st) < 0) {
playlist_errno(error_r); playlist_errno(error);
fclose(file); fclose(file);
return false; return false;
} }
if (st.st_size / (MPD_PATH_MAX + 1) >= (off_t)playlist_max_length) { if (st.st_size / (MPD_PATH_MAX + 1) >= (off_t)playlist_max_length) {
fclose(file); fclose(file);
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_TOO_LARGE,
PLAYLIST_RESULT_TOO_LARGE,
"Stored playlist is too large"); "Stored playlist is too large");
return false; return false;
} }
...@@ -399,23 +386,23 @@ spl_append_song(const char *utf8path, Song *song, GError **error_r) ...@@ -399,23 +386,23 @@ spl_append_song(const char *utf8path, Song *song, GError **error_r)
} }
bool bool
spl_append_uri(const char *url, const char *utf8file, GError **error_r) spl_append_uri(const char *url, const char *utf8file, Error &error)
{ {
if (uri_has_scheme(url)) { if (uri_has_scheme(url)) {
Song *song = Song::NewRemote(url); Song *song = Song::NewRemote(url);
bool success = spl_append_song(utf8file, song, error_r); bool success = spl_append_song(utf8file, song, error);
song->Free(); song->Free();
return success; return success;
} else { } else {
const Database *db = GetDatabase(error_r); const Database *db = GetDatabase(error);
if (db == nullptr) if (db == nullptr)
return false; return false;
Song *song = db->GetSong(url, error_r); Song *song = db->GetSong(url, error);
if (song == nullptr) if (song == nullptr)
return false; return false;
bool success = spl_append_song(utf8file, song, error_r); bool success = spl_append_song(utf8file, song, error);
db->ReturnSong(song); db->ReturnSong(song);
return success; return success;
} }
...@@ -423,24 +410,22 @@ spl_append_uri(const char *url, const char *utf8file, GError **error_r) ...@@ -423,24 +410,22 @@ spl_append_uri(const char *url, const char *utf8file, GError **error_r)
static bool static bool
spl_rename_internal(const Path &from_path_fs, const Path &to_path_fs, spl_rename_internal(const Path &from_path_fs, const Path &to_path_fs,
GError **error_r) Error &error)
{ {
if (!FileExists(from_path_fs)) { if (!FileExists(from_path_fs)) {
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_NO_SUCH_LIST,
PLAYLIST_RESULT_NO_SUCH_LIST,
"No such playlist"); "No such playlist");
return false; return false;
} }
if (FileExists(to_path_fs)) { if (FileExists(to_path_fs)) {
g_set_error_literal(error_r, playlist_quark(), error.Set(playlist_domain, PLAYLIST_RESULT_LIST_EXISTS,
PLAYLIST_RESULT_LIST_EXISTS,
"Playlist exists already"); "Playlist exists already");
return false; return false;
} }
if (!RenameFile(from_path_fs, to_path_fs)) { if (!RenameFile(from_path_fs, to_path_fs)) {
playlist_errno(error_r); playlist_errno(error);
return false; return false;
} }
...@@ -449,18 +434,18 @@ spl_rename_internal(const Path &from_path_fs, const Path &to_path_fs, ...@@ -449,18 +434,18 @@ spl_rename_internal(const Path &from_path_fs, const Path &to_path_fs,
} }
bool bool
spl_rename(const char *utf8from, const char *utf8to, GError **error_r) spl_rename(const char *utf8from, const char *utf8to, Error &error)
{ {
if (spl_map(error_r).IsNull()) if (spl_map(error).IsNull())
return false; return false;
Path from_path_fs = spl_map_to_fs(utf8from, error_r); Path from_path_fs = spl_map_to_fs(utf8from, error);
if (from_path_fs.IsNull()) if (from_path_fs.IsNull())
return false; return false;
Path to_path_fs = spl_map_to_fs(utf8to, error_r); Path to_path_fs = spl_map_to_fs(utf8to, error);
if (to_path_fs.IsNull()) if (to_path_fs.IsNull())
return false; return false;
return spl_rename_internal(from_path_fs, to_path_fs, error_r); return spl_rename_internal(from_path_fs, to_path_fs, error);
} }
...@@ -20,14 +20,13 @@ ...@@ -20,14 +20,13 @@
#ifndef MPD_PLAYLIST_FILE_HXX #ifndef MPD_PLAYLIST_FILE_HXX
#define MPD_PLAYLIST_FILE_HXX #define MPD_PLAYLIST_FILE_HXX
#include "gerror.h"
#include <vector> #include <vector>
#include <string> #include <string>
struct Song; struct Song;
struct PlaylistInfo; struct PlaylistInfo;
class PlaylistVector; class PlaylistVector;
class Error;
typedef std::vector<std::string> PlaylistFileContents; typedef std::vector<std::string> PlaylistFileContents;
...@@ -51,31 +50,31 @@ spl_valid_name(const char *name_utf8); ...@@ -51,31 +50,31 @@ spl_valid_name(const char *name_utf8);
* NULL if an error occurred. * NULL if an error occurred.
*/ */
PlaylistVector PlaylistVector
ListPlaylistFiles(GError **error_r); ListPlaylistFiles(Error &error);
PlaylistFileContents PlaylistFileContents
LoadPlaylistFile(const char *utf8path, GError **error_r); LoadPlaylistFile(const char *utf8path, Error &error);
bool bool
spl_move_index(const char *utf8path, unsigned src, unsigned dest, spl_move_index(const char *utf8path, unsigned src, unsigned dest,
GError **error_r); Error &error);
bool bool
spl_clear(const char *utf8path, GError **error_r); spl_clear(const char *utf8path, Error &error);
bool bool
spl_delete(const char *name_utf8, GError **error_r); spl_delete(const char *name_utf8, Error &error);
bool bool
spl_remove_index(const char *utf8path, unsigned pos, GError **error_r); spl_remove_index(const char *utf8path, unsigned pos, Error &error);
bool bool
spl_append_song(const char *utf8path, Song *song, GError **error_r); spl_append_song(const char *utf8path, Song *song, Error &error);
bool bool
spl_append_uri(const char *file, const char *utf8file, GError **error_r); spl_append_uri(const char *file, const char *utf8file, Error &error);
bool bool
spl_rename(const char *utf8from, const char *utf8to, GError **error_r); spl_rename(const char *utf8from, const char *utf8to, Error &error);
#endif #endif
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "Client.hxx" #include "Client.hxx"
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "util/Error.hxx"
void void
playlist_print_uris(Client *client, const struct playlist *playlist) playlist_print_uris(Client *client, const struct playlist *playlist)
...@@ -112,11 +113,11 @@ playlist_print_changes_position(Client *client, ...@@ -112,11 +113,11 @@ playlist_print_changes_position(Client *client,
static bool static bool
PrintSongDetails(Client *client, const char *uri_utf8) PrintSongDetails(Client *client, const char *uri_utf8)
{ {
const Database *db = GetDatabase(nullptr); const Database *db = GetDatabase(IgnoreError());
if (db == nullptr) if (db == nullptr)
return false; return false;
Song *song = db->GetSong(uri_utf8, nullptr); Song *song = db->GetSong(uri_utf8, IgnoreError());
if (song == nullptr) if (song == nullptr)
return false; return false;
...@@ -127,14 +128,11 @@ PrintSongDetails(Client *client, const char *uri_utf8) ...@@ -127,14 +128,11 @@ PrintSongDetails(Client *client, const char *uri_utf8)
bool bool
spl_print(Client *client, const char *name_utf8, bool detail, spl_print(Client *client, const char *name_utf8, bool detail,
GError **error_r) Error &error)
{ {
GError *error = NULL; PlaylistFileContents contents = LoadPlaylistFile(name_utf8, error);
PlaylistFileContents contents = LoadPlaylistFile(name_utf8, &error); if (contents.empty() && error.IsDefined())
if (contents.empty() && error != nullptr) {
g_propagate_error(error_r, error);
return false; return false;
}
for (const auto &uri_utf8 : contents) { for (const auto &uri_utf8 : contents) {
if (!detail || !PrintSongDetails(client, uri_utf8.c_str())) if (!detail || !PrintSongDetails(client, uri_utf8.c_str()))
......
...@@ -20,13 +20,12 @@ ...@@ -20,13 +20,12 @@
#ifndef MPD_PLAYLIST_PRINT_HXX #ifndef MPD_PLAYLIST_PRINT_HXX
#define MPD_PLAYLIST_PRINT_HXX #define MPD_PLAYLIST_PRINT_HXX
#include "gerror.h"
#include <stdint.h> #include <stdint.h>
struct playlist; struct playlist;
class SongFilter; class SongFilter;
class Client; class Client;
class Error;
/** /**
* Sends the whole playlist to the client, song URIs only. * Sends the whole playlist to the client, song URIs only.
...@@ -94,7 +93,7 @@ playlist_print_changes_position(Client *client, ...@@ -94,7 +93,7 @@ playlist_print_changes_position(Client *client,
*/ */
bool bool
spl_print(Client *client, const char *name_utf8, bool detail, spl_print(Client *client, const char *name_utf8, bool detail,
GError **error_r); Error &error);
/** /**
* Send the playlist file to the client. * Send the playlist file to the client.
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/StringUtil.hxx" #include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "conf.h" #include "conf.h"
#include "mpd_error.h" #include "mpd_error.h"
...@@ -219,7 +220,8 @@ playlist_list_open_stream_mime2(struct input_stream *is, const char *mime) ...@@ -219,7 +220,8 @@ playlist_list_open_stream_mime2(struct input_stream *is, const char *mime)
string_array_contains(plugin->mime_types, mime)) { string_array_contains(plugin->mime_types, mime)) {
/* rewind the stream, so each plugin gets a /* rewind the stream, so each plugin gets a
fresh start */ fresh start */
input_stream_seek(is, 0, SEEK_SET, NULL); Error error;
input_stream_seek(is, 0, SEEK_SET, error);
playlist = playlist_plugin_open_stream(plugin, is); playlist = playlist_plugin_open_stream(plugin, is);
if (playlist != NULL) if (playlist != NULL)
...@@ -264,7 +266,8 @@ playlist_list_open_stream_suffix(struct input_stream *is, const char *suffix) ...@@ -264,7 +266,8 @@ playlist_list_open_stream_suffix(struct input_stream *is, const char *suffix)
string_array_contains(plugin->suffixes, suffix)) { string_array_contains(plugin->suffixes, suffix)) {
/* rewind the stream, so each plugin gets a /* rewind the stream, so each plugin gets a
fresh start */ fresh start */
input_stream_seek(is, 0, SEEK_SET, NULL); Error error;
input_stream_seek(is, 0, SEEK_SET, error);
playlist = playlist_plugin_open_stream(plugin, is); playlist = playlist_plugin_open_stream(plugin, is);
if (playlist != NULL) if (playlist != NULL)
...@@ -318,9 +321,7 @@ struct playlist_provider * ...@@ -318,9 +321,7 @@ struct playlist_provider *
playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond,
struct input_stream **is_r) struct input_stream **is_r)
{ {
GError *error = NULL;
const char *suffix; const char *suffix;
struct input_stream *is;
struct playlist_provider *playlist; struct playlist_provider *playlist;
assert(path_fs != NULL); assert(path_fs != NULL);
...@@ -329,12 +330,11 @@ playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond, ...@@ -329,12 +330,11 @@ playlist_list_open_path(const char *path_fs, Mutex &mutex, Cond &cond,
if (suffix == NULL || !playlist_suffix_supported(suffix)) if (suffix == NULL || !playlist_suffix_supported(suffix))
return NULL; return NULL;
is = input_stream_open(path_fs, mutex, cond, &error); Error error;
input_stream *is = input_stream_open(path_fs, mutex, cond, error);
if (is == NULL) { if (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;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -99,14 +100,11 @@ bool ...@@ -99,14 +100,11 @@ bool
playlist_load_spl(struct playlist *playlist, struct player_control *pc, playlist_load_spl(struct playlist *playlist, struct player_control *pc,
const char *name_utf8, const char *name_utf8,
unsigned start_index, unsigned end_index, unsigned start_index, unsigned end_index,
GError **error_r) Error &error)
{ {
GError *error = NULL; PlaylistFileContents contents = LoadPlaylistFile(name_utf8, error);
PlaylistFileContents contents = LoadPlaylistFile(name_utf8, &error); if (contents.empty() && error.IsDefined())
if (contents.empty() && error != nullptr) {
g_propagate_error(error_r, error);
return false; return false;
}
if (end_index > contents.size()) if (end_index > contents.size())
end_index = contents.size(); end_index = contents.size();
......
...@@ -28,6 +28,7 @@ struct Song; ...@@ -28,6 +28,7 @@ struct Song;
struct queue; struct queue;
struct playlist; struct playlist;
struct player_control; struct player_control;
class Error;
void void
playlist_print_song(FILE *fp, const Song *song); playlist_print_song(FILE *fp, const Song *song);
...@@ -55,6 +56,6 @@ bool ...@@ -55,6 +56,6 @@ bool
playlist_load_spl(struct playlist *playlist, struct player_control *pc, playlist_load_spl(struct playlist *playlist, struct player_control *pc,
const char *name_utf8, const char *name_utf8,
unsigned start_index, unsigned end_index, unsigned start_index, unsigned end_index,
GError **error_r); Error &error);
#endif #endif
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "Tag.hxx" #include "Tag.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "Song.hxx" #include "Song.hxx"
#include <glib.h> #include <glib.h>
...@@ -102,11 +103,11 @@ playlist_check_load_song(const Song *song, const char *uri, bool secure) ...@@ -102,11 +103,11 @@ playlist_check_load_song(const Song *song, const char *uri, bool secure)
if (dest == NULL) if (dest == NULL)
return NULL; return NULL;
} else { } else {
const Database *db = GetDatabase(nullptr); const Database *db = GetDatabase(IgnoreError());
if (db == nullptr) if (db == nullptr)
return nullptr; return nullptr;
Song *tmp = db->GetSong(uri, nullptr); Song *tmp = db->GetSong(uri, IgnoreError());
if (tmp == NULL) if (tmp == NULL)
/* not found in database */ /* not found in database */
return NULL; return NULL;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "ls.hxx" #include "ls.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include <string.h> #include <string.h>
...@@ -52,8 +53,8 @@ handle_add(Client *client, gcc_unused int argc, char *argv[]) ...@@ -52,8 +53,8 @@ handle_add(Client *client, gcc_unused 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);
result = client->partition.AppendFile(path_utf8); result = client->partition.AppendFile(path_utf8);
...@@ -72,8 +73,8 @@ handle_add(Client *client, gcc_unused int argc, char *argv[]) ...@@ -72,8 +73,8 @@ handle_add(Client *client, gcc_unused int argc, char *argv[])
} }
const DatabaseSelection selection(uri, true); const DatabaseSelection selection(uri, true);
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);
} }
...@@ -95,8 +96,8 @@ handle_addid(Client *client, int argc, char *argv[]) ...@@ -95,8 +96,8 @@ handle_addid(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);
result = client->partition.AppendFile(path_utf8, &added_id); result = client->partition.AppendFile(path_utf8, &added_id);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "DatabaseGlue.hxx" #include "DatabaseGlue.hxx"
#include "TextFile.hxx" #include "TextFile.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include <stdlib.h> #include <stdlib.h>
...@@ -90,11 +91,10 @@ queue_load_song(TextFile &file, const char *line, queue *queue) ...@@ -90,11 +91,10 @@ queue_load_song(TextFile &file, const char *line, queue *queue)
if (!uri_has_scheme(uri) && !g_path_is_absolute(uri)) if (!uri_has_scheme(uri) && !g_path_is_absolute(uri))
return; return;
GError *error = NULL; Error error;
song = song_load(file, NULL, uri, &error); song = song_load(file, NULL, uri, error);
if (song == NULL) { if (song == NULL) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return; return;
} }
} else { } else {
...@@ -110,11 +110,11 @@ queue_load_song(TextFile &file, const char *line, queue *queue) ...@@ -110,11 +110,11 @@ queue_load_song(TextFile &file, const char *line, queue *queue)
if (uri_has_scheme(uri)) { if (uri_has_scheme(uri)) {
song = Song::NewRemote(uri); song = Song::NewRemote(uri);
} else { } else {
db = GetDatabase(nullptr); db = GetDatabase(IgnoreError());
if (db == nullptr) if (db == nullptr)
return; return;
song = db->GetSong(uri, nullptr); song = db->GetSong(uri, IgnoreError());
if (song == nullptr) if (song == nullptr)
return; return;
} }
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "TextFile.hxx" #include "TextFile.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/StringUtil.hxx" #include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -36,11 +38,7 @@ ...@@ -36,11 +38,7 @@
#define SONG_MTIME "mtime" #define SONG_MTIME "mtime"
#define SONG_END "song_end" #define SONG_END "song_end"
static GQuark static constexpr Domain song_save_domain("song_save");
song_save_quark(void)
{
return g_quark_from_static_string("song_save");
}
void void
song_save(FILE *fp, const Song *song) song_save(FILE *fp, const Song *song)
...@@ -61,7 +59,7 @@ song_save(FILE *fp, const Song *song) ...@@ -61,7 +59,7 @@ song_save(FILE *fp, const Song *song)
Song * Song *
song_load(TextFile &file, Directory *parent, const char *uri, song_load(TextFile &file, Directory *parent, const char *uri,
GError **error_r) Error &error)
{ {
Song *song = parent != NULL Song *song = parent != NULL
? Song::NewFile(uri, parent) ? Song::NewFile(uri, parent)
...@@ -78,7 +76,7 @@ song_load(TextFile &file, Directory *parent, const char *uri, ...@@ -78,7 +76,7 @@ song_load(TextFile &file, Directory *parent, const char *uri,
song->tag->EndAdd(); song->tag->EndAdd();
song->Free(); song->Free();
g_set_error(error_r, song_save_quark(), 0, error.Format(song_save_domain,
"unknown line in db: %s", line); "unknown line in db: %s", line);
return NULL; return NULL;
} }
...@@ -120,7 +118,7 @@ song_load(TextFile &file, Directory *parent, const char *uri, ...@@ -120,7 +118,7 @@ song_load(TextFile &file, Directory *parent, const char *uri,
song->tag->EndAdd(); song->tag->EndAdd();
song->Free(); song->Free();
g_set_error(error_r, song_save_quark(), 0, error.Format(song_save_domain,
"unknown line in db: %s", line); "unknown line in db: %s", line);
return NULL; return NULL;
} }
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#ifndef MPD_SONG_SAVE_HXX #ifndef MPD_SONG_SAVE_HXX
#define MPD_SONG_SAVE_HXX #define MPD_SONG_SAVE_HXX
#include "gerror.h"
#include <stdio.h> #include <stdio.h>
#define SONG_BEGIN "song_begin: " #define SONG_BEGIN "song_begin: "
...@@ -29,6 +27,7 @@ ...@@ -29,6 +27,7 @@
struct Song; struct Song;
struct Directory; struct Directory;
class TextFile; class TextFile;
class Error;
void void
song_save(FILE *fp, const Song *song); song_save(FILE *fp, const Song *song);
...@@ -37,12 +36,11 @@ song_save(FILE *fp, const Song *song); ...@@ -37,12 +36,11 @@ song_save(FILE *fp, const Song *song);
* Loads a song from the input file. Reading stops after the * Loads a song from the input file. Reading stops after the
* "song_end" line. * "song_end" line.
* *
* @param error_r location to store the error occurring, or NULL to * @param error location to store the error occurring
* ignore errors
* @return true on success, false on error * @return true on success, false on error
*/ */
Song * Song *
song_load(TextFile &file, Directory *parent, const char *uri, song_load(TextFile &file, Directory *parent, const char *uri,
GError **error_r); Error &error);
#endif #endif
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#ifndef MPD_SONG_STICKER_HXX #ifndef MPD_SONG_STICKER_HXX
#define MPD_SONG_STICKER_HXX #define MPD_SONG_STICKER_HXX
#include "gerror.h"
struct Song; struct Song;
struct Directory; struct Directory;
struct sticker; struct sticker;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "config.h" /* must be first for large file support */ #include "config.h" /* must be first for large file support */
#include "Song.hxx" #include "Song.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "Directory.hxx" #include "Directory.hxx"
#include "Mapper.hxx" #include "Mapper.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
...@@ -127,9 +128,10 @@ Song::UpdateFile() ...@@ -127,9 +128,10 @@ Song::UpdateFile()
/* open the input_stream (if not already /* open the input_stream (if not already
open) */ open) */
if (is == NULL) { if (is == NULL) {
Error error;
is = input_stream_open(path_fs.c_str(), is = input_stream_open(path_fs.c_str(),
mutex, cond, mutex, cond,
NULL); error);
} }
/* now try the stream_tag() method */ /* now try the stream_tag() method */
...@@ -143,7 +145,8 @@ Song::UpdateFile() ...@@ -143,7 +145,8 @@ Song::UpdateFile()
delete tag; delete tag;
tag = nullptr; tag = nullptr;
input_stream_lock_seek(is, 0, SEEK_SET, NULL); Error error;
input_stream_lock_seek(is, 0, SEEK_SET, error);
} }
} }
......
...@@ -29,6 +29,7 @@ extern "C" { ...@@ -29,6 +29,7 @@ extern "C" {
#include "DatabaseGlue.hxx" #include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx" #include "DatabasePlugin.hxx"
#include "DatabaseSimple.hxx" #include "DatabaseSimple.hxx"
#include "util/Error.hxx"
struct stats stats; struct stats stats;
...@@ -44,19 +45,18 @@ void stats_global_finish(void) ...@@ -44,19 +45,18 @@ void stats_global_finish(void)
void stats_update(void) void stats_update(void)
{ {
GError *error = nullptr; Error error;
DatabaseStats stats2; DatabaseStats stats2;
const DatabaseSelection selection("", true); const DatabaseSelection selection("", true);
if (GetDatabase()->GetStats(selection, stats2, &error)) { if (GetDatabase()->GetStats(selection, stats2, error)) {
stats.song_count = stats2.song_count; stats.song_count = stats2.song_count;
stats.song_duration = stats2.total_duration; stats.song_duration = stats2.total_duration;
stats.artist_count = stats2.artist_count; stats.artist_count = stats2.artist_count;
stats.album_count = stats2.album_count; stats.album_count = stats2.album_count;
} else { } else {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
stats.song_count = 0; stats.song_count = 0;
stats.song_duration = 0; stats.song_duration = 0;
......
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
#include "StickerDatabase.hxx" #include "StickerDatabase.hxx"
#include "CommandError.hxx" #include "CommandError.hxx"
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <string.h> #include <string.h>
...@@ -39,7 +42,7 @@ struct sticker_song_find_data { ...@@ -39,7 +42,7 @@ struct sticker_song_find_data {
static void static void
sticker_song_find_print_cb(Song *song, const char *value, sticker_song_find_print_cb(Song *song, const char *value,
gpointer user_data) void *user_data)
{ {
struct sticker_song_find_data *data = struct sticker_song_find_data *data =
(struct sticker_song_find_data *)user_data; (struct sticker_song_find_data *)user_data;
...@@ -51,14 +54,14 @@ sticker_song_find_print_cb(Song *song, const char *value, ...@@ -51,14 +54,14 @@ sticker_song_find_print_cb(Song *song, const char *value,
static enum command_return static enum command_return
handle_sticker_song(Client *client, int argc, char *argv[]) handle_sticker_song(Client *client, int argc, char *argv[])
{ {
GError *error = nullptr; Error error;
const Database *db = GetDatabase(&error); const Database *db = GetDatabase(error);
if (db == nullptr) if (db == nullptr)
return print_error(client, error); return print_error(client, error);
/* get song song_id key */ /* get song song_id key */
if (argc == 5 && strcmp(argv[1], "get") == 0) { if (argc == 5 && strcmp(argv[1], "get") == 0) {
Song *song = db->GetSong(argv[3], &error); Song *song = db->GetSong(argv[3], error);
if (song == nullptr) if (song == nullptr)
return print_error(client, error); return print_error(client, error);
...@@ -76,7 +79,7 @@ handle_sticker_song(Client *client, int argc, char *argv[]) ...@@ -76,7 +79,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
return COMMAND_RETURN_OK; return COMMAND_RETURN_OK;
/* list song song_id */ /* list song song_id */
} else if (argc == 4 && strcmp(argv[1], "list") == 0) { } else if (argc == 4 && strcmp(argv[1], "list") == 0) {
Song *song = db->GetSong(argv[3], &error); Song *song = db->GetSong(argv[3], error);
if (song == nullptr) if (song == nullptr)
return print_error(client, error); return print_error(client, error);
...@@ -90,7 +93,7 @@ handle_sticker_song(Client *client, int argc, char *argv[]) ...@@ -90,7 +93,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
return COMMAND_RETURN_OK; return COMMAND_RETURN_OK;
/* set song song_id id key */ /* set song song_id id key */
} else if (argc == 6 && strcmp(argv[1], "set") == 0) { } else if (argc == 6 && strcmp(argv[1], "set") == 0) {
Song *song = db->GetSong(argv[3], &error); Song *song = db->GetSong(argv[3], error);
if (song == nullptr) if (song == nullptr)
return print_error(client, error); return print_error(client, error);
...@@ -106,7 +109,7 @@ handle_sticker_song(Client *client, int argc, char *argv[]) ...@@ -106,7 +109,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
/* delete song song_id [key] */ /* delete song song_id [key] */
} else if ((argc == 4 || argc == 5) && } else if ((argc == 4 || argc == 5) &&
strcmp(argv[1], "delete") == 0) { strcmp(argv[1], "delete") == 0) {
Song *song = db->GetSong(argv[3], &error); Song *song = db->GetSong(argv[3], error);
if (song == nullptr) if (song == nullptr)
return print_error(client, error); return print_error(client, error);
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "StickerDatabase.hxx" #include "StickerDatabase.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "Idle.hxx" #include "Idle.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <string> #include <string>
#include <map> #include <map>
...@@ -81,21 +83,17 @@ static const char sticker_sql_create[] = ...@@ -81,21 +83,17 @@ static const char sticker_sql_create[] =
static sqlite3 *sticker_db; static sqlite3 *sticker_db;
static sqlite3_stmt *sticker_stmt[G_N_ELEMENTS(sticker_sql)]; static sqlite3_stmt *sticker_stmt[G_N_ELEMENTS(sticker_sql)];
static GQuark static constexpr Domain sticker_domain("sticker");
sticker_quark(void)
{
return g_quark_from_static_string("sticker");
}
static sqlite3_stmt * static sqlite3_stmt *
sticker_prepare(const char *sql, GError **error_r) sticker_prepare(const char *sql, Error &error)
{ {
int ret; int ret;
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
ret = sqlite3_prepare_v2(sticker_db, sql, -1, &stmt, NULL); ret = sqlite3_prepare_v2(sticker_db, sql, -1, &stmt, NULL);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
g_set_error(error_r, sticker_quark(), ret, error.Format(sticker_domain, ret,
"sqlite3_prepare_v2() failed: %s", "sqlite3_prepare_v2() failed: %s",
sqlite3_errmsg(sticker_db)); sqlite3_errmsg(sticker_db));
return NULL; return NULL;
...@@ -105,7 +103,7 @@ sticker_prepare(const char *sql, GError **error_r) ...@@ -105,7 +103,7 @@ sticker_prepare(const char *sql, GError **error_r)
} }
bool bool
sticker_global_init(Path &&path, GError **error_r) sticker_global_init(Path &&path, Error &error)
{ {
int ret; int ret;
...@@ -118,7 +116,7 @@ sticker_global_init(Path &&path, GError **error_r) ...@@ -118,7 +116,7 @@ sticker_global_init(Path &&path, GError **error_r)
ret = sqlite3_open(path.c_str(), &sticker_db); ret = sqlite3_open(path.c_str(), &sticker_db);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
const std::string utf8 = path.ToUTF8(); const std::string utf8 = path.ToUTF8();
g_set_error(error_r, sticker_quark(), ret, error.Format(sticker_domain, ret,
"Failed to open sqlite database '%s': %s", "Failed to open sqlite database '%s': %s",
utf8.c_str(), sqlite3_errmsg(sticker_db)); utf8.c_str(), sqlite3_errmsg(sticker_db));
return false; return false;
...@@ -128,7 +126,7 @@ sticker_global_init(Path &&path, GError **error_r) ...@@ -128,7 +126,7 @@ sticker_global_init(Path &&path, GError **error_r)
ret = sqlite3_exec(sticker_db, sticker_sql_create, NULL, NULL, NULL); ret = sqlite3_exec(sticker_db, sticker_sql_create, NULL, NULL, NULL);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
g_set_error(error_r, sticker_quark(), ret, error.Format(sticker_domain, ret,
"Failed to create sticker table: %s", "Failed to create sticker table: %s",
sqlite3_errmsg(sticker_db)); sqlite3_errmsg(sticker_db));
return false; return false;
...@@ -139,7 +137,7 @@ sticker_global_init(Path &&path, GError **error_r) ...@@ -139,7 +137,7 @@ sticker_global_init(Path &&path, GError **error_r)
for (unsigned i = 0; i < G_N_ELEMENTS(sticker_sql); ++i) { for (unsigned i = 0; i < G_N_ELEMENTS(sticker_sql); ++i) {
assert(sticker_sql[i] != NULL); assert(sticker_sql[i] != NULL);
sticker_stmt[i] = sticker_prepare(sticker_sql[i], error_r); sticker_stmt[i] = sticker_prepare(sticker_sql[i], error);
if (sticker_stmt[i] == NULL) if (sticker_stmt[i] == NULL)
return false; return false;
} }
......
...@@ -42,8 +42,7 @@ ...@@ -42,8 +42,7 @@
#ifndef MPD_STICKER_DATABASE_HXX #ifndef MPD_STICKER_DATABASE_HXX
#define MPD_STICKER_DATABASE_HXX #define MPD_STICKER_DATABASE_HXX
#include "gerror.h" class Error;
class Path; class Path;
struct sticker; struct sticker;
...@@ -55,7 +54,7 @@ struct sticker; ...@@ -55,7 +54,7 @@ struct sticker;
* @return true on success, false on error * @return true on success, false on error
*/ */
bool bool
sticker_global_init(Path &&path, GError **error_r); sticker_global_init(Path &&path, Error &error);
/** /**
* Close the sticker database. * Close the sticker database.
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include "TagFile.hxx" #include "TagFile.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "DecoderList.hxx" #include "DecoderList.hxx"
#include "DecoderPlugin.hxx" #include "DecoderPlugin.hxx"
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
...@@ -59,9 +60,11 @@ tag_file_scan(const char *path_fs, ...@@ -59,9 +60,11 @@ tag_file_scan(const char *path_fs,
if (plugin->scan_stream != NULL) { if (plugin->scan_stream != NULL) {
/* open the input_stream (if not already /* open the input_stream (if not already
open) */ open) */
if (is == nullptr) if (is == nullptr) {
Error error;
is = input_stream_open(path_fs, mutex, cond, is = input_stream_open(path_fs, mutex, cond,
NULL); error);
}
/* now try the stream_tag() method */ /* now try the stream_tag() method */
if (is != NULL) { if (is != NULL) {
...@@ -70,7 +73,8 @@ tag_file_scan(const char *path_fs, ...@@ -70,7 +73,8 @@ tag_file_scan(const char *path_fs,
handler_ctx)) handler_ctx))
break; break;
input_stream_lock_seek(is, 0, SEEK_SET, NULL); Error error;
input_stream_lock_seek(is, 0, SEEK_SET, error);
} }
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "TagTable.hxx" #include "TagTable.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
extern "C" { extern "C" {
#include "riff.h" #include "riff.h"
...@@ -29,7 +30,6 @@ extern "C" { ...@@ -29,7 +30,6 @@ extern "C" {
} }
#include "conf.h" #include "conf.h"
#include "io_error.h"
#include <glib.h> #include <glib.h>
#include <id3tag.h> #include <id3tag.h>
...@@ -545,13 +545,11 @@ tag_id3_riff_aiff_load(FILE *file) ...@@ -545,13 +545,11 @@ tag_id3_riff_aiff_load(FILE *file)
} }
struct id3_tag * struct id3_tag *
tag_id3_load(const char *path_fs, GError **error_r) tag_id3_load(const char *path_fs, Error &error)
{ {
FILE *file = fopen(path_fs, "rb"); FILE *file = fopen(path_fs, "rb");
if (file == nullptr) { if (file == nullptr) {
g_set_error(error_r, errno_quark(), errno, error.FormatErrno("Failed to open file %s", path_fs);
"Failed to open file %s: %s",
path_fs, g_strerror(errno));
return nullptr; return nullptr;
} }
...@@ -570,13 +568,11 @@ bool ...@@ -570,13 +568,11 @@ bool
tag_id3_scan(const char *path_fs, tag_id3_scan(const char *path_fs,
const struct tag_handler *handler, void *handler_ctx) const struct tag_handler *handler, void *handler_ctx)
{ {
GError *error = nullptr; Error error;
struct id3_tag *tag = tag_id3_load(path_fs, &error); struct id3_tag *tag = tag_id3_load(path_fs, error);
if (tag == nullptr) { if (tag == nullptr) {
if (error != nullptr) { if (error.IsDefined())
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
}
return false; return false;
} }
......
...@@ -22,11 +22,11 @@ ...@@ -22,11 +22,11 @@
#include "check.h" #include "check.h"
#include "gcc.h" #include "gcc.h"
#include "gerror.h"
struct tag_handler; struct tag_handler;
struct Tag; struct Tag;
struct id3_tag; struct id3_tag;
class Error;
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
...@@ -42,10 +42,10 @@ tag_id3_import(struct id3_tag *); ...@@ -42,10 +42,10 @@ tag_id3_import(struct id3_tag *);
* return value must be freed with id3_tag_delete(). * return value must be freed with id3_tag_delete().
* *
* @return NULL on error or if no ID3 tag was found in the file (no * @return NULL on error or if no ID3 tag was found in the file (no
* GError will be set) * Error will be set)
*/ */
struct id3_tag * struct id3_tag *
tag_id3_load(const char *path_fs, GError **error_r); tag_id3_load(const char *path_fs, Error &error);
/** /**
* Import all tags from the provided id3_tag *tag * Import all tags from the provided id3_tag *tag
......
/* /*
* Copyright (C) 2003-2011 The Music Player Daemon Project * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "TextInputStream.hxx" #include "TextInputStream.hxx"
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "util/fifo_buffer.h" #include "util/fifo_buffer.h"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -40,7 +41,6 @@ TextInputStream::~TextInputStream() ...@@ -40,7 +41,6 @@ TextInputStream::~TextInputStream()
bool TextInputStream::ReadLine(std::string &line) bool TextInputStream::ReadLine(std::string &line)
{ {
GError *error = nullptr;
void *dest; void *dest;
const char *src, *p; const char *src, *p;
size_t length, nbytes; size_t length, nbytes;
...@@ -53,13 +53,13 @@ bool TextInputStream::ReadLine(std::string &line) ...@@ -53,13 +53,13 @@ bool TextInputStream::ReadLine(std::string &line)
newline character */ newline character */
--length; --length;
Error error;
nbytes = input_stream_lock_read(is, dest, length, nbytes = input_stream_lock_read(is, dest, length,
&error); error);
if (nbytes > 0) if (nbytes > 0)
fifo_buffer_append(buffer, nbytes); fifo_buffer_append(buffer, nbytes);
else if (error != nullptr) { else if (error.IsDefined()) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return false; return false;
} }
} else } else
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "ArchivePlugin.hxx" #include "ArchivePlugin.hxx"
#include "ArchiveFile.hxx" #include "ArchiveFile.hxx"
#include "ArchiveVisitor.hxx" #include "ArchiveVisitor.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -101,11 +102,10 @@ update_archive_file2(Directory *parent, const char *name, ...@@ -101,11 +102,10 @@ update_archive_file2(Directory *parent, const char *name,
const Path path_fs = map_directory_child_fs(parent, name); const Path path_fs = map_directory_child_fs(parent, name);
/* open archive */ /* open archive */
GError *error = NULL; Error error;
ArchiveFile *file = archive_file_open(plugin, path_fs.c_str(), &error); ArchiveFile *file = archive_file_open(plugin, path_fs.c_str(), error);
if (file == NULL) { if (file == NULL) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return; return;
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "DatabaseSimple.hxx" #include "DatabaseSimple.hxx"
#include "Idle.hxx" #include "Idle.hxx"
#include "GlobalEvents.hxx" #include "GlobalEvents.hxx"
#include "util/Error.hxx"
extern "C" { extern "C" {
#include "stats.h" #include "stats.h"
...@@ -77,12 +78,10 @@ static void * update_task(void *_path) ...@@ -77,12 +78,10 @@ static void * update_task(void *_path)
modified = update_walk(path, discard); modified = update_walk(path, discard);
if (modified || !db_exists()) { if (modified || !db_exists()) {
GError *error = NULL; Error error;
if (!db_save(&error)) { if (!db_save(error))
g_warning("Failed to save database: %s", g_warning("Failed to save database: %s",
error->message); error.GetMessage());
g_error_free(error);
}
} }
if (path != NULL && *path != 0) if (path != NULL && *path != 0)
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "InputStream.hxx" #include "InputStream.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/RefCount.hxx" #include "util/RefCount.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
...@@ -85,7 +87,7 @@ public: ...@@ -85,7 +87,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) override; Error &error) override;
}; };
struct Bzip2InputStream { struct Bzip2InputStream {
...@@ -103,12 +105,14 @@ struct Bzip2InputStream { ...@@ -103,12 +105,14 @@ struct Bzip2InputStream {
Mutex &mutex, Cond &cond); Mutex &mutex, Cond &cond);
~Bzip2InputStream(); ~Bzip2InputStream();
bool Open(GError **error_r); bool Open(Error &error);
void Close(); void Close();
}; };
extern const struct input_plugin bz2_inputplugin; extern const struct input_plugin bz2_inputplugin;
static constexpr Domain bz2_domain("bz2");
static inline GQuark static inline GQuark
bz2_quark(void) bz2_quark(void)
{ {
...@@ -118,7 +122,7 @@ bz2_quark(void) ...@@ -118,7 +122,7 @@ bz2_quark(void)
/* single archive handling allocation helpers */ /* single archive handling allocation helpers */
inline bool inline bool
Bzip2InputStream::Open(GError **error_r) Bzip2InputStream::Open(Error &error)
{ {
bzstream.bzalloc = nullptr; bzstream.bzalloc = nullptr;
bzstream.bzfree = nullptr; bzstream.bzfree = nullptr;
...@@ -129,7 +133,7 @@ Bzip2InputStream::Open(GError **error_r) ...@@ -129,7 +133,7 @@ Bzip2InputStream::Open(GError **error_r)
int ret = BZ2_bzDecompressInit(&bzstream, 0, 0); int ret = BZ2_bzDecompressInit(&bzstream, 0, 0);
if (ret != BZ_OK) { if (ret != BZ_OK) {
g_set_error(error_r, bz2_quark(), ret, error.Set(bz2_domain, ret,
"BZ2_bzDecompressInit() has failed"); "BZ2_bzDecompressInit() has failed");
return false; return false;
} }
...@@ -147,11 +151,11 @@ Bzip2InputStream::Close() ...@@ -147,11 +151,11 @@ Bzip2InputStream::Close()
/* archive open && listing routine */ /* archive open && listing routine */
static ArchiveFile * static ArchiveFile *
bz2_open(const char *pathname, GError **error_r) bz2_open(const char *pathname, Error &error)
{ {
static Mutex mutex; static Mutex mutex;
static Cond cond; static Cond cond;
input_stream *is = input_stream_open(pathname, mutex, cond, error_r); input_stream *is = input_stream_open(pathname, mutex, cond, error);
if (is == nullptr) if (is == nullptr)
return nullptr; return nullptr;
...@@ -176,10 +180,10 @@ Bzip2InputStream::~Bzip2InputStream() ...@@ -176,10 +180,10 @@ Bzip2InputStream::~Bzip2InputStream()
input_stream * input_stream *
Bzip2ArchiveFile::OpenStream(const char *path, Bzip2ArchiveFile::OpenStream(const char *path,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
Bzip2InputStream *bis = new Bzip2InputStream(*this, path, mutex, cond); Bzip2InputStream *bis = new Bzip2InputStream(*this, path, mutex, cond);
if (!bis->Open(error_r)) { if (!bis->Open(error)) {
delete bis; delete bis;
return NULL; return NULL;
} }
...@@ -197,7 +201,7 @@ bz2_is_close(struct input_stream *is) ...@@ -197,7 +201,7 @@ bz2_is_close(struct input_stream *is)
} }
static bool static bool
bz2_fillbuffer(Bzip2InputStream *bis, GError **error_r) bz2_fillbuffer(Bzip2InputStream *bis, Error &error)
{ {
size_t count; size_t count;
bz_stream *bzstream; bz_stream *bzstream;
...@@ -209,7 +213,7 @@ bz2_fillbuffer(Bzip2InputStream *bis, GError **error_r) ...@@ -209,7 +213,7 @@ bz2_fillbuffer(Bzip2InputStream *bis, GError **error_r)
count = input_stream_read(bis->archive->istream, count = input_stream_read(bis->archive->istream,
bis->buffer, sizeof(bis->buffer), bis->buffer, sizeof(bis->buffer),
error_r); error);
if (count == 0) if (count == 0)
return false; return false;
...@@ -220,7 +224,7 @@ bz2_fillbuffer(Bzip2InputStream *bis, GError **error_r) ...@@ -220,7 +224,7 @@ bz2_fillbuffer(Bzip2InputStream *bis, GError **error_r)
static size_t static size_t
bz2_is_read(struct input_stream *is, void *ptr, size_t length, bz2_is_read(struct input_stream *is, void *ptr, size_t length,
GError **error_r) Error &error)
{ {
Bzip2InputStream *bis = (Bzip2InputStream *)is; Bzip2InputStream *bis = (Bzip2InputStream *)is;
bz_stream *bzstream; bz_stream *bzstream;
...@@ -235,7 +239,7 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length, ...@@ -235,7 +239,7 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length,
bzstream->avail_out = length; bzstream->avail_out = length;
do { do {
if (!bz2_fillbuffer(bis, error_r)) if (!bz2_fillbuffer(bis, error))
return 0; return 0;
bz_result = BZ2_bzDecompress(bzstream); bz_result = BZ2_bzDecompress(bzstream);
...@@ -246,7 +250,7 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length, ...@@ -246,7 +250,7 @@ bz2_is_read(struct input_stream *is, void *ptr, size_t length,
} }
if (bz_result != BZ_OK) { if (bz_result != BZ_OK) {
g_set_error(error_r, bz2_quark(), bz_result, error.Set(bz2_domain, bz_result,
"BZ2_bzDecompress() has failed"); "BZ2_bzDecompress() has failed");
return 0; return 0;
} }
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "InputStream.hxx" #include "InputStream.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/RefCount.hxx" #include "util/RefCount.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <cdio/cdio.h> #include <cdio/cdio.h>
#include <cdio/iso9660.h> #include <cdio/iso9660.h>
...@@ -69,16 +71,12 @@ public: ...@@ -69,16 +71,12 @@ 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) override; Error &error) override;
}; };
extern const struct input_plugin iso9660_input_plugin; extern const struct input_plugin iso9660_input_plugin;
static inline GQuark static constexpr Domain iso9660_domain("iso9660");
iso9660_quark(void)
{
return g_quark_from_static_string("iso9660");
}
/* archive open && listing routine */ /* archive open && listing routine */
...@@ -115,12 +113,12 @@ Iso9660ArchiveFile::Visit(const char *psz_path, ArchiveVisitor &visitor) ...@@ -115,12 +113,12 @@ Iso9660ArchiveFile::Visit(const char *psz_path, ArchiveVisitor &visitor)
} }
static ArchiveFile * static ArchiveFile *
iso9660_archive_open(const char *pathname, GError **error_r) iso9660_archive_open(const char *pathname, Error &error)
{ {
/* open archive */ /* open archive */
auto iso = iso9660_open(pathname); auto iso = iso9660_open(pathname);
if (iso == nullptr) { if (iso == nullptr) {
g_set_error(error_r, iso9660_quark(), 0, error.Format(iso9660_domain,
"Failed to open ISO9660 file %s", pathname); "Failed to open ISO9660 file %s", pathname);
return NULL; return NULL;
} }
...@@ -166,11 +164,11 @@ struct Iso9660InputStream { ...@@ -166,11 +164,11 @@ struct Iso9660InputStream {
input_stream * input_stream *
Iso9660ArchiveFile::OpenStream(const char *pathname, Iso9660ArchiveFile::OpenStream(const char *pathname,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
auto statbuf = iso9660_ifs_stat_translate(iso, pathname); auto statbuf = iso9660_ifs_stat_translate(iso, pathname);
if (statbuf == nullptr) { if (statbuf == nullptr) {
g_set_error(error_r, iso9660_quark(), 0, error.Format(iso9660_domain,
"not found in the ISO file: %s", pathname); "not found in the ISO file: %s", pathname);
return NULL; return NULL;
} }
...@@ -191,7 +189,8 @@ iso9660_input_close(struct input_stream *is) ...@@ -191,7 +189,8 @@ iso9660_input_close(struct input_stream *is)
static size_t static size_t
iso9660_input_read(struct input_stream *is, void *ptr, size_t size, GError **error_r) iso9660_input_read(struct input_stream *is, void *ptr, size_t size,
Error &error)
{ {
Iso9660InputStream *iis = (Iso9660InputStream *)is; Iso9660InputStream *iis = (Iso9660InputStream *)is;
int toread, readed = 0; int toread, readed = 0;
...@@ -215,9 +214,9 @@ iso9660_input_read(struct input_stream *is, void *ptr, size_t size, GError **err ...@@ -215,9 +214,9 @@ iso9660_input_read(struct input_stream *is, void *ptr, size_t size, GError **err
iis->statbuf->lsn + cur_block, no_blocks); iis->statbuf->lsn + cur_block, no_blocks);
if (readed != no_blocks * ISO_BLOCKSIZE) { if (readed != no_blocks * ISO_BLOCKSIZE) {
g_set_error(error_r, iso9660_quark(), 0, error.Format(iso9660_domain,
"error reading ISO file at lsn %lu", "error reading ISO file at lsn %lu",
(long unsigned int) cur_block); (unsigned long)cur_block);
return 0; return 0;
} }
if (left_bytes < size) { if (left_bytes < size) {
......
...@@ -30,9 +30,11 @@ ...@@ -30,9 +30,11 @@
#include "InputStream.hxx" #include "InputStream.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/RefCount.hxx" #include "util/RefCount.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <zzip/zzip.h> #include <zzip/zzip.h>
#include <glib.h>
#include <string.h> #include <string.h>
class ZzipArchiveFile final : public ArchiveFile { class ZzipArchiveFile final : public ArchiveFile {
...@@ -61,26 +63,22 @@ public: ...@@ -61,26 +63,22 @@ 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) override; Error &error) override;
}; };
extern const struct input_plugin zzip_input_plugin; extern const struct input_plugin zzip_input_plugin;
static inline GQuark static constexpr Domain zzip_domain("zzip");
zzip_quark(void)
{
return g_quark_from_static_string("zzip");
}
/* archive open && listing routine */ /* archive open && listing routine */
static ArchiveFile * static ArchiveFile *
zzip_archive_open(const char *pathname, GError **error_r) zzip_archive_open(const char *pathname, Error &error)
{ {
ZZIP_DIR *dir = zzip_dir_open(pathname, NULL); ZZIP_DIR *dir = zzip_dir_open(pathname, NULL);
if (dir == nullptr) { if (dir == nullptr) {
g_set_error(error_r, zzip_quark(), 0, error.Format(zzip_domain, "Failed to open ZIP file %s",
"Failed to open ZIP file %s", pathname); pathname);
return NULL; return NULL;
} }
...@@ -133,12 +131,12 @@ struct ZzipInputStream { ...@@ -133,12 +131,12 @@ struct ZzipInputStream {
input_stream * input_stream *
ZzipArchiveFile::OpenStream(const char *pathname, ZzipArchiveFile::OpenStream(const char *pathname,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
ZZIP_FILE *_file = zzip_file_open(dir, pathname, 0); ZZIP_FILE *_file = zzip_file_open(dir, pathname, 0);
if (_file == nullptr) { if (_file == nullptr) {
g_set_error(error_r, zzip_quark(), 0, error.Format(zzip_domain, "not found in the ZIP file: %s",
"not found in the ZIP file: %s", pathname); pathname);
return NULL; return NULL;
} }
...@@ -159,15 +157,14 @@ zzip_input_close(struct input_stream *is) ...@@ -159,15 +157,14 @@ zzip_input_close(struct input_stream *is)
static size_t static size_t
zzip_input_read(struct input_stream *is, void *ptr, size_t size, zzip_input_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r) Error &error)
{ {
ZzipInputStream *zis = (ZzipInputStream *)is; ZzipInputStream *zis = (ZzipInputStream *)is;
int ret; int ret;
ret = zzip_file_read(zis->file, ptr, size); ret = zzip_file_read(zis->file, ptr, size);
if (ret < 0) { if (ret < 0) {
g_set_error(error_r, zzip_quark(), ret, error.Set(zzip_domain, "zzip_file_read() has failed");
"zzip_file_read() has failed");
return 0; return 0;
} }
...@@ -186,13 +183,12 @@ zzip_input_eof(struct input_stream *is) ...@@ -186,13 +183,12 @@ zzip_input_eof(struct input_stream *is)
static bool static bool
zzip_input_seek(struct input_stream *is, zzip_input_seek(struct input_stream *is,
goffset offset, int whence, GError **error_r) goffset offset, int whence, Error &error)
{ {
ZzipInputStream *zis = (ZzipInputStream *)is; ZzipInputStream *zis = (ZzipInputStream *)is;
zzip_off_t ofs = zzip_seek(zis->file, offset, whence); zzip_off_t ofs = zzip_seek(zis->file, offset, whence);
if (ofs != -1) { if (ofs != -1) {
g_set_error(error_r, zzip_quark(), ofs, error.Set(zzip_domain, "zzip_seek() has failed");
"zzip_seek() has failed");
is->offset = ofs; is->offset = ofs;
return true; return true;
} }
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include "gcc.h" #include "gcc.h"
#include "conf.h" #include "conf.h"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#undef MPD_DIRECTORY_H #undef MPD_DIRECTORY_H
#undef MPD_SONG_H #undef MPD_SONG_H
...@@ -46,39 +48,34 @@ class ProxyDatabase : public Database { ...@@ -46,39 +48,34 @@ class ProxyDatabase : public Database {
public: public:
static Database *Create(const config_param &param, static Database *Create(const config_param &param,
GError **error_r); Error &error);
virtual bool Open(GError **error_r) override; virtual bool Open(Error &error) override;
virtual void Close() override; virtual void Close() override;
virtual Song *GetSong(const char *uri_utf8, virtual Song *GetSong(const char *uri_utf8,
GError **error_r) const override; Error &error) const override;
virtual void ReturnSong(Song *song) const; virtual void ReturnSong(Song *song) const;
virtual bool Visit(const DatabaseSelection &selection, virtual bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory, VisitDirectory visit_directory,
VisitSong visit_song, VisitSong visit_song,
VisitPlaylist visit_playlist, VisitPlaylist visit_playlist,
GError **error_r) const override; Error &error) const override;
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 override; Error &error) const override;
virtual bool GetStats(const DatabaseSelection &selection, virtual bool GetStats(const DatabaseSelection &selection,
DatabaseStats &stats, DatabaseStats &stats,
GError **error_r) const override; Error &error) const override;
protected: protected:
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
}; };
gcc_pure static constexpr Domain libmpdclient_domain("libmpdclient");
static inline GQuark
libmpdclient_quark(void)
{
return g_quark_from_static_string("libmpdclient");
}
static constexpr struct { static constexpr struct {
enum tag_type d; enum tag_type d;
...@@ -116,23 +113,23 @@ Convert(enum tag_type tag_type) ...@@ -116,23 +113,23 @@ Convert(enum tag_type tag_type)
} }
static bool static bool
CheckError(struct mpd_connection *connection, GError **error_r) CheckError(struct mpd_connection *connection, Error &error)
{ {
const auto error = mpd_connection_get_error(connection); const auto code = mpd_connection_get_error(connection);
if (error == MPD_ERROR_SUCCESS) if (code == MPD_ERROR_SUCCESS)
return true; return true;
g_set_error_literal(error_r, libmpdclient_quark(), (int)error, error.Set(libmpdclient_domain, (int)code,
mpd_connection_get_error_message(connection)); mpd_connection_get_error_message(connection));
mpd_connection_clear_error(connection); mpd_connection_clear_error(connection);
return false; return false;
} }
Database * Database *
ProxyDatabase::Create(const config_param &param, GError **error_r) ProxyDatabase::Create(const config_param &param, Error &error)
{ {
ProxyDatabase *db = new ProxyDatabase(); ProxyDatabase *db = new ProxyDatabase();
if (!db->Configure(param, error_r)) { if (!db->Configure(param, error)) {
delete db; delete db;
db = NULL; db = NULL;
} }
...@@ -141,7 +138,7 @@ ProxyDatabase::Create(const config_param &param, GError **error_r) ...@@ -141,7 +138,7 @@ ProxyDatabase::Create(const config_param &param, GError **error_r)
} }
bool bool
ProxyDatabase::Configure(const config_param &param, GError **) ProxyDatabase::Configure(const config_param &param, gcc_unused Error &error)
{ {
host = param.GetBlockValue("host", ""); host = param.GetBlockValue("host", "");
port = param.GetBlockValue("port", 0u); port = param.GetBlockValue("port", 0u);
...@@ -150,17 +147,16 @@ ProxyDatabase::Configure(const config_param &param, GError **) ...@@ -150,17 +147,16 @@ ProxyDatabase::Configure(const config_param &param, GError **)
} }
bool bool
ProxyDatabase::Open(GError **error_r) ProxyDatabase::Open(Error &error)
{ {
connection = mpd_connection_new(host.empty() ? NULL : host.c_str(), connection = mpd_connection_new(host.empty() ? NULL : host.c_str(),
port, 0); port, 0);
if (connection == NULL) { if (connection == NULL) {
g_set_error_literal(error_r, libmpdclient_quark(), error.Set(libmpdclient_domain, (int)MPD_ERROR_OOM, "Out of memory");
(int)MPD_ERROR_OOM, "Out of memory");
return false; return false;
} }
if (!CheckError(connection, error_r)) { if (!CheckError(connection, error)) {
mpd_connection_free(connection); mpd_connection_free(connection);
return false; return false;
} }
...@@ -183,13 +179,13 @@ static Song * ...@@ -183,13 +179,13 @@ static Song *
Convert(const struct mpd_song *song); Convert(const struct mpd_song *song);
Song * Song *
ProxyDatabase::GetSong(const char *uri, GError **error_r) const ProxyDatabase::GetSong(const char *uri, Error &error) const
{ {
// TODO: implement // TODO: implement
// TODO: auto-reconnect // TODO: auto-reconnect
if (!mpd_send_list_meta(connection, uri)) { if (!mpd_send_list_meta(connection, uri)) {
CheckError(connection, error_r); CheckError(connection, error);
return nullptr; return nullptr;
} }
...@@ -202,13 +198,12 @@ ProxyDatabase::GetSong(const char *uri, GError **error_r) const ...@@ -202,13 +198,12 @@ ProxyDatabase::GetSong(const char *uri, GError **error_r) const
if (song2 != nullptr) if (song2 != nullptr)
song2->Free(); song2->Free();
CheckError(connection, error_r); CheckError(connection, error);
return nullptr; return nullptr;
} }
if (song2 == nullptr) if (song2 == nullptr)
g_set_error(error_r, db_quark(), DB_NOT_FOUND, error.Format(db_domain, DB_NOT_FOUND, "No such song: %s", uri);
"No such song: %s", uri);
return song2; return song2;
} }
...@@ -226,19 +221,19 @@ ProxyDatabase::ReturnSong(Song *song) const ...@@ -226,19 +221,19 @@ ProxyDatabase::ReturnSong(Song *song) const
static bool static bool
Visit(struct mpd_connection *connection, const char *uri, Visit(struct mpd_connection *connection, const char *uri,
bool recursive, VisitDirectory visit_directory, VisitSong visit_song, bool recursive, VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist, GError **error_r); VisitPlaylist visit_playlist, Error &error);
static bool static bool
Visit(struct mpd_connection *connection, Visit(struct mpd_connection *connection,
bool recursive, const struct mpd_directory *directory, bool recursive, const struct mpd_directory *directory,
VisitDirectory visit_directory, VisitSong visit_song, VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist, GError **error_r) VisitPlaylist visit_playlist, Error &error)
{ {
const char *path = mpd_directory_get_path(directory); const char *path = mpd_directory_get_path(directory);
if (visit_directory) { if (visit_directory) {
Directory *d = Directory::NewGeneric(path, &detached_root); Directory *d = Directory::NewGeneric(path, &detached_root);
bool success = visit_directory(*d, error_r); bool success = visit_directory(*d, error);
d->Free(); d->Free();
if (!success) if (!success)
return false; return false;
...@@ -246,7 +241,7 @@ Visit(struct mpd_connection *connection, ...@@ -246,7 +241,7 @@ Visit(struct mpd_connection *connection,
if (recursive && if (recursive &&
!Visit(connection, path, recursive, !Visit(connection, path, recursive,
visit_directory, visit_song, visit_playlist, error_r)) visit_directory, visit_song, visit_playlist, error))
return false; return false;
return true; return true;
...@@ -290,13 +285,13 @@ Convert(const struct mpd_song *song) ...@@ -290,13 +285,13 @@ Convert(const struct mpd_song *song)
static bool static bool
Visit(const struct mpd_song *song, Visit(const struct mpd_song *song,
VisitSong visit_song, GError **error_r) VisitSong visit_song, Error &error)
{ {
if (!visit_song) if (!visit_song)
return true; return true;
Song *s = Convert(song); Song *s = Convert(song);
bool success = visit_song(*s, error_r); bool success = visit_song(*s, error);
s->Free(); s->Free();
return success; return success;
...@@ -304,7 +299,7 @@ Visit(const struct mpd_song *song, ...@@ -304,7 +299,7 @@ Visit(const struct mpd_song *song,
static bool static bool
Visit(const struct mpd_playlist *playlist, Visit(const struct mpd_playlist *playlist,
VisitPlaylist visit_playlist, GError **error_r) VisitPlaylist visit_playlist, Error &error)
{ {
if (!visit_playlist) if (!visit_playlist)
return true; return true;
...@@ -312,7 +307,7 @@ Visit(const struct mpd_playlist *playlist, ...@@ -312,7 +307,7 @@ Visit(const struct mpd_playlist *playlist,
PlaylistInfo p(mpd_playlist_get_path(playlist), PlaylistInfo p(mpd_playlist_get_path(playlist),
mpd_playlist_get_last_modified(playlist)); mpd_playlist_get_last_modified(playlist));
return visit_playlist(p, detached_root, error_r); return visit_playlist(p, detached_root, error);
} }
class ProxyEntity { class ProxyEntity {
...@@ -356,13 +351,13 @@ ReceiveEntities(struct mpd_connection *connection) ...@@ -356,13 +351,13 @@ ReceiveEntities(struct mpd_connection *connection)
static bool static bool
Visit(struct mpd_connection *connection, const char *uri, Visit(struct mpd_connection *connection, const char *uri,
bool recursive, VisitDirectory visit_directory, VisitSong visit_song, bool recursive, VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist, GError **error_r) VisitPlaylist visit_playlist, Error &error)
{ {
if (!mpd_send_list_meta(connection, uri)) if (!mpd_send_list_meta(connection, uri))
return CheckError(connection, error_r); return CheckError(connection, error);
std::list<ProxyEntity> entities(ReceiveEntities(connection)); std::list<ProxyEntity> entities(ReceiveEntities(connection));
if (!CheckError(connection, error_r)) if (!CheckError(connection, error))
return false; return false;
for (const auto &entity : entities) { for (const auto &entity : entities) {
...@@ -374,25 +369,25 @@ Visit(struct mpd_connection *connection, const char *uri, ...@@ -374,25 +369,25 @@ Visit(struct mpd_connection *connection, const char *uri,
if (!Visit(connection, recursive, if (!Visit(connection, recursive,
mpd_entity_get_directory(entity), mpd_entity_get_directory(entity),
visit_directory, visit_song, visit_playlist, visit_directory, visit_song, visit_playlist,
error_r)) error))
return false; return false;
break; break;
case MPD_ENTITY_TYPE_SONG: case MPD_ENTITY_TYPE_SONG:
if (!Visit(mpd_entity_get_song(entity), visit_song, if (!Visit(mpd_entity_get_song(entity), visit_song,
error_r)) error))
return false; return false;
break; break;
case MPD_ENTITY_TYPE_PLAYLIST: case MPD_ENTITY_TYPE_PLAYLIST:
if (!Visit(mpd_entity_get_playlist(entity), if (!Visit(mpd_entity_get_playlist(entity),
visit_playlist, error_r)) visit_playlist, error))
return false; return false;
break; break;
} }
} }
return CheckError(connection, error_r); return CheckError(connection, error);
} }
bool bool
...@@ -400,55 +395,54 @@ ProxyDatabase::Visit(const DatabaseSelection &selection, ...@@ -400,55 +395,54 @@ ProxyDatabase::Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory, VisitDirectory visit_directory,
VisitSong visit_song, VisitSong visit_song,
VisitPlaylist visit_playlist, VisitPlaylist visit_playlist,
GError **error_r) const Error &error) const
{ {
// TODO: match // TODO: match
// TODO: auto-reconnect // TODO: auto-reconnect
return ::Visit(connection, selection.uri, selection.recursive, return ::Visit(connection, selection.uri, selection.recursive,
visit_directory, visit_song, visit_playlist, visit_directory, visit_song, visit_playlist,
error_r); error);
} }
bool bool
ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection, ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection,
enum tag_type tag_type, enum tag_type tag_type,
VisitString visit_string, VisitString visit_string,
GError **error_r) const Error &error) const
{ {
enum mpd_tag_type tag_type2 = Convert(tag_type); enum mpd_tag_type tag_type2 = Convert(tag_type);
if (tag_type2 == MPD_TAG_COUNT) { if (tag_type2 == MPD_TAG_COUNT) {
g_set_error_literal(error_r, libmpdclient_quark(), 0, error.Set(libmpdclient_domain, "Unsupported tag");
"Unsupported tag");
return false; return false;
} }
if (!mpd_search_db_tags(connection, tag_type2)) if (!mpd_search_db_tags(connection, tag_type2))
return CheckError(connection, error_r); return CheckError(connection, error);
// TODO: match // TODO: match
(void)selection; (void)selection;
if (!mpd_search_commit(connection)) if (!mpd_search_commit(connection))
return CheckError(connection, error_r); return CheckError(connection, error);
bool result = true; bool result = true;
struct mpd_pair *pair; struct mpd_pair *pair;
while (result && while (result &&
(pair = mpd_recv_pair_tag(connection, tag_type2)) != nullptr) { (pair = mpd_recv_pair_tag(connection, tag_type2)) != nullptr) {
result = visit_string(pair->value, error_r); result = visit_string(pair->value, error);
mpd_return_pair(connection, pair); mpd_return_pair(connection, pair);
} }
return mpd_response_finish(connection) && return mpd_response_finish(connection) &&
CheckError(connection, error_r) && CheckError(connection, error) &&
result; result;
} }
bool bool
ProxyDatabase::GetStats(const DatabaseSelection &selection, ProxyDatabase::GetStats(const DatabaseSelection &selection,
DatabaseStats &stats, GError **error_r) const DatabaseStats &stats, Error &error) const
{ {
// TODO: match // TODO: match
(void)selection; (void)selection;
...@@ -456,7 +450,7 @@ ProxyDatabase::GetStats(const DatabaseSelection &selection, ...@@ -456,7 +450,7 @@ ProxyDatabase::GetStats(const DatabaseSelection &selection,
struct mpd_stats *stats2 = struct mpd_stats *stats2 =
mpd_run_stats(connection); mpd_run_stats(connection);
if (stats2 == nullptr) if (stats2 == nullptr)
return CheckError(connection, error_r); return CheckError(connection, error);
stats.song_count = mpd_stats_get_number_of_songs(stats2); stats.song_count = mpd_stats_get_number_of_songs(stats2);
stats.total_duration = mpd_stats_get_db_play_time(stats2); stats.total_duration = mpd_stats_get_db_play_time(stats2);
......
...@@ -29,22 +29,19 @@ ...@@ -29,22 +29,19 @@
#include "TextFile.hxx" #include "TextFile.hxx"
#include "conf.h" #include "conf.h"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
gcc_const static constexpr Domain simple_db_domain("simple_db");
static inline GQuark
simple_db_quark(void)
{
return g_quark_from_static_string("simple_db");
}
Database * Database *
SimpleDatabase::Create(const config_param &param, GError **error_r) SimpleDatabase::Create(const config_param &param, Error &error)
{ {
SimpleDatabase *db = new SimpleDatabase(); SimpleDatabase *db = new SimpleDatabase();
if (!db->Configure(param, error_r)) { if (!db->Configure(param, error)) {
delete db; delete db;
db = NULL; db = NULL;
} }
...@@ -53,16 +50,12 @@ SimpleDatabase::Create(const config_param &param, GError **error_r) ...@@ -53,16 +50,12 @@ SimpleDatabase::Create(const config_param &param, GError **error_r)
} }
bool bool
SimpleDatabase::Configure(const config_param &param, GError **error_r) SimpleDatabase::Configure(const config_param &param, Error &error)
{ {
GError *error = NULL; path = param.GetBlockPath("path", error);
path = param.GetBlockPath("path", &error);
if (path.IsNull()) { if (path.IsNull()) {
if (error != NULL) if (!error.IsDefined())
g_propagate_error(error_r, error); error.Set(simple_db_domain,
else
g_set_error(error_r, simple_db_quark(), 0,
"No \"path\" parameter specified"); "No \"path\" parameter specified");
return false; return false;
} }
...@@ -73,7 +66,7 @@ SimpleDatabase::Configure(const config_param &param, GError **error_r) ...@@ -73,7 +66,7 @@ SimpleDatabase::Configure(const config_param &param, GError **error_r)
} }
bool bool
SimpleDatabase::Check(GError **error_r) const SimpleDatabase::Check(Error &error) const
{ {
assert(!path.IsNull()); assert(!path.IsNull());
assert(!path.empty()); assert(!path.empty());
...@@ -88,15 +81,14 @@ SimpleDatabase::Check(GError **error_r) const ...@@ -88,15 +81,14 @@ SimpleDatabase::Check(GError **error_r) const
/* Check that the parent part of the path is a directory */ /* Check that the parent part of the path is a directory */
struct stat st; struct stat st;
if (!StatFile(dirPath, st)) { if (!StatFile(dirPath, st)) {
g_set_error(error_r, simple_db_quark(), errno, error.FormatErrno("Couldn't stat parent directory of db file "
"Couldn't stat parent directory of db file " "\"%s\"",
"\"%s\": %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
if (!S_ISDIR(st.st_mode)) { if (!S_ISDIR(st.st_mode)) {
g_set_error(error_r, simple_db_quark(), 0, error.Format(simple_db_domain,
"Couldn't create db file \"%s\" because the " "Couldn't create db file \"%s\" because the "
"parent path is not a directory", "parent path is not a directory",
path_utf8.c_str()); path_utf8.c_str());
...@@ -105,11 +97,10 @@ SimpleDatabase::Check(GError **error_r) const ...@@ -105,11 +97,10 @@ SimpleDatabase::Check(GError **error_r) const
/* Check if we can write to the directory */ /* Check if we can write to the directory */
if (!CheckAccess(dirPath, X_OK | W_OK)) { if (!CheckAccess(dirPath, X_OK | W_OK)) {
int error = errno; const int e = errno;
const std::string dirPath_utf8 = dirPath.ToUTF8(); const std::string dirPath_utf8 = dirPath.ToUTF8();
g_set_error(error_r, simple_db_quark(), error, error.FormatErrno(e, "Can't create db file in \"%s\"",
"Can't create db file in \"%s\": %s", dirPath_utf8.c_str());
dirPath_utf8.c_str(), g_strerror(error));
return false; return false;
} }
...@@ -119,14 +110,13 @@ SimpleDatabase::Check(GError **error_r) const ...@@ -119,14 +110,13 @@ SimpleDatabase::Check(GError **error_r) const
/* Path exists, now check if it's a regular file */ /* Path exists, now check if it's a regular file */
struct stat st; struct stat st;
if (!StatFile(path, st)) { if (!StatFile(path, st)) {
g_set_error(error_r, simple_db_quark(), errno, error.FormatErrno("Couldn't stat db file \"%s\"",
"Couldn't stat db file \"%s\": %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
if (!S_ISREG(st.st_mode)) { if (!S_ISREG(st.st_mode)) {
g_set_error(error_r, simple_db_quark(), 0, error.Format(simple_db_domain,
"db file \"%s\" is not a regular file", "db file \"%s\" is not a regular file",
path_utf8.c_str()); path_utf8.c_str());
return false; return false;
...@@ -134,9 +124,8 @@ SimpleDatabase::Check(GError **error_r) const ...@@ -134,9 +124,8 @@ SimpleDatabase::Check(GError **error_r) const
/* And check that we can write to it */ /* And check that we can write to it */
if (!CheckAccess(path, R_OK | W_OK)) { if (!CheckAccess(path, R_OK | W_OK)) {
g_set_error(error_r, simple_db_quark(), errno, error.FormatErrno("Can't open db file \"%s\" for reading/writing",
"Can't open db file \"%s\" for reading/writing: %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
...@@ -144,20 +133,19 @@ SimpleDatabase::Check(GError **error_r) const ...@@ -144,20 +133,19 @@ SimpleDatabase::Check(GError **error_r) const
} }
bool bool
SimpleDatabase::Load(GError **error_r) SimpleDatabase::Load(Error &error)
{ {
assert(!path.empty()); assert(!path.empty());
assert(root != NULL); assert(root != NULL);
TextFile file(path); TextFile file(path);
if (file.HasFailed()) { if (file.HasFailed()) {
g_set_error(error_r, simple_db_quark(), errno, error.FormatErrno("Failed to open database file \"%s\"",
"Failed to open database file \"%s\": %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
if (!db_load_internal(file, root, error_r)) if (!db_load_internal(file, root, error))
return false; return false;
struct stat st; struct stat st;
...@@ -168,7 +156,7 @@ SimpleDatabase::Load(GError **error_r) ...@@ -168,7 +156,7 @@ SimpleDatabase::Load(GError **error_r)
} }
bool bool
SimpleDatabase::Open(GError **error_r) SimpleDatabase::Open(Error &error)
{ {
root = Directory::NewRoot(); root = Directory::NewRoot();
mtime = 0; mtime = 0;
...@@ -177,14 +165,13 @@ SimpleDatabase::Open(GError **error_r) ...@@ -177,14 +165,13 @@ SimpleDatabase::Open(GError **error_r)
borrowed_song_count = 0; borrowed_song_count = 0;
#endif #endif
GError *error = NULL; if (!Load(error)) {
if (!Load(&error)) {
root->Free(); root->Free();
g_warning("Failed to load database: %s", error->message); g_warning("Failed to load database: %s", error.GetMessage());
g_error_free(error); error.Clear();
if (!Check(error_r)) if (!Check(error))
return false; return false;
root = Directory::NewRoot(); root = Directory::NewRoot();
...@@ -203,7 +190,7 @@ SimpleDatabase::Close() ...@@ -203,7 +190,7 @@ SimpleDatabase::Close()
} }
Song * Song *
SimpleDatabase::GetSong(const char *uri, GError **error_r) const SimpleDatabase::GetSong(const char *uri, Error &error) const
{ {
assert(root != NULL); assert(root != NULL);
...@@ -211,7 +198,7 @@ SimpleDatabase::GetSong(const char *uri, GError **error_r) const ...@@ -211,7 +198,7 @@ SimpleDatabase::GetSong(const char *uri, GError **error_r) const
Song *song = root->LookupSong(uri); Song *song = root->LookupSong(uri);
db_unlock(); db_unlock();
if (song == NULL) if (song == NULL)
g_set_error(error_r, db_quark(), DB_NOT_FOUND, error.Format(db_domain, DB_NOT_FOUND,
"No such song: %s", uri); "No such song: %s", uri);
#ifndef NDEBUG #ifndef NDEBUG
else else
...@@ -248,7 +235,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, ...@@ -248,7 +235,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory, VisitDirectory visit_directory,
VisitSong visit_song, VisitSong visit_song,
VisitPlaylist visit_playlist, VisitPlaylist visit_playlist,
GError **error_r) const Error &error) const
{ {
ScopeDatabaseLock protect; ScopeDatabaseLock protect;
...@@ -258,42 +245,41 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, ...@@ -258,42 +245,41 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
Song *song = root->LookupSong(selection.uri); Song *song = root->LookupSong(selection.uri);
if (song != nullptr) if (song != nullptr)
return !selection.Match(*song) || return !selection.Match(*song) ||
visit_song(*song, error_r); visit_song(*song, error);
} }
g_set_error(error_r, db_quark(), DB_NOT_FOUND, error.Set(db_domain, DB_NOT_FOUND, "No such directory");
"No such directory");
return false; return false;
} }
if (selection.recursive && visit_directory && if (selection.recursive && visit_directory &&
!visit_directory(*directory, error_r)) !visit_directory(*directory, error))
return false; return false;
return directory->Walk(selection.recursive, selection.filter, return directory->Walk(selection.recursive, selection.filter,
visit_directory, visit_song, visit_playlist, visit_directory, visit_song, visit_playlist,
error_r); error);
} }
bool bool
SimpleDatabase::VisitUniqueTags(const DatabaseSelection &selection, SimpleDatabase::VisitUniqueTags(const DatabaseSelection &selection,
enum tag_type tag_type, enum tag_type tag_type,
VisitString visit_string, VisitString visit_string,
GError **error_r) const Error &error) const
{ {
return ::VisitUniqueTags(*this, selection, tag_type, visit_string, return ::VisitUniqueTags(*this, selection, tag_type, visit_string,
error_r); error);
} }
bool bool
SimpleDatabase::GetStats(const DatabaseSelection &selection, SimpleDatabase::GetStats(const DatabaseSelection &selection,
DatabaseStats &stats, GError **error_r) const DatabaseStats &stats, Error &error) const
{ {
return ::GetStats(*this, selection, stats, error_r); return ::GetStats(*this, selection, stats, error);
} }
bool bool
SimpleDatabase::Save(GError **error_r) SimpleDatabase::Save(Error &error)
{ {
db_lock(); db_lock();
...@@ -309,18 +295,15 @@ SimpleDatabase::Save(GError **error_r) ...@@ -309,18 +295,15 @@ SimpleDatabase::Save(GError **error_r)
FILE *fp = FOpen(path, FOpenMode::WriteText); FILE *fp = FOpen(path, FOpenMode::WriteText);
if (!fp) { if (!fp) {
g_set_error(error_r, simple_db_quark(), errno, error.FormatErrno("unable to write to db file \"%s\"",
"unable to write to db file \"%s\": %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
db_save_internal(fp, root); db_save_internal(fp, root);
if (ferror(fp)) { if (ferror(fp)) {
g_set_error(error_r, simple_db_quark(), errno, error.SetErrno("Failed to write to database file");
"Failed to write to database file: %s",
g_strerror(errno));
fclose(fp); fclose(fp);
return false; return false;
} }
......
...@@ -53,7 +53,7 @@ public: ...@@ -53,7 +53,7 @@ public:
return root; return root;
} }
bool Save(GError **error_r); bool Save(Error &error);
gcc_pure gcc_pure
time_t GetLastModified() const { time_t GetLastModified() const {
...@@ -61,37 +61,37 @@ public: ...@@ -61,37 +61,37 @@ public:
} }
static Database *Create(const config_param &param, static Database *Create(const config_param &param,
GError **error_r); Error &error);
virtual bool Open(GError **error_r) override; virtual bool Open(Error &error) override;
virtual void Close() override; virtual void Close() override;
virtual Song *GetSong(const char *uri_utf8, virtual Song *GetSong(const char *uri_utf8,
GError **error_r) const override; Error &error) const override;
virtual void ReturnSong(Song *song) const; virtual void ReturnSong(Song *song) const;
virtual bool Visit(const DatabaseSelection &selection, virtual bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory, VisitDirectory visit_directory,
VisitSong visit_song, VisitSong visit_song,
VisitPlaylist visit_playlist, VisitPlaylist visit_playlist,
GError **error_r) const override; Error &error) const override;
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 override; Error &error) const override;
virtual bool GetStats(const DatabaseSelection &selection, virtual bool GetStats(const DatabaseSelection &selection,
DatabaseStats &stats, DatabaseStats &stats,
GError **error_r) const override; Error &error) const override;
protected: protected:
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
gcc_pure gcc_pure
bool Check(GError **error_r) const; bool Check(Error &error) const;
bool Load(GError **error_r); bool Load(Error &error);
gcc_pure gcc_pure
const Directory *LookupDirectory(const char *uri) const; const Directory *LookupDirectory(const char *uri) const;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include <adplug/adplug.h> #include <adplug/adplug.h>
#include <adplug/emuopl.h> #include <adplug/emuopl.h>
...@@ -38,12 +39,11 @@ static unsigned sample_rate; ...@@ -38,12 +39,11 @@ static unsigned sample_rate;
static bool static bool
adplug_init(const config_param &param) adplug_init(const config_param &param)
{ {
GError *error = NULL; Error error;
sample_rate = param.GetBlockValue("sample_rate", 48000u); sample_rate = param.GetBlockValue("sample_rate", 48000u);
if (!audio_check_sample_rate(sample_rate, &error)) { if (!audio_check_sample_rate(sample_rate, error)) {
g_warning("%s\n", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return false; return false;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "util/Error.hxx"
#include <audiofile.h> #include <audiofile.h>
#include <af_vfs.h> #include <af_vfs.h>
...@@ -53,13 +54,11 @@ static ssize_t ...@@ -53,13 +54,11 @@ static ssize_t
audiofile_file_read(AFvirtualfile *vfile, void *data, size_t length) audiofile_file_read(AFvirtualfile *vfile, void *data, size_t length)
{ {
struct input_stream *is = (struct input_stream *) vfile->closure; struct input_stream *is = (struct input_stream *) vfile->closure;
GError *error = nullptr;
size_t nbytes;
nbytes = input_stream_lock_read(is, data, length, &error); Error error;
if (nbytes == 0 && error != nullptr) { size_t nbytes = input_stream_lock_read(is, data, length, error);
g_warning("%s", error->message); if (nbytes == 0 && error.IsDefined()) {
g_error_free(error); g_warning("%s", error.GetMessage());
return -1; return -1;
} }
...@@ -93,7 +92,9 @@ audiofile_file_seek(AFvirtualfile *vfile, AFfileoffset offset, int is_relative) ...@@ -93,7 +92,9 @@ audiofile_file_seek(AFvirtualfile *vfile, AFfileoffset offset, int is_relative)
{ {
struct input_stream *is = (struct input_stream *) vfile->closure; struct input_stream *is = (struct input_stream *) vfile->closure;
int whence = (is_relative ? SEEK_CUR : SEEK_SET); int whence = (is_relative ? SEEK_CUR : SEEK_SET);
if (input_stream_lock_seek(is, offset, whence, nullptr)) {
Error error;
if (input_stream_lock_seek(is, offset, whence, error)) {
return input_stream_get_offset(is); return input_stream_get_offset(is);
} else { } else {
return -1; return -1;
...@@ -156,7 +157,6 @@ audiofile_setup_sample_format(AFfilehandle af_fp) ...@@ -156,7 +157,6 @@ audiofile_setup_sample_format(AFfilehandle af_fp)
static void static void
audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
{ {
GError *error = nullptr;
AFvirtualfile *vf; AFvirtualfile *vf;
int fs, frame_count; int fs, frame_count;
AFfilehandle af_fp; AFfilehandle af_fp;
...@@ -180,13 +180,13 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is) ...@@ -180,13 +180,13 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
return; return;
} }
Error error;
if (!audio_format_init_checked(audio_format, if (!audio_format_init_checked(audio_format,
afGetRate(af_fp, AF_DEFAULT_TRACK), afGetRate(af_fp, AF_DEFAULT_TRACK),
audiofile_setup_sample_format(af_fp), audiofile_setup_sample_format(af_fp),
afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK), afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK),
&error)) { error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
afCloseFile(af_fp); afCloseFile(af_fp);
return; return;
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "util/bit_reverse.h" #include "util/bit_reverse.h"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "TagId3.hxx" #include "TagId3.hxx"
#include "util/Error.hxx"
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
...@@ -64,7 +65,7 @@ dsdlib_skip_to(struct decoder *decoder, struct input_stream *is, ...@@ -64,7 +65,7 @@ dsdlib_skip_to(struct decoder *decoder, struct input_stream *is,
goffset offset) goffset offset)
{ {
if (input_stream_is_seekable(is)) if (input_stream_is_seekable(is))
return input_stream_seek(is, offset, SEEK_SET, nullptr); return input_stream_seek(is, offset, SEEK_SET, IgnoreError());
if (input_stream_get_offset(is) > offset) if (input_stream_get_offset(is) > offset)
return false; return false;
...@@ -97,7 +98,7 @@ dsdlib_skip(struct decoder *decoder, struct input_stream *is, ...@@ -97,7 +98,7 @@ dsdlib_skip(struct decoder *decoder, struct input_stream *is,
return true; return true;
if (input_stream_is_seekable(is)) if (input_stream_is_seekable(is))
return input_stream_seek(is, delta, SEEK_CUR, nullptr); return input_stream_seek(is, delta, SEEK_CUR, IgnoreError());
char buffer[8192]; char buffer[8192];
while (delta > 0) { while (delta > 0) {
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "util/bit_reverse.h" #include "util/bit_reverse.h"
#include "util/Error.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "DsdLib.hxx" #include "DsdLib.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
...@@ -432,13 +433,12 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is) ...@@ -432,13 +433,12 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
if (!dsdiff_read_metadata(decoder, is, &metadata, &chunk_header)) if (!dsdiff_read_metadata(decoder, is, &metadata, &chunk_header))
return; return;
GError *error = nullptr; Error error;
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8,
SampleFormat::DSD, SampleFormat::DSD,
metadata.channels, &error)) { metadata.channels, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return; return;
} }
...@@ -490,7 +490,7 @@ dsdiff_scan_stream(struct input_stream *is, ...@@ -490,7 +490,7 @@ dsdiff_scan_stream(struct input_stream *is,
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8,
SampleFormat::DSD, SampleFormat::DSD,
metadata.channels, nullptr)) metadata.channels, IgnoreError()))
/* refuse to parse files which we cannot play anyway */ /* refuse to parse files which we cannot play anyway */
return false; return false;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "util/bit_reverse.h" #include "util/bit_reverse.h"
#include "util/Error.hxx"
#include "DsdLib.hxx" #include "DsdLib.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
...@@ -284,13 +285,12 @@ dsf_stream_decode(struct decoder *decoder, struct input_stream *is) ...@@ -284,13 +285,12 @@ dsf_stream_decode(struct decoder *decoder, struct input_stream *is)
if (!dsf_read_metadata(decoder, is, &metadata)) if (!dsf_read_metadata(decoder, is, &metadata))
return; return;
GError *error = NULL; Error error;
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8,
SampleFormat::DSD, SampleFormat::DSD,
metadata.channels, &error)) { metadata.channels, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return; return;
} }
/* Calculate song time from DSD chunk size and sample frequency */ /* Calculate song time from DSD chunk size and sample frequency */
...@@ -320,7 +320,7 @@ dsf_scan_stream(struct input_stream *is, ...@@ -320,7 +320,7 @@ dsf_scan_stream(struct input_stream *is,
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8, if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8,
SampleFormat::DSD, SampleFormat::DSD,
metadata.channels, NULL)) metadata.channels, IgnoreError()))
/* refuse to parse files which we cannot play anyway */ /* refuse to parse files which we cannot play anyway */
return false; return false;
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "DecoderBuffer.hxx" #include "DecoderBuffer.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <neaacdec.h> #include <neaacdec.h>
...@@ -42,14 +44,7 @@ static const unsigned adts_sample_rates[] = ...@@ -42,14 +44,7 @@ static const unsigned adts_sample_rates[] =
16000, 12000, 11025, 8000, 7350, 0, 0, 0 16000, 12000, 11025, 8000, 7350, 0, 0, 0
}; };
/** static constexpr Domain faad_decoder_domain("faad_decoder");
* The GLib quark used for errors reported by this plugin.
*/
static inline GQuark
faad_decoder_quark(void)
{
return g_quark_from_static_string("faad");
}
/** /**
* Check whether the buffer head is an AAC frame, and return the frame * Check whether the buffer head is an AAC frame, and return the frame
...@@ -211,7 +206,7 @@ faad_song_duration(DecoderBuffer *buffer, struct input_stream *is) ...@@ -211,7 +206,7 @@ faad_song_duration(DecoderBuffer *buffer, struct input_stream *is)
/* obtain the duration from the ADTS header */ /* obtain the duration from the ADTS header */
float song_length = adts_song_duration(buffer); float song_length = adts_song_duration(buffer);
input_stream_lock_seek(is, tagsize, SEEK_SET, nullptr); input_stream_lock_seek(is, tagsize, SEEK_SET, IgnoreError());
data = (const uint8_t *)decoder_buffer_read(buffer, &length); data = (const uint8_t *)decoder_buffer_read(buffer, &length);
if (data != nullptr) if (data != nullptr)
...@@ -248,7 +243,7 @@ faad_song_duration(DecoderBuffer *buffer, struct input_stream *is) ...@@ -248,7 +243,7 @@ faad_song_duration(DecoderBuffer *buffer, struct input_stream *is)
*/ */
static bool static bool
faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
AudioFormat &audio_format, GError **error_r) AudioFormat &audio_format, Error &error)
{ {
int32_t nbytes; int32_t nbytes;
uint32_t sample_rate; uint32_t sample_rate;
...@@ -266,8 +261,7 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, ...@@ -266,8 +261,7 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
const unsigned char *data = (const unsigned char *) const unsigned char *data = (const unsigned char *)
decoder_buffer_read(buffer, &length); decoder_buffer_read(buffer, &length);
if (data == nullptr) { if (data == nullptr) {
g_set_error(error_r, faad_decoder_quark(), 0, error.Set(faad_decoder_domain, "Empty file");
"Empty file");
return false; return false;
} }
...@@ -277,15 +271,14 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, ...@@ -277,15 +271,14 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
length, length,
sample_rate_p, &channels); sample_rate_p, &channels);
if (nbytes < 0) { if (nbytes < 0) {
g_set_error(error_r, faad_decoder_quark(), 0, error.Set(faad_decoder_domain, "Not an AAC stream");
"Not an AAC stream");
return false; return false;
} }
decoder_buffer_consume(buffer, nbytes); decoder_buffer_consume(buffer, nbytes);
return audio_format_init_checked(audio_format, sample_rate, return audio_format_init_checked(audio_format, sample_rate,
SampleFormat::S16, channels, error_r); SampleFormat::S16, channels, error);
} }
/** /**
...@@ -336,7 +329,8 @@ faad_get_file_time_float(struct input_stream *is) ...@@ -336,7 +329,8 @@ faad_get_file_time_float(struct input_stream *is)
decoder_buffer_fill(buffer); decoder_buffer_fill(buffer);
ret = faad_decoder_init(decoder, buffer, audio_format, nullptr); ret = faad_decoder_init(decoder, buffer, audio_format,
IgnoreError());
if (ret) if (ret)
length = 0; length = 0;
...@@ -368,7 +362,6 @@ faad_get_file_time(struct input_stream *is) ...@@ -368,7 +362,6 @@ faad_get_file_time(struct input_stream *is)
static void static void
faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is) faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
{ {
GError *error = nullptr;
float total_time = 0; float total_time = 0;
AudioFormat audio_format; AudioFormat audio_format;
bool ret; bool ret;
...@@ -400,10 +393,10 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is) ...@@ -400,10 +393,10 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
/* initialize it */ /* initialize it */
ret = faad_decoder_init(decoder, buffer, audio_format, &error); Error error;
ret = faad_decoder_init(decoder, buffer, audio_format, error);
if (!ret) { if (!ret) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
NeAACDecClose(decoder); NeAACDecClose(decoder);
return; return;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -124,7 +125,8 @@ mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence) ...@@ -124,7 +125,8 @@ mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence)
if (whence == AVSEEK_SIZE) if (whence == AVSEEK_SIZE)
return stream->input->size; return stream->input->size;
if (!input_stream_lock_seek(stream->input, pos, whence, NULL)) Error error;
if (!input_stream_lock_seek(stream->input, pos, whence, error))
return -1; return -1;
return stream->input->offset; return stream->input->offset;
...@@ -343,10 +345,12 @@ ffmpeg_probe(struct decoder *decoder, struct input_stream *is) ...@@ -343,10 +345,12 @@ ffmpeg_probe(struct decoder *decoder, struct input_stream *is)
PADDING = 16, PADDING = 16,
}; };
Error error;
unsigned char *buffer = (unsigned char *)g_malloc(BUFFER_SIZE); unsigned char *buffer = (unsigned char *)g_malloc(BUFFER_SIZE);
size_t nbytes = decoder_read(decoder, is, buffer, BUFFER_SIZE); size_t nbytes = decoder_read(decoder, is, buffer, BUFFER_SIZE);
if (nbytes <= PADDING || if (nbytes <= PADDING ||
!input_stream_lock_seek(is, 0, SEEK_SET, NULL)) { !input_stream_lock_seek(is, 0, SEEK_SET, error)) {
g_free(buffer); g_free(buffer);
return NULL; return NULL;
} }
...@@ -427,14 +431,13 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) ...@@ -427,14 +431,13 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
if (sample_format == SampleFormat::UNDEFINED) if (sample_format == SampleFormat::UNDEFINED)
return; return;
GError *error = NULL; Error error;
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, if (!audio_format_init_checked(audio_format,
codec_context->sample_rate, codec_context->sample_rate,
sample_format, sample_format,
codec_context->channels, &error)) { codec_context->channels, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
avformat_close_input(&format_context); avformat_close_input(&format_context);
return; return;
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "FlacMetadata.hxx" #include "FlacMetadata.hxx"
#include "FlacPcm.hxx" #include "FlacPcm.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -68,13 +69,12 @@ flac_got_stream_info(struct flac_data *data, ...@@ -68,13 +69,12 @@ flac_got_stream_info(struct flac_data *data,
if (data->initialized || data->unsupported) if (data->initialized || data->unsupported)
return; return;
GError *error = nullptr; Error error;
if (!audio_format_init_checked(data->audio_format, if (!audio_format_init_checked(data->audio_format,
stream_info->sample_rate, stream_info->sample_rate,
flac_sample_format(stream_info->bits_per_sample), flac_sample_format(stream_info->bits_per_sample),
stream_info->channels, &error)) { stream_info->channels, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
data->unsupported = true; data->unsupported = true;
return; return;
} }
...@@ -131,13 +131,12 @@ flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header) ...@@ -131,13 +131,12 @@ flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header)
if (data->unsupported) if (data->unsupported)
return false; return false;
GError *error = nullptr; Error error;
if (!audio_format_init_checked(data->audio_format, if (!audio_format_init_checked(data->audio_format,
header->sample_rate, header->sample_rate,
flac_sample_format(header->bits_per_sample), flac_sample_format(header->bits_per_sample),
header->channels, &error)) { header->channels, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
data->unsupported = true; data->unsupported = true;
return false; return false;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "FlacCommon.hxx" #include "FlacCommon.hxx"
#include "FlacMetadata.hxx" #include "FlacMetadata.hxx"
#include "OggCodec.hxx" #include "OggCodec.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -330,7 +331,7 @@ oggflac_decode(struct decoder *decoder, struct input_stream *input_stream) ...@@ -330,7 +331,7 @@ oggflac_decode(struct decoder *decoder, struct input_stream *input_stream)
/* rewind the stream, because ogg_codec_detect() has /* rewind the stream, because ogg_codec_detect() has
moved it */ moved it */
input_stream_lock_seek(input_stream, 0, SEEK_SET, nullptr); input_stream_lock_seek(input_stream, 0, SEEK_SET, IgnoreError());
flac_decode_internal(decoder, input_stream, true); flac_decode_internal(decoder, input_stream, true);
} }
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "config.h" #include "config.h"
#include "FlacIOHandle.hxx" #include "FlacIOHandle.hxx"
#include "io_error.h" #include "util/Error.hxx"
#include "gcc.h" #include "gcc.h"
#include <errno.h> #include <errno.h>
...@@ -35,21 +35,20 @@ FlacIORead(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle) ...@@ -35,21 +35,20 @@ FlacIORead(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
/* libFLAC is very picky about short reads, and expects the IO /* libFLAC is very picky about short reads, and expects the IO
callback to fill the whole buffer (undocumented!) */ callback to fill the whole buffer (undocumented!) */
GError *error = nullptr; Error error;
while (p < end) { while (p < end) {
size_t nbytes = input_stream_lock_read(is, p, end - p, &error); size_t nbytes = input_stream_lock_read(is, p, end - p, error);
if (nbytes == 0) { if (nbytes == 0) {
if (error == nullptr) if (!error.IsDefined())
/* end of file */ /* end of file */
break; break;
if (error->domain == errno_quark()) if (error.IsDomain(errno_domain))
errno = error->code; errno = error.GetCode();
else else
/* just some random non-zero /* just some random non-zero
errno value */ errno value */
errno = EINVAL; errno = EINVAL;
g_error_free(error);
return 0; return 0;
} }
...@@ -67,7 +66,8 @@ FlacIOSeek(FLAC__IOHandle handle, FLAC__int64 offset, int whence) ...@@ -67,7 +66,8 @@ FlacIOSeek(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
{ {
input_stream *is = (input_stream *)handle; input_stream *is = (input_stream *)handle;
return input_stream_lock_seek(is, offset, whence, nullptr) ? 0 : -1; Error error;
return input_stream_lock_seek(is, offset, whence, error) ? 0 : -1;
} }
static FLAC__int64 static FLAC__int64
......
...@@ -20,8 +20,9 @@ ...@@ -20,8 +20,9 @@
#include "config.h" #include "config.h"
#include "FlacInput.hxx" #include "FlacInput.hxx"
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "gcc.h"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "util/Error.hxx"
#include "gcc.h"
FLAC__StreamDecoderReadStatus FLAC__StreamDecoderReadStatus
FlacInput::Read(FLAC__byte buffer[], size_t *bytes) FlacInput::Read(FLAC__byte buffer[], size_t *bytes)
...@@ -47,9 +48,10 @@ FlacInput::Seek(FLAC__uint64 absolute_byte_offset) ...@@ -47,9 +48,10 @@ FlacInput::Seek(FLAC__uint64 absolute_byte_offset)
if (!input_stream->seekable) if (!input_stream->seekable)
return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
::Error error;
if (!input_stream_lock_seek(input_stream, if (!input_stream_lock_seek(input_stream,
absolute_byte_offset, SEEK_SET, absolute_byte_offset, SEEK_SET,
nullptr)) error))
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
return FLAC__STREAM_DECODER_SEEK_STATUS_OK; return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "FluidsynthDecoderPlugin.hxx" #include "FluidsynthDecoderPlugin.hxx"
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include "conf.h" #include "conf.h"
#include <glib.h> #include <glib.h>
...@@ -73,12 +74,11 @@ fluidsynth_mpd_log_function(int level, char *message, gcc_unused void *data) ...@@ -73,12 +74,11 @@ fluidsynth_mpd_log_function(int level, char *message, gcc_unused void *data)
static bool static bool
fluidsynth_init(const config_param &param) fluidsynth_init(const config_param &param)
{ {
GError *error = nullptr; Error error;
sample_rate = param.GetBlockValue("sample_rate", 48000u); sample_rate = param.GetBlockValue("sample_rate", 48000u);
if (!audio_check_sample_rate(sample_rate, &error)) { if (!audio_check_sample_rate(sample_rate, error)) {
g_warning("%s\n", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return false; return false;
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
#include <assert.h> #include <assert.h>
...@@ -152,13 +153,12 @@ gme_file_decode(struct decoder *decoder, const char *path_fs) ...@@ -152,13 +153,12 @@ gme_file_decode(struct decoder *decoder, const char *path_fs)
/* initialize the MPD decoder */ /* initialize the MPD decoder */
GError *error = nullptr; Error error;
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, GME_SAMPLE_RATE, if (!audio_format_init_checked(audio_format, GME_SAMPLE_RATE,
SampleFormat::S16, GME_CHANNELS, SampleFormat::S16, GME_CHANNELS,
&error)) { error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
gme_free_info(ti); gme_free_info(ti);
gme_delete(emu); gme_delete(emu);
return; return;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "TagRva2.hxx" #include "TagRva2.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include <assert.h> #include <assert.h>
#include <unistd.h> #include <unistd.h>
...@@ -203,8 +204,9 @@ MadDecoder::MadDecoder(struct decoder *_decoder, ...@@ -203,8 +204,9 @@ MadDecoder::MadDecoder(struct decoder *_decoder,
inline bool inline bool
MadDecoder::Seek(long offset) MadDecoder::Seek(long offset)
{ {
Error error;
if (!input_stream_lock_seek(input_stream, offset, SEEK_SET, if (!input_stream_lock_seek(input_stream, offset, SEEK_SET,
nullptr)) error))
return false; return false;
mad_stream_buffer(&stream, input_buffer, 0); mad_stream_buffer(&stream, input_buffer, 0);
...@@ -1124,16 +1126,14 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) ...@@ -1124,16 +1126,14 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
return; return;
} }
Error error;
AudioFormat audio_format; AudioFormat audio_format;
GError *error = nullptr;
if (!audio_format_init_checked(audio_format, if (!audio_format_init_checked(audio_format,
data.frame.header.samplerate, data.frame.header.samplerate,
SampleFormat::S24_P32, SampleFormat::S24_P32,
MAD_NCHANNELS(&data.frame.header), MAD_NCHANNELS(&data.frame.header),
&error)) { error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
delete tag; delete tag;
return; return;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "util/Error.hxx"
#include <mpc/mpcdec.h> #include <mpc/mpcdec.h>
...@@ -53,7 +54,8 @@ mpc_seek_cb(mpc_reader *reader, mpc_int32_t offset) ...@@ -53,7 +54,8 @@ mpc_seek_cb(mpc_reader *reader, mpc_int32_t offset)
struct mpc_decoder_data *data = struct mpc_decoder_data *data =
(struct mpc_decoder_data *)reader->data; (struct mpc_decoder_data *)reader->data;
return input_stream_lock_seek(data->is, offset, SEEK_SET, nullptr); return input_stream_lock_seek(data->is, offset, SEEK_SET,
IgnoreError());
} }
static mpc_int32_t static mpc_int32_t
...@@ -153,13 +155,12 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) ...@@ -153,13 +155,12 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
mpc_streaminfo info; mpc_streaminfo info;
mpc_demux_get_info(demux, &info); mpc_demux_get_info(demux, &info);
GError *error = nullptr; Error error;
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, info.sample_freq, if (!audio_format_init_checked(audio_format, info.sample_freq,
SampleFormat::S24_P32, SampleFormat::S24_P32,
info.channels, &error)) { info.channels, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
mpc_demux_exit(demux); mpc_demux_exit(demux);
return; return;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -58,7 +59,6 @@ static bool ...@@ -58,7 +59,6 @@ static bool
mpd_mpg123_open(mpg123_handle *handle, const char *path_fs, mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
AudioFormat &audio_format) AudioFormat &audio_format)
{ {
GError *gerror = nullptr;
char *path_dup; char *path_dup;
int error; int error;
int channels, encoding; int channels, encoding;
...@@ -90,10 +90,10 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs, ...@@ -90,10 +90,10 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
return false; return false;
} }
Error error2;
if (!audio_format_init_checked(audio_format, rate, SampleFormat::S16, if (!audio_format_init_checked(audio_format, rate, SampleFormat::S16,
channels, &gerror)) { channels, error2)) {
g_warning("%s", gerror->message); g_warning("%s", error2.GetMessage());
g_error_free(gerror);
return false; return false;
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "util/Error.hxx"
#include <opus.h> #include <opus.h>
#include <ogg/ogg.h> #include <ogg/ogg.h>
...@@ -271,7 +272,7 @@ mpd_opus_stream_decode(struct decoder *decoder, ...@@ -271,7 +272,7 @@ mpd_opus_stream_decode(struct decoder *decoder,
/* rewind the stream, because ogg_codec_detect() has /* rewind the stream, because ogg_codec_detect() has
moved it */ moved it */
input_stream_lock_seek(input_stream, 0, SEEK_SET, nullptr); input_stream_lock_seek(input_stream, 0, SEEK_SET, IgnoreError());
MPDOpusDecoder d(decoder, input_stream); MPDOpusDecoder d(decoder, input_stream);
OggSyncState oy(*input_stream, decoder); OggSyncState oy(*input_stream, decoder);
...@@ -302,7 +303,8 @@ SeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet, ...@@ -302,7 +303,8 @@ SeekFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet,
oy.Reset(); oy.Reset();
return input_stream_lock_seek(is, -65536, SEEK_END, nullptr) && Error error;
return input_stream_lock_seek(is, -65536, SEEK_END, error) &&
oy.ExpectPageSeekIn(os) && oy.ExpectPageSeekIn(os) &&
OggFindEOS(oy, os, packet); OggFindEOS(oy, os, packet);
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include "decoder/PcmDecoderPlugin.hxx" #include "decoder/PcmDecoderPlugin.hxx"
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "util/Error.hxx"
extern "C" { extern "C" {
#include "util/byte_reverse.h" #include "util/byte_reverse.h"
...@@ -46,7 +47,6 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is) ...@@ -46,7 +47,6 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is)
const bool reverse_endian = mime != nullptr && const bool reverse_endian = mime != nullptr &&
strcmp(mime, "audio/x-mpd-cdda-pcm-reverse") == 0; strcmp(mime, "audio/x-mpd-cdda-pcm-reverse") == 0;
GError *error = nullptr;
enum decoder_command cmd; enum decoder_command cmd;
const double time_to_size = audio_format.GetTimeToSize(); const double time_to_size = audio_format.GetTimeToSize();
...@@ -81,12 +81,13 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is) ...@@ -81,12 +81,13 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is)
if (cmd == DECODE_COMMAND_SEEK) { if (cmd == DECODE_COMMAND_SEEK) {
goffset offset = (goffset)(time_to_size * goffset offset = (goffset)(time_to_size *
decoder_seek_where(decoder)); decoder_seek_where(decoder));
Error error;
if (input_stream_lock_seek(is, offset, SEEK_SET, if (input_stream_lock_seek(is, offset, SEEK_SET,
&error)) { error)) {
decoder_command_finished(decoder); decoder_command_finished(decoder);
} else { } else {
g_warning("seeking failed: %s", error->message); g_warning("seeking failed: %s", error.GetMessage());
g_error_free(error);
decoder_seek_error(decoder); decoder_seek_error(decoder);
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "util/Error.hxx"
#include <sndfile.h> #include <sndfile.h>
...@@ -40,10 +41,8 @@ static sf_count_t ...@@ -40,10 +41,8 @@ static sf_count_t
sndfile_vio_seek(sf_count_t offset, int whence, void *user_data) sndfile_vio_seek(sf_count_t offset, int whence, void *user_data)
{ {
struct input_stream *is = (struct input_stream *)user_data; struct input_stream *is = (struct input_stream *)user_data;
bool success;
success = input_stream_lock_seek(is, offset, whence, nullptr); if (!input_stream_lock_seek(is, offset, whence, IgnoreError()))
if (!success)
return -1; return -1;
return input_stream_get_offset(is); return input_stream_get_offset(is);
...@@ -53,13 +52,11 @@ static sf_count_t ...@@ -53,13 +52,11 @@ static sf_count_t
sndfile_vio_read(void *ptr, sf_count_t count, void *user_data) sndfile_vio_read(void *ptr, sf_count_t count, void *user_data)
{ {
struct input_stream *is = (struct input_stream *)user_data; struct input_stream *is = (struct input_stream *)user_data;
GError *error = nullptr;
size_t nbytes;
nbytes = input_stream_lock_read(is, ptr, count, &error); Error error;
if (nbytes == 0 && error != nullptr) { size_t nbytes = input_stream_lock_read(is, ptr, count, error);
g_warning("%s", error->message); if (nbytes == 0 && error.IsDefined()) {
g_error_free(error); g_warning("%s", error.GetMessage());
return -1; return -1;
} }
...@@ -116,7 +113,6 @@ time_to_frame(float t, const AudioFormat *audio_format) ...@@ -116,7 +113,6 @@ time_to_frame(float t, const AudioFormat *audio_format)
static void static void
sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
{ {
GError *error = nullptr;
SNDFILE *sf; SNDFILE *sf;
SF_INFO info; SF_INFO info;
size_t frame_size; size_t frame_size;
...@@ -135,12 +131,12 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) ...@@ -135,12 +131,12 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
/* for now, always read 32 bit samples. Later, we could lower /* for now, always read 32 bit samples. Later, we could lower
MPD's CPU usage by reading 16 bit samples with MPD's CPU usage by reading 16 bit samples with
sf_readf_short() on low-quality source files. */ sf_readf_short() on low-quality source files. */
Error error;
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, info.samplerate, if (!audio_format_init_checked(audio_format, info.samplerate,
SampleFormat::S32, SampleFormat::S32,
info.channels, &error)) { info.channels, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return; return;
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "OggCodec.hxx" #include "OggCodec.hxx"
#include "util/Error.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
...@@ -80,9 +81,10 @@ static int ogg_seek_cb(void *data, ogg_int64_t offset, int whence) ...@@ -80,9 +81,10 @@ static int ogg_seek_cb(void *data, ogg_int64_t offset, int whence)
{ {
struct vorbis_input_stream *vis = (struct vorbis_input_stream *)data; struct vorbis_input_stream *vis = (struct vorbis_input_stream *)data;
Error error;
return vis->seekable && return vis->seekable &&
(!vis->decoder || decoder_get_command(vis->decoder) != DECODE_COMMAND_STOP) && (!vis->decoder || decoder_get_command(vis->decoder) != DECODE_COMMAND_STOP) &&
input_stream_lock_seek(vis->input_stream, offset, whence, NULL) input_stream_lock_seek(vis->input_stream, offset, whence, error)
? 0 : -1; ? 0 : -1;
} }
...@@ -182,14 +184,12 @@ static void ...@@ -182,14 +184,12 @@ static void
vorbis_stream_decode(struct decoder *decoder, vorbis_stream_decode(struct decoder *decoder,
struct input_stream *input_stream) struct input_stream *input_stream)
{ {
GError *error = NULL;
if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS) if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS)
return; return;
/* rewind the stream, because ogg_codec_detect() has /* rewind the stream, because ogg_codec_detect() has
moved it */ moved it */
input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); input_stream_lock_seek(input_stream, 0, SEEK_SET, IgnoreError());
struct vorbis_input_stream vis; struct vorbis_input_stream vis;
OggVorbis_File vf; OggVorbis_File vf;
...@@ -202,6 +202,7 @@ vorbis_stream_decode(struct decoder *decoder, ...@@ -202,6 +202,7 @@ vorbis_stream_decode(struct decoder *decoder,
return; return;
} }
Error error;
AudioFormat audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(audio_format, vi->rate, if (!audio_format_init_checked(audio_format, vi->rate,
#ifdef HAVE_TREMOR #ifdef HAVE_TREMOR
...@@ -209,9 +210,8 @@ vorbis_stream_decode(struct decoder *decoder, ...@@ -209,9 +210,8 @@ vorbis_stream_decode(struct decoder *decoder,
#else #else
SampleFormat::FLOAT, SampleFormat::FLOAT,
#endif #endif
vi->channels, &error)) { vi->channels, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return; return;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "ApeTag.hxx" #include "ApeTag.hxx"
#include "util/Error.hxx"
#include <wavpack/wavpack.h> #include <wavpack/wavpack.h>
#include <glib.h> #include <glib.h>
...@@ -137,7 +138,6 @@ wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample) ...@@ -137,7 +138,6 @@ wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample)
static void static void
wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek) wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
{ {
GError *error = NULL;
bool is_float; bool is_float;
SampleFormat sample_format; SampleFormat sample_format;
AudioFormat audio_format; AudioFormat audio_format;
...@@ -150,12 +150,12 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek) ...@@ -150,12 +150,12 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
wavpack_bits_to_sample_format(is_float, wavpack_bits_to_sample_format(is_float,
WavpackGetBytesPerSample(wpc)); WavpackGetBytesPerSample(wpc));
Error error;
if (!audio_format_init_checked(audio_format, if (!audio_format_init_checked(audio_format,
WavpackGetSampleRate(wpc), WavpackGetSampleRate(wpc),
sample_format, sample_format,
WavpackGetNumChannels(wpc), &error)) { WavpackGetNumChannels(wpc), error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return; return;
} }
...@@ -401,14 +401,16 @@ wavpack_input_get_pos(void *id) ...@@ -401,14 +401,16 @@ wavpack_input_get_pos(void *id)
static int static int
wavpack_input_set_pos_abs(void *id, uint32_t pos) wavpack_input_set_pos_abs(void *id, uint32_t pos)
{ {
return input_stream_lock_seek(wpin(id)->is, pos, SEEK_SET, NULL) Error error;
return input_stream_lock_seek(wpin(id)->is, pos, SEEK_SET, error)
? 0 : -1; ? 0 : -1;
} }
static int static int
wavpack_input_set_pos_rel(void *id, int32_t delta, int mode) wavpack_input_set_pos_rel(void *id, int32_t delta, int mode)
{ {
return input_stream_lock_seek(wpin(id)->is, delta, mode, NULL) Error error;
return input_stream_lock_seek(wpin(id)->is, delta, mode, error)
? 0 : -1; ? 0 : -1;
} }
...@@ -476,7 +478,9 @@ wavpack_open_wvc(struct decoder *decoder, const char *uri, ...@@ -476,7 +478,9 @@ wavpack_open_wvc(struct decoder *decoder, const char *uri,
return nullptr; return nullptr;
wvc_url = g_strconcat(uri, "c", NULL); wvc_url = g_strconcat(uri, "c", NULL);
is_wvc = input_stream_open(wvc_url, mutex, cond, NULL);
Error error;
is_wvc = input_stream_open(wvc_url, mutex, cond, error);
g_free(wvc_url); g_free(wvc_url);
if (is_wvc == NULL) if (is_wvc == NULL)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "WildmidiDecoderPlugin.hxx" #include "WildmidiDecoderPlugin.hxx"
#include "DecoderAPI.hxx" #include "DecoderAPI.hxx"
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "util/Error.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "fs/FileSystem.hxx" #include "fs/FileSystem.hxx"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
...@@ -39,10 +40,10 @@ static constexpr unsigned WILDMIDI_SAMPLE_RATE = 48000; ...@@ -39,10 +40,10 @@ static constexpr unsigned WILDMIDI_SAMPLE_RATE = 48000;
static bool static bool
wildmidi_init(const config_param &param) wildmidi_init(const config_param &param)
{ {
GError *error = nullptr; Error error;
const Path path = param.GetBlockPath("config_file", const Path path = param.GetBlockPath("config_file",
"/etc/timidity/timidity.cfg", "/etc/timidity/timidity.cfg",
&error); error);
if (path.IsNull()) if (path.IsNull())
FatalError(error); FatalError(error);
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/fifo_buffer.h" #include "util/fifo_buffer.h"
extern "C" { extern "C" {
...@@ -58,15 +61,11 @@ struct flac_encoder { ...@@ -58,15 +61,11 @@ struct flac_encoder {
flac_encoder():encoder(flac_encoder_plugin) {} flac_encoder():encoder(flac_encoder_plugin) {}
}; };
static inline GQuark static constexpr Domain flac_encoder_domain("vorbis_encoder");
flac_encoder_quark(void)
{
return g_quark_from_static_string("flac_encoder");
}
static bool static bool
flac_encoder_configure(struct flac_encoder *encoder, const config_param &param, flac_encoder_configure(struct flac_encoder *encoder, const config_param &param,
gcc_unused GError **error) gcc_unused Error &error)
{ {
encoder->compression = param.GetBlockValue("compression", 5u); encoder->compression = param.GetBlockValue("compression", 5u);
...@@ -74,7 +73,7 @@ flac_encoder_configure(struct flac_encoder *encoder, const config_param &param, ...@@ -74,7 +73,7 @@ flac_encoder_configure(struct flac_encoder *encoder, const config_param &param,
} }
static Encoder * static Encoder *
flac_encoder_init(const config_param &param, GError **error) flac_encoder_init(const config_param &param, Error &error)
{ {
flac_encoder *encoder = new flac_encoder(); flac_encoder *encoder = new flac_encoder();
...@@ -100,11 +99,11 @@ flac_encoder_finish(Encoder *_encoder) ...@@ -100,11 +99,11 @@ flac_encoder_finish(Encoder *_encoder)
static bool static bool
flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample, flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample,
GError **error) Error &error)
{ {
if ( !FLAC__stream_encoder_set_compression_level(encoder->fse, if ( !FLAC__stream_encoder_set_compression_level(encoder->fse,
encoder->compression)) { encoder->compression)) {
g_set_error(error, flac_encoder_quark(), 0, error.Format(config_domain,
"error setting flac compression to %d", "error setting flac compression to %d",
encoder->compression); encoder->compression);
return false; return false;
...@@ -112,21 +111,21 @@ flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample, ...@@ -112,21 +111,21 @@ flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample,
if ( !FLAC__stream_encoder_set_channels(encoder->fse, if ( !FLAC__stream_encoder_set_channels(encoder->fse,
encoder->audio_format.channels)) { encoder->audio_format.channels)) {
g_set_error(error, flac_encoder_quark(), 0, error.Format(config_domain,
"error setting flac channels num to %d", "error setting flac channels num to %d",
encoder->audio_format.channels); encoder->audio_format.channels);
return false; return false;
} }
if ( !FLAC__stream_encoder_set_bits_per_sample(encoder->fse, if ( !FLAC__stream_encoder_set_bits_per_sample(encoder->fse,
bits_per_sample)) { bits_per_sample)) {
g_set_error(error, flac_encoder_quark(), 0, error.Format(config_domain,
"error setting flac bit format to %d", "error setting flac bit format to %d",
bits_per_sample); bits_per_sample);
return false; return false;
} }
if ( !FLAC__stream_encoder_set_sample_rate(encoder->fse, if ( !FLAC__stream_encoder_set_sample_rate(encoder->fse,
encoder->audio_format.sample_rate)) { encoder->audio_format.sample_rate)) {
g_set_error(error, flac_encoder_quark(), 0, error.Format(config_domain,
"error setting flac sample rate to %d", "error setting flac sample rate to %d",
encoder->audio_format.sample_rate); encoder->audio_format.sample_rate);
return false; return false;
...@@ -161,8 +160,7 @@ flac_encoder_close(Encoder *_encoder) ...@@ -161,8 +160,7 @@ flac_encoder_close(Encoder *_encoder)
} }
static bool static bool
flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error)
GError **error)
{ {
struct flac_encoder *encoder = (struct flac_encoder *)_encoder; struct flac_encoder *encoder = (struct flac_encoder *)_encoder;
unsigned bits_per_sample; unsigned bits_per_sample;
...@@ -191,8 +189,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, ...@@ -191,8 +189,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
/* allocate the encoder */ /* allocate the encoder */
encoder->fse = FLAC__stream_encoder_new(); encoder->fse = FLAC__stream_encoder_new();
if (encoder->fse == nullptr) { if (encoder->fse == nullptr) {
g_set_error(error, flac_encoder_quark(), 0, error.Set(flac_encoder_domain, "flac_new() failed");
"flac_new() failed");
return false; return false;
} }
...@@ -213,7 +210,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, ...@@ -213,7 +210,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
nullptr, nullptr, nullptr, encoder); nullptr, nullptr, nullptr, encoder);
if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
g_set_error(error, flac_encoder_quark(), 0, error.Format(flac_encoder_domain,
"failed to initialize encoder: %s\n", "failed to initialize encoder: %s\n",
FLAC__StreamEncoderInitStatusString[init_status]); FLAC__StreamEncoderInitStatusString[init_status]);
flac_encoder_close(_encoder); flac_encoder_close(_encoder);
...@@ -226,7 +223,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, ...@@ -226,7 +223,7 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
static bool static bool
flac_encoder_flush(Encoder *_encoder, gcc_unused GError **error) flac_encoder_flush(Encoder *_encoder, gcc_unused Error &error)
{ {
struct flac_encoder *encoder = (struct flac_encoder *)_encoder; struct flac_encoder *encoder = (struct flac_encoder *)_encoder;
...@@ -255,7 +252,7 @@ pcm16_to_flac(int32_t *out, const int16_t *in, unsigned num_samples) ...@@ -255,7 +252,7 @@ pcm16_to_flac(int32_t *out, const int16_t *in, unsigned num_samples)
static bool static bool
flac_encoder_write(Encoder *_encoder, flac_encoder_write(Encoder *_encoder,
const void *data, size_t length, const void *data, size_t length,
gcc_unused GError **error) gcc_unused Error &error)
{ {
struct flac_encoder *encoder = (struct flac_encoder *)_encoder; struct flac_encoder *encoder = (struct flac_encoder *)_encoder;
unsigned num_frames, num_samples; unsigned num_frames, num_samples;
...@@ -298,8 +295,7 @@ flac_encoder_write(Encoder *_encoder, ...@@ -298,8 +295,7 @@ flac_encoder_write(Encoder *_encoder,
if (!FLAC__stream_encoder_process_interleaved(encoder->fse, if (!FLAC__stream_encoder_process_interleaved(encoder->fse,
(const FLAC__int32 *)buffer, (const FLAC__int32 *)buffer,
num_frames)) { num_frames)) {
g_set_error(error, flac_encoder_quark(), 0, error.Set(flac_encoder_domain, "flac encoder process failed");
"flac encoder process failed");
return false; return false;
} }
......
...@@ -21,8 +21,11 @@ ...@@ -21,8 +21,11 @@
#include "LameEncoderPlugin.hxx" #include "LameEncoderPlugin.hxx"
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "ConfigError.hxx"
#include "util/ReusableArray.hxx" #include "util/ReusableArray.hxx"
#include "util/Manual.hxx" #include "util/Manual.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <lame/lame.h> #include <lame/lame.h>
...@@ -45,17 +48,13 @@ struct LameEncoder final { ...@@ -45,17 +48,13 @@ struct LameEncoder final {
LameEncoder():encoder(lame_encoder_plugin) {} LameEncoder():encoder(lame_encoder_plugin) {}
bool Configure(const config_param &param, GError **error); bool Configure(const config_param &param, Error &error);
}; };
static inline GQuark static constexpr Domain lame_encoder_domain("lame_encoder");
lame_encoder_quark(void)
{
return g_quark_from_static_string("lame_encoder");
}
bool bool
LameEncoder::Configure(const config_param &param, GError **error) LameEncoder::Configure(const config_param &param, Error &error)
{ {
const char *value; const char *value;
char *endptr; char *endptr;
...@@ -67,7 +66,7 @@ LameEncoder::Configure(const config_param &param, GError **error) ...@@ -67,7 +66,7 @@ LameEncoder::Configure(const config_param &param, GError **error)
quality = g_ascii_strtod(value, &endptr); quality = g_ascii_strtod(value, &endptr);
if (*endptr != '\0' || quality < -1.0 || quality > 10.0) { if (*endptr != '\0' || quality < -1.0 || quality > 10.0) {
g_set_error(error, lame_encoder_quark(), 0, error.Format(config_domain,
"quality \"%s\" is not a number in the " "quality \"%s\" is not a number in the "
"range -1 to 10, line %i", "range -1 to 10, line %i",
value, param.line); value, param.line);
...@@ -75,7 +74,7 @@ LameEncoder::Configure(const config_param &param, GError **error) ...@@ -75,7 +74,7 @@ LameEncoder::Configure(const config_param &param, GError **error)
} }
if (param.GetBlockValue("bitrate") != nullptr) { if (param.GetBlockValue("bitrate") != nullptr) {
g_set_error(error, lame_encoder_quark(), 0, error.Format(config_domain,
"quality and bitrate are " "quality and bitrate are "
"both defined (line %i)", "both defined (line %i)",
param.line); param.line);
...@@ -86,7 +85,7 @@ LameEncoder::Configure(const config_param &param, GError **error) ...@@ -86,7 +85,7 @@ LameEncoder::Configure(const config_param &param, GError **error)
value = param.GetBlockValue("bitrate"); value = param.GetBlockValue("bitrate");
if (value == nullptr) { if (value == nullptr) {
g_set_error(error, lame_encoder_quark(), 0, error.Format(config_domain,
"neither bitrate nor quality defined " "neither bitrate nor quality defined "
"at line %i", "at line %i",
param.line); param.line);
...@@ -97,7 +96,7 @@ LameEncoder::Configure(const config_param &param, GError **error) ...@@ -97,7 +96,7 @@ LameEncoder::Configure(const config_param &param, GError **error)
bitrate = g_ascii_strtoll(value, &endptr, 10); bitrate = g_ascii_strtoll(value, &endptr, 10);
if (*endptr != '\0' || bitrate <= 0) { if (*endptr != '\0' || bitrate <= 0) {
g_set_error(error, lame_encoder_quark(), 0, error.Format(config_domain,
"bitrate at line %i should be a positive integer", "bitrate at line %i should be a positive integer",
param.line); param.line);
return false; return false;
...@@ -108,12 +107,12 @@ LameEncoder::Configure(const config_param &param, GError **error) ...@@ -108,12 +107,12 @@ LameEncoder::Configure(const config_param &param, GError **error)
} }
static Encoder * static Encoder *
lame_encoder_init(const config_param &param, GError **error_r) lame_encoder_init(const config_param &param, Error &error)
{ {
LameEncoder *encoder = new LameEncoder(); LameEncoder *encoder = new LameEncoder();
/* load configuration from "param" */ /* load configuration from "param" */
if (!encoder->Configure(param, error_r)) { if (!encoder->Configure(param, error)) {
/* configuration has failed, roll back and return error */ /* configuration has failed, roll back and return error */
delete encoder; delete encoder;
return nullptr; return nullptr;
...@@ -133,18 +132,18 @@ lame_encoder_finish(Encoder *_encoder) ...@@ -133,18 +132,18 @@ lame_encoder_finish(Encoder *_encoder)
} }
static bool static bool
lame_encoder_setup(LameEncoder *encoder, GError **error) lame_encoder_setup(LameEncoder *encoder, Error &error)
{ {
if (encoder->quality >= -1.0) { if (encoder->quality >= -1.0) {
/* a quality was configured (VBR) */ /* a quality was configured (VBR) */
if (0 != lame_set_VBR(encoder->gfp, vbr_rh)) { if (0 != lame_set_VBR(encoder->gfp, vbr_rh)) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain,
"error setting lame VBR mode"); "error setting lame VBR mode");
return false; return false;
} }
if (0 != lame_set_VBR_q(encoder->gfp, encoder->quality)) { if (0 != lame_set_VBR_q(encoder->gfp, encoder->quality)) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain,
"error setting lame VBR quality"); "error setting lame VBR quality");
return false; return false;
} }
...@@ -152,7 +151,7 @@ lame_encoder_setup(LameEncoder *encoder, GError **error) ...@@ -152,7 +151,7 @@ lame_encoder_setup(LameEncoder *encoder, GError **error)
/* a bit rate was configured */ /* a bit rate was configured */
if (0 != lame_set_brate(encoder->gfp, encoder->bitrate)) { if (0 != lame_set_brate(encoder->gfp, encoder->bitrate)) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain,
"error setting lame bitrate"); "error setting lame bitrate");
return false; return false;
} }
...@@ -160,27 +159,27 @@ lame_encoder_setup(LameEncoder *encoder, GError **error) ...@@ -160,27 +159,27 @@ lame_encoder_setup(LameEncoder *encoder, GError **error)
if (0 != lame_set_num_channels(encoder->gfp, if (0 != lame_set_num_channels(encoder->gfp,
encoder->audio_format.channels)) { encoder->audio_format.channels)) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain,
"error setting lame num channels"); "error setting lame num channels");
return false; return false;
} }
if (0 != lame_set_in_samplerate(encoder->gfp, if (0 != lame_set_in_samplerate(encoder->gfp,
encoder->audio_format.sample_rate)) { encoder->audio_format.sample_rate)) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain,
"error setting lame sample rate"); "error setting lame sample rate");
return false; return false;
} }
if (0 != lame_set_out_samplerate(encoder->gfp, if (0 != lame_set_out_samplerate(encoder->gfp,
encoder->audio_format.sample_rate)) { encoder->audio_format.sample_rate)) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain,
"error setting lame out sample rate"); "error setting lame out sample rate");
return false; return false;
} }
if (0 > lame_init_params(encoder->gfp)) { if (0 > lame_init_params(encoder->gfp)) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain,
"error initializing lame params"); "error initializing lame params");
return false; return false;
} }
...@@ -189,8 +188,7 @@ lame_encoder_setup(LameEncoder *encoder, GError **error) ...@@ -189,8 +188,7 @@ lame_encoder_setup(LameEncoder *encoder, GError **error)
} }
static bool static bool
lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error)
GError **error)
{ {
LameEncoder *encoder = (LameEncoder *)_encoder; LameEncoder *encoder = (LameEncoder *)_encoder;
...@@ -201,8 +199,7 @@ lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, ...@@ -201,8 +199,7 @@ lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
encoder->gfp = lame_init(); encoder->gfp = lame_init();
if (encoder->gfp == nullptr) { if (encoder->gfp == nullptr) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain, "lame_init() failed");
"lame_init() failed");
return false; return false;
} }
...@@ -229,7 +226,7 @@ lame_encoder_close(Encoder *_encoder) ...@@ -229,7 +226,7 @@ lame_encoder_close(Encoder *_encoder)
static bool static bool
lame_encoder_write(Encoder *_encoder, lame_encoder_write(Encoder *_encoder,
const void *data, size_t length, const void *data, size_t length,
gcc_unused GError **error) gcc_unused Error &error)
{ {
LameEncoder *encoder = (LameEncoder *)_encoder; LameEncoder *encoder = (LameEncoder *)_encoder;
const int16_t *src = (const int16_t*)data; const int16_t *src = (const int16_t*)data;
...@@ -254,8 +251,7 @@ lame_encoder_write(Encoder *_encoder, ...@@ -254,8 +251,7 @@ lame_encoder_write(Encoder *_encoder,
output_buffer_size); output_buffer_size);
if (bytes_out < 0) { if (bytes_out < 0) {
g_set_error(error, lame_encoder_quark(), 0, error.Set(lame_encoder_domain, "lame encoder failed");
"lame encoder failed");
return false; return false;
} }
......
...@@ -26,8 +26,6 @@ extern "C" { ...@@ -26,8 +26,6 @@ extern "C" {
} }
#include "gcc.h" #include "gcc.h"
#include <glib.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
...@@ -41,7 +39,7 @@ struct NullEncoder final { ...@@ -41,7 +39,7 @@ struct NullEncoder final {
static Encoder * static Encoder *
null_encoder_init(gcc_unused const config_param &param, null_encoder_init(gcc_unused const config_param &param,
gcc_unused GError **error) gcc_unused Error &error)
{ {
NullEncoder *encoder = new NullEncoder(); NullEncoder *encoder = new NullEncoder();
return &encoder->encoder; return &encoder->encoder;
...@@ -67,7 +65,7 @@ null_encoder_close(Encoder *_encoder) ...@@ -67,7 +65,7 @@ null_encoder_close(Encoder *_encoder)
static bool static bool
null_encoder_open(Encoder *_encoder, null_encoder_open(Encoder *_encoder,
gcc_unused AudioFormat &audio_format, gcc_unused AudioFormat &audio_format,
gcc_unused GError **error) gcc_unused Error &error)
{ {
NullEncoder *encoder = (NullEncoder *)_encoder; NullEncoder *encoder = (NullEncoder *)_encoder;
encoder->buffer = growing_fifo_new(); encoder->buffer = growing_fifo_new();
...@@ -77,7 +75,7 @@ null_encoder_open(Encoder *_encoder, ...@@ -77,7 +75,7 @@ null_encoder_open(Encoder *_encoder,
static bool static bool
null_encoder_write(Encoder *_encoder, null_encoder_write(Encoder *_encoder,
const void *data, size_t length, const void *data, size_t length,
gcc_unused GError **error) gcc_unused Error &error)
{ {
NullEncoder *encoder = (NullEncoder *)_encoder; NullEncoder *encoder = (NullEncoder *)_encoder;
......
...@@ -22,11 +22,15 @@ ...@@ -22,11 +22,15 @@
#include "OggStream.hxx" #include "OggStream.hxx"
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "mpd_error.h" #include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <opus.h> #include <opus.h>
#include <ogg/ogg.h> #include <ogg/ogg.h>
#include <glib.h>
#include <assert.h> #include <assert.h>
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
...@@ -66,16 +70,11 @@ struct opus_encoder { ...@@ -66,16 +70,11 @@ struct opus_encoder {
opus_encoder():encoder(opus_encoder_plugin) {} opus_encoder():encoder(opus_encoder_plugin) {}
}; };
gcc_const static constexpr Domain opus_encoder_domain("opus_encoder");
static inline GQuark
opus_encoder_quark(void)
{
return g_quark_from_static_string("opus_encoder");
}
static bool static bool
opus_encoder_configure(struct opus_encoder *encoder, opus_encoder_configure(struct opus_encoder *encoder,
const config_param &param, GError **error_r) const config_param &param, Error &error)
{ {
const char *value = param.GetBlockValue("bitrate", "auto"); const char *value = param.GetBlockValue("bitrate", "auto");
if (strcmp(value, "auto") == 0) if (strcmp(value, "auto") == 0)
...@@ -87,16 +86,14 @@ opus_encoder_configure(struct opus_encoder *encoder, ...@@ -87,16 +86,14 @@ opus_encoder_configure(struct opus_encoder *encoder,
encoder->bitrate = strtoul(value, &endptr, 10); encoder->bitrate = strtoul(value, &endptr, 10);
if (endptr == value || *endptr != 0 || if (endptr == value || *endptr != 0 ||
encoder->bitrate < 500 || encoder->bitrate > 512000) { encoder->bitrate < 500 || encoder->bitrate > 512000) {
g_set_error(error_r, opus_encoder_quark(), 0, error.Set(config_domain, "Invalid bit rate");
"Invalid bit rate");
return false; return false;
} }
} }
encoder->complexity = param.GetBlockValue("complexity", 10u); encoder->complexity = param.GetBlockValue("complexity", 10u);
if (encoder->complexity > 10) { if (encoder->complexity > 10) {
g_set_error(error_r, opus_encoder_quark(), 0, error.Format(config_domain, "Invalid complexity");
"Invalid complexity");
return false; return false;
} }
...@@ -108,8 +105,7 @@ opus_encoder_configure(struct opus_encoder *encoder, ...@@ -108,8 +105,7 @@ opus_encoder_configure(struct opus_encoder *encoder,
else if (strcmp(value, "music") == 0) else if (strcmp(value, "music") == 0)
encoder->signal = OPUS_SIGNAL_MUSIC; encoder->signal = OPUS_SIGNAL_MUSIC;
else { else {
g_set_error(error_r, opus_encoder_quark(), 0, error.Format(config_domain, "Invalid signal");
"Invalid signal");
return false; return false;
} }
...@@ -117,7 +113,7 @@ opus_encoder_configure(struct opus_encoder *encoder, ...@@ -117,7 +113,7 @@ opus_encoder_configure(struct opus_encoder *encoder,
} }
static Encoder * static Encoder *
opus_encoder_init(const config_param &param, GError **error) opus_encoder_init(const config_param &param, Error &error)
{ {
opus_encoder *encoder = new opus_encoder(); opus_encoder *encoder = new opus_encoder();
...@@ -144,7 +140,7 @@ opus_encoder_finish(Encoder *_encoder) ...@@ -144,7 +140,7 @@ opus_encoder_finish(Encoder *_encoder)
static bool static bool
opus_encoder_open(Encoder *_encoder, opus_encoder_open(Encoder *_encoder,
AudioFormat &audio_format, AudioFormat &audio_format,
GError **error_r) Error &error)
{ {
struct opus_encoder *encoder = (struct opus_encoder *)_encoder; struct opus_encoder *encoder = (struct opus_encoder *)_encoder;
...@@ -171,14 +167,14 @@ opus_encoder_open(Encoder *_encoder, ...@@ -171,14 +167,14 @@ opus_encoder_open(Encoder *_encoder,
encoder->audio_format = audio_format; encoder->audio_format = audio_format;
encoder->frame_size = audio_format.GetFrameSize(); encoder->frame_size = audio_format.GetFrameSize();
int error; int error_code;
encoder->enc = opus_encoder_create(audio_format.sample_rate, encoder->enc = opus_encoder_create(audio_format.sample_rate,
audio_format.channels, audio_format.channels,
OPUS_APPLICATION_AUDIO, OPUS_APPLICATION_AUDIO,
&error); &error_code);
if (encoder->enc == nullptr) { if (encoder->enc == nullptr) {
g_set_error_literal(error_r, opus_encoder_quark(), error, error.Set(opus_encoder_domain, error_code,
opus_strerror(error)); opus_strerror(error_code));
return false; return false;
} }
...@@ -212,7 +208,7 @@ opus_encoder_close(Encoder *_encoder) ...@@ -212,7 +208,7 @@ opus_encoder_close(Encoder *_encoder)
static bool static bool
opus_encoder_do_encode(struct opus_encoder *encoder, bool eos, opus_encoder_do_encode(struct opus_encoder *encoder, bool eos,
GError **error_r) Error &error)
{ {
assert(encoder->buffer_position == encoder->buffer_size); assert(encoder->buffer_position == encoder->buffer_size);
...@@ -229,8 +225,7 @@ opus_encoder_do_encode(struct opus_encoder *encoder, bool eos, ...@@ -229,8 +225,7 @@ opus_encoder_do_encode(struct opus_encoder *encoder, bool eos,
encoder->buffer2, encoder->buffer2,
sizeof(encoder->buffer2)); sizeof(encoder->buffer2));
if (result < 0) { if (result < 0) {
g_set_error_literal(error_r, opus_encoder_quark(), 0, error.Set(opus_encoder_domain, "Opus encoder error");
"Opus encoder error");
return false; return false;
} }
...@@ -251,7 +246,7 @@ opus_encoder_do_encode(struct opus_encoder *encoder, bool eos, ...@@ -251,7 +246,7 @@ opus_encoder_do_encode(struct opus_encoder *encoder, bool eos,
} }
static bool static bool
opus_encoder_end(Encoder *_encoder, GError **error_r) opus_encoder_end(Encoder *_encoder, Error &error)
{ {
struct opus_encoder *encoder = (struct opus_encoder *)_encoder; struct opus_encoder *encoder = (struct opus_encoder *)_encoder;
...@@ -261,11 +256,11 @@ opus_encoder_end(Encoder *_encoder, GError **error_r) ...@@ -261,11 +256,11 @@ opus_encoder_end(Encoder *_encoder, GError **error_r)
encoder->buffer_size - encoder->buffer_position); encoder->buffer_size - encoder->buffer_position);
encoder->buffer_position = encoder->buffer_size; encoder->buffer_position = encoder->buffer_size;
return opus_encoder_do_encode(encoder, true, error_r); return opus_encoder_do_encode(encoder, true, error);
} }
static bool static bool
opus_encoder_flush(Encoder *_encoder, gcc_unused GError **error) opus_encoder_flush(Encoder *_encoder, gcc_unused Error &error)
{ {
struct opus_encoder *encoder = (struct opus_encoder *)_encoder; struct opus_encoder *encoder = (struct opus_encoder *)_encoder;
...@@ -275,7 +270,7 @@ opus_encoder_flush(Encoder *_encoder, gcc_unused GError **error) ...@@ -275,7 +270,7 @@ opus_encoder_flush(Encoder *_encoder, gcc_unused GError **error)
static bool static bool
opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames, opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames,
GError **error_r) Error &error)
{ {
size_t fill_bytes = fill_frames * encoder->frame_size; size_t fill_bytes = fill_frames * encoder->frame_size;
...@@ -291,7 +286,7 @@ opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames, ...@@ -291,7 +286,7 @@ opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames,
fill_bytes -= nbytes; fill_bytes -= nbytes;
if (encoder->buffer_position == encoder->buffer_size && if (encoder->buffer_position == encoder->buffer_size &&
!opus_encoder_do_encode(encoder, false, error_r)) !opus_encoder_do_encode(encoder, false, error))
return false; return false;
} }
...@@ -301,7 +296,7 @@ opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames, ...@@ -301,7 +296,7 @@ opus_encoder_write_silence(struct opus_encoder *encoder, unsigned fill_frames,
static bool static bool
opus_encoder_write(Encoder *_encoder, opus_encoder_write(Encoder *_encoder,
const void *_data, size_t length, const void *_data, size_t length,
GError **error_r) Error &error)
{ {
struct opus_encoder *encoder = (struct opus_encoder *)_encoder; struct opus_encoder *encoder = (struct opus_encoder *)_encoder;
const uint8_t *data = (const uint8_t *)_data; const uint8_t *data = (const uint8_t *)_data;
...@@ -313,7 +308,7 @@ opus_encoder_write(Encoder *_encoder, ...@@ -313,7 +308,7 @@ opus_encoder_write(Encoder *_encoder,
assert(encoder->buffer_position == 0); assert(encoder->buffer_position == 0);
if (!opus_encoder_write_silence(encoder, encoder->lookahead, if (!opus_encoder_write_silence(encoder, encoder->lookahead,
error_r)) error))
return false; return false;
encoder->lookahead = 0; encoder->lookahead = 0;
...@@ -332,7 +327,7 @@ opus_encoder_write(Encoder *_encoder, ...@@ -332,7 +327,7 @@ opus_encoder_write(Encoder *_encoder,
encoder->buffer_position += nbytes; encoder->buffer_position += nbytes;
if (encoder->buffer_position == encoder->buffer_size && if (encoder->buffer_position == encoder->buffer_size &&
!opus_encoder_do_encode(encoder, false, error_r)) !opus_encoder_do_encode(encoder, false, error))
return false; return false;
} }
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
#include "TwolameEncoderPlugin.hxx" #include "TwolameEncoderPlugin.hxx"
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <twolame.h> #include <twolame.h>
...@@ -50,17 +53,13 @@ struct TwolameEncoder final { ...@@ -50,17 +53,13 @@ struct TwolameEncoder final {
TwolameEncoder():encoder(twolame_encoder_plugin) {} TwolameEncoder():encoder(twolame_encoder_plugin) {}
bool Configure(const config_param &param, GError **error); bool Configure(const config_param &param, Error &error);
}; };
static inline GQuark static constexpr Domain twolame_encoder_domain("twolame_encoder");
twolame_encoder_quark(void)
{
return g_quark_from_static_string("twolame_encoder");
}
bool bool
TwolameEncoder::Configure(const config_param &param, GError **error) TwolameEncoder::Configure(const config_param &param, Error &error)
{ {
const char *value; const char *value;
char *endptr; char *endptr;
...@@ -72,7 +71,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error) ...@@ -72,7 +71,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error)
quality = g_ascii_strtod(value, &endptr); quality = g_ascii_strtod(value, &endptr);
if (*endptr != '\0' || quality < -1.0 || quality > 10.0) { if (*endptr != '\0' || quality < -1.0 || quality > 10.0) {
g_set_error(error, twolame_encoder_quark(), 0, error.Format(config_domain,
"quality \"%s\" is not a number in the " "quality \"%s\" is not a number in the "
"range -1 to 10, line %i", "range -1 to 10, line %i",
value, param.line); value, param.line);
...@@ -80,7 +79,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error) ...@@ -80,7 +79,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error)
} }
if (param.GetBlockValue("bitrate") != nullptr) { if (param.GetBlockValue("bitrate") != nullptr) {
g_set_error(error, twolame_encoder_quark(), 0, error.Format(config_domain,
"quality and bitrate are " "quality and bitrate are "
"both defined (line %i)", "both defined (line %i)",
param.line); param.line);
...@@ -91,7 +90,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error) ...@@ -91,7 +90,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error)
value = param.GetBlockValue("bitrate"); value = param.GetBlockValue("bitrate");
if (value == nullptr) { if (value == nullptr) {
g_set_error(error, twolame_encoder_quark(), 0, error.Format(config_domain,
"neither bitrate nor quality defined " "neither bitrate nor quality defined "
"at line %i", "at line %i",
param.line); param.line);
...@@ -102,7 +101,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error) ...@@ -102,7 +101,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error)
bitrate = g_ascii_strtoll(value, &endptr, 10); bitrate = g_ascii_strtoll(value, &endptr, 10);
if (*endptr != '\0' || bitrate <= 0) { if (*endptr != '\0' || bitrate <= 0) {
g_set_error(error, twolame_encoder_quark(), 0, error.Format(config_domain,
"bitrate at line %i should be a positive integer", "bitrate at line %i should be a positive integer",
param.line); param.line);
return false; return false;
...@@ -113,7 +112,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error) ...@@ -113,7 +112,7 @@ TwolameEncoder::Configure(const config_param &param, GError **error)
} }
static Encoder * static Encoder *
twolame_encoder_init(const config_param &param, GError **error_r) twolame_encoder_init(const config_param &param, Error &error_r)
{ {
g_debug("libtwolame version %s", get_twolame_version()); g_debug("libtwolame version %s", get_twolame_version());
...@@ -140,18 +139,18 @@ twolame_encoder_finish(Encoder *_encoder) ...@@ -140,18 +139,18 @@ twolame_encoder_finish(Encoder *_encoder)
} }
static bool static bool
twolame_encoder_setup(TwolameEncoder *encoder, GError **error) twolame_encoder_setup(TwolameEncoder *encoder, Error &error)
{ {
if (encoder->quality >= -1.0) { if (encoder->quality >= -1.0) {
/* a quality was configured (VBR) */ /* a quality was configured (VBR) */
if (0 != twolame_set_VBR(encoder->options, true)) { if (0 != twolame_set_VBR(encoder->options, true)) {
g_set_error(error, twolame_encoder_quark(), 0, error.Set(twolame_encoder_domain,
"error setting twolame VBR mode"); "error setting twolame VBR mode");
return false; return false;
} }
if (0 != twolame_set_VBR_q(encoder->options, encoder->quality)) { if (0 != twolame_set_VBR_q(encoder->options, encoder->quality)) {
g_set_error(error, twolame_encoder_quark(), 0, error.Set(twolame_encoder_domain,
"error setting twolame VBR quality"); "error setting twolame VBR quality");
return false; return false;
} }
...@@ -159,7 +158,7 @@ twolame_encoder_setup(TwolameEncoder *encoder, GError **error) ...@@ -159,7 +158,7 @@ twolame_encoder_setup(TwolameEncoder *encoder, GError **error)
/* a bit rate was configured */ /* a bit rate was configured */
if (0 != twolame_set_brate(encoder->options, encoder->bitrate)) { if (0 != twolame_set_brate(encoder->options, encoder->bitrate)) {
g_set_error(error, twolame_encoder_quark(), 0, error.Set(twolame_encoder_domain,
"error setting twolame bitrate"); "error setting twolame bitrate");
return false; return false;
} }
...@@ -167,20 +166,20 @@ twolame_encoder_setup(TwolameEncoder *encoder, GError **error) ...@@ -167,20 +166,20 @@ twolame_encoder_setup(TwolameEncoder *encoder, GError **error)
if (0 != twolame_set_num_channels(encoder->options, if (0 != twolame_set_num_channels(encoder->options,
encoder->audio_format.channels)) { encoder->audio_format.channels)) {
g_set_error(error, twolame_encoder_quark(), 0, error.Set(twolame_encoder_domain,
"error setting twolame num channels"); "error setting twolame num channels");
return false; return false;
} }
if (0 != twolame_set_in_samplerate(encoder->options, if (0 != twolame_set_in_samplerate(encoder->options,
encoder->audio_format.sample_rate)) { encoder->audio_format.sample_rate)) {
g_set_error(error, twolame_encoder_quark(), 0, error.Set(twolame_encoder_domain,
"error setting twolame sample rate"); "error setting twolame sample rate");
return false; return false;
} }
if (0 > twolame_init_params(encoder->options)) { if (0 > twolame_init_params(encoder->options)) {
g_set_error(error, twolame_encoder_quark(), 0, error.Set(twolame_encoder_domain,
"error initializing twolame params"); "error initializing twolame params");
return false; return false;
} }
...@@ -190,7 +189,7 @@ twolame_encoder_setup(TwolameEncoder *encoder, GError **error) ...@@ -190,7 +189,7 @@ twolame_encoder_setup(TwolameEncoder *encoder, GError **error)
static bool static bool
twolame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, twolame_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
GError **error) Error &error)
{ {
TwolameEncoder *encoder = (TwolameEncoder *)_encoder; TwolameEncoder *encoder = (TwolameEncoder *)_encoder;
...@@ -201,8 +200,7 @@ twolame_encoder_open(Encoder *_encoder, AudioFormat &audio_format, ...@@ -201,8 +200,7 @@ twolame_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
encoder->options = twolame_init(); encoder->options = twolame_init();
if (encoder->options == nullptr) { if (encoder->options == nullptr) {
g_set_error(error, twolame_encoder_quark(), 0, error.Set(twolame_encoder_domain, "twolame_init() failed");
"twolame_init() failed");
return false; return false;
} }
...@@ -227,7 +225,7 @@ twolame_encoder_close(Encoder *_encoder) ...@@ -227,7 +225,7 @@ twolame_encoder_close(Encoder *_encoder)
} }
static bool static bool
twolame_encoder_flush(Encoder *_encoder, gcc_unused GError **error) twolame_encoder_flush(Encoder *_encoder, gcc_unused Error &error)
{ {
TwolameEncoder *encoder = (TwolameEncoder *)_encoder; TwolameEncoder *encoder = (TwolameEncoder *)_encoder;
...@@ -238,7 +236,7 @@ twolame_encoder_flush(Encoder *_encoder, gcc_unused GError **error) ...@@ -238,7 +236,7 @@ twolame_encoder_flush(Encoder *_encoder, gcc_unused GError **error)
static bool static bool
twolame_encoder_write(Encoder *_encoder, twolame_encoder_write(Encoder *_encoder,
const void *data, size_t length, const void *data, size_t length,
gcc_unused GError **error) gcc_unused Error &error)
{ {
TwolameEncoder *encoder = (TwolameEncoder *)_encoder; TwolameEncoder *encoder = (TwolameEncoder *)_encoder;
const int16_t *src = (const int16_t*)data; const int16_t *src = (const int16_t*)data;
...@@ -254,8 +252,7 @@ twolame_encoder_write(Encoder *_encoder, ...@@ -254,8 +252,7 @@ twolame_encoder_write(Encoder *_encoder,
encoder->output_buffer, encoder->output_buffer,
sizeof(encoder->output_buffer)); sizeof(encoder->output_buffer));
if (bytes_out < 0) { if (bytes_out < 0) {
g_set_error(error, twolame_encoder_quark(), 0, error.Set(twolame_encoder_domain, "twolame encoder failed");
"twolame encoder failed");
return false; return false;
} }
......
...@@ -23,10 +23,14 @@ ...@@ -23,10 +23,14 @@
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "mpd_error.h" #include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <vorbis/vorbisenc.h> #include <vorbis/vorbisenc.h>
#include <glib.h>
#include <assert.h> #include <assert.h>
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
...@@ -54,15 +58,11 @@ struct vorbis_encoder { ...@@ -54,15 +58,11 @@ struct vorbis_encoder {
vorbis_encoder():encoder(vorbis_encoder_plugin) {} vorbis_encoder():encoder(vorbis_encoder_plugin) {}
}; };
static inline GQuark static constexpr Domain vorbis_encoder_domain("vorbis_encoder");
vorbis_encoder_quark(void)
{
return g_quark_from_static_string("vorbis_encoder");
}
static bool static bool
vorbis_encoder_configure(struct vorbis_encoder *encoder, vorbis_encoder_configure(struct vorbis_encoder *encoder,
const config_param &param, GError **error) const config_param &param, Error &error)
{ {
const char *value = param.GetBlockValue("quality"); const char *value = param.GetBlockValue("quality");
if (value != nullptr) { if (value != nullptr) {
...@@ -73,7 +73,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, ...@@ -73,7 +73,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder,
if (*endptr != '\0' || encoder->quality < -1.0 || if (*endptr != '\0' || encoder->quality < -1.0 ||
encoder->quality > 10.0) { encoder->quality > 10.0) {
g_set_error(error, vorbis_encoder_quark(), 0, error.Format(config_domain,
"quality \"%s\" is not a number in the " "quality \"%s\" is not a number in the "
"range -1 to 10, line %i", "range -1 to 10, line %i",
value, param.line); value, param.line);
...@@ -81,7 +81,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, ...@@ -81,7 +81,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder,
} }
if (param.GetBlockValue("bitrate") != nullptr) { if (param.GetBlockValue("bitrate") != nullptr) {
g_set_error(error, vorbis_encoder_quark(), 0, error.Format(config_domain,
"quality and bitrate are " "quality and bitrate are "
"both defined (line %i)", "both defined (line %i)",
param.line); param.line);
...@@ -92,7 +92,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, ...@@ -92,7 +92,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder,
value = param.GetBlockValue("bitrate"); value = param.GetBlockValue("bitrate");
if (value == nullptr) { if (value == nullptr) {
g_set_error(error, vorbis_encoder_quark(), 0, error.Format(config_domain,
"neither bitrate nor quality defined " "neither bitrate nor quality defined "
"at line %i", "at line %i",
param.line); param.line);
...@@ -104,7 +104,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, ...@@ -104,7 +104,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder,
char *endptr; char *endptr;
encoder->bitrate = g_ascii_strtoll(value, &endptr, 10); encoder->bitrate = g_ascii_strtoll(value, &endptr, 10);
if (*endptr != '\0' || encoder->bitrate <= 0) { if (*endptr != '\0' || encoder->bitrate <= 0) {
g_set_error(error, vorbis_encoder_quark(), 0, error.Format(config_domain,
"bitrate at line %i should be a positive integer", "bitrate at line %i should be a positive integer",
param.line); param.line);
return false; return false;
...@@ -115,7 +115,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder, ...@@ -115,7 +115,7 @@ vorbis_encoder_configure(struct vorbis_encoder *encoder,
} }
static Encoder * static Encoder *
vorbis_encoder_init(const config_param &param, GError **error) vorbis_encoder_init(const config_param &param, Error &error)
{ {
vorbis_encoder *encoder = new vorbis_encoder(); vorbis_encoder *encoder = new vorbis_encoder();
...@@ -140,7 +140,7 @@ vorbis_encoder_finish(Encoder *_encoder) ...@@ -140,7 +140,7 @@ vorbis_encoder_finish(Encoder *_encoder)
} }
static bool static bool
vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error) vorbis_encoder_reinit(struct vorbis_encoder *encoder, Error &error)
{ {
vorbis_info_init(&encoder->vi); vorbis_info_init(&encoder->vi);
...@@ -151,7 +151,7 @@ vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error) ...@@ -151,7 +151,7 @@ vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error)
encoder->audio_format.channels, encoder->audio_format.channels,
encoder->audio_format.sample_rate, encoder->audio_format.sample_rate,
encoder->quality * 0.1)) { encoder->quality * 0.1)) {
g_set_error(error, vorbis_encoder_quark(), 0, error.Set(vorbis_encoder_domain,
"error initializing vorbis vbr"); "error initializing vorbis vbr");
vorbis_info_clear(&encoder->vi); vorbis_info_clear(&encoder->vi);
return false; return false;
...@@ -163,7 +163,7 @@ vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error) ...@@ -163,7 +163,7 @@ vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error)
encoder->audio_format.channels, encoder->audio_format.channels,
encoder->audio_format.sample_rate, -1.0, encoder->audio_format.sample_rate, -1.0,
encoder->bitrate * 1000, -1.0)) { encoder->bitrate * 1000, -1.0)) {
g_set_error(error, vorbis_encoder_quark(), 0, error.Set(vorbis_encoder_domain,
"error initializing vorbis encoder"); "error initializing vorbis encoder");
vorbis_info_clear(&encoder->vi); vorbis_info_clear(&encoder->vi);
return false; return false;
...@@ -203,7 +203,7 @@ vorbis_encoder_send_header(struct vorbis_encoder *encoder) ...@@ -203,7 +203,7 @@ vorbis_encoder_send_header(struct vorbis_encoder *encoder)
static bool static bool
vorbis_encoder_open(Encoder *_encoder, vorbis_encoder_open(Encoder *_encoder,
AudioFormat &audio_format, AudioFormat &audio_format,
GError **error) Error &error)
{ {
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
...@@ -250,7 +250,7 @@ vorbis_encoder_blockout(struct vorbis_encoder *encoder) ...@@ -250,7 +250,7 @@ vorbis_encoder_blockout(struct vorbis_encoder *encoder)
} }
static bool static bool
vorbis_encoder_flush(Encoder *_encoder, gcc_unused GError **error) vorbis_encoder_flush(Encoder *_encoder, gcc_unused Error &error)
{ {
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
...@@ -259,7 +259,7 @@ vorbis_encoder_flush(Encoder *_encoder, gcc_unused GError **error) ...@@ -259,7 +259,7 @@ vorbis_encoder_flush(Encoder *_encoder, gcc_unused GError **error)
} }
static bool static bool
vorbis_encoder_pre_tag(Encoder *_encoder, gcc_unused GError **error) vorbis_encoder_pre_tag(Encoder *_encoder, gcc_unused Error &error)
{ {
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
...@@ -290,7 +290,7 @@ copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag *tag) ...@@ -290,7 +290,7 @@ copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag *tag)
static bool static bool
vorbis_encoder_tag(Encoder *_encoder, const Tag *tag, vorbis_encoder_tag(Encoder *_encoder, const Tag *tag,
gcc_unused GError **error) gcc_unused Error &error)
{ {
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
vorbis_comment comment; vorbis_comment comment;
...@@ -324,7 +324,7 @@ interleaved_to_vorbis_buffer(float **dest, const float *src, ...@@ -324,7 +324,7 @@ interleaved_to_vorbis_buffer(float **dest, const float *src,
static bool static bool
vorbis_encoder_write(Encoder *_encoder, vorbis_encoder_write(Encoder *_encoder,
const void *data, size_t length, const void *data, size_t length,
gcc_unused GError **error) gcc_unused Error &error)
{ {
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
......
...@@ -84,7 +84,7 @@ fill_wave_header(struct wave_header *header, int channels, int bits, ...@@ -84,7 +84,7 @@ fill_wave_header(struct wave_header *header, int channels, int bits,
static Encoder * static Encoder *
wave_encoder_init(gcc_unused const config_param &param, wave_encoder_init(gcc_unused const config_param &param,
gcc_unused GError **error) gcc_unused Error &error)
{ {
WaveEncoder *encoder = new WaveEncoder(); WaveEncoder *encoder = new WaveEncoder();
return &encoder->encoder; return &encoder->encoder;
...@@ -101,7 +101,7 @@ wave_encoder_finish(Encoder *_encoder) ...@@ -101,7 +101,7 @@ wave_encoder_finish(Encoder *_encoder)
static bool static bool
wave_encoder_open(Encoder *_encoder, wave_encoder_open(Encoder *_encoder,
AudioFormat &audio_format, AudioFormat &audio_format,
gcc_unused GError **error) gcc_unused Error &error)
{ {
WaveEncoder *encoder = (WaveEncoder *)_encoder; WaveEncoder *encoder = (WaveEncoder *)_encoder;
...@@ -196,7 +196,7 @@ pcm24_to_wave(uint8_t *dst8, const uint32_t *src32, size_t length) ...@@ -196,7 +196,7 @@ pcm24_to_wave(uint8_t *dst8, const uint32_t *src32, size_t length)
static bool static bool
wave_encoder_write(Encoder *_encoder, wave_encoder_write(Encoder *_encoder,
const void *src, size_t length, const void *src, size_t length,
gcc_unused GError **error) gcc_unused Error &error)
{ {
WaveEncoder *encoder = (WaveEncoder *)_encoder; WaveEncoder *encoder = (WaveEncoder *)_encoder;
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "BufferedSocket.hxx" #include "BufferedSocket.hxx"
#include "system/SocketError.hxx" #include "system/SocketError.hxx"
#include "util/fifo_buffer.h" #include "util/fifo_buffer.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
...@@ -97,8 +99,11 @@ BufferedSocket::ResumeInput() ...@@ -97,8 +99,11 @@ BufferedSocket::ResumeInput()
case InputResult::MORE: case InputResult::MORE:
if (fifo_buffer_is_full(input)) { if (fifo_buffer_is_full(input)) {
// TODO // TODO
OnSocketError(g_error_new_literal(g_quark_from_static_string("buffered_socket"), static constexpr Domain buffered_socket_domain("buffered_socket");
0, "Input buffer is full")); Error error;
error.Set(buffered_socket_domain,
"Input buffer is full");
OnSocketError(std::move(error));
return false; return false;
} }
......
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
#include "check.h" #include "check.h"
#include "SocketMonitor.hxx" #include "SocketMonitor.hxx"
#include "gerror.h"
#include "gcc.h" #include "gcc.h"
struct fifo_buffer; struct fifo_buffer;
class Error;
/** /**
* A #SocketMonitor specialization that adds an input buffer. * A #SocketMonitor specialization that adds an input buffer.
...@@ -96,7 +96,7 @@ protected: ...@@ -96,7 +96,7 @@ protected:
}; };
virtual InputResult OnSocketInput(const void *data, size_t length) = 0; virtual InputResult OnSocketInput(const void *data, size_t length) = 0;
virtual void OnSocketError(GError *error) = 0; virtual void OnSocketError(Error &&error) = 0;
virtual void OnSocketClosed() = 0; virtual void OnSocketClosed() = 0;
virtual bool OnSocketReady(unsigned flags) override; virtual bool OnSocketReady(unsigned flags) override;
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "FullyBufferedSocket.hxx" #include "FullyBufferedSocket.hxx"
#include "system/SocketError.hxx" #include "system/SocketError.hxx"
#include "util/fifo_buffer.h" #include "util/fifo_buffer.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
...@@ -98,8 +100,10 @@ FullyBufferedSocket::Write(const void *data, size_t length) ...@@ -98,8 +100,10 @@ FullyBufferedSocket::Write(const void *data, size_t length)
if (!output.Append(data, length)) { if (!output.Append(data, length)) {
// TODO // TODO
OnSocketError(g_error_new_literal(g_quark_from_static_string("buffered_socket"), static constexpr Domain buffered_socket_domain("buffered_socket");
0, "Output buffer is full")); Error error;
error.Set(buffered_socket_domain, "Output buffer is full");
OnSocketError(std::move(error));
return false; return false;
} }
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include "event/SocketMonitor.hxx" #include "event/SocketMonitor.hxx"
#include "system/Resolver.hxx" #include "system/Resolver.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -96,7 +98,7 @@ public: ...@@ -96,7 +98,7 @@ public:
path = g_strdup(_path); path = g_strdup(_path);
} }
bool Open(GError **error_r); bool Open(Error &error);
using SocketMonitor::IsDefined; using SocketMonitor::IsDefined;
using SocketMonitor::Close; using SocketMonitor::Close;
...@@ -114,11 +116,7 @@ private: ...@@ -114,11 +116,7 @@ private:
virtual bool OnSocketReady(unsigned flags) override; virtual bool OnSocketReady(unsigned flags) override;
}; };
static GQuark static constexpr Domain server_socket_domain("server_socket");
server_socket_quark(void)
{
return g_quark_from_static_string("server_socket");
}
/** /**
* Wraper for sockaddr_to_string() which never fails. * Wraper for sockaddr_to_string() which never fails.
...@@ -126,7 +124,7 @@ server_socket_quark(void) ...@@ -126,7 +124,7 @@ server_socket_quark(void)
char * char *
OneServerSocket::ToString() const OneServerSocket::ToString() const
{ {
char *p = sockaddr_to_string(address, address_length, nullptr); char *p = sockaddr_to_string(address, address_length, IgnoreError());
if (p == nullptr) if (p == nullptr)
p = g_strdup("[unknown]"); p = g_strdup("[unknown]");
return p; return p;
...@@ -190,14 +188,14 @@ OneServerSocket::OnSocketReady(gcc_unused unsigned flags) ...@@ -190,14 +188,14 @@ OneServerSocket::OnSocketReady(gcc_unused unsigned flags)
} }
inline bool inline bool
OneServerSocket::Open(GError **error_r) OneServerSocket::Open(Error &error)
{ {
assert(!IsDefined()); assert(!IsDefined());
int _fd = socket_bind_listen(address->sa_family, int _fd = socket_bind_listen(address->sa_family,
SOCK_STREAM, 0, SOCK_STREAM, 0,
address, address_length, 5, address, address_length, 5,
error_r); error);
if (_fd < 0) if (_fd < 0)
return false; return false;
...@@ -221,10 +219,10 @@ ServerSocket::ServerSocket(EventLoop &_loop) ...@@ -221,10 +219,10 @@ ServerSocket::ServerSocket(EventLoop &_loop)
ServerSocket::~ServerSocket() {} ServerSocket::~ServerSocket() {}
bool bool
ServerSocket::Open(GError **error_r) ServerSocket::Open(Error &error)
{ {
OneServerSocket *good = nullptr, *bad = nullptr; OneServerSocket *good = nullptr, *bad = nullptr;
GError *last_error = nullptr; Error last_error;
for (auto &i : sockets) { for (auto &i : sockets) {
assert(i.GetSerial() > 0); assert(i.GetSerial() > 0);
...@@ -232,33 +230,33 @@ ServerSocket::Open(GError **error_r) ...@@ -232,33 +230,33 @@ ServerSocket::Open(GError **error_r)
if (bad != nullptr && i.GetSerial() != bad->GetSerial()) { if (bad != nullptr && i.GetSerial() != bad->GetSerial()) {
Close(); Close();
g_propagate_error(error_r, last_error); error = std::move(last_error);
return false; return false;
} }
GError *error = nullptr; Error error2;
if (!i.Open(&error)) { if (!i.Open(error2)) {
if (good != nullptr && good->GetSerial() == i.GetSerial()) { if (good != nullptr && good->GetSerial() == i.GetSerial()) {
char *address_string = i.ToString(); char *address_string = i.ToString();
char *good_string = good->ToString(); char *good_string = good->ToString();
g_warning("bind to '%s' failed: %s " g_warning("bind to '%s' failed: %s "
"(continuing anyway, because " "(continuing anyway, because "
"binding to '%s' succeeded)", "binding to '%s' succeeded)",
address_string, error->message, address_string, error2.GetMessage(),
good_string); good_string);
g_free(address_string); g_free(address_string);
g_free(good_string); g_free(good_string);
g_error_free(error);
} else if (bad == nullptr) { } else if (bad == nullptr) {
bad = &i; bad = &i;
char *address_string = i.ToString(); char *address_string = i.ToString();
g_propagate_prefixed_error(&last_error, error, error2.FormatPrefix("Failed to bind to '%s': ",
"Failed to bind to '%s': ",
address_string); address_string);
g_free(address_string); g_free(address_string);
} else
g_error_free(error); last_error = std::move(error2);
}
continue; continue;
} }
...@@ -269,14 +267,13 @@ ServerSocket::Open(GError **error_r) ...@@ -269,14 +267,13 @@ ServerSocket::Open(GError **error_r)
if (bad != nullptr) { if (bad != nullptr) {
bad = nullptr; bad = nullptr;
g_error_free(last_error); last_error.Clear();
last_error = nullptr;
} }
} }
if (bad != nullptr) { if (bad != nullptr) {
Close(); Close();
g_propagate_error(error_r, last_error); error = std::move(last_error);
return false; return false;
} }
...@@ -301,7 +298,7 @@ ServerSocket::AddAddress(const sockaddr &address, size_t address_length) ...@@ -301,7 +298,7 @@ ServerSocket::AddAddress(const sockaddr &address, size_t address_length)
} }
bool bool
ServerSocket::AddFD(int fd, GError **error_r) ServerSocket::AddFD(int fd, Error &error)
{ {
assert(fd >= 0); assert(fd >= 0);
...@@ -309,8 +306,8 @@ ServerSocket::AddFD(int fd, GError **error_r) ...@@ -309,8 +306,8 @@ ServerSocket::AddFD(int fd, GError **error_r)
socklen_t address_length = sizeof(address); socklen_t address_length = sizeof(address);
if (getsockname(fd, (struct sockaddr *)&address, if (getsockname(fd, (struct sockaddr *)&address,
&address_length) < 0) { &address_length) < 0) {
SetSocketError(error_r); SetSocketError(error);
g_prefix_error(error_r, "Failed to get socket address"); error.AddPrefix("Failed to get socket address: ");
return false; return false;
} }
...@@ -351,12 +348,11 @@ ServerSocket::AddPortIPv6(unsigned port) ...@@ -351,12 +348,11 @@ ServerSocket::AddPortIPv6(unsigned port)
#endif /* HAVE_TCP */ #endif /* HAVE_TCP */
bool bool
ServerSocket::AddPort(unsigned port, GError **error_r) ServerSocket::AddPort(unsigned port, Error &error)
{ {
#ifdef HAVE_TCP #ifdef HAVE_TCP
if (port == 0 || port > 0xffff) { if (port == 0 || port > 0xffff) {
g_set_error(error_r, server_socket_quark(), 0, error.Set(server_socket_domain, "Invalid TCP port");
"Invalid TCP port");
return false; return false;
} }
...@@ -371,19 +367,18 @@ ServerSocket::AddPort(unsigned port, GError **error_r) ...@@ -371,19 +367,18 @@ ServerSocket::AddPort(unsigned port, GError **error_r)
#else /* HAVE_TCP */ #else /* HAVE_TCP */
(void)port; (void)port;
g_set_error(error_r, server_socket_quark(), 0, error.Set(server_socket_domain, "TCP support is disabled");
"TCP support is disabled");
return false; return false;
#endif /* HAVE_TCP */ #endif /* HAVE_TCP */
} }
bool bool
ServerSocket::AddHost(const char *hostname, unsigned port, GError **error_r) ServerSocket::AddHost(const char *hostname, unsigned port, Error &error)
{ {
#ifdef HAVE_TCP #ifdef HAVE_TCP
struct addrinfo *ai = resolve_host_port(hostname, port, struct addrinfo *ai = resolve_host_port(hostname, port,
AI_PASSIVE, SOCK_STREAM, AI_PASSIVE, SOCK_STREAM,
error_r); error);
if (ai == nullptr) if (ai == nullptr)
return false; return false;
...@@ -399,21 +394,20 @@ ServerSocket::AddHost(const char *hostname, unsigned port, GError **error_r) ...@@ -399,21 +394,20 @@ ServerSocket::AddHost(const char *hostname, unsigned port, GError **error_r)
(void)hostname; (void)hostname;
(void)port; (void)port;
g_set_error(error_r, server_socket_quark(), 0, error.Set(server_socket_domain, "TCP support is disabled");
"TCP support is disabled");
return false; return false;
#endif /* HAVE_TCP */ #endif /* HAVE_TCP */
} }
bool bool
ServerSocket::AddPath(const char *path, GError **error_r) ServerSocket::AddPath(const char *path, Error &error)
{ {
#ifdef HAVE_UN #ifdef HAVE_UN
struct sockaddr_un s_un; struct sockaddr_un s_un;
size_t path_length = strlen(path); size_t path_length = strlen(path);
if (path_length >= sizeof(s_un.sun_path)) { if (path_length >= sizeof(s_un.sun_path)) {
g_set_error(error_r, server_socket_quark(), 0, error.Set(server_socket_domain,
"UNIX socket path is too long"); "UNIX socket path is too long");
return false; return false;
} }
...@@ -430,7 +424,7 @@ ServerSocket::AddPath(const char *path, GError **error_r) ...@@ -430,7 +424,7 @@ ServerSocket::AddPath(const char *path, GError **error_r)
#else /* !HAVE_UN */ #else /* !HAVE_UN */
(void)path; (void)path;
g_set_error(error_r, server_socket_quark(), 0, error.Set(server_socket_domain,
"UNIX domain socket support is disabled"); "UNIX domain socket support is disabled");
return false; return false;
#endif /* !HAVE_UN */ #endif /* !HAVE_UN */
......
...@@ -20,14 +20,13 @@ ...@@ -20,14 +20,13 @@
#ifndef MPD_SERVER_SOCKET_HXX #ifndef MPD_SERVER_SOCKET_HXX
#define MPD_SERVER_SOCKET_HXX #define MPD_SERVER_SOCKET_HXX
#include "gerror.h"
#include <forward_list> #include <forward_list>
#include <stddef.h> #include <stddef.h>
struct sockaddr; struct sockaddr;
class EventLoop; class EventLoop;
class Error;
typedef void (*server_socket_callback_t)(int fd, typedef void (*server_socket_callback_t)(int fd,
const struct sockaddr *address, const struct sockaddr *address,
...@@ -79,7 +78,7 @@ public: ...@@ -79,7 +78,7 @@ public:
* ignore errors * ignore errors
* @return true on success * @return true on success
*/ */
bool AddPort(unsigned port, GError **error_r); bool AddPort(unsigned port, Error &error);
/** /**
* Resolves a host name, and adds listeners on all addresses in the * Resolves a host name, and adds listeners on all addresses in the
...@@ -91,7 +90,7 @@ public: ...@@ -91,7 +90,7 @@ public:
* ignore errors * ignore errors
* @return true on success * @return true on success
*/ */
bool AddHost(const char *hostname, unsigned port, GError **error_r); bool AddHost(const char *hostname, unsigned port, Error &error);
/** /**
* Add a listener on a Unix domain socket. * Add a listener on a Unix domain socket.
...@@ -101,16 +100,16 @@ public: ...@@ -101,16 +100,16 @@ public:
* ignore errors * ignore errors
* @return true on success * @return true on success
*/ */
bool AddPath(const char *path, GError **error_r); bool AddPath(const char *path, Error &error);
/** /**
* Add a socket descriptor that is accepting connections. After this * Add a socket descriptor that is accepting connections. After this
* has been called, don't call server_socket_open(), because the * has been called, don't call server_socket_open(), because the
* socket is already open. * socket is already open.
*/ */
bool AddFD(int fd, GError **error_r); bool AddFD(int fd, Error &error);
bool Open(GError **error_r); bool Open(Error &error);
void Close(); void Close();
protected: protected:
......
...@@ -46,21 +46,22 @@ public: ...@@ -46,21 +46,22 @@ public:
delete filter; delete filter;
} }
virtual AudioFormat Open(AudioFormat &af, GError **error_r); virtual AudioFormat Open(AudioFormat &af, Error &error) override;
virtual void Close(); virtual void Close() override;
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, GError **error_r); size_t *dest_size_r,
Error &error) override;
}; };
AudioFormat AudioFormat
AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r) AutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error)
{ {
assert(in_audio_format.IsValid()); assert(in_audio_format.IsValid());
/* open the "real" filter */ /* open the "real" filter */
const AudioFormat child_audio_format = in_audio_format; const AudioFormat child_audio_format = in_audio_format;
AudioFormat out_audio_format = filter->Open(in_audio_format, error_r); AudioFormat out_audio_format = filter->Open(in_audio_format, error);
if (!out_audio_format.IsDefined()) if (!out_audio_format.IsDefined())
return out_audio_format; return out_audio_format;
...@@ -70,7 +71,7 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r) ...@@ -70,7 +71,7 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r)
/* yes - create a convert_filter */ /* yes - create a convert_filter */
const config_param empty; const config_param empty;
convert = filter_new(&convert_filter_plugin, empty, error_r); convert = filter_new(&convert_filter_plugin, empty, error);
if (convert == nullptr) { if (convert == nullptr) {
filter->Close(); filter->Close();
return AudioFormat::Undefined(); return AudioFormat::Undefined();
...@@ -78,7 +79,7 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r) ...@@ -78,7 +79,7 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r)
AudioFormat audio_format2 = in_audio_format; AudioFormat audio_format2 = in_audio_format;
AudioFormat audio_format3 = AudioFormat audio_format3 =
convert->Open(audio_format2, error_r); convert->Open(audio_format2, error);
if (!audio_format3.IsDefined()) { if (!audio_format3.IsDefined()) {
delete convert; delete convert;
filter->Close(); filter->Close();
...@@ -108,15 +109,15 @@ AutoConvertFilter::Close() ...@@ -108,15 +109,15 @@ AutoConvertFilter::Close()
const void * const void *
AutoConvertFilter::FilterPCM(const void *src, size_t src_size, AutoConvertFilter::FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r) size_t *dest_size_r, Error &error)
{ {
if (convert != nullptr) { if (convert != nullptr) {
src = convert->FilterPCM(src, src_size, &src_size, error_r); src = convert->FilterPCM(src, src_size, &src_size, error);
if (src == nullptr) if (src == nullptr)
return nullptr; return nullptr;
} }
return filter->FilterPCM(src, src_size, dest_size_r, error_r); return filter->FilterPCM(src, src_size, dest_size_r, error);
} }
Filter * Filter *
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -53,10 +55,10 @@ public: ...@@ -53,10 +55,10 @@ public:
children.emplace_back(name, filter); children.emplace_back(name, filter);
} }
virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; virtual AudioFormat Open(AudioFormat &af, Error &error) override;
virtual void Close(); virtual void Close();
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, GError **error_r); size_t *dest_size_r, Error &error);
private: private:
/** /**
...@@ -66,15 +68,11 @@ private: ...@@ -66,15 +68,11 @@ private:
void CloseUntil(const Filter *until); void CloseUntil(const Filter *until);
}; };
static inline GQuark static constexpr Domain chain_filter_domain("chain_filter");
filter_quark(void)
{
return g_quark_from_static_string("filter");
}
static Filter * static Filter *
chain_filter_init(gcc_unused const config_param &param, chain_filter_init(gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return new ChainFilter(); return new ChainFilter();
} }
...@@ -99,11 +97,11 @@ ChainFilter::CloseUntil(const Filter *until) ...@@ -99,11 +97,11 @@ ChainFilter::CloseUntil(const Filter *until)
static AudioFormat static AudioFormat
chain_open_child(const char *name, Filter *filter, chain_open_child(const char *name, Filter *filter,
const AudioFormat &prev_audio_format, const AudioFormat &prev_audio_format,
GError **error_r) Error &error)
{ {
AudioFormat conv_audio_format = prev_audio_format; AudioFormat conv_audio_format = prev_audio_format;
const AudioFormat next_audio_format = const AudioFormat next_audio_format =
filter->Open(conv_audio_format, error_r); filter->Open(conv_audio_format, error);
if (!next_audio_format.IsDefined()) if (!next_audio_format.IsDefined())
return next_audio_format; return next_audio_format;
...@@ -111,7 +109,8 @@ chain_open_child(const char *name, Filter *filter, ...@@ -111,7 +109,8 @@ chain_open_child(const char *name, Filter *filter,
struct audio_format_string s; struct audio_format_string s;
filter->Close(); filter->Close();
g_set_error(error_r, filter_quark(), 0,
error.Format(chain_filter_domain,
"Audio format not supported by filter '%s': %s", "Audio format not supported by filter '%s': %s",
name, name,
audio_format_to_string(prev_audio_format, &s)); audio_format_to_string(prev_audio_format, &s));
...@@ -122,13 +121,13 @@ chain_open_child(const char *name, Filter *filter, ...@@ -122,13 +121,13 @@ chain_open_child(const char *name, Filter *filter,
} }
AudioFormat AudioFormat
ChainFilter::Open(AudioFormat &in_audio_format, GError **error_r) ChainFilter::Open(AudioFormat &in_audio_format, Error &error)
{ {
AudioFormat audio_format = in_audio_format; AudioFormat audio_format = in_audio_format;
for (auto &child : children) { for (auto &child : children) {
audio_format = chain_open_child(child.name, child.filter, audio_format = chain_open_child(child.name, child.filter,
audio_format, error_r); audio_format, error);
if (!audio_format.IsDefined()) { if (!audio_format.IsDefined()) {
/* rollback, close all children */ /* rollback, close all children */
CloseUntil(child.filter); CloseUntil(child.filter);
...@@ -149,13 +148,13 @@ ChainFilter::Close() ...@@ -149,13 +148,13 @@ ChainFilter::Close()
const void * const void *
ChainFilter::FilterPCM(const void *src, size_t src_size, ChainFilter::FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r) size_t *dest_size_r, Error &error)
{ {
for (auto &child : children) { for (auto &child : children) {
/* feed the output of the previous filter as input /* feed the output of the previous filter as input
into the current one */ into the current one */
src = child.filter->FilterPCM(src, src_size, &src_size, src = child.filter->FilterPCM(src, src_size, &src_size,
error_r); error);
if (src == NULL) if (src == NULL)
return NULL; return NULL;
} }
......
...@@ -56,21 +56,22 @@ public: ...@@ -56,21 +56,22 @@ public:
out_audio_format = _out_audio_format; out_audio_format = _out_audio_format;
} }
virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; virtual AudioFormat Open(AudioFormat &af, Error &error) override;
virtual void Close(); virtual void Close() override;
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, GError **error_r); size_t *dest_size_r,
Error &error) override;
}; };
static Filter * static Filter *
convert_filter_init(gcc_unused const config_param &param, convert_filter_init(gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return new ConvertFilter(); return new ConvertFilter();
} }
AudioFormat AudioFormat
ConvertFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r) ConvertFilter::Open(AudioFormat &audio_format, gcc_unused Error &error)
{ {
assert(audio_format.IsValid()); assert(audio_format.IsValid());
...@@ -91,7 +92,7 @@ ConvertFilter::Close() ...@@ -91,7 +92,7 @@ ConvertFilter::Close()
const void * const void *
ConvertFilter::FilterPCM(const void *src, size_t src_size, ConvertFilter::FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r) size_t *dest_size_r, Error &error)
{ {
if (in_audio_format == out_audio_format) { if (in_audio_format == out_audio_format) {
/* optimized special case: no-op */ /* optimized special case: no-op */
...@@ -102,7 +103,7 @@ ConvertFilter::FilterPCM(const void *src, size_t src_size, ...@@ -102,7 +103,7 @@ ConvertFilter::FilterPCM(const void *src, size_t src_size,
return state->Convert(in_audio_format, return state->Convert(in_audio_format,
src, src_size, src, src_size,
out_audio_format, dest_size_r, out_audio_format, dest_size_r,
error_r); error);
} }
const struct filter_plugin convert_filter_plugin = { const struct filter_plugin convert_filter_plugin = {
......
...@@ -34,21 +34,21 @@ class NormalizeFilter final : public Filter { ...@@ -34,21 +34,21 @@ class NormalizeFilter final : public Filter {
PcmBuffer buffer; PcmBuffer buffer;
public: public:
virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; virtual AudioFormat Open(AudioFormat &af, Error &error) override;
virtual void Close(); virtual void Close();
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, GError **error_r); size_t *dest_size_r, Error &error);
}; };
static Filter * static Filter *
normalize_filter_init(gcc_unused const config_param &param, normalize_filter_init(gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return new NormalizeFilter(); return new NormalizeFilter();
} }
AudioFormat AudioFormat
NormalizeFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r) NormalizeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error)
{ {
audio_format.format = SampleFormat::S16; audio_format.format = SampleFormat::S16;
...@@ -66,7 +66,7 @@ NormalizeFilter::Close() ...@@ -66,7 +66,7 @@ NormalizeFilter::Close()
const void * const void *
NormalizeFilter::FilterPCM(const void *src, size_t src_size, NormalizeFilter::FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, gcc_unused GError **error_r) size_t *dest_size_r, gcc_unused Error &error)
{ {
int16_t *dest = (int16_t *)buffer.Get(src_size); int16_t *dest = (int16_t *)buffer.Get(src_size);
memcpy(dest, src, src_size); memcpy(dest, src, src_size);
......
...@@ -34,15 +34,15 @@ ...@@ -34,15 +34,15 @@
class NullFilter final : public Filter { class NullFilter final : public Filter {
public: public:
virtual AudioFormat Open(AudioFormat &af, virtual AudioFormat Open(AudioFormat &af,
gcc_unused GError **error_r) { gcc_unused Error &error) override {
return af; return af;
} }
virtual void Close() {} virtual void Close() override {}
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,
gcc_unused GError **error_r) { gcc_unused Error &error) override {
*dest_size_r = src_size; *dest_size_r = src_size;
return src; return src;
} }
...@@ -50,7 +50,7 @@ public: ...@@ -50,7 +50,7 @@ public:
static Filter * static Filter *
null_filter_init(gcc_unused const config_param &param, null_filter_init(gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return new NullFilter(); return new NullFilter();
} }
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include "MixerControl.hxx" #include "MixerControl.hxx"
#include "pcm/PcmVolume.hxx" #include "pcm/PcmVolume.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -114,17 +116,13 @@ public: ...@@ -114,17 +116,13 @@ public:
*/ */
void Update(); void Update();
virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; virtual AudioFormat Open(AudioFormat &af, Error &error) override;
virtual void Close(); virtual void Close();
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, GError **error_r); size_t *dest_size_r, Error &error);
}; };
static inline GQuark static constexpr Domain replay_gain_domain("replay_gain");
replay_gain_quark(void)
{
return g_quark_from_static_string("replay_gain");
}
void void
ReplayGainFilter::Update() ReplayGainFilter::Update()
...@@ -145,24 +143,22 @@ ReplayGainFilter::Update() ...@@ -145,24 +143,22 @@ ReplayGainFilter::Update()
if (_volume > 100) if (_volume > 100)
_volume = 100; _volume = 100;
GError *error = NULL; Error error;
if (!mixer_set_volume(mixer, _volume, &error)) { if (!mixer_set_volume(mixer, _volume, error))
g_warning("Failed to update hardware mixer: %s", g_warning("Failed to update hardware mixer: %s",
error->message); error.GetMessage());
g_error_free(error);
}
} }
} }
static Filter * static Filter *
replay_gain_filter_init(gcc_unused const config_param &param, replay_gain_filter_init(gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return new ReplayGainFilter(); return new ReplayGainFilter();
} }
AudioFormat AudioFormat
ReplayGainFilter::Open(AudioFormat &af, gcc_unused GError **error_r) ReplayGainFilter::Open(AudioFormat &af, gcc_unused Error &error)
{ {
format = af; format = af;
...@@ -177,7 +173,7 @@ ReplayGainFilter::Close() ...@@ -177,7 +173,7 @@ ReplayGainFilter::Close()
const void * const void *
ReplayGainFilter::FilterPCM(const void *src, size_t src_size, ReplayGainFilter::FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r) size_t *dest_size_r, Error &error)
{ {
*dest_size_r = src_size; *dest_size_r = src_size;
...@@ -201,8 +197,7 @@ ReplayGainFilter::FilterPCM(const void *src, size_t src_size, ...@@ -201,8 +197,7 @@ ReplayGainFilter::FilterPCM(const void *src, size_t src_size,
format.format, format.format,
volume); volume);
if (!success) { if (!success) {
g_set_error(error_r, replay_gain_quark(), 0, error.Set(replay_gain_domain, "pcm_volume() has failed");
"pcm_volume() has failed");
return NULL; return NULL;
} }
......
...@@ -41,13 +41,16 @@ ...@@ -41,13 +41,16 @@
#include "config.h" #include "config.h"
#include "conf.h" #include "conf.h"
#include "ConfigQuark.hxx" #include "ConfigError.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "FilterPlugin.hxx" #include "FilterPlugin.hxx"
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
...@@ -118,16 +121,16 @@ public: ...@@ -118,16 +121,16 @@ public:
* @param filter a route_filter whose min_channels and sources[] to set * @param filter a route_filter whose min_channels and sources[] to set
* @return true on success, false on error * @return true on success, false on error
*/ */
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; virtual AudioFormat Open(AudioFormat &af, Error &error) override;
virtual void Close(); virtual void Close();
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, GError **error_r); size_t *dest_size_r, Error &error);
}; };
bool bool
RouteFilter::Configure(const config_param &param, GError **error_r) { RouteFilter::Configure(const config_param &param, Error &error) {
/* TODO: /* TODO:
* With a more clever way of marking "don't copy to output N", * With a more clever way of marking "don't copy to output N",
...@@ -160,7 +163,7 @@ RouteFilter::Configure(const config_param &param, GError **error_r) { ...@@ -160,7 +163,7 @@ RouteFilter::Configure(const config_param &param, GError **error_r) {
// Split the a>b string into source and destination // Split the a>b string into source and destination
sd = g_strsplit(tokens[c], ">", 2); sd = g_strsplit(tokens[c], ">", 2);
if (g_strv_length(sd) != 2) { if (g_strv_length(sd) != 2) {
g_set_error(error_r, config_quark(), 1, error.Format(config_domain,
"Invalid copy around %d in routes spec: %s", "Invalid copy around %d in routes spec: %s",
param.line, tokens[c]); param.line, tokens[c]);
g_strfreev(sd); g_strfreev(sd);
...@@ -183,7 +186,7 @@ RouteFilter::Configure(const config_param &param, GError **error_r) { ...@@ -183,7 +186,7 @@ RouteFilter::Configure(const config_param &param, GError **error_r) {
if (!audio_valid_channel_count(min_output_channels)) { if (!audio_valid_channel_count(min_output_channels)) {
g_strfreev(tokens); g_strfreev(tokens);
g_set_error(error_r, audio_format_quark(), 0, error.Format(config_domain,
"Invalid number of output channels requested: %d", "Invalid number of output channels requested: %d",
min_output_channels); min_output_channels);
return false; return false;
...@@ -207,7 +210,7 @@ RouteFilter::Configure(const config_param &param, GError **error_r) { ...@@ -207,7 +210,7 @@ RouteFilter::Configure(const config_param &param, GError **error_r) {
// Split the a>b string into source and destination // Split the a>b string into source and destination
sd = g_strsplit(tokens[c], ">", 2); sd = g_strsplit(tokens[c], ">", 2);
if (g_strv_length(sd) != 2) { if (g_strv_length(sd) != 2) {
g_set_error(error_r, config_quark(), 1, error.Format(config_domain,
"Invalid copy around %d in routes spec: %s", "Invalid copy around %d in routes spec: %s",
param.line, tokens[c]); param.line, tokens[c]);
g_strfreev(sd); g_strfreev(sd);
...@@ -229,10 +232,10 @@ RouteFilter::Configure(const config_param &param, GError **error_r) { ...@@ -229,10 +232,10 @@ RouteFilter::Configure(const config_param &param, GError **error_r) {
} }
static Filter * static Filter *
route_filter_init(const config_param &param, GError **error_r) route_filter_init(const config_param &param, Error &error)
{ {
RouteFilter *filter = new RouteFilter(); RouteFilter *filter = new RouteFilter();
if (!filter->Configure(param, error_r)) { if (!filter->Configure(param, error)) {
delete filter; delete filter;
return nullptr; return nullptr;
} }
...@@ -241,7 +244,7 @@ route_filter_init(const config_param &param, GError **error_r) ...@@ -241,7 +244,7 @@ route_filter_init(const config_param &param, GError **error_r)
} }
AudioFormat AudioFormat
RouteFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r) RouteFilter::Open(AudioFormat &audio_format, gcc_unused Error &error)
{ {
// Copy the input format for later reference // Copy the input format for later reference
input_format = audio_format; input_format = audio_format;
...@@ -266,7 +269,7 @@ RouteFilter::Close() ...@@ -266,7 +269,7 @@ RouteFilter::Close()
const void * const void *
RouteFilter::FilterPCM(const void *src, size_t src_size, RouteFilter::FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, gcc_unused GError **error_r) size_t *dest_size_r, gcc_unused Error &error)
{ {
size_t number_of_frames = src_size / input_frame_size; size_t number_of_frames = src_size / input_frame_size;
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "pcm/PcmVolume.hxx" #include "pcm/PcmVolume.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -58,27 +60,23 @@ public: ...@@ -58,27 +60,23 @@ public:
volume = _volume; volume = _volume;
} }
virtual AudioFormat Open(AudioFormat &af, GError **error_r) override; virtual AudioFormat Open(AudioFormat &af, Error &error) override;
virtual void Close(); virtual void Close();
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, GError **error_r); size_t *dest_size_r, Error &error);
}; };
static inline GQuark static constexpr Domain volume_domain("pcm_volume");
volume_quark(void)
{
return g_quark_from_static_string("pcm_volume");
}
static Filter * static Filter *
volume_filter_init(gcc_unused const config_param &param, volume_filter_init(gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return new VolumeFilter(); return new VolumeFilter();
} }
AudioFormat AudioFormat
VolumeFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r) VolumeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error)
{ {
format = audio_format; format = audio_format;
...@@ -93,7 +91,7 @@ VolumeFilter::Close() ...@@ -93,7 +91,7 @@ VolumeFilter::Close()
const void * const void *
VolumeFilter::FilterPCM(const void *src, size_t src_size, VolumeFilter::FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r) size_t *dest_size_r, Error &error)
{ {
*dest_size_r = src_size; *dest_size_r = src_size;
...@@ -117,8 +115,7 @@ VolumeFilter::FilterPCM(const void *src, size_t src_size, ...@@ -117,8 +115,7 @@ VolumeFilter::FilterPCM(const void *src, size_t src_size,
format.format, format.format,
volume); volume);
if (!success) { if (!success) {
g_set_error(error_r, volume_quark(), 0, error.Set(volume_domain, "pcm_volume() has failed");
"pcm_volume() has failed");
return NULL; return NULL;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "ArchivePlugin.hxx" #include "ArchivePlugin.hxx"
#include "ArchiveFile.hxx" #include "ArchiveFile.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -38,7 +39,7 @@ ...@@ -38,7 +39,7 @@
static struct input_stream * static struct input_stream *
input_archive_open(const char *pathname, input_archive_open(const char *pathname,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
const struct archive_plugin *arplug; const struct archive_plugin *arplug;
char *archive, *filename, *suffix, *pname; char *archive, *filename, *suffix, *pname;
...@@ -63,14 +64,14 @@ input_archive_open(const char *pathname, ...@@ -63,14 +64,14 @@ input_archive_open(const char *pathname,
return NULL; return NULL;
} }
auto file = archive_file_open(arplug, archive, error_r); auto file = archive_file_open(arplug, archive, error);
if (file == NULL) { if (file == NULL) {
g_free(pname); g_free(pname);
return NULL; return NULL;
} }
//setup fileops //setup fileops
is = file->OpenStream(filename, mutex, cond, error_r); is = file->OpenStream(filename, mutex, cond, error);
g_free(pname); g_free(pname);
file->Close(); file->Close();
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "InputInternal.hxx" #include "InputInternal.hxx"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
...@@ -71,11 +73,7 @@ struct CdioParanoiaInputStream { ...@@ -71,11 +73,7 @@ struct CdioParanoiaInputStream {
} }
}; };
static inline GQuark static constexpr Domain cdio_domain("cdio");
cdio_quark(void)
{
return g_quark_from_static_string("cdio");
}
static void static void
input_cdio_close(struct input_stream *is) input_cdio_close(struct input_stream *is)
...@@ -91,7 +89,7 @@ struct cdio_uri { ...@@ -91,7 +89,7 @@ struct cdio_uri {
}; };
static bool static bool
parse_cdio_uri(struct cdio_uri *dest, const char *src, GError **error_r) parse_cdio_uri(struct cdio_uri *dest, const char *src, Error &error)
{ {
if (!g_str_has_prefix(src, "cdda://")) if (!g_str_has_prefix(src, "cdda://"))
return false; return false;
...@@ -125,8 +123,7 @@ parse_cdio_uri(struct cdio_uri *dest, const char *src, GError **error_r) ...@@ -125,8 +123,7 @@ parse_cdio_uri(struct cdio_uri *dest, const char *src, GError **error_r)
char *endptr; char *endptr;
dest->track = strtoul(track, &endptr, 10); dest->track = strtoul(track, &endptr, 10);
if (*endptr != 0) { if (*endptr != 0) {
g_set_error(error_r, cdio_quark(), 0, error.Set(cdio_domain, "Malformed track number");
"Malformed track number");
return false; return false;
} }
...@@ -154,10 +151,10 @@ cdio_detect_device(void) ...@@ -154,10 +151,10 @@ cdio_detect_device(void)
static struct input_stream * static struct input_stream *
input_cdio_open(const char *uri, input_cdio_open(const char *uri,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
struct cdio_uri parsed_uri; struct cdio_uri parsed_uri;
if (!parse_cdio_uri(&parsed_uri, uri, error_r)) if (!parse_cdio_uri(&parsed_uri, uri, error))
return nullptr; return nullptr;
CdioParanoiaInputStream *i = CdioParanoiaInputStream *i =
...@@ -169,7 +166,7 @@ input_cdio_open(const char *uri, ...@@ -169,7 +166,7 @@ input_cdio_open(const char *uri,
? g_strdup(parsed_uri.device) ? g_strdup(parsed_uri.device)
: cdio_detect_device(); : cdio_detect_device();
if (device == nullptr) { if (device == nullptr) {
g_set_error(error_r, cdio_quark(), 0, error.Set(cdio_domain,
"Unable find or access a CD-ROM drive with an audio CD in it."); "Unable find or access a CD-ROM drive with an audio CD in it.");
delete i; delete i;
return nullptr; return nullptr;
...@@ -182,8 +179,7 @@ input_cdio_open(const char *uri, ...@@ -182,8 +179,7 @@ input_cdio_open(const char *uri,
i->drv = cdio_cddap_identify_cdio(i->cdio, 1, nullptr); i->drv = cdio_cddap_identify_cdio(i->cdio, 1, nullptr);
if ( !i->drv ) { if ( !i->drv ) {
g_set_error(error_r, cdio_quark(), 0, error.Set(cdio_domain, "Unable to identify audio CD disc.");
"Unable to identify audio CD disc.");
delete i; delete i;
return nullptr; return nullptr;
} }
...@@ -191,7 +187,7 @@ input_cdio_open(const char *uri, ...@@ -191,7 +187,7 @@ input_cdio_open(const char *uri,
cdda_verbose_set(i->drv, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); cdda_verbose_set(i->drv, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
if ( 0 != cdio_cddap_open(i->drv) ) { if ( 0 != cdio_cddap_open(i->drv) ) {
g_set_error(error_r, cdio_quark(), 0, "Unable to open disc."); error.Set(cdio_domain, "Unable to open disc.");
delete i; delete i;
return nullptr; return nullptr;
} }
...@@ -211,8 +207,7 @@ input_cdio_open(const char *uri, ...@@ -211,8 +207,7 @@ input_cdio_open(const char *uri,
reverse_endian = G_BYTE_ORDER == G_LITTLE_ENDIAN; reverse_endian = G_BYTE_ORDER == G_LITTLE_ENDIAN;
break; break;
default: default:
g_set_error(error_r, cdio_quark(), 0, error.Format(cdio_domain, "Drive returns unknown data type %d",
"Drive returns unknown data type %d",
data_bigendianp(i->drv)); data_bigendianp(i->drv));
delete i; delete i;
return nullptr; return nullptr;
...@@ -250,7 +245,7 @@ input_cdio_open(const char *uri, ...@@ -250,7 +245,7 @@ input_cdio_open(const char *uri,
static bool static bool
input_cdio_seek(struct input_stream *is, input_cdio_seek(struct input_stream *is,
goffset offset, int whence, GError **error_r) goffset offset, int whence, Error &error)
{ {
CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is; CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is;
...@@ -267,8 +262,7 @@ input_cdio_seek(struct input_stream *is, ...@@ -267,8 +262,7 @@ input_cdio_seek(struct input_stream *is,
} }
if (offset < 0 || offset > cis->base.size) { if (offset < 0 || offset > cis->base.size) {
g_set_error(error_r, cdio_quark(), 0, error.Format(cdio_domain, "Invalid offset to seek %ld (%ld)",
"Invalid offset to seek %ld (%ld)",
(long int)offset, (long int)cis->base.size); (long int)offset, (long int)cis->base.size);
return false; return false;
} }
...@@ -288,7 +282,7 @@ input_cdio_seek(struct input_stream *is, ...@@ -288,7 +282,7 @@ input_cdio_seek(struct input_stream *is,
static size_t static size_t
input_cdio_read(struct input_stream *is, void *ptr, size_t length, input_cdio_read(struct input_stream *is, void *ptr, size_t length,
GError **error_r) Error &error)
{ {
CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is; CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is;
size_t nbytes = 0; size_t nbytes = 0;
...@@ -319,7 +313,7 @@ input_cdio_read(struct input_stream *is, void *ptr, size_t length, ...@@ -319,7 +313,7 @@ input_cdio_read(struct input_stream *is, void *ptr, size_t length,
free(s_mess); free(s_mess);
} }
if (!rbuf) { if (!rbuf) {
g_set_error(error_r, cdio_quark(), 0, error.Set(cdio_domain,
"paranoia read error. Stopping."); "paranoia read error. Stopping.");
return 0; return 0;
} }
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include "event/MultiSocketMonitor.hxx" #include "event/MultiSocketMonitor.hxx"
#include "event/Call.hxx" #include "event/Call.hxx"
#include "IOThread.hxx" #include "IOThread.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h> #include <assert.h>
...@@ -162,16 +164,14 @@ struct input_curl { ...@@ -162,16 +164,14 @@ struct input_curl {
input_stream_tag() */ input_stream_tag() */
Tag *tag; Tag *tag;
GError *postponed_error; Error postponed_error;
input_curl(const char *url, Mutex &mutex, Cond &cond) input_curl(const char *url, Mutex &mutex, Cond &cond)
:base(input_plugin_curl, url, mutex, cond), :base(input_plugin_curl, url, mutex, cond),
range(nullptr), request_headers(nullptr), range(nullptr), request_headers(nullptr),
paused(false), paused(false),
meta_name(nullptr), meta_name(nullptr),
tag(nullptr), tag(nullptr) {}
postponed_error(nullptr) {
}
~input_curl(); ~input_curl();
...@@ -215,12 +215,9 @@ static struct { ...@@ -215,12 +215,9 @@ static struct {
CurlSockets *sockets; CurlSockets *sockets;
} curl; } curl;
gcc_const static constexpr Domain http_domain("http");
static inline GQuark static constexpr Domain curl_domain("curl");
curl_quark(void) static constexpr Domain curlm_domain("curlm");
{
return g_quark_from_static_string("curl");
}
/** /**
* Find a request by its CURL "easy" handle. * Find a request by its CURL "easy" handle.
...@@ -319,7 +316,7 @@ CurlSockets::UpdateSockets() ...@@ -319,7 +316,7 @@ CurlSockets::UpdateSockets()
* Runs in the I/O thread. No lock needed. * Runs in the I/O thread. No lock needed.
*/ */
static bool static bool
input_curl_easy_add(struct input_curl *c, GError **error_r) input_curl_easy_add(struct input_curl *c, Error &error)
{ {
assert(io_thread_inside()); assert(io_thread_inside());
assert(c != NULL); assert(c != NULL);
...@@ -330,7 +327,7 @@ input_curl_easy_add(struct input_curl *c, GError **error_r) ...@@ -330,7 +327,7 @@ input_curl_easy_add(struct input_curl *c, GError **error_r)
CURLMcode mcode = curl_multi_add_handle(curl.multi, c->easy); CURLMcode mcode = curl_multi_add_handle(curl.multi, c->easy);
if (mcode != CURLM_OK) { if (mcode != CURLM_OK) {
g_set_error(error_r, curl_quark(), mcode, error.Format(curlm_domain, mcode,
"curl_multi_add_handle() failed: %s", "curl_multi_add_handle() failed: %s",
curl_multi_strerror(mcode)); curl_multi_strerror(mcode));
return false; return false;
...@@ -346,14 +343,14 @@ input_curl_easy_add(struct input_curl *c, GError **error_r) ...@@ -346,14 +343,14 @@ input_curl_easy_add(struct input_curl *c, GError **error_r)
* any thread. Caller must not hold a mutex. * any thread. Caller must not hold a mutex.
*/ */
static bool static bool
input_curl_easy_add_indirect(struct input_curl *c, GError **error_r) input_curl_easy_add_indirect(struct input_curl *c, Error &error)
{ {
assert(c != NULL); assert(c != NULL);
assert(c->easy != NULL); assert(c->easy != NULL);
bool result; bool result;
BlockingCall(io_thread_get(), [c, error_r, &result](){ BlockingCall(io_thread_get(), [c, &error, &result](){
result = input_curl_easy_add(c, error_r); result = input_curl_easy_add(c, error);
}); });
return result; return result;
} }
...@@ -409,27 +406,25 @@ input_curl_easy_free_indirect(struct input_curl *c) ...@@ -409,27 +406,25 @@ input_curl_easy_free_indirect(struct input_curl *c)
* Runs in the I/O thread. The caller must not hold locks. * Runs in the I/O thread. The caller must not hold locks.
*/ */
static void static void
input_curl_abort_all_requests(GError *error) input_curl_abort_all_requests(const Error &error)
{ {
assert(io_thread_inside()); assert(io_thread_inside());
assert(error != NULL); assert(error.IsDefined());
while (!curl.requests.empty()) { while (!curl.requests.empty()) {
struct input_curl *c = curl.requests.front(); struct input_curl *c = curl.requests.front();
assert(c->postponed_error == NULL); assert(!c->postponed_error.IsDefined());
input_curl_easy_free(c); input_curl_easy_free(c);
const ScopeLock protect(c->base.mutex); const ScopeLock protect(c->base.mutex);
c->postponed_error = g_error_copy(error); c->postponed_error.Set(error);
c->base.ready = true; c->base.ready = true;
c->base.cond.broadcast(); c->base.cond.broadcast();
} }
g_error_free(error);
} }
/** /**
...@@ -443,16 +438,15 @@ input_curl_request_done(struct input_curl *c, CURLcode result, long status) ...@@ -443,16 +438,15 @@ input_curl_request_done(struct input_curl *c, CURLcode result, long status)
assert(io_thread_inside()); assert(io_thread_inside());
assert(c != NULL); assert(c != NULL);
assert(c->easy == NULL); assert(c->easy == NULL);
assert(c->postponed_error == NULL); assert(!c->postponed_error.IsDefined());
const ScopeLock protect(c->base.mutex); const ScopeLock protect(c->base.mutex);
if (result != CURLE_OK) { if (result != CURLE_OK) {
c->postponed_error = g_error_new(curl_quark(), result, c->postponed_error.Format(curl_domain, result,
"curl failed: %s", "curl failed: %s", c->error);
c->error);
} else if (status < 200 || status >= 300) { } else if (status < 200 || status >= 300) {
c->postponed_error = g_error_new(curl_quark(), 0, c->postponed_error.Format(http_domain, status,
"got HTTP status %ld", "got HTTP status %ld",
status); status);
} }
...@@ -513,7 +507,8 @@ input_curl_perform(void) ...@@ -513,7 +507,8 @@ input_curl_perform(void)
} while (mcode == CURLM_CALL_MULTI_PERFORM); } while (mcode == CURLM_CALL_MULTI_PERFORM);
if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) { if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) {
GError *error = g_error_new(curl_quark(), mcode, Error error;
error.Format(curlm_domain, mcode,
"curl_multi_perform() failed: %s", "curl_multi_perform() failed: %s",
curl_multi_strerror(mcode)); curl_multi_strerror(mcode));
input_curl_abort_all_requests(error); input_curl_abort_all_requests(error);
...@@ -559,13 +554,12 @@ CurlSockets::DispatchSockets() ...@@ -559,13 +554,12 @@ CurlSockets::DispatchSockets()
*/ */
static bool static bool
input_curl_init(const config_param &param, input_curl_init(const config_param &param, Error &error)
gcc_unused GError **error_r)
{ {
CURLcode code = curl_global_init(CURL_GLOBAL_ALL); CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
if (code != CURLE_OK) { if (code != CURLE_OK) {
g_set_error(error_r, curl_quark(), code, error.Format(curl_domain, code,
"curl_global_init() failed: %s\n", "curl_global_init() failed: %s",
curl_easy_strerror(code)); curl_easy_strerror(code));
return false; return false;
} }
...@@ -588,8 +582,7 @@ input_curl_init(const config_param &param, ...@@ -588,8 +582,7 @@ input_curl_init(const config_param &param,
curl.multi = curl_multi_init(); curl.multi = curl_multi_init();
if (curl.multi == NULL) { if (curl.multi == NULL) {
g_set_error(error_r, curl_quark(), 0, error.Set(curl_domain, 0, "curl_multi_init() failed");
"curl_multi_init() failed");
return false; return false;
} }
...@@ -639,20 +632,17 @@ input_curl::~input_curl() ...@@ -639,20 +632,17 @@ input_curl::~input_curl()
g_free(meta_name); g_free(meta_name);
input_curl_easy_free_indirect(this); input_curl_easy_free_indirect(this);
if (postponed_error != NULL)
g_error_free(postponed_error);
} }
static bool static bool
input_curl_check(struct input_stream *is, GError **error_r) input_curl_check(struct input_stream *is, Error &error)
{ {
struct input_curl *c = (struct input_curl *)is; struct input_curl *c = (struct input_curl *)is;
bool success = c->postponed_error == NULL; bool success = !c->postponed_error.IsDefined();
if (!success) { if (!success) {
g_propagate_error(error_r, c->postponed_error); error = std::move(c->postponed_error);
c->postponed_error = NULL; c->postponed_error.Clear();
} }
return success; return success;
...@@ -669,14 +659,14 @@ input_curl_tag(struct input_stream *is) ...@@ -669,14 +659,14 @@ input_curl_tag(struct input_stream *is)
} }
static bool static bool
fill_buffer(struct input_curl *c, GError **error_r) fill_buffer(struct input_curl *c, Error &error)
{ {
while (c->easy != NULL && c->buffers.empty()) while (c->easy != NULL && c->buffers.empty())
c->base.cond.wait(c->base.mutex); c->base.cond.wait(c->base.mutex);
if (c->postponed_error != NULL) { if (c->postponed_error.IsDefined()) {
g_propagate_error(error_r, c->postponed_error); error = std::move(c->postponed_error);
c->postponed_error = NULL; c->postponed_error.Clear();
return false; return false;
} }
...@@ -754,13 +744,13 @@ input_curl_available(struct input_stream *is) ...@@ -754,13 +744,13 @@ input_curl_available(struct input_stream *is)
{ {
struct input_curl *c = (struct input_curl *)is; struct input_curl *c = (struct input_curl *)is;
return c->postponed_error != NULL || c->easy == NULL || return c->postponed_error.IsDefined() || c->easy == NULL ||
!c->buffers.empty(); !c->buffers.empty();
} }
static size_t static size_t
input_curl_read(struct input_stream *is, void *ptr, size_t size, input_curl_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r) Error &error)
{ {
struct input_curl *c = (struct input_curl *)is; struct input_curl *c = (struct input_curl *)is;
bool success; bool success;
...@@ -770,7 +760,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size, ...@@ -770,7 +760,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size,
do { do {
/* fill the buffer */ /* fill the buffer */
success = fill_buffer(c, error_r); success = fill_buffer(c, error);
if (!success) if (!success)
return 0; return 0;
...@@ -927,14 +917,13 @@ input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream) ...@@ -927,14 +917,13 @@ input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
} }
static bool static bool
input_curl_easy_init(struct input_curl *c, GError **error_r) input_curl_easy_init(struct input_curl *c, Error &error)
{ {
CURLcode code; CURLcode code;
c->easy = curl_easy_init(); c->easy = curl_easy_init();
if (c->easy == NULL) { if (c->easy == NULL) {
g_set_error(error_r, curl_quark(), 0, error.Set(curl_domain, "curl_easy_init() failed");
"curl_easy_init() failed");
return false; return false;
} }
...@@ -971,7 +960,7 @@ input_curl_easy_init(struct input_curl *c, GError **error_r) ...@@ -971,7 +960,7 @@ input_curl_easy_init(struct input_curl *c, GError **error_r)
code = curl_easy_setopt(c->easy, CURLOPT_URL, c->base.uri.c_str()); code = curl_easy_setopt(c->easy, CURLOPT_URL, c->base.uri.c_str());
if (code != CURLE_OK) { if (code != CURLE_OK) {
g_set_error(error_r, curl_quark(), code, error.Format(curl_domain, code,
"curl_easy_setopt() failed: %s", "curl_easy_setopt() failed: %s",
curl_easy_strerror(code)); curl_easy_strerror(code));
return false; return false;
...@@ -987,7 +976,7 @@ input_curl_easy_init(struct input_curl *c, GError **error_r) ...@@ -987,7 +976,7 @@ input_curl_easy_init(struct input_curl *c, GError **error_r)
static bool static bool
input_curl_seek(struct input_stream *is, goffset offset, int whence, input_curl_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r) Error &error)
{ {
struct input_curl *c = (struct input_curl *)is; struct input_curl *c = (struct input_curl *)is;
bool ret; bool ret;
...@@ -1059,7 +1048,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence, ...@@ -1059,7 +1048,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
return true; return true;
} }
ret = input_curl_easy_init(c, error_r); ret = input_curl_easy_init(c, error);
if (!ret) if (!ret)
return false; return false;
...@@ -1072,7 +1061,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence, ...@@ -1072,7 +1061,7 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
c->base.ready = false; c->base.ready = false;
if (!input_curl_easy_add_indirect(c, error_r)) if (!input_curl_easy_add_indirect(c, error))
return false; return false;
c->base.mutex.lock(); c->base.mutex.lock();
...@@ -1080,9 +1069,9 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence, ...@@ -1080,9 +1069,9 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
while (!c->base.ready) while (!c->base.ready)
c->base.cond.wait(c->base.mutex); c->base.cond.wait(c->base.mutex);
if (c->postponed_error != NULL) { if (c->postponed_error.IsDefined()) {
g_propagate_error(error_r, c->postponed_error); error = std::move(c->postponed_error);
c->postponed_error = NULL; c->postponed_error.Clear();
return false; return false;
} }
...@@ -1091,19 +1080,19 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence, ...@@ -1091,19 +1080,19 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
static struct input_stream * static struct input_stream *
input_curl_open(const char *url, Mutex &mutex, Cond &cond, input_curl_open(const char *url, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
if (strncmp(url, "http://", 7) != 0) if (strncmp(url, "http://", 7) != 0)
return NULL; return NULL;
struct input_curl *c = new input_curl(url, mutex, cond); struct input_curl *c = new input_curl(url, mutex, cond);
if (!input_curl_easy_init(c, error_r)) { if (!input_curl_easy_init(c, error)) {
delete c; delete c;
return NULL; return NULL;
} }
if (!input_curl_easy_add_indirect(c, error_r)) { if (!input_curl_easy_add_indirect(c, error)) {
delete c; delete c;
return NULL; return NULL;
} }
......
...@@ -124,7 +124,7 @@ static void callback(gcc_unused struct despotify_session* ds, ...@@ -124,7 +124,7 @@ static void callback(gcc_unused struct despotify_session* ds,
static struct input_stream * static struct input_stream *
input_despotify_open(const char *url, input_despotify_open(const char *url,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
struct despotify_session *session; struct despotify_session *session;
struct ds_link *ds_link; struct ds_link *ds_link;
...@@ -172,7 +172,7 @@ input_despotify_open(const char *url, ...@@ -172,7 +172,7 @@ input_despotify_open(const char *url,
static size_t static size_t
input_despotify_read(struct input_stream *is, void *ptr, size_t size, input_despotify_read(struct input_stream *is, void *ptr, size_t size,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
DespotifyInputStream *ctx = (DespotifyInputStream *)is; DespotifyInputStream *ctx = (DespotifyInputStream *)is;
size_t to_cpy = size; size_t to_cpy = size;
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "InputInternal.hxx" #include "InputInternal.hxx"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
extern "C" { extern "C" {
#include <libavutil/avutil.h> #include <libavutil/avutil.h>
...@@ -62,11 +64,7 @@ struct FfmpegInputStream { ...@@ -62,11 +64,7 @@ struct FfmpegInputStream {
} }
}; };
static inline GQuark static constexpr Domain ffmpeg_domain("ffmpeg");
ffmpeg_quark(void)
{
return g_quark_from_static_string("ffmpeg");
}
static inline bool static inline bool
input_ffmpeg_supported(void) input_ffmpeg_supported(void)
...@@ -77,14 +75,13 @@ input_ffmpeg_supported(void) ...@@ -77,14 +75,13 @@ input_ffmpeg_supported(void)
static bool static bool
input_ffmpeg_init(gcc_unused const config_param &param, input_ffmpeg_init(gcc_unused const config_param &param,
gcc_unused GError **error_r) Error &error)
{ {
av_register_all(); av_register_all();
/* disable this plugin if there's no registered protocol */ /* disable this plugin if there's no registered protocol */
if (!input_ffmpeg_supported()) { if (!input_ffmpeg_supported()) {
g_set_error(error_r, ffmpeg_quark(), 0, error.Set(ffmpeg_domain, "No protocol");
"No protocol");
return false; return false;
} }
...@@ -94,7 +91,7 @@ input_ffmpeg_init(gcc_unused const config_param &param, ...@@ -94,7 +91,7 @@ input_ffmpeg_init(gcc_unused const config_param &param,
static struct input_stream * static struct input_stream *
input_ffmpeg_open(const char *uri, input_ffmpeg_open(const char *uri,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
if (!g_str_has_prefix(uri, "gopher://") && if (!g_str_has_prefix(uri, "gopher://") &&
!g_str_has_prefix(uri, "rtp://") && !g_str_has_prefix(uri, "rtp://") &&
...@@ -107,7 +104,7 @@ input_ffmpeg_open(const char *uri, ...@@ -107,7 +104,7 @@ input_ffmpeg_open(const char *uri,
AVIOContext *h; AVIOContext *h;
int ret = avio_open(&h, uri, AVIO_FLAG_READ); int ret = avio_open(&h, uri, AVIO_FLAG_READ);
if (ret != 0) { if (ret != 0) {
g_set_error(error_r, ffmpeg_quark(), ret, error.Set(ffmpeg_domain, ret,
"libavformat failed to open the URI"); "libavformat failed to open the URI");
return nullptr; return nullptr;
} }
...@@ -118,15 +115,14 @@ input_ffmpeg_open(const char *uri, ...@@ -118,15 +115,14 @@ input_ffmpeg_open(const char *uri,
static size_t static size_t
input_ffmpeg_read(struct input_stream *is, void *ptr, size_t size, input_ffmpeg_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r) Error &error)
{ {
FfmpegInputStream *i = (FfmpegInputStream *)is; FfmpegInputStream *i = (FfmpegInputStream *)is;
int ret = avio_read(i->h, (unsigned char *)ptr, size); int ret = avio_read(i->h, (unsigned char *)ptr, size);
if (ret <= 0) { if (ret <= 0) {
if (ret < 0) if (ret < 0)
g_set_error(error_r, ffmpeg_quark(), 0, error.Set(ffmpeg_domain, "avio_read() failed");
"url_read() failed");
i->eof = true; i->eof = true;
return false; return false;
...@@ -154,7 +150,7 @@ input_ffmpeg_eof(struct input_stream *is) ...@@ -154,7 +150,7 @@ input_ffmpeg_eof(struct input_stream *is)
static bool static bool
input_ffmpeg_seek(struct input_stream *is, goffset offset, int whence, input_ffmpeg_seek(struct input_stream *is, goffset offset, int whence,
gcc_unused GError **error_r) Error &error)
{ {
FfmpegInputStream *i = (FfmpegInputStream *)is; FfmpegInputStream *i = (FfmpegInputStream *)is;
int64_t ret = avio_seek(i->h, offset, whence); int64_t ret = avio_seek(i->h, offset, whence);
...@@ -163,7 +159,7 @@ input_ffmpeg_seek(struct input_stream *is, goffset offset, int whence, ...@@ -163,7 +159,7 @@ input_ffmpeg_seek(struct input_stream *is, goffset offset, int whence,
i->eof = false; i->eof = false;
return true; return true;
} else { } else {
g_set_error(error_r, ffmpeg_quark(), 0, "url_seek() failed"); error.Set(ffmpeg_domain, "avio_seek() failed");
return false; return false;
} }
} }
......
...@@ -22,9 +22,10 @@ ...@@ -22,9 +22,10 @@
#include "InputInternal.hxx" #include "InputInternal.hxx"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "open.h" #include "open.h"
#include "io_error.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
...@@ -35,6 +36,8 @@ ...@@ -35,6 +36,8 @@
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "input_file" #define G_LOG_DOMAIN "input_file"
static constexpr Domain file_domain("file");
struct FileInputStream { struct FileInputStream {
struct input_stream base; struct input_stream base;
...@@ -57,7 +60,7 @@ struct FileInputStream { ...@@ -57,7 +60,7 @@ struct FileInputStream {
static struct input_stream * static struct input_stream *
input_file_open(const char *filename, input_file_open(const char *filename,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
int fd, ret; int fd, ret;
struct stat st; struct stat st;
...@@ -68,24 +71,20 @@ input_file_open(const char *filename, ...@@ -68,24 +71,20 @@ input_file_open(const char *filename,
fd = open_cloexec(filename, O_RDONLY|O_BINARY, 0); fd = open_cloexec(filename, O_RDONLY|O_BINARY, 0);
if (fd < 0) { if (fd < 0) {
if (errno != ENOENT && errno != ENOTDIR) if (errno != ENOENT && errno != ENOTDIR)
g_set_error(error_r, errno_quark(), errno, error.FormatErrno("Failed to open \"%s\"",
"Failed to open \"%s\": %s", filename);
filename, g_strerror(errno));
return nullptr; return nullptr;
} }
ret = fstat(fd, &st); ret = fstat(fd, &st);
if (ret < 0) { if (ret < 0) {
g_set_error(error_r, errno_quark(), errno, error.FormatErrno("Failed to stat \"%s\"", filename);
"Failed to stat \"%s\": %s",
filename, g_strerror(errno));
close(fd); close(fd);
return nullptr; return nullptr;
} }
if (!S_ISREG(st.st_mode)) { if (!S_ISREG(st.st_mode)) {
g_set_error(error_r, errno_quark(), 0, error.Format(file_domain, "Not a regular file: %s", filename);
"Not a regular file: %s", filename);
close(fd); close(fd);
return nullptr; return nullptr;
} }
...@@ -101,14 +100,13 @@ input_file_open(const char *filename, ...@@ -101,14 +100,13 @@ input_file_open(const char *filename,
static bool static bool
input_file_seek(struct input_stream *is, goffset offset, int whence, input_file_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r) Error &error)
{ {
FileInputStream *fis = (FileInputStream *)is; FileInputStream *fis = (FileInputStream *)is;
offset = (goffset)lseek(fis->fd, (off_t)offset, whence); offset = (goffset)lseek(fis->fd, (off_t)offset, whence);
if (offset < 0) { if (offset < 0) {
g_set_error(error_r, errno_quark(), errno, error.SetErrno("Failed to seek");
"Failed to seek: %s", g_strerror(errno));
return false; return false;
} }
...@@ -118,15 +116,14 @@ input_file_seek(struct input_stream *is, goffset offset, int whence, ...@@ -118,15 +116,14 @@ input_file_seek(struct input_stream *is, goffset offset, int whence,
static size_t static size_t
input_file_read(struct input_stream *is, void *ptr, size_t size, input_file_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r) Error &error)
{ {
FileInputStream *fis = (FileInputStream *)is; FileInputStream *fis = (FileInputStream *)is;
ssize_t nbytes; ssize_t nbytes;
nbytes = read(fis->fd, ptr, size); nbytes = read(fis->fd, ptr, size);
if (nbytes < 0) { if (nbytes < 0) {
g_set_error(error_r, errno_quark(), errno, error.SetErrno("Failed to read");
"Failed to read: %s", g_strerror(errno));
return 0; return 0;
} }
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "InputInternal.hxx" #include "InputInternal.hxx"
#include "InputStream.hxx" #include "InputStream.hxx"
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
#include <libmms/mmsx.h> #include <libmms/mmsx.h>
...@@ -56,16 +58,12 @@ struct MmsInputStream { ...@@ -56,16 +58,12 @@ struct MmsInputStream {
} }
}; };
static inline GQuark static constexpr Domain mms_domain("mms");
mms_quark(void)
{
return g_quark_from_static_string("mms");
}
static struct input_stream * static struct input_stream *
input_mms_open(const char *url, input_mms_open(const char *url,
Mutex &mutex, Cond &cond, Mutex &mutex, Cond &cond,
GError **error_r) Error &error)
{ {
if (!g_str_has_prefix(url, "mms://") && if (!g_str_has_prefix(url, "mms://") &&
!g_str_has_prefix(url, "mmsh://") && !g_str_has_prefix(url, "mmsh://") &&
...@@ -75,7 +73,7 @@ input_mms_open(const char *url, ...@@ -75,7 +73,7 @@ input_mms_open(const char *url,
const auto mms = mmsx_connect(nullptr, nullptr, url, 128 * 1024); const auto mms = mmsx_connect(nullptr, nullptr, url, 128 * 1024);
if (mms == nullptr) { if (mms == nullptr) {
g_set_error(error_r, mms_quark(), 0, "mmsx_connect() failed"); error.Set(mms_domain, "mmsx_connect() failed");
return nullptr; return nullptr;
} }
...@@ -85,18 +83,15 @@ input_mms_open(const char *url, ...@@ -85,18 +83,15 @@ input_mms_open(const char *url,
static size_t static size_t
input_mms_read(struct input_stream *is, void *ptr, size_t size, input_mms_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r) Error &error)
{ {
MmsInputStream *m = (MmsInputStream *)is; MmsInputStream *m = (MmsInputStream *)is;
int ret; int ret;
ret = mmsx_read(nullptr, m->mms, (char *)ptr, size); ret = mmsx_read(nullptr, m->mms, (char *)ptr, size);
if (ret <= 0) { if (ret <= 0) {
if (ret < 0) { if (ret < 0)
g_set_error(error_r, mms_quark(), errno, error.SetErrno("mmsx_read() failed");
"mmsx_read() failed: %s",
g_strerror(errno));
}
m->eof = true; m->eof = true;
return false; return false;
......
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#include "InputPlugin.hxx" #include "InputPlugin.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include <glib.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
...@@ -112,11 +110,11 @@ input_rewind_close(struct input_stream *is) ...@@ -112,11 +110,11 @@ input_rewind_close(struct input_stream *is)
} }
static bool static bool
input_rewind_check(struct input_stream *is, GError **error_r) input_rewind_check(struct input_stream *is, Error &error)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
return input_stream_check(r->input, error_r); return input_stream_check(r->input, error);
} }
static void static void
...@@ -146,7 +144,7 @@ input_rewind_available(struct input_stream *is) ...@@ -146,7 +144,7 @@ input_rewind_available(struct input_stream *is)
static size_t static size_t
input_rewind_read(struct input_stream *is, void *ptr, size_t size, input_rewind_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r) Error &error)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
...@@ -167,7 +165,7 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size, ...@@ -167,7 +165,7 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size,
} else { } else {
/* pass method call to underlying stream */ /* pass method call to underlying stream */
size_t nbytes = input_stream_read(r->input, ptr, size, error_r); size_t nbytes = input_stream_read(r->input, ptr, size, error);
if (r->input->offset > (goffset)sizeof(r->buffer)) if (r->input->offset > (goffset)sizeof(r->buffer))
/* disable buffering */ /* disable buffering */
...@@ -197,7 +195,7 @@ input_rewind_eof(struct input_stream *is) ...@@ -197,7 +195,7 @@ input_rewind_eof(struct input_stream *is)
static bool static bool
input_rewind_seek(struct input_stream *is, goffset offset, int whence, input_rewind_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r) Error &error)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
...@@ -216,7 +214,7 @@ input_rewind_seek(struct input_stream *is, goffset offset, int whence, ...@@ -216,7 +214,7 @@ input_rewind_seek(struct input_stream *is, goffset offset, int whence,
return true; return true;
} else { } else {
bool success = input_stream_seek(r->input, offset, whence, bool success = input_stream_seek(r->input, offset, whence,
error_r); error);
r->CopyAttributes(); r->CopyAttributes();
/* disable the buffer, because r->input has left the /* disable the buffer, because r->input has left the
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "event/MultiSocketMonitor.hxx" #include "event/MultiSocketMonitor.hxx"
#include "event/Loop.hxx" #include "event/Loop.hxx"
#include "util/ReusableArray.hxx" #include "util/ReusableArray.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <algorithm> #include <algorithm>
...@@ -68,23 +70,15 @@ public: ...@@ -68,23 +70,15 @@ public:
AlsaMixer():Mixer(alsa_mixer_plugin) {} AlsaMixer():Mixer(alsa_mixer_plugin) {}
void Configure(const config_param &param); void Configure(const config_param &param);
bool Setup(GError **error_r); bool Setup(Error &error);
bool Open(GError **error_r); bool Open(Error &error);
void Close(); void Close();
int GetVolume(GError **error_r); int GetVolume(Error &error);
bool SetVolume(unsigned volume, GError **error_r); bool SetVolume(unsigned volume, Error &error);
}; };
/** static constexpr Domain alsa_mixer_domain("alsa_mixer");
* The quark used for GError.domain.
*/
gcc_const
static inline GQuark
alsa_mixer_quark(void)
{
return g_quark_from_static_string("alsa_mixer");
}
int int
AlsaMixerMonitor::PrepareSockets() AlsaMixerMonitor::PrepareSockets()
...@@ -158,7 +152,7 @@ AlsaMixer::Configure(const config_param &param) ...@@ -158,7 +152,7 @@ AlsaMixer::Configure(const config_param &param)
static Mixer * static Mixer *
alsa_mixer_init(gcc_unused void *ao, const config_param &param, alsa_mixer_init(gcc_unused void *ao, const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
AlsaMixer *am = new AlsaMixer(); AlsaMixer *am = new AlsaMixer();
am->Configure(param); am->Configure(param);
...@@ -194,12 +188,12 @@ alsa_mixer_lookup_elem(snd_mixer_t *handle, const char *name, unsigned idx) ...@@ -194,12 +188,12 @@ alsa_mixer_lookup_elem(snd_mixer_t *handle, const char *name, unsigned idx)
} }
inline bool inline bool
AlsaMixer::Setup(GError **error_r) AlsaMixer::Setup(Error &error)
{ {
int err; int err;
if ((err = snd_mixer_attach(handle, device)) < 0) { if ((err = snd_mixer_attach(handle, device)) < 0) {
g_set_error(error_r, alsa_mixer_quark(), err, error.Format(alsa_mixer_domain, err,
"failed to attach to %s: %s", "failed to attach to %s: %s",
device, snd_strerror(err)); device, snd_strerror(err));
return false; return false;
...@@ -207,14 +201,14 @@ AlsaMixer::Setup(GError **error_r) ...@@ -207,14 +201,14 @@ AlsaMixer::Setup(GError **error_r)
if ((err = snd_mixer_selem_register(handle, NULL, if ((err = snd_mixer_selem_register(handle, NULL,
NULL)) < 0) { NULL)) < 0) {
g_set_error(error_r, alsa_mixer_quark(), err, error.Format(alsa_mixer_domain, err,
"snd_mixer_selem_register() failed: %s", "snd_mixer_selem_register() failed: %s",
snd_strerror(err)); snd_strerror(err));
return false; return false;
} }
if ((err = snd_mixer_load(handle)) < 0) { if ((err = snd_mixer_load(handle)) < 0) {
g_set_error(error_r, alsa_mixer_quark(), err, error.Format(alsa_mixer_domain, err,
"snd_mixer_load() failed: %s\n", "snd_mixer_load() failed: %s\n",
snd_strerror(err)); snd_strerror(err));
return false; return false;
...@@ -222,7 +216,7 @@ AlsaMixer::Setup(GError **error_r) ...@@ -222,7 +216,7 @@ AlsaMixer::Setup(GError **error_r)
elem = alsa_mixer_lookup_elem(handle, control, index); elem = alsa_mixer_lookup_elem(handle, control, index);
if (elem == NULL) { if (elem == NULL) {
g_set_error(error_r, alsa_mixer_quark(), 0, error.Format(alsa_mixer_domain, 0,
"no such mixer control: %s", control); "no such mixer control: %s", control);
return false; return false;
} }
...@@ -238,7 +232,7 @@ AlsaMixer::Setup(GError **error_r) ...@@ -238,7 +232,7 @@ AlsaMixer::Setup(GError **error_r)
} }
inline bool inline bool
AlsaMixer::Open(GError **error_r) AlsaMixer::Open(Error &error)
{ {
int err; int err;
...@@ -246,12 +240,12 @@ AlsaMixer::Open(GError **error_r) ...@@ -246,12 +240,12 @@ AlsaMixer::Open(GError **error_r)
err = snd_mixer_open(&handle, 0); err = snd_mixer_open(&handle, 0);
if (err < 0) { if (err < 0) {
g_set_error(error_r, alsa_mixer_quark(), err, error.Format(alsa_mixer_domain, err,
"snd_mixer_open() failed: %s", snd_strerror(err)); "snd_mixer_open() failed: %s", snd_strerror(err));
return false; return false;
} }
if (!Setup(error_r)) { if (!Setup(error)) {
snd_mixer_close(handle); snd_mixer_close(handle);
return false; return false;
} }
...@@ -260,11 +254,11 @@ AlsaMixer::Open(GError **error_r) ...@@ -260,11 +254,11 @@ AlsaMixer::Open(GError **error_r)
} }
static bool static bool
alsa_mixer_open(Mixer *data, GError **error_r) alsa_mixer_open(Mixer *data, Error &error)
{ {
AlsaMixer *am = (AlsaMixer *)data; AlsaMixer *am = (AlsaMixer *)data;
return am->Open(error_r); return am->Open(error);
} }
inline void inline void
...@@ -286,7 +280,7 @@ alsa_mixer_close(Mixer *data) ...@@ -286,7 +280,7 @@ alsa_mixer_close(Mixer *data)
} }
inline int inline int
AlsaMixer::GetVolume(GError **error_r) AlsaMixer::GetVolume(Error &error)
{ {
int err; int err;
int ret; int ret;
...@@ -296,7 +290,7 @@ AlsaMixer::GetVolume(GError **error_r) ...@@ -296,7 +290,7 @@ AlsaMixer::GetVolume(GError **error_r)
err = snd_mixer_handle_events(handle); err = snd_mixer_handle_events(handle);
if (err < 0) { if (err < 0) {
g_set_error(error_r, alsa_mixer_quark(), err, error.Format(alsa_mixer_domain, err,
"snd_mixer_handle_events() failed: %s", "snd_mixer_handle_events() failed: %s",
snd_strerror(err)); snd_strerror(err));
return false; return false;
...@@ -306,7 +300,7 @@ AlsaMixer::GetVolume(GError **error_r) ...@@ -306,7 +300,7 @@ AlsaMixer::GetVolume(GError **error_r)
SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_LEFT,
&level); &level);
if (err < 0) { if (err < 0) {
g_set_error(error_r, alsa_mixer_quark(), err, error.Format(alsa_mixer_domain, err,
"failed to read ALSA volume: %s", "failed to read ALSA volume: %s",
snd_strerror(err)); snd_strerror(err));
return false; return false;
...@@ -325,14 +319,14 @@ AlsaMixer::GetVolume(GError **error_r) ...@@ -325,14 +319,14 @@ AlsaMixer::GetVolume(GError **error_r)
} }
static int static int
alsa_mixer_get_volume(Mixer *mixer, GError **error_r) alsa_mixer_get_volume(Mixer *mixer, Error &error)
{ {
AlsaMixer *am = (AlsaMixer *)mixer; AlsaMixer *am = (AlsaMixer *)mixer;
return am->GetVolume(error_r); return am->GetVolume(error);
} }
inline bool inline bool
AlsaMixer::SetVolume(unsigned volume, GError **error_r) AlsaMixer::SetVolume(unsigned volume, Error &error)
{ {
float vol; float vol;
long level; long level;
...@@ -351,7 +345,7 @@ AlsaMixer::SetVolume(unsigned volume, GError **error_r) ...@@ -351,7 +345,7 @@ AlsaMixer::SetVolume(unsigned volume, GError **error_r)
err = snd_mixer_selem_set_playback_volume_all(elem, level); err = snd_mixer_selem_set_playback_volume_all(elem, level);
if (err < 0) { if (err < 0) {
g_set_error(error_r, alsa_mixer_quark(), err, error.Format(alsa_mixer_domain, err,
"failed to set ALSA volume: %s", "failed to set ALSA volume: %s",
snd_strerror(err)); snd_strerror(err));
return false; return false;
...@@ -361,10 +355,10 @@ AlsaMixer::SetVolume(unsigned volume, GError **error_r) ...@@ -361,10 +355,10 @@ AlsaMixer::SetVolume(unsigned volume, GError **error_r)
} }
static bool static bool
alsa_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) alsa_mixer_set_volume(Mixer *mixer, unsigned volume, Error &error)
{ {
AlsaMixer *am = (AlsaMixer *)mixer; AlsaMixer *am = (AlsaMixer *)mixer;
return am->SetVolume(volume, error_r); return am->SetVolume(volume, error);
} }
const struct mixer_plugin alsa_mixer_plugin = { const struct mixer_plugin alsa_mixer_plugin = {
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "MixerInternal.hxx" #include "MixerInternal.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -51,22 +53,15 @@ class OssMixer : public Mixer { ...@@ -51,22 +53,15 @@ class OssMixer : public Mixer {
public: public:
OssMixer():Mixer(oss_mixer_plugin) {} OssMixer():Mixer(oss_mixer_plugin) {}
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
bool Open(GError **error_r); bool Open(Error &error);
void Close(); void Close();
int GetVolume(GError **error_r); int GetVolume(Error &error);
bool SetVolume(unsigned volume, GError **error_r); bool SetVolume(unsigned volume, Error &error);
}; };
/** static constexpr Domain oss_mixer_domain("oss_mixer");
* The quark used for GError.domain.
*/
static inline GQuark
oss_mixer_quark(void)
{
return g_quark_from_static_string("oss_mixer");
}
static int static int
oss_find_mixer(const char *name) oss_find_mixer(const char *name)
...@@ -84,16 +79,15 @@ oss_find_mixer(const char *name) ...@@ -84,16 +79,15 @@ oss_find_mixer(const char *name)
} }
inline bool inline bool
OssMixer::Configure(const config_param &param, GError **error_r) OssMixer::Configure(const config_param &param, Error &error)
{ {
device = param.GetBlockValue("mixer_device", device = param.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT);
VOLUME_MIXER_OSS_DEFAULT);
control = param.GetBlockValue("mixer_control"); control = param.GetBlockValue("mixer_control");
if (control != NULL) { if (control != NULL) {
volume_control = oss_find_mixer(control); volume_control = oss_find_mixer(control);
if (volume_control < 0) { if (volume_control < 0) {
g_set_error(error_r, oss_mixer_quark(), 0, error.Format(oss_mixer_domain, 0,
"no such mixer control: %s", control); "no such mixer control: %s", control);
return false; return false;
} }
...@@ -105,11 +99,11 @@ OssMixer::Configure(const config_param &param, GError **error_r) ...@@ -105,11 +99,11 @@ OssMixer::Configure(const config_param &param, GError **error_r)
static Mixer * static Mixer *
oss_mixer_init(gcc_unused void *ao, const config_param &param, oss_mixer_init(gcc_unused void *ao, const config_param &param,
GError **error_r) Error &error)
{ {
OssMixer *om = new OssMixer(); OssMixer *om = new OssMixer();
if (!om->Configure(param, error_r)) { if (!om->Configure(param, error)) {
delete om; delete om;
return nullptr; return nullptr;
} }
...@@ -141,13 +135,11 @@ oss_mixer_close(Mixer *data) ...@@ -141,13 +135,11 @@ oss_mixer_close(Mixer *data)
} }
inline bool inline bool
OssMixer::Open(GError **error_r) OssMixer::Open(Error &error)
{ {
device_fd = open_cloexec(device, O_RDONLY, 0); device_fd = open_cloexec(device, O_RDONLY, 0);
if (device_fd < 0) { if (device_fd < 0) {
g_set_error(error_r, oss_mixer_quark(), errno, error.FormatErrno("failed to open %s", device);
"failed to open %s: %s",
device, g_strerror(errno));
return false; return false;
} }
...@@ -155,15 +147,13 @@ OssMixer::Open(GError **error_r) ...@@ -155,15 +147,13 @@ OssMixer::Open(GError **error_r)
int devmask = 0; int devmask = 0;
if (ioctl(device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { if (ioctl(device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) {
g_set_error(error_r, oss_mixer_quark(), errno, error.SetErrno("READ_DEVMASK failed");
"READ_DEVMASK failed: %s",
g_strerror(errno));
Close(); Close();
return false; return false;
} }
if (((1 << volume_control) & devmask) == 0) { if (((1 << volume_control) & devmask) == 0) {
g_set_error(error_r, oss_mixer_quark(), 0, error.Format(oss_mixer_domain, 0,
"mixer control \"%s\" not usable", "mixer control \"%s\" not usable",
control); control);
Close(); Close();
...@@ -175,15 +165,15 @@ OssMixer::Open(GError **error_r) ...@@ -175,15 +165,15 @@ OssMixer::Open(GError **error_r)
} }
static bool static bool
oss_mixer_open(Mixer *data, GError **error_r) oss_mixer_open(Mixer *data, Error &error)
{ {
OssMixer *om = (OssMixer *) data; OssMixer *om = (OssMixer *) data;
return om->Open(error_r); return om->Open(error);
} }
inline int inline int
OssMixer::GetVolume(GError **error_r) OssMixer::GetVolume(Error &error)
{ {
int left, right, level; int left, right, level;
int ret; int ret;
...@@ -192,9 +182,7 @@ OssMixer::GetVolume(GError **error_r) ...@@ -192,9 +182,7 @@ OssMixer::GetVolume(GError **error_r)
ret = ioctl(device_fd, MIXER_READ(volume_control), &level); ret = ioctl(device_fd, MIXER_READ(volume_control), &level);
if (ret < 0) { if (ret < 0) {
g_set_error(error_r, oss_mixer_quark(), errno, error.SetErrno("failed to read OSS volume");
"failed to read OSS volume: %s",
g_strerror(errno));
return false; return false;
} }
...@@ -210,14 +198,14 @@ OssMixer::GetVolume(GError **error_r) ...@@ -210,14 +198,14 @@ OssMixer::GetVolume(GError **error_r)
} }
static int static int
oss_mixer_get_volume(Mixer *mixer, GError **error_r) oss_mixer_get_volume(Mixer *mixer, Error &error)
{ {
OssMixer *om = (OssMixer *)mixer; OssMixer *om = (OssMixer *)mixer;
return om->GetVolume(error_r); return om->GetVolume(error);
} }
inline bool inline bool
OssMixer::SetVolume(unsigned volume, GError **error_r) OssMixer::SetVolume(unsigned volume, Error &error)
{ {
int level; int level;
int ret; int ret;
...@@ -229,9 +217,7 @@ OssMixer::SetVolume(unsigned volume, GError **error_r) ...@@ -229,9 +217,7 @@ OssMixer::SetVolume(unsigned volume, GError **error_r)
ret = ioctl(device_fd, MIXER_WRITE(volume_control), &level); ret = ioctl(device_fd, MIXER_WRITE(volume_control), &level);
if (ret < 0) { if (ret < 0) {
g_set_error(error_r, oss_mixer_quark(), errno, error.SetErrno("failed to set OSS volume");
"failed to set OSS volume: %s",
g_strerror(errno));
return false; return false;
} }
...@@ -239,10 +225,10 @@ OssMixer::SetVolume(unsigned volume, GError **error_r) ...@@ -239,10 +225,10 @@ OssMixer::SetVolume(unsigned volume, GError **error_r)
} }
static bool static bool
oss_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) oss_mixer_set_volume(Mixer *mixer, unsigned volume, Error &error)
{ {
OssMixer *om = (OssMixer *)mixer; OssMixer *om = (OssMixer *)mixer;
return om->SetVolume(volume, error_r); return om->SetVolume(volume, error);
} }
const struct mixer_plugin oss_mixer_plugin = { const struct mixer_plugin oss_mixer_plugin = {
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "output/PulseOutputPlugin.hxx" #include "output/PulseOutputPlugin.hxx"
#include "conf.h" #include "conf.h"
#include "GlobalEvents.hxx" #include "GlobalEvents.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -52,14 +54,7 @@ struct PulseMixer final : public Mixer { ...@@ -52,14 +54,7 @@ struct PulseMixer final : public Mixer {
} }
}; };
/** static constexpr Domain pulse_mixer_domain("pulse_mixer");
* The quark used for GError.domain.
*/
static inline GQuark
pulse_mixer_quark(void)
{
return g_quark_from_static_string("pulse_mixer");
}
static void static void
pulse_mixer_offline(PulseMixer *pm) pulse_mixer_offline(PulseMixer *pm)
...@@ -154,12 +149,12 @@ pulse_mixer_on_change(PulseMixer *pm, ...@@ -154,12 +149,12 @@ pulse_mixer_on_change(PulseMixer *pm,
static Mixer * static Mixer *
pulse_mixer_init(void *ao, gcc_unused const config_param &param, pulse_mixer_init(void *ao, gcc_unused const config_param &param,
GError **error_r) Error &error)
{ {
PulseOutput *po = (PulseOutput *)ao; PulseOutput *po = (PulseOutput *)ao;
if (ao == NULL) { if (ao == NULL) {
g_set_error(error_r, pulse_mixer_quark(), 0, error.Set(pulse_mixer_domain,
"The pulse mixer cannot work without the audio output"); "The pulse mixer cannot work without the audio output");
return nullptr; return nullptr;
} }
...@@ -182,7 +177,7 @@ pulse_mixer_finish(Mixer *data) ...@@ -182,7 +177,7 @@ pulse_mixer_finish(Mixer *data)
} }
static int static int
pulse_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) pulse_mixer_get_volume(Mixer *mixer, gcc_unused Error &error)
{ {
PulseMixer *pm = (PulseMixer *) mixer; PulseMixer *pm = (PulseMixer *) mixer;
int ret; int ret;
...@@ -199,7 +194,7 @@ pulse_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) ...@@ -199,7 +194,7 @@ pulse_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r)
} }
static bool static bool
pulse_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) pulse_mixer_set_volume(Mixer *mixer, unsigned volume, Error &error)
{ {
PulseMixer *pm = (PulseMixer *) mixer; PulseMixer *pm = (PulseMixer *) mixer;
struct pa_cvolume cvolume; struct pa_cvolume cvolume;
...@@ -209,13 +204,13 @@ pulse_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) ...@@ -209,13 +204,13 @@ pulse_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r)
if (!pm->online) { if (!pm->online) {
pulse_output_unlock(pm->output); pulse_output_unlock(pm->output);
g_set_error(error_r, pulse_mixer_quark(), 0, "disconnected"); error.Set(pulse_mixer_domain, "disconnected");
return false; return false;
} }
pa_cvolume_set(&cvolume, pm->volume.channels, pa_cvolume_set(&cvolume, pm->volume.channels,
(pa_volume_t)volume * PA_VOLUME_NORM / 100 + 0.5); (pa_volume_t)volume * PA_VOLUME_NORM / 100 + 0.5);
success = pulse_output_set_volume(pm->output, &cvolume, error_r); success = pulse_output_set_volume(pm->output, &cvolume, error);
if (success) if (success)
pm->volume = cvolume; pm->volume = cvolume;
......
...@@ -35,7 +35,7 @@ struct RoarMixer final : public Mixer { ...@@ -35,7 +35,7 @@ struct RoarMixer final : public Mixer {
static Mixer * static Mixer *
roar_mixer_init(void *ao, gcc_unused const config_param &param, roar_mixer_init(void *ao, gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return new RoarMixer((RoarOutput *)ao); return new RoarMixer((RoarOutput *)ao);
} }
...@@ -49,7 +49,7 @@ roar_mixer_finish(Mixer *data) ...@@ -49,7 +49,7 @@ roar_mixer_finish(Mixer *data)
} }
static int static int
roar_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) roar_mixer_get_volume(Mixer *mixer, gcc_unused Error &error)
{ {
RoarMixer *self = (RoarMixer *)mixer; RoarMixer *self = (RoarMixer *)mixer;
return roar_output_get_volume(self->self); return roar_output_get_volume(self->self);
...@@ -57,7 +57,7 @@ roar_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) ...@@ -57,7 +57,7 @@ roar_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r)
static bool static bool
roar_mixer_set_volume(Mixer *mixer, unsigned volume, roar_mixer_set_volume(Mixer *mixer, unsigned volume,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
RoarMixer *self = (RoarMixer *)mixer; RoarMixer *self = (RoarMixer *)mixer;
return roar_output_set_volume(self->self, volume); return roar_output_set_volume(self->self, volume);
......
...@@ -26,10 +26,18 @@ ...@@ -26,10 +26,18 @@
#include "filter/VolumeFilterPlugin.hxx" #include "filter/VolumeFilterPlugin.hxx"
#include "pcm/PcmVolume.hxx" #include "pcm/PcmVolume.hxx"
#include "ConfigData.hxx" #include "ConfigData.hxx"
#include "util/Error.hxx"
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
static Filter *
CreateVolumeFilter()
{
Error error;
return filter_new(&volume_filter_plugin, config_param(), error);
}
struct SoftwareMixer final : public Mixer { struct SoftwareMixer final : public Mixer {
Filter *filter; Filter *filter;
...@@ -37,8 +45,7 @@ struct SoftwareMixer final : public Mixer { ...@@ -37,8 +45,7 @@ struct SoftwareMixer final : public Mixer {
SoftwareMixer() SoftwareMixer()
:Mixer(software_mixer_plugin), :Mixer(software_mixer_plugin),
filter(filter_new(&volume_filter_plugin, config_param(), filter(CreateVolumeFilter()),
nullptr)),
volume(100) volume(100)
{ {
assert(filter != nullptr); assert(filter != nullptr);
...@@ -52,7 +59,7 @@ struct SoftwareMixer final : public Mixer { ...@@ -52,7 +59,7 @@ struct SoftwareMixer final : public Mixer {
static Mixer * static Mixer *
software_mixer_init(gcc_unused void *ao, software_mixer_init(gcc_unused void *ao,
gcc_unused const config_param &param, gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return new SoftwareMixer(); return new SoftwareMixer();
} }
...@@ -66,7 +73,7 @@ software_mixer_finish(Mixer *data) ...@@ -66,7 +73,7 @@ software_mixer_finish(Mixer *data)
} }
static int static int
software_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) software_mixer_get_volume(Mixer *mixer, gcc_unused Error &error)
{ {
SoftwareMixer *sm = (SoftwareMixer *)mixer; SoftwareMixer *sm = (SoftwareMixer *)mixer;
...@@ -75,7 +82,7 @@ software_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r) ...@@ -75,7 +82,7 @@ software_mixer_get_volume(Mixer *mixer, gcc_unused GError **error_r)
static bool static bool
software_mixer_set_volume(Mixer *mixer, unsigned volume, software_mixer_set_volume(Mixer *mixer, unsigned volume,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
SoftwareMixer *sm = (SoftwareMixer *)mixer; SoftwareMixer *sm = (SoftwareMixer *)mixer;
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "MixerInternal.hxx" #include "MixerInternal.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "output/WinmmOutputPlugin.hxx" #include "output/WinmmOutputPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <mmsystem.h> #include <mmsystem.h>
...@@ -40,11 +42,7 @@ struct WinmmMixer final : public Mixer { ...@@ -40,11 +42,7 @@ struct WinmmMixer final : public Mixer {
} }
}; };
static inline GQuark static constexpr Domain winmm_mixer_domain("winmm_mixer");
winmm_mixer_quark(void)
{
return g_quark_from_static_string("winmm_mixer");
}
static inline int static inline int
winmm_volume_decode(DWORD volume) winmm_volume_decode(DWORD volume)
...@@ -61,7 +59,7 @@ winmm_volume_encode(int volume) ...@@ -61,7 +59,7 @@ winmm_volume_encode(int volume)
static Mixer * static Mixer *
winmm_mixer_init(void *ao, gcc_unused const config_param &param, winmm_mixer_init(void *ao, gcc_unused const config_param &param,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
assert(ao != nullptr); assert(ao != nullptr);
...@@ -77,7 +75,7 @@ winmm_mixer_finish(Mixer *data) ...@@ -77,7 +75,7 @@ winmm_mixer_finish(Mixer *data)
} }
static int static int
winmm_mixer_get_volume(Mixer *mixer, GError **error_r) winmm_mixer_get_volume(Mixer *mixer, Error &error)
{ {
WinmmMixer *wm = (WinmmMixer *) mixer; WinmmMixer *wm = (WinmmMixer *) mixer;
DWORD volume; DWORD volume;
...@@ -85,8 +83,7 @@ winmm_mixer_get_volume(Mixer *mixer, GError **error_r) ...@@ -85,8 +83,7 @@ winmm_mixer_get_volume(Mixer *mixer, GError **error_r)
MMRESULT result = waveOutGetVolume(handle, &volume); MMRESULT result = waveOutGetVolume(handle, &volume);
if (result != MMSYSERR_NOERROR) { if (result != MMSYSERR_NOERROR) {
g_set_error(error_r, 0, winmm_mixer_quark(), error.Set(winmm_mixer_domain, "Failed to get winmm volume");
"Failed to get winmm volume");
return -1; return -1;
} }
...@@ -94,7 +91,7 @@ winmm_mixer_get_volume(Mixer *mixer, GError **error_r) ...@@ -94,7 +91,7 @@ winmm_mixer_get_volume(Mixer *mixer, GError **error_r)
} }
static bool static bool
winmm_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) winmm_mixer_set_volume(Mixer *mixer, unsigned volume, Error &error)
{ {
WinmmMixer *wm = (WinmmMixer *) mixer; WinmmMixer *wm = (WinmmMixer *) mixer;
DWORD value = winmm_volume_encode(volume); DWORD value = winmm_volume_encode(volume);
...@@ -102,8 +99,7 @@ winmm_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r) ...@@ -102,8 +99,7 @@ winmm_mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r)
MMRESULT result = waveOutSetVolume(handle, value); MMRESULT result = waveOutSetVolume(handle, value);
if (result != MMSYSERR_NOERROR) { if (result != MMSYSERR_NOERROR) {
g_set_error(error_r, 0, winmm_mixer_quark(), error.Set(winmm_mixer_domain, "Failed to set winmm volume");
"Failed to set winmm volume");
return false; return false;
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <stdlib.h> #include <stdlib.h>
/* This macro is used as an intermediate step to a proper error handling /* This macro is used as an intermediate step to a proper error handling
* using GError in mpd. It is used for unrecoverable error conditions * using #Error in mpd. It is used for unrecoverable error conditions
* and exits immediately. The long-term goal is to replace this macro by * and exits immediately. The long-term goal is to replace this macro by
* proper error handling. */ * proper error handling. */
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "MixerList.hxx" #include "MixerList.hxx"
#include "pcm/PcmExport.hxx" #include "pcm/PcmExport.hxx"
#include "util/Manual.hxx" #include "util/Manual.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
...@@ -115,9 +117,9 @@ struct AlsaOutput { ...@@ -115,9 +117,9 @@ struct AlsaOutput {
AlsaOutput():mode(0), writei(snd_pcm_writei) { AlsaOutput():mode(0), writei(snd_pcm_writei) {
} }
bool Init(const config_param &param, GError **error_r) { bool Init(const config_param &param, Error &error) {
return ao_base_init(&base, &alsa_output_plugin, return ao_base_init(&base, &alsa_output_plugin,
param, error_r); param, error);
} }
void Deinit() { void Deinit() {
...@@ -125,14 +127,7 @@ struct AlsaOutput { ...@@ -125,14 +127,7 @@ struct AlsaOutput {
} }
}; };
/** static constexpr Domain alsa_output_domain("alsa_output");
* The quark used for GError.domain.
*/
static inline GQuark
alsa_output_quark(void)
{
return g_quark_from_static_string("alsa_output");
}
static const char * static const char *
alsa_device(const AlsaOutput *ad) alsa_device(const AlsaOutput *ad)
...@@ -170,11 +165,11 @@ alsa_configure(AlsaOutput *ad, const config_param &param) ...@@ -170,11 +165,11 @@ alsa_configure(AlsaOutput *ad, const config_param &param)
} }
static struct audio_output * static struct audio_output *
alsa_init(const config_param &param, GError **error_r) alsa_init(const config_param &param, Error &error)
{ {
AlsaOutput *ad = new AlsaOutput(); AlsaOutput *ad = new AlsaOutput();
if (!ad->Init(param, error_r)) { if (!ad->Init(param, error)) {
delete ad; delete ad;
return NULL; return NULL;
} }
...@@ -197,7 +192,7 @@ alsa_finish(struct audio_output *ao) ...@@ -197,7 +192,7 @@ alsa_finish(struct audio_output *ao)
} }
static bool static bool
alsa_output_enable(struct audio_output *ao, gcc_unused GError **error_r) alsa_output_enable(struct audio_output *ao, gcc_unused Error &error)
{ {
AlsaOutput *ad = (AlsaOutput *)ao; AlsaOutput *ad = (AlsaOutput *)ao;
...@@ -394,7 +389,7 @@ alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, ...@@ -394,7 +389,7 @@ alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
*/ */
static bool static bool
alsa_setup(AlsaOutput *ad, AudioFormat &audio_format, alsa_setup(AlsaOutput *ad, AudioFormat &audio_format,
bool *packed_r, bool *reverse_endian_r, GError **error) bool *packed_r, bool *reverse_endian_r, Error &error)
{ {
unsigned int sample_rate = audio_format.sample_rate; unsigned int sample_rate = audio_format.sample_rate;
unsigned int channels = audio_format.channels; unsigned int channels = audio_format.channels;
...@@ -438,7 +433,7 @@ configure_hw: ...@@ -438,7 +433,7 @@ configure_hw:
err = alsa_output_setup_format(ad->pcm, hwparams, audio_format, err = alsa_output_setup_format(ad->pcm, hwparams, audio_format,
packed_r, reverse_endian_r); packed_r, reverse_endian_r);
if (err < 0) { if (err < 0) {
g_set_error(error, alsa_output_quark(), err, error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support format %s: %s", "ALSA device \"%s\" does not support format %s: %s",
alsa_device(ad), alsa_device(ad),
sample_format_to_string(audio_format.format), sample_format_to_string(audio_format.format),
...@@ -454,7 +449,7 @@ configure_hw: ...@@ -454,7 +449,7 @@ configure_hw:
err = snd_pcm_hw_params_set_channels_near(ad->pcm, hwparams, err = snd_pcm_hw_params_set_channels_near(ad->pcm, hwparams,
&channels); &channels);
if (err < 0) { if (err < 0) {
g_set_error(error, alsa_output_quark(), err, error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support %i channels: %s", "ALSA device \"%s\" does not support %i channels: %s",
alsa_device(ad), (int)audio_format.channels, alsa_device(ad), (int)audio_format.channels,
snd_strerror(-err)); snd_strerror(-err));
...@@ -465,7 +460,7 @@ configure_hw: ...@@ -465,7 +460,7 @@ configure_hw:
err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams, err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams,
&sample_rate, NULL); &sample_rate, NULL);
if (err < 0 || sample_rate == 0) { if (err < 0 || sample_rate == 0) {
g_set_error(error, alsa_output_quark(), err, error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support %u Hz audio", "ALSA device \"%s\" does not support %u Hz audio",
alsa_device(ad), audio_format.sample_rate); alsa_device(ad), audio_format.sample_rate);
return false; return false;
...@@ -594,7 +589,7 @@ configure_hw: ...@@ -594,7 +589,7 @@ configure_hw:
return true; return true;
error: error:
g_set_error(error, alsa_output_quark(), err, error.Format(alsa_output_domain, err,
"Error opening ALSA device \"%s\" (%s): %s", "Error opening ALSA device \"%s\" (%s): %s",
alsa_device(ad), cmd, snd_strerror(-err)); alsa_device(ad), cmd, snd_strerror(-err));
return false; return false;
...@@ -603,7 +598,7 @@ error: ...@@ -603,7 +598,7 @@ error:
static bool static bool
alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
bool *shift8_r, bool *packed_r, bool *reverse_endian_r, bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
GError **error_r) Error &error)
{ {
assert(ad->dsd_usb); assert(ad->dsd_usb);
assert(audio_format.format == SampleFormat::DSD); assert(audio_format.format == SampleFormat::DSD);
...@@ -616,7 +611,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, ...@@ -616,7 +611,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
const AudioFormat check = usb_format; const AudioFormat check = usb_format;
if (!alsa_setup(ad, usb_format, packed_r, reverse_endian_r, error_r)) if (!alsa_setup(ad, usb_format, packed_r, reverse_endian_r, error))
return false; return false;
/* if the device allows only 32 bit, shift all DSD-over-USB /* if the device allows only 32 bit, shift all DSD-over-USB
...@@ -631,7 +626,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, ...@@ -631,7 +626,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
if (usb_format != check) { if (usb_format != check) {
/* no bit-perfect playback, which is required /* no bit-perfect playback, which is required
for DSD over USB */ for DSD over USB */
g_set_error(error_r, alsa_output_quark(), 0, error.Format(alsa_output_domain,
"Failed to configure DSD-over-USB on ALSA device \"%s\"", "Failed to configure DSD-over-USB on ALSA device \"%s\"",
alsa_device(ad)); alsa_device(ad));
g_free(ad->silence); g_free(ad->silence);
...@@ -643,7 +638,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, ...@@ -643,7 +638,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
static bool static bool
alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format, alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format,
GError **error_r) Error &error)
{ {
bool shift8 = false, packed, reverse_endian; bool shift8 = false, packed, reverse_endian;
...@@ -652,9 +647,9 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format, ...@@ -652,9 +647,9 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format,
const bool success = dsd_usb const bool success = dsd_usb
? alsa_setup_dsd(ad, audio_format, ? alsa_setup_dsd(ad, audio_format,
&shift8, &packed, &reverse_endian, &shift8, &packed, &reverse_endian,
error_r) error)
: alsa_setup(ad, audio_format, &packed, &reverse_endian, : alsa_setup(ad, audio_format, &packed, &reverse_endian,
error_r); error);
if (!success) if (!success)
return false; return false;
...@@ -665,14 +660,14 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format, ...@@ -665,14 +660,14 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format,
} }
static bool static bool
alsa_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) alsa_open(struct audio_output *ao, AudioFormat &audio_format, Error &error)
{ {
AlsaOutput *ad = (AlsaOutput *)ao; AlsaOutput *ad = (AlsaOutput *)ao;
int err = snd_pcm_open(&ad->pcm, alsa_device(ad), int err = snd_pcm_open(&ad->pcm, alsa_device(ad),
SND_PCM_STREAM_PLAYBACK, ad->mode); SND_PCM_STREAM_PLAYBACK, ad->mode);
if (err < 0) { if (err < 0) {
g_set_error(error, alsa_output_quark(), err, error.Format(alsa_output_domain, err,
"Failed to open ALSA device \"%s\": %s", "Failed to open ALSA device \"%s\": %s",
alsa_device(ad), snd_strerror(err)); alsa_device(ad), snd_strerror(err));
return false; return false;
...@@ -800,7 +795,7 @@ alsa_close(struct audio_output *ao) ...@@ -800,7 +795,7 @@ alsa_close(struct audio_output *ao)
static size_t static size_t
alsa_play(struct audio_output *ao, const void *chunk, size_t size, alsa_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error) Error &error)
{ {
AlsaOutput *ad = (AlsaOutput *)ao; AlsaOutput *ad = (AlsaOutput *)ao;
...@@ -824,8 +819,7 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -824,8 +819,7 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
if (ret < 0 && ret != -EAGAIN && ret != -EINTR && if (ret < 0 && ret != -EAGAIN && ret != -EINTR &&
alsa_recover(ad, ret) < 0) { alsa_recover(ad, ret) < 0) {
g_set_error(error, alsa_output_quark(), errno, error.Set(alsa_output_domain, ret, snd_strerror(-ret));
"%s", snd_strerror(-errno));
return 0; return 0;
} }
} }
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "config.h" #include "config.h"
#include "AoOutputPlugin.hxx" #include "AoOutputPlugin.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <ao/ao.h> #include <ao/ao.h>
#include <glib.h> #include <glib.h>
...@@ -42,26 +44,22 @@ struct AoOutput { ...@@ -42,26 +44,22 @@ struct AoOutput {
ao_option *options; ao_option *options;
ao_device *device; ao_device *device;
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &ao_output_plugin, param, return ao_base_init(&base, &ao_output_plugin, param,
error_r); error);
} }
void Deinitialize() { void Deinitialize() {
ao_base_finish(&base); ao_base_finish(&base);
} }
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
}; };
static inline GQuark static constexpr Domain ao_output_domain("ao_output");
ao_output_quark(void)
{
return g_quark_from_static_string("ao_output");
}
static void static void
ao_output_error(GError **error_r) ao_output_error(Error &error_r)
{ {
const char *error; const char *error;
...@@ -87,15 +85,15 @@ ao_output_error(GError **error_r) ...@@ -87,15 +85,15 @@ ao_output_error(GError **error_r)
break; break;
default: default:
error = g_strerror(errno); error_r.SetErrno();
return;
} }
g_set_error(error_r, ao_output_quark(), errno, error_r.Set(ao_output_domain, errno, error);
"%s", error);
} }
inline bool inline bool
AoOutput::Configure(const config_param &param, GError **error_r) AoOutput::Configure(const config_param &param, Error &error)
{ {
const char *value; const char *value;
...@@ -115,7 +113,7 @@ AoOutput::Configure(const config_param &param, GError **error_r) ...@@ -115,7 +113,7 @@ AoOutput::Configure(const config_param &param, GError **error_r)
driver = ao_driver_id(value); driver = ao_driver_id(value);
if (driver < 0) { if (driver < 0) {
g_set_error(error_r, ao_output_quark(), 0, error.Format(ao_output_domain,
"\"%s\" is not a valid ao driver", "\"%s\" is not a valid ao driver",
value); value);
return false; return false;
...@@ -123,8 +121,7 @@ AoOutput::Configure(const config_param &param, GError **error_r) ...@@ -123,8 +121,7 @@ AoOutput::Configure(const config_param &param, GError **error_r)
ao_info *ai = ao_driver_info(driver); ao_info *ai = ao_driver_info(driver);
if (ai == nullptr) { if (ai == nullptr) {
g_set_error(error_r, ao_output_quark(), 0, error.Set(ao_output_domain, "problems getting driver info");
"problems getting driver info");
return false; return false;
} }
...@@ -139,7 +136,7 @@ AoOutput::Configure(const config_param &param, GError **error_r) ...@@ -139,7 +136,7 @@ AoOutput::Configure(const config_param &param, GError **error_r)
gchar **key_value = g_strsplit(_options[i], "=", 2); gchar **key_value = g_strsplit(_options[i], "=", 2);
if (key_value[0] == nullptr || key_value[1] == nullptr) { if (key_value[0] == nullptr || key_value[1] == nullptr) {
g_set_error(error_r, ao_output_quark(), 0, error.Format(ao_output_domain,
"problems parsing options \"%s\"", "problems parsing options \"%s\"",
_options[i]); _options[i]);
return false; return false;
...@@ -158,16 +155,16 @@ AoOutput::Configure(const config_param &param, GError **error_r) ...@@ -158,16 +155,16 @@ AoOutput::Configure(const config_param &param, GError **error_r)
} }
static struct audio_output * static struct audio_output *
ao_output_init(const config_param &param, GError **error_r) ao_output_init(const config_param &param, Error &error)
{ {
AoOutput *ad = new AoOutput(); AoOutput *ad = new AoOutput();
if (!ad->Initialize(param, error_r)) { if (!ad->Initialize(param, error)) {
delete ad; delete ad;
return nullptr; return nullptr;
} }
if (!ad->Configure(param, error_r)) { if (!ad->Configure(param, error)) {
ad->Deinitialize(); ad->Deinitialize();
delete ad; delete ad;
return nullptr; return nullptr;
...@@ -201,7 +198,7 @@ ao_output_close(struct audio_output *ao) ...@@ -201,7 +198,7 @@ ao_output_close(struct audio_output *ao)
static bool static bool
ao_output_open(struct audio_output *ao, AudioFormat &audio_format, ao_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) Error &error)
{ {
ao_sample_format format = OUR_AO_FORMAT_INITIALIZER; ao_sample_format format = OUR_AO_FORMAT_INITIALIZER;
AoOutput *ad = (AoOutput *)ao; AoOutput *ad = (AoOutput *)ao;
...@@ -257,7 +254,7 @@ static int ao_play_deconst(ao_device *device, const void *output_samples, ...@@ -257,7 +254,7 @@ static int ao_play_deconst(ao_device *device, const void *output_samples,
static size_t static size_t
ao_output_play(struct audio_output *ao, const void *chunk, size_t size, ao_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error) Error &error)
{ {
AoOutput *ad = (AoOutput *)ao; AoOutput *ad = (AoOutput *)ao;
......
...@@ -19,11 +19,14 @@ ...@@ -19,11 +19,14 @@
#include "config.h" #include "config.h"
#include "FifoOutputPlugin.hxx" #include "FifoOutputPlugin.hxx"
#include "ConfigError.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "Timer.hxx" #include "Timer.hxx"
#include "system/fd_util.h" #include "system/fd_util.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 "open.h" #include "open.h"
#include <glib.h> #include <glib.h>
...@@ -53,31 +56,24 @@ struct FifoOutput { ...@@ -53,31 +56,24 @@ struct FifoOutput {
FifoOutput() FifoOutput()
:path(Path::Null()), input(-1), output(-1), created(false) {} :path(Path::Null()), input(-1), output(-1), created(false) {}
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &fifo_output_plugin, param, return ao_base_init(&base, &fifo_output_plugin, param,
error_r); error);
} }
void Deinitialize() { void Deinitialize() {
ao_base_finish(&base); ao_base_finish(&base);
} }
bool Create(GError **error_r); bool Create(Error &error);
bool Check(GError **error_r); bool Check(Error &error);
void Delete(); void Delete();
bool Open(GError **error_r); bool Open(Error &error);
void Close(); void Close();
}; };
/** static constexpr Domain fifo_output_domain("fifo_output");
* The quark used for GError.domain.
*/
static inline GQuark
fifo_output_quark(void)
{
return g_quark_from_static_string("fifo_output");
}
inline void inline void
FifoOutput::Delete() FifoOutput::Delete()
...@@ -112,12 +108,11 @@ FifoOutput::Close() ...@@ -112,12 +108,11 @@ FifoOutput::Close()
} }
inline bool inline bool
FifoOutput::Create(GError **error_r) FifoOutput::Create(Error &error)
{ {
if (!MakeFifo(path, 0666)) { if (!MakeFifo(path, 0666)) {
g_set_error(error_r, fifo_output_quark(), errno, error.FormatErrno("Couldn't create FIFO \"%s\"",
"Couldn't create FIFO \"%s\": %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
...@@ -126,23 +121,22 @@ FifoOutput::Create(GError **error_r) ...@@ -126,23 +121,22 @@ FifoOutput::Create(GError **error_r)
} }
inline bool inline bool
FifoOutput::Check(GError **error_r) FifoOutput::Check(Error &error)
{ {
struct stat st; struct stat st;
if (!StatFile(path, st)) { if (!StatFile(path, st)) {
if (errno == ENOENT) { if (errno == ENOENT) {
/* Path doesn't exist */ /* Path doesn't exist */
return Create(error_r); return Create(error);
} }
g_set_error(error_r, fifo_output_quark(), errno, error.FormatErrno("Failed to stat FIFO \"%s\"",
"Failed to stat FIFO \"%s\": %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
if (!S_ISFIFO(st.st_mode)) { if (!S_ISFIFO(st.st_mode)) {
g_set_error(error_r, fifo_output_quark(), 0, error.Format(fifo_output_domain,
"\"%s\" already exists, but is not a FIFO", "\"%s\" already exists, but is not a FIFO",
path_utf8.c_str()); path_utf8.c_str());
return false; return false;
...@@ -152,25 +146,23 @@ FifoOutput::Check(GError **error_r) ...@@ -152,25 +146,23 @@ FifoOutput::Check(GError **error_r)
} }
inline bool inline bool
FifoOutput::Open(GError **error_r) FifoOutput::Open(Error &error)
{ {
if (!Check(error_r)) if (!Check(error))
return false; return false;
input = OpenFile(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0); input = OpenFile(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0);
if (input < 0) { if (input < 0) {
g_set_error(error_r, fifo_output_quark(), errno, error.FormatErrno("Could not open FIFO \"%s\" for reading",
"Could not open FIFO \"%s\" for reading: %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
Close(); Close();
return false; return false;
} }
output = OpenFile(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0); output = OpenFile(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0);
if (output < 0) { if (output < 0) {
g_set_error(error_r, fifo_output_quark(), errno, error.FormatErrno("Could not open FIFO \"%s\" for writing",
"Could not open FIFO \"%s\" for writing: %s", path_utf8.c_str());
path_utf8.c_str(), g_strerror(errno));
Close(); Close();
return false; return false;
} }
...@@ -179,37 +171,34 @@ FifoOutput::Open(GError **error_r) ...@@ -179,37 +171,34 @@ FifoOutput::Open(GError **error_r)
} }
static bool static bool
fifo_open(FifoOutput *fd, GError **error_r) fifo_open(FifoOutput *fd, Error &error)
{ {
return fd->Open(error_r); return fd->Open(error);
} }
static struct audio_output * static struct audio_output *
fifo_output_init(const config_param &param, GError **error_r) fifo_output_init(const config_param &param, Error &error)
{ {
GError *error = nullptr;
FifoOutput *fd = new FifoOutput(); FifoOutput *fd = new FifoOutput();
fd->path = param.GetBlockPath("path", &error); fd->path = param.GetBlockPath("path", error);
if (fd->path.IsNull()) { if (fd->path.IsNull()) {
delete fd; delete fd;
if (error != nullptr)
g_propagate_error(error_r, error); if (!error.IsDefined())
else error.Set(config_domain,
g_set_error(error_r, fifo_output_quark(), 0,
"No \"path\" parameter specified"); "No \"path\" parameter specified");
return nullptr; return nullptr;
} }
fd->path_utf8 = fd->path.ToUTF8(); fd->path_utf8 = fd->path.ToUTF8();
if (!fd->Initialize(param, error_r)) { if (!fd->Initialize(param, error)) {
delete fd; delete fd;
return nullptr; return nullptr;
} }
if (!fifo_open(fd, error_r)) { if (!fifo_open(fd, error)) {
fd->Deinitialize(); fd->Deinitialize();
delete fd; delete fd;
return nullptr; return nullptr;
...@@ -230,7 +219,7 @@ fifo_output_finish(struct audio_output *ao) ...@@ -230,7 +219,7 @@ fifo_output_finish(struct audio_output *ao)
static bool static bool
fifo_output_open(struct audio_output *ao, AudioFormat &audio_format, fifo_output_open(struct audio_output *ao, AudioFormat &audio_format,
gcc_unused GError **error) gcc_unused Error &error)
{ {
FifoOutput *fd = (FifoOutput *)ao; FifoOutput *fd = (FifoOutput *)ao;
...@@ -277,7 +266,7 @@ fifo_output_delay(struct audio_output *ao) ...@@ -277,7 +266,7 @@ fifo_output_delay(struct audio_output *ao)
static size_t static size_t
fifo_output_play(struct audio_output *ao, const void *chunk, size_t size, fifo_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error) Error &error)
{ {
FifoOutput *fd = (FifoOutput *)ao; FifoOutput *fd = (FifoOutput *)ao;
ssize_t bytes; ssize_t bytes;
...@@ -301,9 +290,8 @@ fifo_output_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -301,9 +290,8 @@ fifo_output_play(struct audio_output *ao, const void *chunk, size_t size,
continue; continue;
} }
g_set_error(error, fifo_output_quark(), errno, error.FormatErrno("Failed to write to FIFO %s",
"Failed to write to FIFO %s: %s", fd->path_utf8.c_str());
fd->path_utf8.c_str(), g_strerror(errno));
return 0; return 0;
} }
} }
......
...@@ -431,10 +431,9 @@ HttpdClient::OnSocketInput(const void *data, size_t length) ...@@ -431,10 +431,9 @@ HttpdClient::OnSocketInput(const void *data, size_t length)
} }
void void
HttpdClient::OnSocketError(GError *error) HttpdClient::OnSocketError(Error &&error)
{ {
g_warning("error on HTTP client: %s", error->message); g_warning("error on HTTP client: %s", error.GetMessage());
g_error_free(error);
} }
void void
......
...@@ -179,7 +179,7 @@ protected: ...@@ -179,7 +179,7 @@ protected:
virtual bool OnSocketReady(unsigned flags) override; virtual bool OnSocketReady(unsigned flags) override;
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;
}; };
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <forward_list> #include <forward_list>
struct config_param; struct config_param;
class Error;
class EventLoop; class EventLoop;
class ServerSocket; class ServerSocket;
class HttpdClient; class HttpdClient;
...@@ -123,21 +124,20 @@ struct HttpdOutput final : private ServerSocket { ...@@ -123,21 +124,20 @@ struct HttpdOutput final : private ServerSocket {
HttpdOutput(EventLoop &_loop); HttpdOutput(EventLoop &_loop);
~HttpdOutput(); ~HttpdOutput();
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
bool Bind(GError **error_r); bool Bind(Error &error);
void Unbind(); void Unbind();
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.
*/ */
bool OpenEncoder(AudioFormat &audio_format, bool OpenEncoder(AudioFormat &audio_format, Error &error);
GError **error_r);
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.
*/ */
bool Open(AudioFormat &audio_format, GError **error_r); bool Open(AudioFormat &audio_format, Error &error);
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.
...@@ -194,7 +194,7 @@ struct HttpdOutput final : private ServerSocket { ...@@ -194,7 +194,7 @@ struct HttpdOutput final : private ServerSocket {
*/ */
void BroadcastFromEncoder(); void BroadcastFromEncoder();
bool EncodeAndPlay(const void *chunk, size_t size, GError **error_r); bool EncodeAndPlay(const void *chunk, size_t size, Error &error);
void SendTag(const Tag *tag); void SendTag(const Tag *tag);
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include "IcyMetaDataServer.hxx" #include "IcyMetaDataServer.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "Main.hxx" #include "Main.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h> #include <assert.h>
...@@ -45,14 +47,7 @@ ...@@ -45,14 +47,7 @@
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "httpd_output" #define G_LOG_DOMAIN "httpd_output"
/** static constexpr Domain httpd_output_domain("httpd_output");
* The quark used for GError.domain.
*/
static inline GQuark
httpd_output_quark(void)
{
return g_quark_from_static_string("httpd_output");
}
inline inline
HttpdOutput::HttpdOutput(EventLoop &_loop) HttpdOutput::HttpdOutput(EventLoop &_loop)
...@@ -73,12 +68,12 @@ HttpdOutput::~HttpdOutput() ...@@ -73,12 +68,12 @@ HttpdOutput::~HttpdOutput()
} }
inline bool inline bool
HttpdOutput::Bind(GError **error_r) HttpdOutput::Bind(Error &error)
{ {
open = false; open = false;
const ScopeLock protect(mutex); const ScopeLock protect(mutex);
return ServerSocket::Open(error_r); return ServerSocket::Open(error);
} }
inline void inline void
...@@ -91,7 +86,7 @@ HttpdOutput::Unbind() ...@@ -91,7 +86,7 @@ HttpdOutput::Unbind()
} }
inline bool inline bool
HttpdOutput::Configure(const config_param &param, GError **error_r) HttpdOutput::Configure(const config_param &param, Error &error)
{ {
/* read configuration */ /* read configuration */
name = param.GetBlockValue("name", "Set name in config"); name = param.GetBlockValue("name", "Set name in config");
...@@ -104,7 +99,7 @@ HttpdOutput::Configure(const config_param &param, GError **error_r) ...@@ -104,7 +99,7 @@ HttpdOutput::Configure(const config_param &param, GError **error_r)
param.GetBlockValue("encoder", "vorbis"); param.GetBlockValue("encoder", "vorbis");
const auto encoder_plugin = encoder_plugin_get(encoder_name); const auto encoder_plugin = encoder_plugin_get(encoder_name);
if (encoder_plugin == NULL) { if (encoder_plugin == NULL) {
g_set_error(error_r, httpd_output_quark(), 0, error.Format(httpd_output_domain,
"No such encoder: %s", encoder_name); "No such encoder: %s", encoder_name);
return false; return false;
} }
...@@ -116,14 +111,14 @@ HttpdOutput::Configure(const config_param &param, GError **error_r) ...@@ -116,14 +111,14 @@ HttpdOutput::Configure(const config_param &param, GError **error_r)
const char *bind_to_address = param.GetBlockValue("bind_to_address"); const char *bind_to_address = param.GetBlockValue("bind_to_address");
bool success = bind_to_address != NULL && bool success = bind_to_address != NULL &&
strcmp(bind_to_address, "any") != 0 strcmp(bind_to_address, "any") != 0
? AddHost(bind_to_address, port, error_r) ? AddHost(bind_to_address, port, error)
: AddPort(port, error_r); : AddPort(port, error);
if (!success) if (!success)
return false; return false;
/* initialize encoder */ /* initialize encoder */
encoder = encoder_init(*encoder_plugin, param, error_r); encoder = encoder_init(*encoder_plugin, param, error);
if (encoder == nullptr) if (encoder == nullptr)
return false; return false;
...@@ -136,18 +131,17 @@ HttpdOutput::Configure(const config_param &param, GError **error_r) ...@@ -136,18 +131,17 @@ HttpdOutput::Configure(const config_param &param, GError **error_r)
} }
static struct audio_output * static struct audio_output *
httpd_output_init(const struct config_param &param, httpd_output_init(const config_param &param, Error &error)
GError **error_r)
{ {
HttpdOutput *httpd = new HttpdOutput(*main_loop); HttpdOutput *httpd = new HttpdOutput(*main_loop);
if (!ao_base_init(&httpd->base, &httpd_output_plugin, param, if (!ao_base_init(&httpd->base, &httpd_output_plugin, param,
error_r)) { error)) {
delete httpd; delete httpd;
return nullptr; return nullptr;
} }
if (!httpd->Configure(param, error_r)) { if (!httpd->Configure(param, error)) {
ao_base_finish(&httpd->base); ao_base_finish(&httpd->base);
delete httpd; delete httpd;
return nullptr; return nullptr;
...@@ -205,7 +199,8 @@ HttpdOutput::OnAccept(int fd, const sockaddr &address, ...@@ -205,7 +199,8 @@ HttpdOutput::OnAccept(int fd, const sockaddr &address,
#ifdef HAVE_LIBWRAP #ifdef HAVE_LIBWRAP
if (address.sa_family != AF_UNIX) { if (address.sa_family != AF_UNIX) {
char *hostaddr = sockaddr_to_string(&address, address_length, NULL); char *hostaddr = sockaddr_to_string(&address, address_length,
IgnoreError());
const char *progname = g_get_prgname(); const char *progname = g_get_prgname();
struct request_info req; struct request_info req;
...@@ -249,7 +244,7 @@ HttpdOutput::ReadPage() ...@@ -249,7 +244,7 @@ HttpdOutput::ReadPage()
/* we have fed a lot of input into the encoder, but it /* we have fed a lot of input into the encoder, but it
didn't give anything back yet - flush now to avoid didn't give anything back yet - flush now to avoid
buffer underruns */ buffer underruns */
encoder_flush(encoder, NULL); encoder_flush(encoder, IgnoreError());
unflushed_input = 0; unflushed_input = 0;
} }
...@@ -273,11 +268,11 @@ HttpdOutput::ReadPage() ...@@ -273,11 +268,11 @@ HttpdOutput::ReadPage()
} }
static bool static bool
httpd_output_enable(struct audio_output *ao, GError **error_r) httpd_output_enable(struct audio_output *ao, Error &error)
{ {
HttpdOutput *httpd = Cast(ao); HttpdOutput *httpd = Cast(ao);
return httpd->Bind(error_r); return httpd->Bind(error);
} }
static void static void
...@@ -289,7 +284,7 @@ httpd_output_disable(struct audio_output *ao) ...@@ -289,7 +284,7 @@ httpd_output_disable(struct audio_output *ao)
} }
inline bool inline bool
HttpdOutput::OpenEncoder(AudioFormat &audio_format, GError **error) HttpdOutput::OpenEncoder(AudioFormat &audio_format, Error &error)
{ {
if (!encoder_open(encoder, audio_format, error)) if (!encoder_open(encoder, audio_format, error))
return false; return false;
...@@ -305,14 +300,14 @@ HttpdOutput::OpenEncoder(AudioFormat &audio_format, GError **error) ...@@ -305,14 +300,14 @@ HttpdOutput::OpenEncoder(AudioFormat &audio_format, GError **error)
} }
inline bool inline bool
HttpdOutput::Open(AudioFormat &audio_format, GError **error_r) HttpdOutput::Open(AudioFormat &audio_format, Error &error)
{ {
assert(!open); assert(!open);
assert(clients.empty()); assert(clients.empty());
/* open the encoder */ /* open the encoder */
if (!OpenEncoder(audio_format, error_r)) if (!OpenEncoder(audio_format, error))
return false; return false;
/* initialize other attributes */ /* initialize other attributes */
...@@ -327,7 +322,7 @@ HttpdOutput::Open(AudioFormat &audio_format, GError **error_r) ...@@ -327,7 +322,7 @@ HttpdOutput::Open(AudioFormat &audio_format, GError **error_r)
static bool static bool
httpd_output_open(struct audio_output *ao, AudioFormat &audio_format, httpd_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) Error &error)
{ {
HttpdOutput *httpd = Cast(ao); HttpdOutput *httpd = Cast(ao);
...@@ -439,9 +434,9 @@ HttpdOutput::BroadcastFromEncoder() ...@@ -439,9 +434,9 @@ HttpdOutput::BroadcastFromEncoder()
} }
inline bool inline bool
HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, GError **error_r) HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, Error &error)
{ {
if (!encoder_write(encoder, chunk, size, error_r)) if (!encoder_write(encoder, chunk, size, error))
return false; return false;
unflushed_input += size; unflushed_input += size;
...@@ -452,12 +447,12 @@ HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, GError **error_r) ...@@ -452,12 +447,12 @@ HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, GError **error_r)
static size_t static size_t
httpd_output_play(struct audio_output *ao, const void *chunk, size_t size, httpd_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r) Error &error)
{ {
HttpdOutput *httpd = Cast(ao); HttpdOutput *httpd = Cast(ao);
if (httpd->LockHasClients()) { if (httpd->LockHasClients()) {
if (!httpd->EncodeAndPlay(chunk, size, error_r)) if (!httpd->EncodeAndPlay(chunk, size, error))
return 0; return 0;
} }
...@@ -476,7 +471,7 @@ httpd_output_pause(struct audio_output *ao) ...@@ -476,7 +471,7 @@ httpd_output_pause(struct audio_output *ao)
if (httpd->LockHasClients()) { if (httpd->LockHasClients()) {
static const char silence[1020] = { 0 }; static const char silence[1020] = { 0 };
return httpd_output_play(ao, silence, sizeof(silence), return httpd_output_play(ao, silence, sizeof(silence),
NULL) > 0; IgnoreError()) > 0;
} else { } else {
return true; return true;
} }
...@@ -492,13 +487,13 @@ HttpdOutput::SendTag(const Tag *tag) ...@@ -492,13 +487,13 @@ HttpdOutput::SendTag(const Tag *tag)
/* flush the current stream, and end it */ /* flush the current stream, and end it */
encoder_pre_tag(encoder, NULL); encoder_pre_tag(encoder, IgnoreError());
BroadcastFromEncoder(); BroadcastFromEncoder();
/* send the tag to the encoder - which starts a new /* send the tag to the encoder - which starts a new
stream now */ stream now */
encoder_tag(encoder, tag, NULL); encoder_tag(encoder, tag, IgnoreError());
/* the first page generated by the encoder will now be /* the first page generated by the encoder will now be
used as the new "header" page, which is sent to all used as the new "header" page, which is sent to all
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
#include "config.h" #include "config.h"
#include "JackOutputPlugin.hxx" #include "JackOutputPlugin.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h> #include <assert.h>
...@@ -82,7 +85,7 @@ struct JackOutput { ...@@ -82,7 +85,7 @@ struct JackOutput {
*/ */
bool pause; bool pause;
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &jack_output_plugin, param, return ao_base_init(&base, &jack_output_plugin, param,
error_r); error_r);
} }
...@@ -92,14 +95,7 @@ struct JackOutput { ...@@ -92,14 +95,7 @@ struct JackOutput {
} }
}; };
/** static constexpr Domain jack_output_domain("jack_output");
* The quark used for GError.domain.
*/
static inline GQuark
jack_output_quark(void)
{
return g_quark_from_static_string("jack_output");
}
/** /**
* Determine the number of frames guaranteed to be available on all * Determine the number of frames guaranteed to be available on all
...@@ -250,7 +246,7 @@ mpd_jack_disconnect(JackOutput *jd) ...@@ -250,7 +246,7 @@ mpd_jack_disconnect(JackOutput *jd)
* (e.g. register callbacks). * (e.g. register callbacks).
*/ */
static bool static bool
mpd_jack_connect(JackOutput *jd, GError **error_r) mpd_jack_connect(JackOutput *jd, Error &error)
{ {
jack_status_t status; jack_status_t status;
...@@ -261,7 +257,7 @@ mpd_jack_connect(JackOutput *jd, GError **error_r) ...@@ -261,7 +257,7 @@ mpd_jack_connect(JackOutput *jd, GError **error_r)
jd->client = jack_client_open(jd->name, jd->options, &status, jd->client = jack_client_open(jd->name, jd->options, &status,
jd->server_name); jd->server_name);
if (jd->client == nullptr) { if (jd->client == nullptr) {
g_set_error(error_r, jack_output_quark(), 0, error.Format(jack_output_domain, status,
"Failed to connect to JACK server, status=%d", "Failed to connect to JACK server, status=%d",
status); status);
return false; return false;
...@@ -276,7 +272,7 @@ mpd_jack_connect(JackOutput *jd, GError **error_r) ...@@ -276,7 +272,7 @@ mpd_jack_connect(JackOutput *jd, GError **error_r)
JACK_DEFAULT_AUDIO_TYPE, JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0); JackPortIsOutput, 0);
if (jd->ports[i] == nullptr) { if (jd->ports[i] == nullptr) {
g_set_error(error_r, jack_output_quark(), 0, error.Format(jack_output_domain,
"Cannot register output port \"%s\"", "Cannot register output port \"%s\"",
jd->source_ports[i]); jd->source_ports[i]);
mpd_jack_disconnect(jd); mpd_jack_disconnect(jd);
...@@ -294,14 +290,14 @@ mpd_jack_test_default_device(void) ...@@ -294,14 +290,14 @@ mpd_jack_test_default_device(void)
} }
static unsigned static unsigned
parse_port_list(int line, const char *source, char **dest, GError **error_r) parse_port_list(int line, const char *source, char **dest, Error &error)
{ {
char **list = g_strsplit(source, ",", 0); char **list = g_strsplit(source, ",", 0);
unsigned n = 0; unsigned n = 0;
for (n = 0; list[n] != nullptr; ++n) { for (n = 0; list[n] != nullptr; ++n) {
if (n >= MAX_PORTS) { if (n >= MAX_PORTS) {
g_set_error(error_r, jack_output_quark(), 0, error.Format(config_domain,
"too many port names in line %d", "too many port names in line %d",
line); line);
return 0; return 0;
...@@ -313,7 +309,7 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r) ...@@ -313,7 +309,7 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r)
g_free(list); g_free(list);
if (n == 0) { if (n == 0) {
g_set_error(error_r, jack_output_quark(), 0, error.Format(config_domain,
"at least one port name expected in line %d", "at least one port name expected in line %d",
line); line);
return 0; return 0;
...@@ -323,11 +319,11 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r) ...@@ -323,11 +319,11 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r)
} }
static struct audio_output * static struct audio_output *
mpd_jack_init(const config_param &param, GError **error_r) mpd_jack_init(const config_param &param, Error &error)
{ {
JackOutput *jd = new JackOutput(); JackOutput *jd = new JackOutput();
if (!jd->Initialize(param, error_r)) { if (!jd->Initialize(param, error)) {
delete jd; delete jd;
return nullptr; return nullptr;
} }
...@@ -355,7 +351,7 @@ mpd_jack_init(const config_param &param, GError **error_r) ...@@ -355,7 +351,7 @@ mpd_jack_init(const config_param &param, GError **error_r)
value = param.GetBlockValue("source_ports", "left,right"); value = param.GetBlockValue("source_ports", "left,right");
jd->num_source_ports = parse_port_list(param.line, value, jd->num_source_ports = parse_port_list(param.line, value,
jd->source_ports, error_r); jd->source_ports, error);
if (jd->num_source_ports == 0) if (jd->num_source_ports == 0)
return nullptr; return nullptr;
...@@ -373,7 +369,7 @@ mpd_jack_init(const config_param &param, GError **error_r) ...@@ -373,7 +369,7 @@ mpd_jack_init(const config_param &param, GError **error_r)
if (value != nullptr) { if (value != nullptr) {
jd->num_destination_ports = jd->num_destination_ports =
parse_port_list(param.line, value, parse_port_list(param.line, value,
jd->destination_ports, error_r); jd->destination_ports, error);
if (jd->num_destination_ports == 0) if (jd->num_destination_ports == 0)
return nullptr; return nullptr;
} else { } else {
...@@ -414,14 +410,14 @@ mpd_jack_finish(struct audio_output *ao) ...@@ -414,14 +410,14 @@ mpd_jack_finish(struct audio_output *ao)
} }
static bool static bool
mpd_jack_enable(struct audio_output *ao, GError **error_r) mpd_jack_enable(struct audio_output *ao, Error &error)
{ {
JackOutput *jd = (JackOutput *)ao; JackOutput *jd = (JackOutput *)ao;
for (unsigned i = 0; i < jd->num_source_ports; ++i) for (unsigned i = 0; i < jd->num_source_ports; ++i)
jd->ringbuffer[i] = nullptr; jd->ringbuffer[i] = nullptr;
return mpd_jack_connect(jd, error_r); return mpd_jack_connect(jd, error);
} }
static void static void
...@@ -460,7 +456,7 @@ mpd_jack_stop(JackOutput *jd) ...@@ -460,7 +456,7 @@ mpd_jack_stop(JackOutput *jd)
} }
static bool static bool
mpd_jack_start(JackOutput *jd, GError **error_r) mpd_jack_start(JackOutput *jd, Error &error)
{ {
const char *destination_ports[MAX_PORTS], **jports; const char *destination_ports[MAX_PORTS], **jports;
const char *duplicate_port = nullptr; const char *duplicate_port = nullptr;
...@@ -484,8 +480,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r) ...@@ -484,8 +480,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
} }
if ( jack_activate(jd->client) ) { if ( jack_activate(jd->client) ) {
g_set_error(error_r, jack_output_quark(), 0, error.Set(jack_output_domain, "cannot activate client");
"cannot activate client");
mpd_jack_stop(jd); mpd_jack_stop(jd);
return false; return false;
} }
...@@ -496,8 +491,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r) ...@@ -496,8 +491,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
jports = jack_get_ports(jd->client, nullptr, nullptr, jports = jack_get_ports(jd->client, nullptr, nullptr,
JackPortIsPhysical | JackPortIsInput); JackPortIsPhysical | JackPortIsInput);
if (jports == nullptr) { if (jports == nullptr) {
g_set_error(error_r, jack_output_quark(), 0, error.Set(jack_output_domain, "no ports found");
"no ports found");
mpd_jack_stop(jd); mpd_jack_stop(jd);
return false; return false;
} }
...@@ -551,7 +545,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r) ...@@ -551,7 +545,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
ret = jack_connect(jd->client, jack_port_name(jd->ports[i]), ret = jack_connect(jd->client, jack_port_name(jd->ports[i]),
destination_ports[i]); destination_ports[i]);
if (ret != 0) { if (ret != 0) {
g_set_error(error_r, jack_output_quark(), 0, error.Format(jack_output_domain,
"Not a valid JACK port: %s", "Not a valid JACK port: %s",
destination_ports[i]); destination_ports[i]);
...@@ -571,7 +565,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r) ...@@ -571,7 +565,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
ret = jack_connect(jd->client, jack_port_name(jd->ports[0]), ret = jack_connect(jd->client, jack_port_name(jd->ports[0]),
duplicate_port); duplicate_port);
if (ret != 0) { if (ret != 0) {
g_set_error(error_r, jack_output_quark(), 0, error.Format(jack_output_domain,
"Not a valid JACK port: %s", "Not a valid JACK port: %s",
duplicate_port); duplicate_port);
...@@ -591,7 +585,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r) ...@@ -591,7 +585,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
static bool static bool
mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format, mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r) Error &error)
{ {
JackOutput *jd = (JackOutput *)ao; JackOutput *jd = (JackOutput *)ao;
...@@ -602,13 +596,13 @@ mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format, ...@@ -602,13 +596,13 @@ mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format,
if (jd->client != nullptr && jd->shutdown) if (jd->client != nullptr && jd->shutdown)
mpd_jack_disconnect(jd); mpd_jack_disconnect(jd);
if (jd->client == nullptr && !mpd_jack_connect(jd, error_r)) if (jd->client == nullptr && !mpd_jack_connect(jd, error))
return false; return false;
set_audioformat(jd, audio_format); set_audioformat(jd, audio_format);
jd->audio_format = audio_format; jd->audio_format = audio_format;
if (!mpd_jack_start(jd, error_r)) if (!mpd_jack_start(jd, error))
return false; return false;
return true; return true;
...@@ -701,7 +695,7 @@ mpd_jack_write_samples(JackOutput *jd, const void *src, ...@@ -701,7 +695,7 @@ mpd_jack_write_samples(JackOutput *jd, const void *src,
static size_t static size_t
mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size, mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r) Error &error)
{ {
JackOutput *jd = (JackOutput *)ao; JackOutput *jd = (JackOutput *)ao;
const size_t frame_size = jd->audio_format.GetFrameSize(); const size_t frame_size = jd->audio_format.GetFrameSize();
...@@ -714,7 +708,7 @@ mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -714,7 +708,7 @@ mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size,
while (true) { while (true) {
if (jd->shutdown) { if (jd->shutdown) {
g_set_error(error_r, jack_output_quark(), 0, error.Set(jack_output_domain,
"Refusing to play, because " "Refusing to play, because "
"there is no client thread"); "there is no client thread");
return 0; return 0;
......
...@@ -31,9 +31,9 @@ struct NullOutput { ...@@ -31,9 +31,9 @@ struct NullOutput {
Timer *timer; Timer *timer;
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &null_output_plugin, param, return ao_base_init(&base, &null_output_plugin, param,
error_r); error);
} }
void Deinitialize() { void Deinitialize() {
...@@ -42,11 +42,11 @@ struct NullOutput { ...@@ -42,11 +42,11 @@ struct NullOutput {
}; };
static struct audio_output * static struct audio_output *
null_init(const config_param &param, GError **error_r) null_init(const config_param &param, Error &error)
{ {
NullOutput *nd = new NullOutput(); NullOutput *nd = new NullOutput();
if (!nd->Initialize(param, error_r)) { if (!nd->Initialize(param, error)) {
delete nd; delete nd;
return nullptr; return nullptr;
} }
...@@ -67,7 +67,7 @@ null_finish(struct audio_output *ao) ...@@ -67,7 +67,7 @@ null_finish(struct audio_output *ao)
static bool static bool
null_open(struct audio_output *ao, AudioFormat &audio_format, null_open(struct audio_output *ao, AudioFormat &audio_format,
gcc_unused GError **error) gcc_unused Error &error)
{ {
NullOutput *nd = (NullOutput *)ao; NullOutput *nd = (NullOutput *)ao;
...@@ -98,7 +98,7 @@ null_delay(struct audio_output *ao) ...@@ -98,7 +98,7 @@ null_delay(struct audio_output *ao)
static size_t static size_t
null_play(struct audio_output *ao, gcc_unused const void *chunk, size_t size, null_play(struct audio_output *ao, gcc_unused const void *chunk, size_t size,
gcc_unused GError **error) gcc_unused Error &error)
{ {
NullOutput *nd = (NullOutput *)ao; NullOutput *nd = (NullOutput *)ao;
Timer *timer = nd->timer; Timer *timer = nd->timer;
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include "OSXOutputPlugin.hxx" #include "OSXOutputPlugin.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "util/fifo_buffer.h" #include "util/fifo_buffer.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "thread/Cond.hxx" #include "thread/Cond.hxx"
...@@ -47,14 +49,7 @@ struct OSXOutput { ...@@ -47,14 +49,7 @@ struct OSXOutput {
struct fifo_buffer *buffer; struct fifo_buffer *buffer;
}; };
/** static constexpr Domain osx_output_domain("osx_output");
* The quark used for GError.domain.
*/
static inline GQuark
osx_output_quark(void)
{
return g_quark_from_static_string("osx_output");
}
static bool static bool
osx_output_test_default_device(void) osx_output_test_default_device(void)
...@@ -85,10 +80,10 @@ osx_output_configure(OSXOutput *oo, const config_param &param) ...@@ -85,10 +80,10 @@ osx_output_configure(OSXOutput *oo, const config_param &param)
} }
static struct audio_output * static struct audio_output *
osx_output_init(const config_param &param, GError **error_r) osx_output_init(const config_param &param, Error &error)
{ {
OSXOutput *oo = new OSXOutput(); OSXOutput *oo = new OSXOutput();
if (!ao_base_init(&oo->base, &osx_output_plugin, param, error_r)) { if (!ao_base_init(&oo->base, &osx_output_plugin, param, error)) {
delete oo; delete oo;
return NULL; return NULL;
} }
...@@ -107,7 +102,7 @@ osx_output_finish(struct audio_output *ao) ...@@ -107,7 +102,7 @@ osx_output_finish(struct audio_output *ao)
} }
static bool static bool
osx_output_set_device(OSXOutput *oo, GError **error) osx_output_set_device(OSXOutput *oo, Error &error)
{ {
bool ret = true; bool ret = true;
OSStatus status; OSStatus status;
...@@ -124,7 +119,7 @@ osx_output_set_device(OSXOutput *oo, GError **error) ...@@ -124,7 +119,7 @@ osx_output_set_device(OSXOutput *oo, GError **error)
&size, &size,
NULL); NULL);
if (status != noErr) { if (status != noErr) {
g_set_error(error, osx_output_quark(), status, error.Format(osx_output_domain, status,
"Unable to determine number of OS X audio devices: %s", "Unable to determine number of OS X audio devices: %s",
GetMacOSStatusCommentString(status)); GetMacOSStatusCommentString(status));
ret = false; ret = false;
...@@ -138,7 +133,7 @@ osx_output_set_device(OSXOutput *oo, GError **error) ...@@ -138,7 +133,7 @@ osx_output_set_device(OSXOutput *oo, GError **error)
&size, &size,
deviceids); deviceids);
if (status != noErr) { if (status != noErr) {
g_set_error(error, osx_output_quark(), status, error.Format(osx_output_domain, status,
"Unable to determine OS X audio device IDs: %s", "Unable to determine OS X audio device IDs: %s",
GetMacOSStatusCommentString(status)); GetMacOSStatusCommentString(status));
ret = false; ret = false;
...@@ -152,7 +147,7 @@ osx_output_set_device(OSXOutput *oo, GError **error) ...@@ -152,7 +147,7 @@ osx_output_set_device(OSXOutput *oo, GError **error)
kAudioDevicePropertyDeviceName, kAudioDevicePropertyDeviceName,
&size, name); &size, name);
if (status != noErr) { if (status != noErr) {
g_set_error(error, osx_output_quark(), status, error.Format(osx_output_domain, status,
"Unable to determine OS X device name " "Unable to determine OS X device name "
"(device %u): %s", "(device %u): %s",
(unsigned int) deviceids[i], (unsigned int) deviceids[i],
...@@ -180,7 +175,7 @@ osx_output_set_device(OSXOutput *oo, GError **error) ...@@ -180,7 +175,7 @@ osx_output_set_device(OSXOutput *oo, GError **error)
&(deviceids[i]), &(deviceids[i]),
sizeof(AudioDeviceID)); sizeof(AudioDeviceID));
if (status != noErr) { if (status != noErr) {
g_set_error(error, osx_output_quark(), status, error.Format(osx_output_domain, status,
"Unable to set OS X audio output device: %s", "Unable to set OS X audio output device: %s",
GetMacOSStatusCommentString(status)); GetMacOSStatusCommentString(status));
ret = false; ret = false;
...@@ -237,7 +232,7 @@ osx_render(void *vdata, ...@@ -237,7 +232,7 @@ osx_render(void *vdata,
} }
static bool static bool
osx_output_enable(struct audio_output *ao, GError **error_r) osx_output_enable(struct audio_output *ao, Error &error)
{ {
OSXOutput *oo = (OSXOutput *)ao; OSXOutput *oo = (OSXOutput *)ao;
...@@ -250,20 +245,20 @@ osx_output_enable(struct audio_output *ao, GError **error_r) ...@@ -250,20 +245,20 @@ osx_output_enable(struct audio_output *ao, GError **error_r)
Component comp = FindNextComponent(NULL, &desc); Component comp = FindNextComponent(NULL, &desc);
if (comp == 0) { if (comp == 0) {
g_set_error(error_r, osx_output_quark(), 0, error.Set(osx_output_domain,
"Error finding OS X component"); "Error finding OS X component");
return false; return false;
} }
OSStatus status = OpenAComponent(comp, &oo->au); OSStatus status = OpenAComponent(comp, &oo->au);
if (status != noErr) { if (status != noErr) {
g_set_error(error_r, osx_output_quark(), status, error.Format(osx_output_domain, status,
"Unable to open OS X component: %s", "Unable to open OS X component: %s",
GetMacOSStatusCommentString(status)); GetMacOSStatusCommentString(status));
return false; return false;
} }
if (!osx_output_set_device(oo, error_r)) { if (!osx_output_set_device(oo, error)) {
CloseComponent(oo->au); CloseComponent(oo->au);
return false; return false;
} }
...@@ -279,7 +274,7 @@ osx_output_enable(struct audio_output *ao, GError **error_r) ...@@ -279,7 +274,7 @@ osx_output_enable(struct audio_output *ao, GError **error_r)
&callback, sizeof(callback)); &callback, sizeof(callback));
if (result != noErr) { if (result != noErr) {
CloseComponent(oo->au); CloseComponent(oo->au);
g_set_error(error_r, osx_output_quark(), result, error.Set(osx_output_domain, result,
"unable to set callback for OS X audio unit"); "unable to set callback for OS X audio unit");
return false; return false;
} }
...@@ -316,7 +311,8 @@ osx_output_close(struct audio_output *ao) ...@@ -316,7 +311,8 @@ osx_output_close(struct audio_output *ao)
} }
static bool static bool
osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) osx_output_open(struct audio_output *ao, AudioFormat &audio_format,
Error &error)
{ {
OSXOutput *od = (OSXOutput *)ao; OSXOutput *od = (OSXOutput *)ao;
...@@ -359,14 +355,14 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err ...@@ -359,14 +355,14 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err
&stream_description, &stream_description,
sizeof(stream_description)); sizeof(stream_description));
if (result != noErr) { if (result != noErr) {
g_set_error(error, osx_output_quark(), result, error.Set(osx_output_domain, result,
"Unable to set format on OS X device"); "Unable to set format on OS X device");
return false; return false;
} }
OSStatus status = AudioUnitInitialize(od->au); OSStatus status = AudioUnitInitialize(od->au);
if (status != noErr) { if (status != noErr) {
g_set_error(error, osx_output_quark(), status, error.Set(osx_output_domain, status,
"Unable to initialize OS X audio unit: %s", "Unable to initialize OS X audio unit: %s",
GetMacOSStatusCommentString(status)); GetMacOSStatusCommentString(status));
return false; return false;
...@@ -379,7 +375,7 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err ...@@ -379,7 +375,7 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err
status = AudioOutputUnitStart(od->au); status = AudioOutputUnitStart(od->au);
if (status != 0) { if (status != 0) {
AudioUnitUninitialize(od->au); AudioUnitUninitialize(od->au);
g_set_error(error, osx_output_quark(), status, error.Format(osx_output_domain, status,
"unable to start audio output: %s", "unable to start audio output: %s",
GetMacOSStatusCommentString(status)); GetMacOSStatusCommentString(status));
return false; return false;
...@@ -390,7 +386,7 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err ...@@ -390,7 +386,7 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err
static size_t static size_t
osx_output_play(struct audio_output *ao, const void *chunk, size_t size, osx_output_play(struct audio_output *ao, const void *chunk, size_t size,
gcc_unused GError **error) gcc_unused Error &error)
{ {
OSXOutput *od = (OSXOutput *)ao; OSXOutput *od = (OSXOutput *)ao;
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "config.h" #include "config.h"
#include "OpenALOutputPlugin.hxx" #include "OpenALOutputPlugin.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -49,7 +51,7 @@ struct OpenALOutput { ...@@ -49,7 +51,7 @@ struct OpenALOutput {
ALenum format; ALenum format;
ALuint frequency; ALuint frequency;
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &openal_output_plugin, param, return ao_base_init(&base, &openal_output_plugin, param,
error_r); error_r);
} }
...@@ -59,12 +61,7 @@ struct OpenALOutput { ...@@ -59,12 +61,7 @@ struct OpenALOutput {
} }
}; };
gcc_const static constexpr Domain openal_output_domain("openal_output");
static inline GQuark
openal_output_quark(void)
{
return g_quark_from_static_string("openal_output");
}
static ALenum static ALenum
openal_audio_format(AudioFormat &audio_format) openal_audio_format(AudioFormat &audio_format)
...@@ -115,14 +112,13 @@ openal_is_playing(const OpenALOutput *od) ...@@ -115,14 +112,13 @@ openal_is_playing(const OpenALOutput *od)
} }
static bool static bool
openal_setup_context(OpenALOutput *od, openal_setup_context(OpenALOutput *od, Error &error)
GError **error)
{ {
od->device = alcOpenDevice(od->device_name); od->device = alcOpenDevice(od->device_name);
if (od->device == nullptr) { if (od->device == nullptr) {
g_set_error(error, openal_output_quark(), 0, error.Format(openal_output_domain,
"Error opening OpenAL device \"%s\"\n", "Error opening OpenAL device \"%s\"",
od->device_name); od->device_name);
return false; return false;
} }
...@@ -130,8 +126,8 @@ openal_setup_context(OpenALOutput *od, ...@@ -130,8 +126,8 @@ openal_setup_context(OpenALOutput *od,
od->context = alcCreateContext(od->device, nullptr); od->context = alcCreateContext(od->device, nullptr);
if (od->context == nullptr) { if (od->context == nullptr) {
g_set_error(error, openal_output_quark(), 0, error.Format(openal_output_domain,
"Error creating context for \"%s\"\n", "Error creating context for \"%s\"",
od->device_name); od->device_name);
alcCloseDevice(od->device); alcCloseDevice(od->device);
return false; return false;
...@@ -141,7 +137,7 @@ openal_setup_context(OpenALOutput *od, ...@@ -141,7 +137,7 @@ openal_setup_context(OpenALOutput *od,
} }
static struct audio_output * static struct audio_output *
openal_init(const config_param &param, GError **error_r) openal_init(const config_param &param, Error &error)
{ {
const char *device_name = param.GetBlockValue("device"); const char *device_name = param.GetBlockValue("device");
if (device_name == nullptr) { if (device_name == nullptr) {
...@@ -149,7 +145,7 @@ openal_init(const config_param &param, GError **error_r) ...@@ -149,7 +145,7 @@ openal_init(const config_param &param, GError **error_r)
} }
OpenALOutput *od = new OpenALOutput(); OpenALOutput *od = new OpenALOutput();
if (!od->Initialize(param, error_r)) { if (!od->Initialize(param, error)) {
delete od; delete od;
return nullptr; return nullptr;
} }
...@@ -170,7 +166,7 @@ openal_finish(struct audio_output *ao) ...@@ -170,7 +166,7 @@ openal_finish(struct audio_output *ao)
static bool static bool
openal_open(struct audio_output *ao, AudioFormat &audio_format, openal_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) Error &error)
{ {
OpenALOutput *od = (OpenALOutput *)ao; OpenALOutput *od = (OpenALOutput *)ao;
...@@ -184,16 +180,14 @@ openal_open(struct audio_output *ao, AudioFormat &audio_format, ...@@ -184,16 +180,14 @@ openal_open(struct audio_output *ao, AudioFormat &audio_format,
alGenBuffers(NUM_BUFFERS, od->buffers); alGenBuffers(NUM_BUFFERS, od->buffers);
if (alGetError() != AL_NO_ERROR) { if (alGetError() != AL_NO_ERROR) {
g_set_error(error, openal_output_quark(), 0, error.Set(openal_output_domain, "Failed to generate buffers");
"Failed to generate buffers");
return false; return false;
} }
alGenSources(1, &od->source); alGenSources(1, &od->source);
if (alGetError() != AL_NO_ERROR) { if (alGetError() != AL_NO_ERROR) {
g_set_error(error, openal_output_quark(), 0, error.Set(openal_output_domain, "Failed to generate source");
"Failed to generate source");
alDeleteBuffers(NUM_BUFFERS, od->buffers); alDeleteBuffers(NUM_BUFFERS, od->buffers);
return false; return false;
} }
...@@ -231,7 +225,7 @@ openal_delay(struct audio_output *ao) ...@@ -231,7 +225,7 @@ openal_delay(struct audio_output *ao)
static size_t static size_t
openal_play(struct audio_output *ao, const void *chunk, size_t size, openal_play(struct audio_output *ao, const void *chunk, size_t size,
gcc_unused GError **error) gcc_unused Error &error)
{ {
OpenALOutput *od = (OpenALOutput *)ao; OpenALOutput *od = (OpenALOutput *)ao;
ALuint buffer; ALuint buffer;
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "MixerList.hxx" #include "MixerList.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -80,7 +82,7 @@ struct OssOutput { ...@@ -80,7 +82,7 @@ struct OssOutput {
OssOutput():fd(-1), device(nullptr) {} OssOutput():fd(-1), device(nullptr) {}
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &oss_output_plugin, param, return ao_base_init(&base, &oss_output_plugin, param,
error_r); error_r);
} }
...@@ -90,14 +92,7 @@ struct OssOutput { ...@@ -90,14 +92,7 @@ struct OssOutput {
} }
}; };
/** static constexpr Domain oss_output_domain("oss_output");
* The quark used for GError.domain.
*/
static inline GQuark
oss_output_quark(void)
{
return g_quark_from_static_string("oss_output");
}
enum oss_stat { enum oss_stat {
OSS_STAT_NO_ERROR = 0, OSS_STAT_NO_ERROR = 0,
...@@ -155,7 +150,7 @@ oss_output_test_default_device(void) ...@@ -155,7 +150,7 @@ oss_output_test_default_device(void)
} }
static struct audio_output * static struct audio_output *
oss_open_default(GError **error) oss_open_default(Error &error)
{ {
int err[G_N_ELEMENTS(default_devices)]; int err[G_N_ELEMENTS(default_devices)];
enum oss_stat ret[G_N_ELEMENTS(default_devices)]; enum oss_stat ret[G_N_ELEMENTS(default_devices)];
...@@ -196,18 +191,18 @@ oss_open_default(GError **error) ...@@ -196,18 +191,18 @@ oss_open_default(GError **error)
} }
} }
g_set_error(error, oss_output_quark(), 0, error.Set(oss_output_domain,
"error trying to open default OSS device"); "error trying to open default OSS device");
return NULL; return NULL;
} }
static struct audio_output * static struct audio_output *
oss_output_init(const config_param &param, GError **error_r) oss_output_init(const config_param &param, Error &error)
{ {
const char *device = param.GetBlockValue("device"); const char *device = param.GetBlockValue("device");
if (device != NULL) { if (device != NULL) {
OssOutput *od = new OssOutput(); OssOutput *od = new OssOutput();
if (!od->Initialize(param, error_r)) { if (!od->Initialize(param, error)) {
delete od; delete od;
return NULL; return NULL;
} }
...@@ -216,7 +211,7 @@ oss_output_init(const config_param &param, GError **error_r) ...@@ -216,7 +211,7 @@ oss_output_init(const config_param &param, GError **error_r)
return &od->base; return &od->base;
} }
return oss_open_default(error_r); return oss_open_default(error);
} }
static void static void
...@@ -231,7 +226,7 @@ oss_output_finish(struct audio_output *ao) ...@@ -231,7 +226,7 @@ oss_output_finish(struct audio_output *ao)
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
static bool static bool
oss_output_enable(struct audio_output *ao, gcc_unused GError **error_r) oss_output_enable(struct audio_output *ao, gcc_unused Error &error)
{ {
OssOutput *od = (OssOutput *)ao; OssOutput *od = (OssOutput *)ao;
...@@ -269,16 +264,16 @@ enum oss_setup_result { ...@@ -269,16 +264,16 @@ enum oss_setup_result {
/** /**
* Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is * Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is
* returned. If the parameter is not supported, UNSUPPORTED is * returned. If the parameter is not supported, UNSUPPORTED is
* returned. Any other failure returns ERROR and allocates a GError. * returned. Any other failure returns ERROR and allocates an #Error.
*/ */
static enum oss_setup_result static enum oss_setup_result
oss_try_ioctl_r(int fd, unsigned long request, int *value_r, oss_try_ioctl_r(int fd, unsigned long request, int *value_r,
const char *msg, GError **error_r) const char *msg, Error &error)
{ {
assert(fd >= 0); assert(fd >= 0);
assert(value_r != NULL); assert(value_r != NULL);
assert(msg != NULL); assert(msg != NULL);
assert(error_r == NULL || *error_r == NULL); assert(!error.IsDefined());
int ret = ioctl(fd, request, value_r); int ret = ioctl(fd, request, value_r);
if (ret >= 0) if (ret >= 0)
...@@ -287,19 +282,18 @@ oss_try_ioctl_r(int fd, unsigned long request, int *value_r, ...@@ -287,19 +282,18 @@ oss_try_ioctl_r(int fd, unsigned long request, int *value_r,
if (errno == EINVAL) if (errno == EINVAL)
return UNSUPPORTED; return UNSUPPORTED;
g_set_error(error_r, oss_output_quark(), errno, error.SetErrno(msg);
"%s: %s", msg, g_strerror(errno));
return ERROR; return ERROR;
} }
/** /**
* Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is * Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is
* returned. If the parameter is not supported, UNSUPPORTED is * returned. If the parameter is not supported, UNSUPPORTED is
* returned. Any other failure returns ERROR and allocates a GError. * returned. Any other failure returns ERROR and allocates an #Error.
*/ */
static enum oss_setup_result static enum oss_setup_result
oss_try_ioctl(int fd, unsigned long request, int value, oss_try_ioctl(int fd, unsigned long request, int value,
const char *msg, GError **error_r) const char *msg, Error &error_r)
{ {
return oss_try_ioctl_r(fd, request, &value, msg, error_r); return oss_try_ioctl_r(fd, request, &value, msg, error_r);
} }
...@@ -309,12 +303,12 @@ oss_try_ioctl(int fd, unsigned long request, int value, ...@@ -309,12 +303,12 @@ oss_try_ioctl(int fd, unsigned long request, int value,
* specified number is not supported. * specified number is not supported.
*/ */
static bool static bool
oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r) oss_setup_channels(int fd, AudioFormat &audio_format, Error &error)
{ {
const char *const msg = "Failed to set channel count"; const char *const msg = "Failed to set channel count";
int channels = audio_format.channels; int channels = audio_format.channels;
enum oss_setup_result result = enum oss_setup_result result =
oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error_r); oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error);
switch (result) { switch (result) {
case SUCCESS: case SUCCESS:
if (!audio_valid_channel_count(channels)) if (!audio_valid_channel_count(channels))
...@@ -337,7 +331,7 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r) ...@@ -337,7 +331,7 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r)
channels = i; channels = i;
result = oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, result = oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels,
msg, error_r); msg, error);
switch (result) { switch (result) {
case SUCCESS: case SUCCESS:
if (!audio_valid_channel_count(channels)) if (!audio_valid_channel_count(channels))
...@@ -354,7 +348,7 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r) ...@@ -354,7 +348,7 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r)
} }
} }
g_set_error(error_r, oss_output_quark(), EINVAL, "%s", msg); error.Set(oss_output_domain, msg);
return false; return false;
} }
...@@ -364,13 +358,13 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r) ...@@ -364,13 +358,13 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r)
*/ */
static bool static bool
oss_setup_sample_rate(int fd, AudioFormat &audio_format, oss_setup_sample_rate(int fd, AudioFormat &audio_format,
GError **error_r) Error &error)
{ {
const char *const msg = "Failed to set sample rate"; const char *const msg = "Failed to set sample rate";
int sample_rate = audio_format.sample_rate; int sample_rate = audio_format.sample_rate;
enum oss_setup_result result = enum oss_setup_result result =
oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate, oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate,
msg, error_r); msg, error);
switch (result) { switch (result) {
case SUCCESS: case SUCCESS:
if (!audio_valid_sample_rate(sample_rate)) if (!audio_valid_sample_rate(sample_rate))
...@@ -393,7 +387,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format, ...@@ -393,7 +387,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format,
continue; continue;
result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate, result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate,
msg, error_r); msg, error);
switch (result) { switch (result) {
case SUCCESS: case SUCCESS:
if (!audio_valid_sample_rate(sample_rate)) if (!audio_valid_sample_rate(sample_rate))
...@@ -410,7 +404,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format, ...@@ -410,7 +404,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format,
} }
} }
g_set_error(error_r, oss_output_quark(), EINVAL, "%s", msg); error.Set(oss_output_domain, msg);
return false; return false;
} }
...@@ -498,7 +492,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format, ...@@ -498,7 +492,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format,
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
PcmExport &pcm_export, PcmExport &pcm_export,
#endif #endif
GError **error_r) Error &error)
{ {
int oss_format = sample_format_to_oss(sample_format); int oss_format = sample_format_to_oss(sample_format);
if (oss_format == AFMT_QUERY) if (oss_format == AFMT_QUERY)
...@@ -507,7 +501,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format, ...@@ -507,7 +501,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format,
enum oss_setup_result result = enum oss_setup_result result =
oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE, oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE,
&oss_format, &oss_format,
"Failed to set sample format", error_r); "Failed to set sample format", error);
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
if (result == UNSUPPORTED && sample_format == SampleFormat::S24_P32) { if (result == UNSUPPORTED && sample_format == SampleFormat::S24_P32) {
...@@ -516,7 +510,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format, ...@@ -516,7 +510,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format,
oss_format = AFMT_S24_PACKED; oss_format = AFMT_S24_PACKED;
result = oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE, result = oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE,
&oss_format, &oss_format,
"Failed to set sample format", error_r); "Failed to set sample format", error);
} }
#endif #endif
...@@ -550,7 +544,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, ...@@ -550,7 +544,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
PcmExport &pcm_export, PcmExport &pcm_export,
#endif #endif
GError **error_r) Error &error)
{ {
SampleFormat mpd_format; SampleFormat mpd_format;
enum oss_setup_result result = enum oss_setup_result result =
...@@ -559,7 +553,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, ...@@ -559,7 +553,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
pcm_export, pcm_export,
#endif #endif
error_r); error);
switch (result) { switch (result) {
case SUCCESS: case SUCCESS:
audio_format.format = mpd_format; audio_format.format = mpd_format;
...@@ -597,7 +591,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, ...@@ -597,7 +591,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
pcm_export, pcm_export,
#endif #endif
error_r); error);
switch (result) { switch (result) {
case SUCCESS: case SUCCESS:
audio_format.format = mpd_format; audio_format.format = mpd_format;
...@@ -611,8 +605,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, ...@@ -611,8 +605,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
} }
} }
g_set_error_literal(error_r, oss_output_quark(), EINVAL, error.Set(oss_output_domain, "Failed to set sample format");
"Failed to set sample format");
return false; return false;
} }
...@@ -621,30 +614,29 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format, ...@@ -621,30 +614,29 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
*/ */
static bool static bool
oss_setup(OssOutput *od, AudioFormat &audio_format, oss_setup(OssOutput *od, AudioFormat &audio_format,
GError **error_r) Error &error)
{ {
return oss_setup_channels(od->fd, audio_format, error_r) && return oss_setup_channels(od->fd, audio_format, error) &&
oss_setup_sample_rate(od->fd, audio_format, error_r) && oss_setup_sample_rate(od->fd, audio_format, error) &&
oss_setup_sample_format(od->fd, audio_format, &od->oss_format, oss_setup_sample_format(od->fd, audio_format, &od->oss_format,
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
od->pcm_export, od->pcm_export,
#endif #endif
error_r); error);
} }
/** /**
* Reopen the device with the saved audio_format, without any probing. * Reopen the device with the saved audio_format, without any probing.
*/ */
static bool static bool
oss_reopen(OssOutput *od, GError **error_r) oss_reopen(OssOutput *od, Error &error)
{ {
assert(od->fd < 0); assert(od->fd < 0);
od->fd = open_cloexec(od->device, O_WRONLY, 0); od->fd = open_cloexec(od->device, O_WRONLY, 0);
if (od->fd < 0) { if (od->fd < 0) {
g_set_error(error_r, oss_output_quark(), errno, error.FormatErrno("Error opening OSS device \"%s\"",
"Error opening OSS device \"%s\": %s", od->device);
od->device, g_strerror(errno));
return false; return false;
} }
...@@ -652,35 +644,32 @@ oss_reopen(OssOutput *od, GError **error_r) ...@@ -652,35 +644,32 @@ oss_reopen(OssOutput *od, GError **error_r)
const char *const msg1 = "Failed to set channel count"; const char *const msg1 = "Failed to set channel count";
result = oss_try_ioctl(od->fd, SNDCTL_DSP_CHANNELS, result = oss_try_ioctl(od->fd, SNDCTL_DSP_CHANNELS,
od->audio_format.channels, msg1, error_r); od->audio_format.channels, msg1, error);
if (result != SUCCESS) { if (result != SUCCESS) {
oss_close(od); oss_close(od);
if (result == UNSUPPORTED) if (result == UNSUPPORTED)
g_set_error(error_r, oss_output_quark(), EINVAL, error.Set(oss_output_domain, msg1);
"%s", msg1);
return false; return false;
} }
const char *const msg2 = "Failed to set sample rate"; const char *const msg2 = "Failed to set sample rate";
result = oss_try_ioctl(od->fd, SNDCTL_DSP_SPEED, result = oss_try_ioctl(od->fd, SNDCTL_DSP_SPEED,
od->audio_format.sample_rate, msg2, error_r); od->audio_format.sample_rate, msg2, error);
if (result != SUCCESS) { if (result != SUCCESS) {
oss_close(od); oss_close(od);
if (result == UNSUPPORTED) if (result == UNSUPPORTED)
g_set_error(error_r, oss_output_quark(), EINVAL, error.Set(oss_output_domain, msg2);
"%s", msg2);
return false; return false;
} }
const char *const msg3 = "Failed to set sample format"; const char *const msg3 = "Failed to set sample format";
result = oss_try_ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE, result = oss_try_ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE,
od->oss_format, od->oss_format,
msg3, error_r); msg3, error);
if (result != SUCCESS) { if (result != SUCCESS) {
oss_close(od); oss_close(od);
if (result == UNSUPPORTED) if (result == UNSUPPORTED)
g_set_error(error_r, oss_output_quark(), EINVAL, error.Set(oss_output_domain, msg3);
"%s", msg3);
return false; return false;
} }
...@@ -689,15 +678,14 @@ oss_reopen(OssOutput *od, GError **error_r) ...@@ -689,15 +678,14 @@ oss_reopen(OssOutput *od, GError **error_r)
static bool static bool
oss_output_open(struct audio_output *ao, AudioFormat &audio_format, oss_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) Error &error)
{ {
OssOutput *od = (OssOutput *)ao; OssOutput *od = (OssOutput *)ao;
od->fd = open_cloexec(od->device, O_WRONLY, 0); od->fd = open_cloexec(od->device, O_WRONLY, 0);
if (od->fd < 0) { if (od->fd < 0) {
g_set_error(error, oss_output_quark(), errno, error.FormatErrno("Error opening OSS device \"%s\"",
"Error opening OSS device \"%s\": %s", od->device);
od->device, g_strerror(errno));
return false; return false;
} }
...@@ -731,7 +719,7 @@ oss_output_cancel(struct audio_output *ao) ...@@ -731,7 +719,7 @@ oss_output_cancel(struct audio_output *ao)
static size_t static size_t
oss_output_play(struct audio_output *ao, const void *chunk, size_t size, oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error) Error &error)
{ {
OssOutput *od = (OssOutput *)ao; OssOutput *od = (OssOutput *)ao;
ssize_t ret; ssize_t ret;
...@@ -754,9 +742,7 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -754,9 +742,7 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
} }
if (ret < 0 && errno != EINTR) { if (ret < 0 && errno != EINTR) {
g_set_error(error, oss_output_quark(), errno, error.FormatErrno("Write error on %s", od->device);
"Write error on %s: %s",
od->device, g_strerror(errno));
return 0; return 0;
} }
} }
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
#include "config.h" #include "config.h"
#include "PipeOutputPlugin.hxx" #include "PipeOutputPlugin.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
...@@ -30,33 +33,26 @@ struct PipeOutput { ...@@ -30,33 +33,26 @@ struct PipeOutput {
char *cmd; char *cmd;
FILE *fh; FILE *fh;
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &pipe_output_plugin, param, return ao_base_init(&base, &pipe_output_plugin, param,
error_r); error);
} }
void Deinitialize() { void Deinitialize() {
ao_base_finish(&base); ao_base_finish(&base);
} }
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
}; };
/** static constexpr Domain pipe_output_domain("pipe_output");
* The quark used for GError.domain.
*/
static inline GQuark
pipe_output_quark(void)
{
return g_quark_from_static_string("pipe_output");
}
inline bool inline bool
PipeOutput::Configure(const config_param &param, GError **error_r) PipeOutput::Configure(const config_param &param, Error &error)
{ {
cmd = param.DupBlockString("command"); cmd = param.DupBlockString("command");
if (cmd == nullptr) { if (cmd == nullptr) {
g_set_error(error_r, pipe_output_quark(), 0, error.Set(config_domain,
"No \"command\" parameter specified"); "No \"command\" parameter specified");
return false; return false;
} }
...@@ -65,16 +61,16 @@ PipeOutput::Configure(const config_param &param, GError **error_r) ...@@ -65,16 +61,16 @@ PipeOutput::Configure(const config_param &param, GError **error_r)
} }
static struct audio_output * static struct audio_output *
pipe_output_init(const config_param &param, GError **error_r) pipe_output_init(const config_param &param, Error &error)
{ {
PipeOutput *pd = new PipeOutput(); PipeOutput *pd = new PipeOutput();
if (!pd->Initialize(param, error_r)) { if (!pd->Initialize(param, error)) {
delete pd; delete pd;
return nullptr; return nullptr;
} }
if (!pd->Configure(param, error_r)) { if (!pd->Configure(param, error)) {
pd->Deinitialize(); pd->Deinitialize();
delete pd; delete pd;
return nullptr; return nullptr;
...@@ -96,15 +92,14 @@ pipe_output_finish(struct audio_output *ao) ...@@ -96,15 +92,14 @@ pipe_output_finish(struct audio_output *ao)
static bool static bool
pipe_output_open(struct audio_output *ao, pipe_output_open(struct audio_output *ao,
gcc_unused AudioFormat &audio_format, gcc_unused AudioFormat &audio_format,
gcc_unused GError **error) Error &error)
{ {
PipeOutput *pd = (PipeOutput *)ao; PipeOutput *pd = (PipeOutput *)ao;
pd->fh = popen(pd->cmd, "w"); pd->fh = popen(pd->cmd, "w");
if (pd->fh == nullptr) { if (pd->fh == nullptr) {
g_set_error(error, pipe_output_quark(), errno, error.FormatErrno("Error opening pipe \"%s\"",
"Error opening pipe \"%s\": %s", pd->cmd);
pd->cmd, g_strerror(errno));
return false; return false;
} }
...@@ -120,15 +115,15 @@ pipe_output_close(struct audio_output *ao) ...@@ -120,15 +115,15 @@ pipe_output_close(struct audio_output *ao)
} }
static size_t static size_t
pipe_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error) pipe_output_play(struct audio_output *ao, const void *chunk, size_t size,
Error &error)
{ {
PipeOutput *pd = (PipeOutput *)ao; PipeOutput *pd = (PipeOutput *)ao;
size_t ret; size_t ret;
ret = fwrite(chunk, 1, size, pd->fh); ret = fwrite(chunk, 1, size, pd->fh);
if (ret == 0) if (ret == 0)
g_set_error(error, pipe_output_quark(), errno, error.SetErrno("Write error on pipe");
"Write error on pipe: %s", g_strerror(errno));
return ret; return ret;
} }
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "MixerList.hxx" #include "MixerList.hxx"
#include "mixer/PulseMixerPlugin.hxx" #include "mixer/PulseMixerPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -54,13 +56,13 @@ struct PulseOutput { ...@@ -54,13 +56,13 @@ struct PulseOutput {
size_t writable; size_t writable;
}; };
/** static constexpr Domain pulse_output_domain("pulse_output");
* The quark used for GError.domain.
*/ static void
static inline GQuark SetError(Error &error, pa_context *context, const char *msg)
pulse_output_quark(void)
{ {
return g_quark_from_static_string("pulse_output"); const int e = pa_context_errno(context);
error.Format(pulse_output_domain, e, "%s: %s", msg, pa_strerror(e));
} }
void void
...@@ -112,14 +114,14 @@ pulse_output_clear_mixer(PulseOutput *po, gcc_unused PulseMixer *pm) ...@@ -112,14 +114,14 @@ pulse_output_clear_mixer(PulseOutput *po, gcc_unused PulseMixer *pm)
} }
bool bool
pulse_output_set_volume(PulseOutput *po, pulse_output_set_volume(PulseOutput *po, const pa_cvolume *volume,
const struct pa_cvolume *volume, GError **error_r) Error &error)
{ {
pa_operation *o; pa_operation *o;
if (po->context == nullptr || po->stream == nullptr || if (po->context == nullptr || po->stream == nullptr ||
pa_stream_get_state(po->stream) != PA_STREAM_READY) { pa_stream_get_state(po->stream) != PA_STREAM_READY) {
g_set_error(error_r, pulse_output_quark(), 0, "disconnected"); error.Set(pulse_output_domain, "disconnected");
return false; return false;
} }
...@@ -127,9 +129,8 @@ pulse_output_set_volume(PulseOutput *po, ...@@ -127,9 +129,8 @@ pulse_output_set_volume(PulseOutput *po,
pa_stream_get_index(po->stream), pa_stream_get_index(po->stream),
volume, nullptr, nullptr); volume, nullptr, nullptr);
if (o == nullptr) { if (o == nullptr) {
g_set_error(error_r, pulse_output_quark(), 0, SetError(error, po->context,
"failed to set PulseAudio volume: %s", "failed to set PulseAudio volume");
pa_strerror(pa_context_errno(po->context)));
return false; return false;
} }
...@@ -235,19 +236,15 @@ pulse_output_subscribe_cb(pa_context *context, ...@@ -235,19 +236,15 @@ pulse_output_subscribe_cb(pa_context *context,
* @return true on success, false on error * @return true on success, false on error
*/ */
static bool static bool
pulse_output_connect(PulseOutput *po, GError **error_r) pulse_output_connect(PulseOutput *po, Error &error)
{ {
assert(po != nullptr); assert(po != nullptr);
assert(po->context != nullptr); assert(po->context != nullptr);
int error; if (pa_context_connect(po->context, po->server,
(pa_context_flags_t)0, nullptr) < 0) {
error = pa_context_connect(po->context, po->server, SetError(error, po->context,
(pa_context_flags_t)0, nullptr); "pa_context_connect() has failed");
if (error < 0) {
g_set_error(error_r, pulse_output_quark(), 0,
"pa_context_connect() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
return false; return false;
} }
...@@ -300,7 +297,7 @@ pulse_output_delete_context(PulseOutput *po) ...@@ -300,7 +297,7 @@ pulse_output_delete_context(PulseOutput *po)
* @return true on success, false on error * @return true on success, false on error
*/ */
static bool static bool
pulse_output_setup_context(PulseOutput *po, GError **error_r) pulse_output_setup_context(PulseOutput *po, Error &error)
{ {
assert(po != nullptr); assert(po != nullptr);
assert(po->mainloop != nullptr); assert(po->mainloop != nullptr);
...@@ -308,8 +305,7 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r) ...@@ -308,8 +305,7 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r)
po->context = pa_context_new(pa_threaded_mainloop_get_api(po->mainloop), po->context = pa_context_new(pa_threaded_mainloop_get_api(po->mainloop),
MPD_PULSE_NAME); MPD_PULSE_NAME);
if (po->context == nullptr) { if (po->context == nullptr) {
g_set_error(error_r, pulse_output_quark(), 0, error.Set(pulse_output_domain, "pa_context_new() has failed");
"pa_context_new() has failed");
return false; return false;
} }
...@@ -318,7 +314,7 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r) ...@@ -318,7 +314,7 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r)
pa_context_set_subscribe_callback(po->context, pa_context_set_subscribe_callback(po->context,
pulse_output_subscribe_cb, po); pulse_output_subscribe_cb, po);
if (!pulse_output_connect(po, error_r)) { if (!pulse_output_connect(po, error)) {
pulse_output_delete_context(po); pulse_output_delete_context(po);
return false; return false;
} }
...@@ -327,14 +323,14 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r) ...@@ -327,14 +323,14 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r)
} }
static struct audio_output * static struct audio_output *
pulse_output_init(const config_param &param, GError **error_r) pulse_output_init(const config_param &param, Error &error)
{ {
PulseOutput *po; PulseOutput *po;
g_setenv("PULSE_PROP_media.role", "music", true); g_setenv("PULSE_PROP_media.role", "music", true);
po = new PulseOutput(); po = new PulseOutput();
if (!ao_base_init(&po->base, &pulse_output_plugin, param, error_r)) { if (!ao_base_init(&po->base, &pulse_output_plugin, param, error)) {
delete po; delete po;
return nullptr; return nullptr;
} }
...@@ -361,7 +357,7 @@ pulse_output_finish(struct audio_output *ao) ...@@ -361,7 +357,7 @@ pulse_output_finish(struct audio_output *ao)
} }
static bool static bool
pulse_output_enable(struct audio_output *ao, GError **error_r) pulse_output_enable(struct audio_output *ao, Error &error)
{ {
PulseOutput *po = (PulseOutput *)ao; PulseOutput *po = (PulseOutput *)ao;
...@@ -374,7 +370,7 @@ pulse_output_enable(struct audio_output *ao, GError **error_r) ...@@ -374,7 +370,7 @@ pulse_output_enable(struct audio_output *ao, GError **error_r)
if (po->mainloop == nullptr) { if (po->mainloop == nullptr) {
g_free(po); g_free(po);
g_set_error(error_r, pulse_output_quark(), 0, error.Set(pulse_output_domain,
"pa_threaded_mainloop_new() has failed"); "pa_threaded_mainloop_new() has failed");
return false; return false;
} }
...@@ -386,14 +382,14 @@ pulse_output_enable(struct audio_output *ao, GError **error_r) ...@@ -386,14 +382,14 @@ pulse_output_enable(struct audio_output *ao, GError **error_r)
pa_threaded_mainloop_free(po->mainloop); pa_threaded_mainloop_free(po->mainloop);
po->mainloop = nullptr; po->mainloop = nullptr;
g_set_error(error_r, pulse_output_quark(), 0, error.Set(pulse_output_domain,
"pa_threaded_mainloop_start() has failed"); "pa_threaded_mainloop_start() has failed");
return false; return false;
} }
/* create the libpulse context and connect it */ /* create the libpulse context and connect it */
if (!pulse_output_setup_context(po, error_r)) { if (!pulse_output_setup_context(po, error)) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
pa_threaded_mainloop_stop(po->mainloop); pa_threaded_mainloop_stop(po->mainloop);
pa_threaded_mainloop_free(po->mainloop); pa_threaded_mainloop_free(po->mainloop);
...@@ -429,13 +425,13 @@ pulse_output_disable(struct audio_output *ao) ...@@ -429,13 +425,13 @@ pulse_output_disable(struct audio_output *ao)
* @return true on success, false on error * @return true on success, false on error
*/ */
static bool static bool
pulse_output_wait_connection(PulseOutput *po, GError **error_r) pulse_output_wait_connection(PulseOutput *po, Error &error)
{ {
assert(po->mainloop != nullptr); assert(po->mainloop != nullptr);
pa_context_state_t state; pa_context_state_t state;
if (po->context == nullptr && !pulse_output_setup_context(po, error_r)) if (po->context == nullptr && !pulse_output_setup_context(po, error))
return false; return false;
while (true) { while (true) {
...@@ -449,9 +445,7 @@ pulse_output_wait_connection(PulseOutput *po, GError **error_r) ...@@ -449,9 +445,7 @@ pulse_output_wait_connection(PulseOutput *po, GError **error_r)
case PA_CONTEXT_TERMINATED: case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED: case PA_CONTEXT_FAILED:
/* failure */ /* failure */
g_set_error(error_r, pulse_output_quark(), 0, SetError(error, po->context, "failed to connect");
"failed to connect: %s",
pa_strerror(pa_context_errno(po->context)));
pulse_output_delete_context(po); pulse_output_delete_context(po);
return false; return false;
...@@ -530,16 +524,14 @@ pulse_output_stream_write_cb(gcc_unused pa_stream *stream, size_t nbytes, ...@@ -530,16 +524,14 @@ pulse_output_stream_write_cb(gcc_unused pa_stream *stream, size_t nbytes,
*/ */
static bool static bool
pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss, pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss,
GError **error_r) Error &error)
{ {
assert(po != nullptr); assert(po != nullptr);
assert(po->context != nullptr); assert(po->context != nullptr);
po->stream = pa_stream_new(po->context, po->name, ss, nullptr); po->stream = pa_stream_new(po->context, po->name, ss, nullptr);
if (po->stream == nullptr) { if (po->stream == nullptr) {
g_set_error(error_r, pulse_output_quark(), 0, SetError(error, po->context, "pa_stream_new() has failed");
"pa_stream_new() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
return false; return false;
} }
...@@ -556,11 +548,10 @@ pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss, ...@@ -556,11 +548,10 @@ pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss,
static bool static bool
pulse_output_open(struct audio_output *ao, AudioFormat &audio_format, pulse_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r) Error &error)
{ {
PulseOutput *po = (PulseOutput *)ao; PulseOutput *po = (PulseOutput *)ao;
pa_sample_spec ss; pa_sample_spec ss;
int error;
assert(po->mainloop != nullptr); assert(po->mainloop != nullptr);
...@@ -585,7 +576,7 @@ pulse_output_open(struct audio_output *ao, AudioFormat &audio_format, ...@@ -585,7 +576,7 @@ pulse_output_open(struct audio_output *ao, AudioFormat &audio_format,
} }
} }
if (!pulse_output_wait_connection(po, error_r)) { if (!pulse_output_wait_connection(po, error)) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
return false; return false;
} }
...@@ -600,22 +591,20 @@ pulse_output_open(struct audio_output *ao, AudioFormat &audio_format, ...@@ -600,22 +591,20 @@ pulse_output_open(struct audio_output *ao, AudioFormat &audio_format,
/* create a stream .. */ /* create a stream .. */
if (!pulse_output_setup_stream(po, &ss, error_r)) { if (!pulse_output_setup_stream(po, &ss, error)) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
return false; return false;
} }
/* .. and connect it (asynchronously) */ /* .. and connect it (asynchronously) */
error = pa_stream_connect_playback(po->stream, po->sink, if (pa_stream_connect_playback(po->stream, po->sink,
nullptr, pa_stream_flags_t(0), nullptr, pa_stream_flags_t(0),
nullptr, nullptr); nullptr, nullptr) < 0) {
if (error < 0) {
pulse_output_delete_stream(po); pulse_output_delete_stream(po);
g_set_error(error_r, pulse_output_quark(), 0, SetError(error, po->context,
"pa_stream_connect_playback() has failed: %s", "pa_stream_connect_playback() has failed");
pa_strerror(pa_context_errno(po->context)));
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
return false; return false;
} }
...@@ -661,7 +650,7 @@ pulse_output_close(struct audio_output *ao) ...@@ -661,7 +650,7 @@ pulse_output_close(struct audio_output *ao)
* @return true on success, false on error * @return true on success, false on error
*/ */
static bool static bool
pulse_output_wait_stream(PulseOutput *po, GError **error_r) pulse_output_wait_stream(PulseOutput *po, Error &error)
{ {
while (true) { while (true) {
switch (pa_stream_get_state(po->stream)) { switch (pa_stream_get_state(po->stream)) {
...@@ -671,10 +660,8 @@ pulse_output_wait_stream(PulseOutput *po, GError **error_r) ...@@ -671,10 +660,8 @@ pulse_output_wait_stream(PulseOutput *po, GError **error_r)
case PA_STREAM_FAILED: case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED: case PA_STREAM_TERMINATED:
case PA_STREAM_UNCONNECTED: case PA_STREAM_UNCONNECTED:
g_set_error(error_r, pulse_output_quark(), SetError(error, po->context,
pa_context_errno(po->context), "failed to connect the stream");
"failed to connect the stream: %s",
pa_strerror(pa_context_errno(po->context)));
return false; return false;
case PA_STREAM_CREATING: case PA_STREAM_CREATING:
...@@ -689,7 +676,7 @@ pulse_output_wait_stream(PulseOutput *po, GError **error_r) ...@@ -689,7 +676,7 @@ pulse_output_wait_stream(PulseOutput *po, GError **error_r)
*/ */
static bool static bool
pulse_output_stream_pause(PulseOutput *po, bool pause, pulse_output_stream_pause(PulseOutput *po, bool pause,
GError **error_r) Error &error)
{ {
pa_operation *o; pa_operation *o;
...@@ -700,16 +687,12 @@ pulse_output_stream_pause(PulseOutput *po, bool pause, ...@@ -700,16 +687,12 @@ pulse_output_stream_pause(PulseOutput *po, bool pause,
o = pa_stream_cork(po->stream, pause, o = pa_stream_cork(po->stream, pause,
pulse_output_stream_success_cb, po); pulse_output_stream_success_cb, po);
if (o == nullptr) { if (o == nullptr) {
g_set_error(error_r, pulse_output_quark(), 0, SetError(error, po->context, "pa_stream_cork() has failed");
"pa_stream_cork() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
return false; return false;
} }
if (!pulse_wait_for_operation(po->mainloop, o)) { if (!pulse_wait_for_operation(po->mainloop, o)) {
g_set_error(error_r, pulse_output_quark(), 0, SetError(error, po->context, "pa_stream_cork() has failed");
"pa_stream_cork() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
return false; return false;
} }
...@@ -736,10 +719,9 @@ pulse_output_delay(struct audio_output *ao) ...@@ -736,10 +719,9 @@ pulse_output_delay(struct audio_output *ao)
static size_t static size_t
pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r) Error &error)
{ {
PulseOutput *po = (PulseOutput *)ao; PulseOutput *po = (PulseOutput *)ao;
int error;
assert(po->mainloop != nullptr); assert(po->mainloop != nullptr);
assert(po->stream != nullptr); assert(po->stream != nullptr);
...@@ -748,7 +730,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -748,7 +730,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
/* check if the stream is (already) connected */ /* check if the stream is (already) connected */
if (!pulse_output_wait_stream(po, error_r)) { if (!pulse_output_wait_stream(po, error)) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
return 0; return 0;
} }
...@@ -758,7 +740,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -758,7 +740,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
/* unpause if previously paused */ /* unpause if previously paused */
if (pa_stream_is_corked(po->stream) && if (pa_stream_is_corked(po->stream) &&
!pulse_output_stream_pause(po, false, error_r)) { !pulse_output_stream_pause(po, false, error)) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
return 0; return 0;
} }
...@@ -768,8 +750,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -768,8 +750,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
while (po->writable == 0) { while (po->writable == 0) {
if (pa_stream_is_suspended(po->stream)) { if (pa_stream_is_suspended(po->stream)) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
g_set_error(error_r, pulse_output_quark(), 0, error.Set(pulse_output_domain, "suspended");
"suspended");
return 0; return 0;
} }
...@@ -777,8 +758,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -777,8 +758,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
if (pa_stream_get_state(po->stream) != PA_STREAM_READY) { if (pa_stream_get_state(po->stream) != PA_STREAM_READY) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
g_set_error(error_r, pulse_output_quark(), 0, error.Set(pulse_output_domain, "disconnected");
"disconnected");
return 0; return 0;
} }
} }
...@@ -791,12 +771,11 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size, ...@@ -791,12 +771,11 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
po->writable -= size; po->writable -= size;
error = pa_stream_write(po->stream, chunk, size, nullptr, int result = pa_stream_write(po->stream, chunk, size, nullptr,
0, PA_SEEK_RELATIVE); 0, PA_SEEK_RELATIVE);
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
if (error < 0) { if (result < 0) {
g_set_error(error_r, pulse_output_quark(), error, SetError(error, po->context, "pa_stream_write() failed");
"%s", pa_strerror(error));
return 0; return 0;
} }
...@@ -839,7 +818,6 @@ static bool ...@@ -839,7 +818,6 @@ static bool
pulse_output_pause(struct audio_output *ao) pulse_output_pause(struct audio_output *ao)
{ {
PulseOutput *po = (PulseOutput *)ao; PulseOutput *po = (PulseOutput *)ao;
GError *error = nullptr;
assert(po->mainloop != nullptr); assert(po->mainloop != nullptr);
assert(po->stream != nullptr); assert(po->stream != nullptr);
...@@ -848,10 +826,10 @@ pulse_output_pause(struct audio_output *ao) ...@@ -848,10 +826,10 @@ pulse_output_pause(struct audio_output *ao)
/* check if the stream is (already/still) connected */ /* check if the stream is (already/still) connected */
if (!pulse_output_wait_stream(po, &error)) { Error error;
if (!pulse_output_wait_stream(po, error)) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return false; return false;
} }
...@@ -860,10 +838,9 @@ pulse_output_pause(struct audio_output *ao) ...@@ -860,10 +838,9 @@ pulse_output_pause(struct audio_output *ao)
/* cork the stream */ /* cork the stream */
if (!pa_stream_is_corked(po->stream) && if (!pa_stream_is_corked(po->stream) &&
!pulse_output_stream_pause(po, true, &error)) { !pulse_output_stream_pause(po, true, error)) {
pa_threaded_mainloop_unlock(po->mainloop); pa_threaded_mainloop_unlock(po->mainloop);
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return false; return false;
} }
...@@ -878,11 +855,12 @@ pulse_output_test_default_device(void) ...@@ -878,11 +855,12 @@ pulse_output_test_default_device(void)
bool success; bool success;
const config_param empty; const config_param empty;
PulseOutput *po = (PulseOutput *)pulse_output_init(empty, nullptr); PulseOutput *po = (PulseOutput *)
pulse_output_init(empty, IgnoreError());
if (po == nullptr) if (po == nullptr)
return false; return false;
success = pulse_output_wait_connection(po, nullptr); success = pulse_output_wait_connection(po, IgnoreError());
pulse_output_finish(&po->base); pulse_output_finish(&po->base);
return success; return success;
......
...@@ -20,11 +20,10 @@ ...@@ -20,11 +20,10 @@
#ifndef MPD_PULSE_OUTPUT_PLUGIN_HXX #ifndef MPD_PULSE_OUTPUT_PLUGIN_HXX
#define MPD_PULSE_OUTPUT_PLUGIN_HXX #define MPD_PULSE_OUTPUT_PLUGIN_HXX
#include "gerror.h"
struct PulseOutput; struct PulseOutput;
struct PulseMixer; struct PulseMixer;
struct pa_cvolume; struct pa_cvolume;
class Error;
extern const struct audio_output_plugin pulse_output_plugin; extern const struct audio_output_plugin pulse_output_plugin;
...@@ -42,6 +41,6 @@ pulse_output_clear_mixer(PulseOutput *po, PulseMixer *pm); ...@@ -42,6 +41,6 @@ pulse_output_clear_mixer(PulseOutput *po, PulseMixer *pm);
bool bool
pulse_output_set_volume(PulseOutput *po, pulse_output_set_volume(PulseOutput *po,
const struct pa_cvolume *volume, GError **error_r); const struct pa_cvolume *volume, Error &error);
#endif #endif
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "EncoderPlugin.hxx" #include "EncoderPlugin.hxx"
#include "EncoderList.hxx" #include "EncoderList.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "open.h" #include "open.h"
...@@ -57,7 +60,7 @@ struct RecorderOutput { ...@@ -57,7 +60,7 @@ struct RecorderOutput {
*/ */
char buffer[32768]; char buffer[32768];
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &recorder_output_plugin, param, return ao_base_init(&base, &recorder_output_plugin, param,
error_r); error_r);
} }
...@@ -66,27 +69,20 @@ struct RecorderOutput { ...@@ -66,27 +69,20 @@ struct RecorderOutput {
ao_base_finish(&base); ao_base_finish(&base);
} }
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
bool WriteToFile(const void *data, size_t length, GError **error_r); bool WriteToFile(const void *data, size_t length, Error &error);
/** /**
* Writes pending data from the encoder to the output file. * Writes pending data from the encoder to the output file.
*/ */
bool EncoderToFile(GError **error_r); bool EncoderToFile(Error &error);
}; };
/** static constexpr Domain recorder_output_domain("recorder_output");
* The quark used for GError.domain.
*/
static inline GQuark
recorder_output_quark(void)
{
return g_quark_from_static_string("recorder_output");
}
inline bool inline bool
RecorderOutput::Configure(const config_param &param, GError **error_r) RecorderOutput::Configure(const config_param &param, Error &error)
{ {
/* read configuration */ /* read configuration */
...@@ -94,21 +90,20 @@ RecorderOutput::Configure(const config_param &param, GError **error_r) ...@@ -94,21 +90,20 @@ RecorderOutput::Configure(const config_param &param, GError **error_r)
param.GetBlockValue("encoder", "vorbis"); param.GetBlockValue("encoder", "vorbis");
const auto encoder_plugin = encoder_plugin_get(encoder_name); const auto encoder_plugin = encoder_plugin_get(encoder_name);
if (encoder_plugin == nullptr) { if (encoder_plugin == nullptr) {
g_set_error(error_r, recorder_output_quark(), 0, error.Format(config_domain,
"No such encoder: %s", encoder_name); "No such encoder: %s", encoder_name);
return false; return false;
} }
path = param.GetBlockValue("path"); path = param.GetBlockValue("path");
if (path == nullptr) { if (path == nullptr) {
g_set_error(error_r, recorder_output_quark(), 0, error.Set(config_domain, "'path' not configured");
"'path' not configured");
return false; return false;
} }
/* initialize encoder */ /* initialize encoder */
encoder = encoder_init(*encoder_plugin, param, error_r); encoder = encoder_init(*encoder_plugin, param, error);
if (encoder == nullptr) if (encoder == nullptr)
return false; return false;
...@@ -116,16 +111,16 @@ RecorderOutput::Configure(const config_param &param, GError **error_r) ...@@ -116,16 +111,16 @@ RecorderOutput::Configure(const config_param &param, GError **error_r)
} }
static audio_output * static audio_output *
recorder_output_init(const config_param &param, GError **error_r) recorder_output_init(const config_param &param, Error &error)
{ {
RecorderOutput *recorder = new RecorderOutput(); RecorderOutput *recorder = new RecorderOutput();
if (!recorder->Initialize(param, error_r)) { if (!recorder->Initialize(param, error)) {
delete recorder; delete recorder;
return nullptr; return nullptr;
} }
if (!recorder->Configure(param, error_r)) { if (!recorder->Configure(param, error)) {
recorder->Deinitialize(); recorder->Deinitialize();
delete recorder; delete recorder;
return nullptr; return nullptr;
...@@ -145,7 +140,7 @@ recorder_output_finish(struct audio_output *ao) ...@@ -145,7 +140,7 @@ recorder_output_finish(struct audio_output *ao)
} }
inline bool inline bool
RecorderOutput::WriteToFile(const void *_data, size_t length, GError **error_r) RecorderOutput::WriteToFile(const void *_data, size_t length, Error &error)
{ {
assert(length > 0); assert(length > 0);
...@@ -159,20 +154,18 @@ RecorderOutput::WriteToFile(const void *_data, size_t length, GError **error_r) ...@@ -159,20 +154,18 @@ RecorderOutput::WriteToFile(const void *_data, size_t length, GError **error_r)
return true; return true;
} else if (nbytes == 0) { } else if (nbytes == 0) {
/* shouldn't happen for files */ /* shouldn't happen for files */
g_set_error(error_r, recorder_output_quark(), 0, error.Set(recorder_output_domain,
"write() returned 0"); "write() returned 0");
return false; return false;
} else if (errno != EINTR) { } else if (errno != EINTR) {
g_set_error(error_r, recorder_output_quark(), 0, error.FormatErrno("Failed to write to '%s'", path);
"Failed to write to '%s': %s",
path, g_strerror(errno));
return false; return false;
} }
} }
} }
inline bool inline bool
RecorderOutput::EncoderToFile(GError **error_r) RecorderOutput::EncoderToFile(Error &error)
{ {
assert(fd >= 0); assert(fd >= 0);
...@@ -185,7 +178,7 @@ RecorderOutput::EncoderToFile(GError **error_r) ...@@ -185,7 +178,7 @@ RecorderOutput::EncoderToFile(GError **error_r)
/* write everything into the file */ /* write everything into the file */
if (!WriteToFile(buffer, size, error_r)) if (!WriteToFile(buffer, size, error))
return false; return false;
} }
} }
...@@ -193,7 +186,7 @@ RecorderOutput::EncoderToFile(GError **error_r) ...@@ -193,7 +186,7 @@ RecorderOutput::EncoderToFile(GError **error_r)
static bool static bool
recorder_output_open(struct audio_output *ao, recorder_output_open(struct audio_output *ao,
AudioFormat &audio_format, AudioFormat &audio_format,
GError **error_r) Error &error)
{ {
RecorderOutput *recorder = (RecorderOutput *)ao; RecorderOutput *recorder = (RecorderOutput *)ao;
...@@ -203,21 +196,19 @@ recorder_output_open(struct audio_output *ao, ...@@ -203,21 +196,19 @@ recorder_output_open(struct audio_output *ao,
O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY,
0666); 0666);
if (recorder->fd < 0) { if (recorder->fd < 0) {
g_set_error(error_r, recorder_output_quark(), 0, error.FormatErrno("Failed to create '%s'", recorder->path);
"Failed to create '%s': %s",
recorder->path, g_strerror(errno));
return false; return false;
} }
/* open the encoder */ /* open the encoder */
if (!encoder_open(recorder->encoder, audio_format, error_r)) { if (!encoder_open(recorder->encoder, audio_format, error)) {
close(recorder->fd); close(recorder->fd);
unlink(recorder->path); unlink(recorder->path);
return false; return false;
} }
if (!recorder->EncoderToFile(error_r)) { if (!recorder->EncoderToFile(error)) {
encoder_close(recorder->encoder); encoder_close(recorder->encoder);
close(recorder->fd); close(recorder->fd);
unlink(recorder->path); unlink(recorder->path);
...@@ -234,8 +225,8 @@ recorder_output_close(struct audio_output *ao) ...@@ -234,8 +225,8 @@ recorder_output_close(struct audio_output *ao)
/* flush the encoder and write the rest to the file */ /* flush the encoder and write the rest to the file */
if (encoder_end(recorder->encoder, nullptr)) if (encoder_end(recorder->encoder, IgnoreError()))
recorder->EncoderToFile(nullptr); recorder->EncoderToFile(IgnoreError());
/* now really close everything */ /* now really close everything */
...@@ -246,12 +237,12 @@ recorder_output_close(struct audio_output *ao) ...@@ -246,12 +237,12 @@ recorder_output_close(struct audio_output *ao)
static size_t static size_t
recorder_output_play(struct audio_output *ao, const void *chunk, size_t size, recorder_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r) Error &error)
{ {
RecorderOutput *recorder = (RecorderOutput *)ao; RecorderOutput *recorder = (RecorderOutput *)ao;
return encoder_write(recorder->encoder, chunk, size, error_r) && return encoder_write(recorder->encoder, chunk, size, error) &&
recorder->EncoderToFile(error_r) recorder->EncoderToFile(error)
? size : 0; ? size : 0;
} }
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "MixerList.hxx" #include "MixerList.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -58,11 +60,7 @@ struct RoarOutput { ...@@ -58,11 +60,7 @@ struct RoarOutput {
} }
}; };
static inline GQuark static constexpr Domain roar_output_domain("roar_output");
roar_output_quark(void)
{
return g_quark_from_static_string("roar_output");
}
static int static int
roar_output_get_volume_locked(RoarOutput *roar) roar_output_get_volume_locked(RoarOutput *roar)
...@@ -120,11 +118,11 @@ roar_configure(RoarOutput *self, const config_param &param) ...@@ -120,11 +118,11 @@ roar_configure(RoarOutput *self, const config_param &param)
} }
static struct audio_output * static struct audio_output *
roar_init(const config_param &param, GError **error_r) roar_init(const config_param &param, Error &error)
{ {
RoarOutput *self = new RoarOutput(); RoarOutput *self = new RoarOutput();
if (!ao_base_init(&self->base, &roar_output_plugin, param, error_r)) { if (!ao_base_init(&self->base, &roar_output_plugin, param, error)) {
delete self; delete self;
return nullptr; return nullptr;
} }
...@@ -178,14 +176,14 @@ roar_use_audio_format(struct roar_audio_info *info, ...@@ -178,14 +176,14 @@ roar_use_audio_format(struct roar_audio_info *info,
} }
static bool static bool
roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) roar_open(struct audio_output *ao, AudioFormat &audio_format, Error &error)
{ {
RoarOutput *self = (RoarOutput *)ao; RoarOutput *self = (RoarOutput *)ao;
const ScopeLock protect(self->mutex); const ScopeLock protect(self->mutex);
if (roar_simple_connect(&(self->con), self->host, self->name) < 0) if (roar_simple_connect(&(self->con), self->host, self->name) < 0)
{ {
g_set_error(error, roar_output_quark(), 0, error.Set(roar_output_domain,
"Failed to connect to Roar server"); "Failed to connect to Roar server");
return false; return false;
} }
...@@ -194,8 +192,7 @@ roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) ...@@ -194,8 +192,7 @@ roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
if (self->vss == nullptr || self->err != ROAR_ERROR_NONE) if (self->vss == nullptr || self->err != ROAR_ERROR_NONE)
{ {
g_set_error(error, roar_output_quark(), 0, error.Set(roar_output_domain, "Failed to connect to server");
"Failed to connect to server");
return false; return false;
} }
...@@ -204,7 +201,7 @@ roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error) ...@@ -204,7 +201,7 @@ roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
if (roar_vs_stream(self->vss, &(self->info), ROAR_DIR_PLAY, if (roar_vs_stream(self->vss, &(self->info), ROAR_DIR_PLAY,
&(self->err)) < 0) &(self->err)) < 0)
{ {
g_set_error(error, roar_output_quark(), 0, "Failed to start stream"); error.Set(roar_output_domain, "Failed to start stream");
return false; return false;
} }
roar_vs_role(self->vss, self->role, &(self->err)); roar_vs_role(self->vss, self->role, &(self->err));
...@@ -264,21 +261,22 @@ roar_cancel(struct audio_output *ao) ...@@ -264,21 +261,22 @@ roar_cancel(struct audio_output *ao)
} }
static size_t static size_t
roar_play(struct audio_output *ao, const void *chunk, size_t size, GError **error) roar_play(struct audio_output *ao, const void *chunk, size_t size,
Error &error)
{ {
RoarOutput *self = (RoarOutput *)ao; RoarOutput *self = (RoarOutput *)ao;
ssize_t rc; ssize_t rc;
if (self->vss == nullptr) if (self->vss == nullptr)
{ {
g_set_error(error, roar_output_quark(), 0, "Connection is invalid"); error.Set(roar_output_domain, "Connection is invalid");
return 0; return 0;
} }
rc = roar_vs_write(self->vss, chunk, size, &(self->err)); rc = roar_vs_write(self->vss, chunk, size, &(self->err));
if ( rc <= 0 ) if ( rc <= 0 )
{ {
g_set_error(error, roar_output_quark(), 0, "Failed to play data"); error.Set(roar_output_domain, "Failed to play data");
return 0; return 0;
} }
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "EncoderPlugin.hxx" #include "EncoderPlugin.hxx"
#include "EncoderList.hxx" #include "EncoderList.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "mpd_error.h" #include "mpd_error.h"
#include <shout/shout.h> #include <shout/shout.h>
...@@ -66,28 +69,21 @@ struct ShoutOutput final { ...@@ -66,28 +69,21 @@ struct ShoutOutput final {
shout_free(shout_conn); shout_free(shout_conn);
} }
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &shout_output_plugin, param, return ao_base_init(&base, &shout_output_plugin, param,
error_r); error);
} }
void Deinitialize() { void Deinitialize() {
ao_base_finish(&base); ao_base_finish(&base);
} }
bool Configure(const config_param &param, GError **error_r); bool Configure(const config_param &param, Error &error);
}; };
static int shout_init_count; static int shout_init_count;
/** static constexpr Domain shout_output_domain("shout_output");
* The quark used for GError.domain.
*/
static inline GQuark
shout_output_quark(void)
{
return g_quark_from_static_string("shout_output");
}
static const EncoderPlugin * static const EncoderPlugin *
shout_encoder_plugin_get(const char *name) shout_encoder_plugin_get(const char *name)
...@@ -113,12 +109,12 @@ require_block_string(const config_param &param, const char *name) ...@@ -113,12 +109,12 @@ require_block_string(const config_param &param, const char *name)
} }
inline bool inline bool
ShoutOutput::Configure(const config_param &param, GError **error_r) ShoutOutput::Configure(const config_param &param, Error &error)
{ {
const AudioFormat audio_format = base.config_audio_format; const AudioFormat audio_format = base.config_audio_format;
if (!audio_format.IsFullyDefined()) { if (!audio_format.IsFullyDefined()) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(config_domain,
"Need full audio format specification"); "Need full audio format specification");
return nullptr; return nullptr;
} }
...@@ -127,8 +123,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -127,8 +123,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
const char *mount = require_block_string(param, "mount"); const char *mount = require_block_string(param, "mount");
unsigned port = param.GetBlockValue("port", 0u); unsigned port = param.GetBlockValue("port", 0u);
if (port == 0) { if (port == 0) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(config_domain, "shout port must be configured");
"shout port must be configured");
return false; return false;
} }
...@@ -145,7 +140,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -145,7 +140,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
quality = strtod(value, &test); quality = strtod(value, &test);
if (*test != '\0' || quality < -1.0 || quality > 10.0) { if (*test != '\0' || quality < -1.0 || quality > 10.0) {
g_set_error(error_r, shout_output_quark(), 0, error.Format(config_domain,
"shout quality \"%s\" is not a number in the " "shout quality \"%s\" is not a number in the "
"range -1 to 10, line %i", "range -1 to 10, line %i",
value, param.line); value, param.line);
...@@ -153,7 +148,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -153,7 +148,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
} }
if (param.GetBlockValue("bitrate") != nullptr) { if (param.GetBlockValue("bitrate") != nullptr) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(config_domain,
"quality and bitrate are " "quality and bitrate are "
"both defined"); "both defined");
return false; return false;
...@@ -161,7 +156,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -161,7 +156,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
} else { } else {
value = param.GetBlockValue("bitrate"); value = param.GetBlockValue("bitrate");
if (value == nullptr) { if (value == nullptr) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(config_domain,
"neither bitrate nor quality defined"); "neither bitrate nor quality defined");
return false; return false;
} }
...@@ -170,7 +165,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -170,7 +165,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
bitrate = strtol(value, &test, 10); bitrate = strtol(value, &test, 10);
if (*test != '\0' || bitrate <= 0) { if (*test != '\0' || bitrate <= 0) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(config_domain,
"bitrate must be a positive integer"); "bitrate must be a positive integer");
return false; return false;
} }
...@@ -179,13 +174,13 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -179,13 +174,13 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
const char *encoding = param.GetBlockValue("encoding", "ogg"); const char *encoding = param.GetBlockValue("encoding", "ogg");
const auto encoder_plugin = shout_encoder_plugin_get(encoding); const auto encoder_plugin = shout_encoder_plugin_get(encoding);
if (encoder_plugin == nullptr) { if (encoder_plugin == nullptr) {
g_set_error(error_r, shout_output_quark(), 0, error.Format(config_domain,
"couldn't find shout encoder plugin \"%s\"", "couldn't find shout encoder plugin \"%s\"",
encoding); encoding);
return false; return false;
} }
encoder = encoder_init(*encoder_plugin, param, error_r); encoder = encoder_init(*encoder_plugin, param, error);
if (encoder == nullptr) if (encoder == nullptr)
return false; return false;
...@@ -200,7 +195,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -200,7 +195,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
if (value != nullptr) { if (value != nullptr) {
if (0 == strcmp(value, "shoutcast") && if (0 == strcmp(value, "shoutcast") &&
0 != strcmp(encoding, "mp3")) { 0 != strcmp(encoding, "mp3")) {
g_set_error(error_r, shout_output_quark(), 0, error.Format(config_domain,
"you cannot stream \"%s\" to shoutcast, use mp3", "you cannot stream \"%s\" to shoutcast, use mp3",
encoding); encoding);
return false; return false;
...@@ -211,7 +206,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -211,7 +206,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
else if (0 == strcmp(value, "icecast2")) else if (0 == strcmp(value, "icecast2"))
protocol = SHOUT_PROTOCOL_HTTP; protocol = SHOUT_PROTOCOL_HTTP;
else { else {
g_set_error(error_r, shout_output_quark(), 0, error.Format(config_domain,
"shout protocol \"%s\" is not \"shoutcast\" or " "shout protocol \"%s\" is not \"shoutcast\" or "
"\"icecast1\"or \"icecast2\"", "\"icecast1\"or \"icecast2\"",
value); value);
...@@ -232,8 +227,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -232,8 +227,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
!= SHOUTERR_SUCCESS || != SHOUTERR_SUCCESS ||
shout_set_protocol(shout_conn, protocol) != SHOUTERR_SUCCESS || shout_set_protocol(shout_conn, protocol) != SHOUTERR_SUCCESS ||
shout_set_agent(shout_conn, "MPD") != SHOUTERR_SUCCESS) { shout_set_agent(shout_conn, "MPD") != SHOUTERR_SUCCESS) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(shout_output_domain, shout_get_error(shout_conn));
"%s", shout_get_error(shout_conn));
return false; return false;
} }
...@@ -242,22 +236,19 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -242,22 +236,19 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
value = param.GetBlockValue("genre"); value = param.GetBlockValue("genre");
if (value != nullptr && shout_set_genre(shout_conn, value)) { if (value != nullptr && shout_set_genre(shout_conn, value)) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(shout_output_domain, shout_get_error(shout_conn));
"%s", shout_get_error(shout_conn));
return false; return false;
} }
value = param.GetBlockValue("description"); value = param.GetBlockValue("description");
if (value != nullptr && shout_set_description(shout_conn, value)) { if (value != nullptr && shout_set_description(shout_conn, value)) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(shout_output_domain, shout_get_error(shout_conn));
"%s", shout_get_error(shout_conn));
return false; return false;
} }
value = param.GetBlockValue("url"); value = param.GetBlockValue("url");
if (value != nullptr && shout_set_url(shout_conn, value)) { if (value != nullptr && shout_set_url(shout_conn, value)) {
g_set_error(error_r, shout_output_quark(), 0, error.Set(shout_output_domain, shout_get_error(shout_conn));
"%s", shout_get_error(shout_conn));
return false; return false;
} }
...@@ -287,15 +278,15 @@ ShoutOutput::Configure(const config_param &param, GError **error_r) ...@@ -287,15 +278,15 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
} }
static struct audio_output * static struct audio_output *
my_shout_init_driver(const config_param &param, GError **error_r) my_shout_init_driver(const config_param &param, Error &error)
{ {
ShoutOutput *sd = new ShoutOutput(); ShoutOutput *sd = new ShoutOutput();
if (!sd->Initialize(param, error_r)) { if (!sd->Initialize(param, error)) {
delete sd; delete sd;
return nullptr; return nullptr;
} }
if (!sd->Configure(param, error_r)) { if (!sd->Configure(param, error)) {
sd->Deinitialize(); sd->Deinitialize();
delete sd; delete sd;
return nullptr; return nullptr;
...@@ -310,7 +301,7 @@ my_shout_init_driver(const config_param &param, GError **error_r) ...@@ -310,7 +301,7 @@ my_shout_init_driver(const config_param &param, GError **error_r)
} }
static bool static bool
handle_shout_error(ShoutOutput *sd, int err, GError **error) handle_shout_error(ShoutOutput *sd, int err, Error &error)
{ {
switch (err) { switch (err) {
case SHOUTERR_SUCCESS: case SHOUTERR_SUCCESS:
...@@ -318,7 +309,7 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error) ...@@ -318,7 +309,7 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error)
case SHOUTERR_UNCONNECTED: case SHOUTERR_UNCONNECTED:
case SHOUTERR_SOCKET: case SHOUTERR_SOCKET:
g_set_error(error, shout_output_quark(), err, error.Format(shout_output_domain, err,
"Lost shout connection to %s:%i: %s", "Lost shout connection to %s:%i: %s",
shout_get_host(sd->shout_conn), shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn), shout_get_port(sd->shout_conn),
...@@ -326,7 +317,7 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error) ...@@ -326,7 +317,7 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error)
return false; return false;
default: default:
g_set_error(error, shout_output_quark(), err, error.Format(shout_output_domain, err,
"connection to %s:%i error: %s", "connection to %s:%i error: %s",
shout_get_host(sd->shout_conn), shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn), shout_get_port(sd->shout_conn),
...@@ -338,7 +329,7 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error) ...@@ -338,7 +329,7 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error)
} }
static bool static bool
write_page(ShoutOutput *sd, GError **error) write_page(ShoutOutput *sd, Error &error)
{ {
assert(sd->encoder != nullptr); assert(sd->encoder != nullptr);
...@@ -359,8 +350,8 @@ write_page(ShoutOutput *sd, GError **error) ...@@ -359,8 +350,8 @@ write_page(ShoutOutput *sd, GError **error)
static void close_shout_conn(ShoutOutput * sd) static void close_shout_conn(ShoutOutput * sd)
{ {
if (sd->encoder != nullptr) { if (sd->encoder != nullptr) {
if (encoder_end(sd->encoder, nullptr)) if (encoder_end(sd->encoder, IgnoreError()))
write_page(sd, nullptr); write_page(sd, IgnoreError());
encoder_close(sd->encoder); encoder_close(sd->encoder);
} }
...@@ -406,7 +397,7 @@ my_shout_close_device(struct audio_output *ao) ...@@ -406,7 +397,7 @@ my_shout_close_device(struct audio_output *ao)
} }
static bool static bool
shout_connect(ShoutOutput *sd, GError **error) shout_connect(ShoutOutput *sd, Error &error)
{ {
switch (shout_open(sd->shout_conn)) { switch (shout_open(sd->shout_conn)) {
case SHOUTERR_SUCCESS: case SHOUTERR_SUCCESS:
...@@ -414,7 +405,7 @@ shout_connect(ShoutOutput *sd, GError **error) ...@@ -414,7 +405,7 @@ shout_connect(ShoutOutput *sd, GError **error)
return true; return true;
default: default:
g_set_error(error, shout_output_quark(), 0, error.Format(shout_output_domain,
"problem opening connection to shout server %s:%i: %s", "problem opening connection to shout server %s:%i: %s",
shout_get_host(sd->shout_conn), shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn), shout_get_port(sd->shout_conn),
...@@ -425,7 +416,7 @@ shout_connect(ShoutOutput *sd, GError **error) ...@@ -425,7 +416,7 @@ shout_connect(ShoutOutput *sd, GError **error)
static bool static bool
my_shout_open_device(struct audio_output *ao, AudioFormat &audio_format, my_shout_open_device(struct audio_output *ao, AudioFormat &audio_format,
GError **error) Error &error)
{ {
ShoutOutput *sd = (ShoutOutput *)ao; ShoutOutput *sd = (ShoutOutput *)ao;
...@@ -460,7 +451,7 @@ my_shout_delay(struct audio_output *ao) ...@@ -460,7 +451,7 @@ my_shout_delay(struct audio_output *ao)
static size_t static size_t
my_shout_play(struct audio_output *ao, const void *chunk, size_t size, my_shout_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error) Error &error)
{ {
ShoutOutput *sd = (ShoutOutput *)ao; ShoutOutput *sd = (ShoutOutput *)ao;
...@@ -475,7 +466,7 @@ my_shout_pause(struct audio_output *ao) ...@@ -475,7 +466,7 @@ my_shout_pause(struct audio_output *ao)
{ {
static char silence[1020]; static char silence[1020];
return my_shout_play(ao, silence, sizeof(silence), nullptr); return my_shout_play(ao, silence, sizeof(silence), IgnoreError());
} }
static void static void
...@@ -508,24 +499,17 @@ static void my_shout_set_tag(struct audio_output *ao, ...@@ -508,24 +499,17 @@ static void my_shout_set_tag(struct audio_output *ao,
const Tag *tag) const Tag *tag)
{ {
ShoutOutput *sd = (ShoutOutput *)ao; ShoutOutput *sd = (ShoutOutput *)ao;
GError *error = nullptr;
if (sd->encoder->plugin.tag != nullptr) { if (sd->encoder->plugin.tag != nullptr) {
/* encoder plugin supports stream tags */ /* encoder plugin supports stream tags */
if (!encoder_pre_tag(sd->encoder, &error)) { Error error;
g_warning("%s", error->message); if (!encoder_pre_tag(sd->encoder, error) ||
g_error_free(error); !write_page(sd, error) ||
!encoder_tag(sd->encoder, tag, error)) {
g_warning("%s", error.GetMessage());
return; return;
} }
if (!write_page(sd, nullptr))
return;
if (!encoder_tag(sd->encoder, tag, &error)) {
g_warning("%s", error->message);
g_error_free(error);
}
} else { } else {
/* no stream tag support: fall back to icy-metadata */ /* no stream tag support: fall back to icy-metadata */
char song[1024]; char song[1024];
...@@ -538,7 +522,7 @@ static void my_shout_set_tag(struct audio_output *ao, ...@@ -538,7 +522,7 @@ static void my_shout_set_tag(struct audio_output *ao,
} }
} }
write_page(sd, nullptr); write_page(sd, IgnoreError());
} }
const struct audio_output_plugin shout_output_plugin = { const struct audio_output_plugin shout_output_plugin = {
......
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
#include "SolarisOutputPlugin.hxx" #include "SolarisOutputPlugin.hxx"
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "util/Error.hxx"
#include <glib.h>
#include <sys/stropts.h> #include <sys/stropts.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -61,7 +60,7 @@ struct SolarisOutput { ...@@ -61,7 +60,7 @@ struct SolarisOutput {
int fd; int fd;
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &solaris_output_plugin, param, return ao_base_init(&base, &solaris_output_plugin, param,
error_r); error_r);
} }
...@@ -71,15 +70,6 @@ struct SolarisOutput { ...@@ -71,15 +70,6 @@ struct SolarisOutput {
} }
}; };
/**
* The quark used for GError.domain.
*/
static inline GQuark
solaris_output_quark(void)
{
return g_quark_from_static_string("solaris_output");
}
static bool static bool
solaris_output_test_default_device(void) solaris_output_test_default_device(void)
{ {
...@@ -90,7 +80,7 @@ solaris_output_test_default_device(void) ...@@ -90,7 +80,7 @@ solaris_output_test_default_device(void)
} }
static struct audio_output * static struct audio_output *
solaris_output_init(const config_param &param, GError **error_r) solaris_output_init(const config_param &param, Error &error_r)
{ {
SolarisOutput *so = new SolarisOutput(); SolarisOutput *so = new SolarisOutput();
if (!so->Initialize(param, error_r)) { if (!so->Initialize(param, error_r)) {
...@@ -114,7 +104,7 @@ solaris_output_finish(struct audio_output *ao) ...@@ -114,7 +104,7 @@ solaris_output_finish(struct audio_output *ao)
static bool static bool
solaris_output_open(struct audio_output *ao, AudioFormat &audio_format, solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) Error &error)
{ {
SolarisOutput *so = (SolarisOutput *)ao; SolarisOutput *so = (SolarisOutput *)ao;
struct audio_info info; struct audio_info info;
...@@ -128,9 +118,8 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format, ...@@ -128,9 +118,8 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
so->fd = open_cloexec(so->device, O_WRONLY|O_NONBLOCK, 0); so->fd = open_cloexec(so->device, O_WRONLY|O_NONBLOCK, 0);
if (so->fd < 0) { if (so->fd < 0) {
g_set_error(error, solaris_output_quark(), errno, error.FormatErrno("Failed to open %s",
"Failed to open %s: %s", so->device);
so->device, g_strerror(errno));
return false; return false;
} }
...@@ -144,8 +133,7 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format, ...@@ -144,8 +133,7 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
ret = ioctl(so->fd, AUDIO_GETINFO, &info); ret = ioctl(so->fd, AUDIO_GETINFO, &info);
if (ret < 0) { if (ret < 0) {
g_set_error(error, solaris_output_quark(), errno, error.SetErrno("AUDIO_GETINFO failed");
"AUDIO_GETINFO failed: %s", g_strerror(errno));
close(so->fd); close(so->fd);
return false; return false;
} }
...@@ -157,8 +145,7 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format, ...@@ -157,8 +145,7 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
ret = ioctl(so->fd, AUDIO_SETINFO, &info); ret = ioctl(so->fd, AUDIO_SETINFO, &info);
if (ret < 0) { if (ret < 0) {
g_set_error(error, solaris_output_quark(), errno, error.SetErrno("AUDIO_SETINFO failed");
"AUDIO_SETINFO failed: %s", g_strerror(errno));
close(so->fd); close(so->fd);
return false; return false;
} }
...@@ -176,15 +163,14 @@ solaris_output_close(struct audio_output *ao) ...@@ -176,15 +163,14 @@ solaris_output_close(struct audio_output *ao)
static size_t static size_t
solaris_output_play(struct audio_output *ao, const void *chunk, size_t size, solaris_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error) Error &error)
{ {
SolarisOutput *so = (SolarisOutput *)ao; SolarisOutput *so = (SolarisOutput *)ao;
ssize_t nbytes; ssize_t nbytes;
nbytes = write(so->fd, chunk, size); nbytes = write(so->fd, chunk, size);
if (nbytes <= 0) { if (nbytes <= 0) {
g_set_error(error, solaris_output_quark(), errno, error.SetErrno("Write failed");
"Write failed: %s", g_strerror(errno));
return 0; return 0;
} }
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "MixerList.hxx" #include "MixerList.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
...@@ -51,14 +53,7 @@ struct WinmmOutput { ...@@ -51,14 +53,7 @@ struct WinmmOutput {
unsigned next_buffer; unsigned next_buffer;
}; };
/** static constexpr Domain winmm_output_domain("winmm_output");
* The quark used for GError.domain.
*/
static inline GQuark
winmm_output_quark(void)
{
return g_quark_from_static_string("winmm_output");
}
HWAVEOUT HWAVEOUT
winmm_output_get_handle(WinmmOutput *output) winmm_output_get_handle(WinmmOutput *output)
...@@ -73,7 +68,7 @@ winmm_output_test_default_device(void) ...@@ -73,7 +68,7 @@ winmm_output_test_default_device(void)
} }
static bool static bool
get_device_id(const char *device_name, UINT *device_id, GError **error_r) get_device_id(const char *device_name, UINT *device_id, Error &error)
{ {
/* if device is not specified use wave mapper */ /* if device is not specified use wave mapper */
if (device_name == nullptr) { if (device_name == nullptr) {
...@@ -108,22 +103,22 @@ get_device_id(const char *device_name, UINT *device_id, GError **error_r) ...@@ -108,22 +103,22 @@ get_device_id(const char *device_name, UINT *device_id, GError **error_r)
} }
fail: fail:
g_set_error(error_r, winmm_output_quark(), 0, error.Format(winmm_output_domain,
"device \"%s\" is not found", device_name); "device \"%s\" is not found", device_name);
return false; return false;
} }
static struct audio_output * static struct audio_output *
winmm_output_init(const config_param &param, GError **error_r) winmm_output_init(const config_param &param, Error &error)
{ {
WinmmOutput *wo = new WinmmOutput(); WinmmOutput *wo = new WinmmOutput();
if (!ao_base_init(&wo->base, &winmm_output_plugin, param, error_r)) { if (!ao_base_init(&wo->base, &winmm_output_plugin, param, error)) {
g_free(wo); g_free(wo);
return nullptr; return nullptr;
} }
const char *device = param.GetBlockValue("device"); const char *device = param.GetBlockValue("device");
if (!get_device_id(device, &wo->device_id, error_r)) { if (!get_device_id(device, &wo->device_id, error)) {
ao_base_finish(&wo->base); ao_base_finish(&wo->base);
g_free(wo); g_free(wo);
return nullptr; return nullptr;
...@@ -143,14 +138,13 @@ winmm_output_finish(struct audio_output *ao) ...@@ -143,14 +138,13 @@ winmm_output_finish(struct audio_output *ao)
static bool static bool
winmm_output_open(struct audio_output *ao, AudioFormat &audio_format, winmm_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r) Error &error)
{ {
WinmmOutput *wo = (WinmmOutput *)ao; WinmmOutput *wo = (WinmmOutput *)ao;
wo->event = CreateEvent(nullptr, false, false, nullptr); wo->event = CreateEvent(nullptr, false, false, nullptr);
if (wo->event == nullptr) { if (wo->event == nullptr) {
g_set_error(error_r, winmm_output_quark(), 0, error.Set(winmm_output_domain, "CreateEvent() failed");
"CreateEvent() failed");
return false; return false;
} }
...@@ -186,8 +180,7 @@ winmm_output_open(struct audio_output *ao, AudioFormat &audio_format, ...@@ -186,8 +180,7 @@ winmm_output_open(struct audio_output *ao, AudioFormat &audio_format,
(DWORD_PTR)wo->event, 0, CALLBACK_EVENT); (DWORD_PTR)wo->event, 0, CALLBACK_EVENT);
if (result != MMSYSERR_NOERROR) { if (result != MMSYSERR_NOERROR) {
CloseHandle(wo->event); CloseHandle(wo->event);
g_set_error(error_r, winmm_output_quark(), result, error.Set(winmm_output_domain, "waveOutOpen() failed");
"waveOutOpen() failed");
return false; return false;
} }
...@@ -219,7 +212,7 @@ winmm_output_close(struct audio_output *ao) ...@@ -219,7 +212,7 @@ winmm_output_close(struct audio_output *ao)
static bool static bool
winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer, winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
const void *data, size_t size, const void *data, size_t size,
GError **error_r) Error &error)
{ {
void *dest = buffer->buffer.Get(size); void *dest = buffer->buffer.Get(size);
assert(dest != nullptr); assert(dest != nullptr);
...@@ -233,7 +226,7 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer, ...@@ -233,7 +226,7 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
MMRESULT result = waveOutPrepareHeader(wo->handle, &buffer->hdr, MMRESULT result = waveOutPrepareHeader(wo->handle, &buffer->hdr,
sizeof(buffer->hdr)); sizeof(buffer->hdr));
if (result != MMSYSERR_NOERROR) { if (result != MMSYSERR_NOERROR) {
g_set_error(error_r, winmm_output_quark(), result, error.Set(winmm_output_domain, result,
"waveOutPrepareHeader() failed"); "waveOutPrepareHeader() failed");
return false; return false;
} }
...@@ -246,7 +239,7 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer, ...@@ -246,7 +239,7 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
*/ */
static bool static bool
winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer, winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
GError **error_r) Error &error)
{ {
if ((buffer->hdr.dwFlags & WHDR_DONE) == WHDR_DONE) if ((buffer->hdr.dwFlags & WHDR_DONE) == WHDR_DONE)
/* already finished */ /* already finished */
...@@ -259,7 +252,7 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer, ...@@ -259,7 +252,7 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
if (result == MMSYSERR_NOERROR) if (result == MMSYSERR_NOERROR)
return true; return true;
else if (result != WAVERR_STILLPLAYING) { else if (result != WAVERR_STILLPLAYING) {
g_set_error(error_r, winmm_output_quark(), result, error.Set(winmm_output_domain, result,
"waveOutUnprepareHeader() failed"); "waveOutUnprepareHeader() failed");
return false; return false;
} }
...@@ -270,14 +263,14 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer, ...@@ -270,14 +263,14 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
} }
static size_t static size_t
winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error_r) winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, Error &error)
{ {
WinmmOutput *wo = (WinmmOutput *)ao; WinmmOutput *wo = (WinmmOutput *)ao;
/* get the next buffer from the ring and prepare it */ /* get the next buffer from the ring and prepare it */
WinmmBuffer *buffer = &wo->buffers[wo->next_buffer]; WinmmBuffer *buffer = &wo->buffers[wo->next_buffer];
if (!winmm_drain_buffer(wo, buffer, error_r) || if (!winmm_drain_buffer(wo, buffer, error) ||
!winmm_set_buffer(wo, buffer, chunk, size, error_r)) !winmm_set_buffer(wo, buffer, chunk, size, error))
return 0; return 0;
/* enqueue the buffer */ /* enqueue the buffer */
...@@ -286,7 +279,7 @@ winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GErro ...@@ -286,7 +279,7 @@ winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GErro
if (result != MMSYSERR_NOERROR) { if (result != MMSYSERR_NOERROR) {
waveOutUnprepareHeader(wo->handle, &buffer->hdr, waveOutUnprepareHeader(wo->handle, &buffer->hdr,
sizeof(buffer->hdr)); sizeof(buffer->hdr));
g_set_error(error_r, winmm_output_quark(), result, error.Set(winmm_output_domain, result,
"waveOutWrite() failed"); "waveOutWrite() failed");
return 0; return 0;
} }
...@@ -299,14 +292,14 @@ winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GErro ...@@ -299,14 +292,14 @@ winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GErro
} }
static bool static bool
winmm_drain_all_buffers(WinmmOutput *wo, GError **error_r) winmm_drain_all_buffers(WinmmOutput *wo, Error &error)
{ {
for (unsigned i = wo->next_buffer; i < G_N_ELEMENTS(wo->buffers); ++i) for (unsigned i = wo->next_buffer; i < G_N_ELEMENTS(wo->buffers); ++i)
if (!winmm_drain_buffer(wo, &wo->buffers[i], error_r)) if (!winmm_drain_buffer(wo, &wo->buffers[i], error))
return false; return false;
for (unsigned i = 0; i < wo->next_buffer; ++i) for (unsigned i = 0; i < wo->next_buffer; ++i)
if (!winmm_drain_buffer(wo, &wo->buffers[i], error_r)) if (!winmm_drain_buffer(wo, &wo->buffers[i], error))
return false; return false;
return true; return true;
...@@ -329,7 +322,7 @@ winmm_output_drain(struct audio_output *ao) ...@@ -329,7 +322,7 @@ winmm_output_drain(struct audio_output *ao)
{ {
WinmmOutput *wo = (WinmmOutput *)ao; WinmmOutput *wo = (WinmmOutput *)ao;
if (!winmm_drain_all_buffers(wo, nullptr)) if (!winmm_drain_all_buffers(wo, IgnoreError()))
winmm_stop(wo); winmm_stop(wo);
} }
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "PcmFormat.hxx" #include "PcmFormat.hxx"
#include "pcm_pack.h" #include "pcm_pack.h"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -32,6 +34,8 @@ ...@@ -32,6 +34,8 @@
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "pcm" #define G_LOG_DOMAIN "pcm"
const Domain pcm_convert_domain("pcm_convert");
PcmConvert::PcmConvert() PcmConvert::PcmConvert()
{ {
} }
...@@ -51,7 +55,7 @@ inline const int16_t * ...@@ -51,7 +55,7 @@ inline const int16_t *
PcmConvert::Convert16(const AudioFormat src_format, PcmConvert::Convert16(const AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const AudioFormat dest_format, size_t *dest_size_r, const AudioFormat dest_format, size_t *dest_size_r,
GError **error_r) Error &error)
{ {
const int16_t *buf; const int16_t *buf;
size_t len; size_t len;
...@@ -63,7 +67,7 @@ PcmConvert::Convert16(const AudioFormat src_format, ...@@ -63,7 +67,7 @@ PcmConvert::Convert16(const AudioFormat src_format,
src_buffer, src_size, src_buffer, src_size,
&len); &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"Conversion from %s to 16 bit is not implemented", "Conversion from %s to 16 bit is not implemented",
sample_format_to_string(src_format.format)); sample_format_to_string(src_format.format));
return NULL; return NULL;
...@@ -75,7 +79,7 @@ PcmConvert::Convert16(const AudioFormat src_format, ...@@ -75,7 +79,7 @@ PcmConvert::Convert16(const AudioFormat src_format,
src_format.channels, src_format.channels,
buf, len, &len); buf, len, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"Conversion from %u to %u channels " "Conversion from %u to %u channels "
"is not implemented", "is not implemented",
src_format.channels, src_format.channels,
...@@ -88,7 +92,7 @@ PcmConvert::Convert16(const AudioFormat src_format, ...@@ -88,7 +92,7 @@ PcmConvert::Convert16(const AudioFormat src_format,
buf = resampler.Resample16(dest_format.channels, buf = resampler.Resample16(dest_format.channels,
src_format.sample_rate, buf, len, src_format.sample_rate, buf, len,
dest_format.sample_rate, &len, dest_format.sample_rate, &len,
error_r); error);
if (buf == NULL) if (buf == NULL)
return NULL; return NULL;
} }
...@@ -101,7 +105,7 @@ inline const int32_t * ...@@ -101,7 +105,7 @@ inline const int32_t *
PcmConvert::Convert24(const AudioFormat src_format, PcmConvert::Convert24(const AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const AudioFormat dest_format, size_t *dest_size_r, const AudioFormat dest_format, size_t *dest_size_r,
GError **error_r) Error &error)
{ {
const int32_t *buf; const int32_t *buf;
size_t len; size_t len;
...@@ -112,7 +116,7 @@ PcmConvert::Convert24(const AudioFormat src_format, ...@@ -112,7 +116,7 @@ PcmConvert::Convert24(const AudioFormat src_format,
src_format.format, src_format.format,
src_buffer, src_size, &len); src_buffer, src_size, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"Conversion from %s to 24 bit is not implemented", "Conversion from %s to 24 bit is not implemented",
sample_format_to_string(src_format.format)); sample_format_to_string(src_format.format));
return NULL; return NULL;
...@@ -124,7 +128,7 @@ PcmConvert::Convert24(const AudioFormat src_format, ...@@ -124,7 +128,7 @@ PcmConvert::Convert24(const AudioFormat src_format,
src_format.channels, src_format.channels,
buf, len, &len); buf, len, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"Conversion from %u to %u channels " "Conversion from %u to %u channels "
"is not implemented", "is not implemented",
src_format.channels, src_format.channels,
...@@ -137,7 +141,7 @@ PcmConvert::Convert24(const AudioFormat src_format, ...@@ -137,7 +141,7 @@ PcmConvert::Convert24(const AudioFormat src_format,
buf = resampler.Resample24(dest_format.channels, buf = resampler.Resample24(dest_format.channels,
src_format.sample_rate, buf, len, src_format.sample_rate, buf, len,
dest_format.sample_rate, &len, dest_format.sample_rate, &len,
error_r); error);
if (buf == NULL) if (buf == NULL)
return NULL; return NULL;
} }
...@@ -150,7 +154,7 @@ inline const int32_t * ...@@ -150,7 +154,7 @@ inline const int32_t *
PcmConvert::Convert32(const AudioFormat src_format, PcmConvert::Convert32(const AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const AudioFormat dest_format, size_t *dest_size_r, const AudioFormat dest_format, size_t *dest_size_r,
GError **error_r) Error &error)
{ {
const int32_t *buf; const int32_t *buf;
size_t len; size_t len;
...@@ -161,7 +165,7 @@ PcmConvert::Convert32(const AudioFormat src_format, ...@@ -161,7 +165,7 @@ PcmConvert::Convert32(const AudioFormat src_format,
src_format.format, src_format.format,
src_buffer, src_size, &len); src_buffer, src_size, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"Conversion from %s to 32 bit is not implemented", "Conversion from %s to 32 bit is not implemented",
sample_format_to_string(src_format.format)); sample_format_to_string(src_format.format));
return NULL; return NULL;
...@@ -173,7 +177,7 @@ PcmConvert::Convert32(const AudioFormat src_format, ...@@ -173,7 +177,7 @@ PcmConvert::Convert32(const AudioFormat src_format,
src_format.channels, src_format.channels,
buf, len, &len); buf, len, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"Conversion from %u to %u channels " "Conversion from %u to %u channels "
"is not implemented", "is not implemented",
src_format.channels, src_format.channels,
...@@ -186,7 +190,7 @@ PcmConvert::Convert32(const AudioFormat src_format, ...@@ -186,7 +190,7 @@ PcmConvert::Convert32(const AudioFormat src_format,
buf = resampler.Resample32(dest_format.channels, buf = resampler.Resample32(dest_format.channels,
src_format.sample_rate, buf, len, src_format.sample_rate, buf, len,
dest_format.sample_rate, &len, dest_format.sample_rate, &len,
error_r); error);
if (buf == NULL) if (buf == NULL)
return buf; return buf;
} }
...@@ -199,7 +203,7 @@ inline const float * ...@@ -199,7 +203,7 @@ inline const float *
PcmConvert::ConvertFloat(const AudioFormat src_format, PcmConvert::ConvertFloat(const AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const AudioFormat dest_format, size_t *dest_size_r, const AudioFormat dest_format, size_t *dest_size_r,
GError **error_r) Error &error)
{ {
const float *buffer = (const float *)src_buffer; const float *buffer = (const float *)src_buffer;
size_t size = src_size; size_t size = src_size;
...@@ -212,7 +216,7 @@ PcmConvert::ConvertFloat(const AudioFormat src_format, ...@@ -212,7 +216,7 @@ PcmConvert::ConvertFloat(const AudioFormat src_format,
src_format.format, src_format.format,
buffer, size, &size); buffer, size, &size);
if (buffer == NULL) { if (buffer == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"Conversion from %s to float is not implemented", "Conversion from %s to float is not implemented",
sample_format_to_string(src_format.format)); sample_format_to_string(src_format.format));
return NULL; return NULL;
...@@ -226,7 +230,7 @@ PcmConvert::ConvertFloat(const AudioFormat src_format, ...@@ -226,7 +230,7 @@ PcmConvert::ConvertFloat(const AudioFormat src_format,
src_format.channels, src_format.channels,
buffer, size, &size); buffer, size, &size);
if (buffer == NULL) { if (buffer == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"Conversion from %u to %u channels " "Conversion from %u to %u channels "
"is not implemented", "is not implemented",
src_format.channels, src_format.channels,
...@@ -243,7 +247,7 @@ PcmConvert::ConvertFloat(const AudioFormat src_format, ...@@ -243,7 +247,7 @@ PcmConvert::ConvertFloat(const AudioFormat src_format,
src_format.sample_rate, src_format.sample_rate,
buffer, size, buffer, size,
dest_format.sample_rate, dest_format.sample_rate,
&size, error_r); &size, error);
if (buffer == NULL) if (buffer == NULL)
return NULL; return NULL;
} }
...@@ -257,7 +261,7 @@ PcmConvert::Convert(AudioFormat src_format, ...@@ -257,7 +261,7 @@ PcmConvert::Convert(AudioFormat src_format,
const void *src, size_t src_size, const void *src, size_t src_size,
const AudioFormat dest_format, const AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r) Error &error)
{ {
AudioFormat float_format; AudioFormat float_format;
if (src_format.format == SampleFormat::DSD) { if (src_format.format == SampleFormat::DSD) {
...@@ -266,7 +270,7 @@ PcmConvert::Convert(AudioFormat src_format, ...@@ -266,7 +270,7 @@ PcmConvert::Convert(AudioFormat src_format,
false, (const uint8_t *)src, false, (const uint8_t *)src,
src_size, &f_size); src_size, &f_size);
if (f == NULL) { if (f == NULL) {
g_set_error_literal(error_r, pcm_convert_quark(), 0, error.Set(pcm_convert_domain,
"DSD to PCM conversion failed"); "DSD to PCM conversion failed");
return NULL; return NULL;
} }
...@@ -283,25 +287,25 @@ PcmConvert::Convert(AudioFormat src_format, ...@@ -283,25 +287,25 @@ PcmConvert::Convert(AudioFormat src_format,
case SampleFormat::S16: case SampleFormat::S16:
return Convert16(src_format, src, src_size, return Convert16(src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error);
case SampleFormat::S24_P32: case SampleFormat::S24_P32:
return Convert24(src_format, src, src_size, return Convert24(src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error);
case SampleFormat::S32: case SampleFormat::S32:
return Convert32(src_format, src, src_size, return Convert32(src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error);
case SampleFormat::FLOAT: case SampleFormat::FLOAT:
return ConvertFloat(src_format, src, src_size, return ConvertFloat(src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error);
default: default:
g_set_error(error_r, pcm_convert_quark(), 0, error.Format(pcm_convert_domain,
"PCM conversion to %s is not implemented", "PCM conversion to %s is not implemented",
sample_format_to_string(dest_format.format)); sample_format_to_string(dest_format.format));
return NULL; return NULL;
......
...@@ -25,9 +25,10 @@ ...@@ -25,9 +25,10 @@
#include "PcmResample.hxx" #include "PcmResample.hxx"
#include "PcmBuffer.hxx" #include "PcmBuffer.hxx"
#include <glib.h> #include <stddef.h>
struct AudioFormat; struct AudioFormat;
class Error;
/** /**
* This object is statically allocated (within another struct), and * This object is statically allocated (within another struct), and
...@@ -75,38 +76,34 @@ public: ...@@ -75,38 +76,34 @@ public:
const void *src, size_t src_size, const void *src, size_t src_size,
AudioFormat dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); Error &error);
private: private:
const int16_t *Convert16(AudioFormat src_format, const int16_t *Convert16(AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
AudioFormat dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); Error &error);
const int32_t *Convert24(AudioFormat src_format, const int32_t *Convert24(AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
AudioFormat dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); Error &error);
const int32_t *Convert32(AudioFormat src_format, const int32_t *Convert32(AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
AudioFormat dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); Error &error);
const float *ConvertFloat(AudioFormat src_format, const float *ConvertFloat(AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
AudioFormat dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); Error &error);
}; };
static inline GQuark extern const class Domain pcm_convert_domain;
pcm_convert_quark(void)
{
return g_quark_from_static_string("pcm_convert");
}
#endif #endif
...@@ -39,7 +39,7 @@ pcm_resample_lsr_enabled(void) ...@@ -39,7 +39,7 @@ pcm_resample_lsr_enabled(void)
#endif #endif
bool bool
pcm_resample_global_init(GError **error_r) pcm_resample_global_init(Error &error)
{ {
#ifdef HAVE_LIBSAMPLERATE #ifdef HAVE_LIBSAMPLERATE
const char *converter = const char *converter =
...@@ -47,11 +47,11 @@ pcm_resample_global_init(GError **error_r) ...@@ -47,11 +47,11 @@ pcm_resample_global_init(GError **error_r)
lsr_enabled = strcmp(converter, "internal") != 0; lsr_enabled = strcmp(converter, "internal") != 0;
if (lsr_enabled) if (lsr_enabled)
return pcm_resample_lsr_global_init(converter, error_r); return pcm_resample_lsr_global_init(converter, error);
else else
return true; return true;
#else #else
(void)error_r; (void)error;
return true; return true;
#endif #endif
} }
...@@ -84,7 +84,7 @@ const float * ...@@ -84,7 +84,7 @@ const float *
PcmResampler::ResampleFloat(unsigned channels, unsigned src_rate, PcmResampler::ResampleFloat(unsigned channels, unsigned src_rate,
const float *src_buffer, size_t src_size, const float *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r) Error &error_r)
{ {
#ifdef HAVE_LIBSAMPLERATE #ifdef HAVE_LIBSAMPLERATE
if (pcm_resample_lsr_enabled()) if (pcm_resample_lsr_enabled())
...@@ -110,7 +110,7 @@ const int16_t * ...@@ -110,7 +110,7 @@ const int16_t *
PcmResampler::Resample16(unsigned channels, PcmResampler::Resample16(unsigned channels,
unsigned src_rate, const int16_t *src_buffer, size_t src_size, unsigned src_rate, const int16_t *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r) Error &error_r)
{ {
#ifdef HAVE_LIBSAMPLERATE #ifdef HAVE_LIBSAMPLERATE
if (pcm_resample_lsr_enabled()) if (pcm_resample_lsr_enabled())
...@@ -131,7 +131,7 @@ const int32_t * ...@@ -131,7 +131,7 @@ const int32_t *
PcmResampler::Resample32(unsigned channels, unsigned src_rate, PcmResampler::Resample32(unsigned channels, unsigned src_rate,
const int32_t *src_buffer, size_t src_size, const int32_t *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r) Error &error_r)
{ {
#ifdef HAVE_LIBSAMPLERATE #ifdef HAVE_LIBSAMPLERATE
if (pcm_resample_lsr_enabled()) if (pcm_resample_lsr_enabled())
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include "check.h" #include "check.h"
#include "PcmBuffer.hxx" #include "PcmBuffer.hxx"
#include "gerror.h"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
...@@ -31,6 +30,8 @@ ...@@ -31,6 +30,8 @@
#include <samplerate.h> #include <samplerate.h>
#endif #endif
class Error;
/** /**
* This object is statically allocated (within another struct), and * This object is statically allocated (within another struct), and
* holds buffer allocations and the state for the resampler. * holds buffer allocations and the state for the resampler.
...@@ -75,7 +76,7 @@ struct PcmResampler { ...@@ -75,7 +76,7 @@ struct PcmResampler {
const float *ResampleFloat(unsigned channels, unsigned src_rate, const float *ResampleFloat(unsigned channels, unsigned src_rate,
const float *src_buffer, size_t src_size, const float *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r); Error &error_r);
/** /**
* Resamples 16 bit PCM data. * Resamples 16 bit PCM data.
...@@ -91,7 +92,7 @@ struct PcmResampler { ...@@ -91,7 +92,7 @@ struct PcmResampler {
const int16_t *Resample16(unsigned channels, unsigned src_rate, const int16_t *Resample16(unsigned channels, unsigned src_rate,
const int16_t *src_buffer, size_t src_size, const int16_t *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r); Error &error_r);
/** /**
* Resamples 32 bit PCM data. * Resamples 32 bit PCM data.
...@@ -107,7 +108,7 @@ struct PcmResampler { ...@@ -107,7 +108,7 @@ struct PcmResampler {
const int32_t *Resample32(unsigned channels, unsigned src_rate, const int32_t *Resample32(unsigned channels, unsigned src_rate,
const int32_t *src_buffer, size_t src_size, const int32_t *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r); Error &error_r);
/** /**
* Resamples 24 bit PCM data. * Resamples 24 bit PCM data.
...@@ -123,7 +124,7 @@ struct PcmResampler { ...@@ -123,7 +124,7 @@ struct PcmResampler {
const int32_t *Resample24(unsigned channels, unsigned src_rate, const int32_t *Resample24(unsigned channels, unsigned src_rate,
const int32_t *src_buffer, size_t src_size, const int32_t *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r) Error &error_r)
{ {
/* reuse the 32 bit code - the resampler code doesn't care if /* reuse the 32 bit code - the resampler code doesn't care if
the upper 8 bits are actually used */ the upper 8 bits are actually used */
...@@ -133,6 +134,6 @@ struct PcmResampler { ...@@ -133,6 +134,6 @@ struct PcmResampler {
}; };
bool bool
pcm_resample_global_init(GError **error_r); pcm_resample_global_init(Error &error);
#endif #endif
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#ifdef HAVE_LIBSAMPLERATE #ifdef HAVE_LIBSAMPLERATE
bool bool
pcm_resample_lsr_global_init(const char *converter, GError **error_r); pcm_resample_lsr_global_init(const char *converter, Error &error);
void void
pcm_resample_lsr_init(PcmResampler *state); pcm_resample_lsr_init(PcmResampler *state);
...@@ -50,7 +50,7 @@ pcm_resample_lsr_float(PcmResampler *state, ...@@ -50,7 +50,7 @@ pcm_resample_lsr_float(PcmResampler *state,
unsigned src_rate, unsigned src_rate,
const float *src_buffer, size_t src_size, const float *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r); Error &error);
const int16_t * const int16_t *
pcm_resample_lsr_16(PcmResampler *state, pcm_resample_lsr_16(PcmResampler *state,
...@@ -58,7 +58,7 @@ pcm_resample_lsr_16(PcmResampler *state, ...@@ -58,7 +58,7 @@ pcm_resample_lsr_16(PcmResampler *state,
unsigned src_rate, unsigned src_rate,
const int16_t *src_buffer, size_t src_size, const int16_t *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r); Error &error);
const int32_t * const int32_t *
pcm_resample_lsr_32(PcmResampler *state, pcm_resample_lsr_32(PcmResampler *state,
...@@ -67,7 +67,7 @@ pcm_resample_lsr_32(PcmResampler *state, ...@@ -67,7 +67,7 @@ pcm_resample_lsr_32(PcmResampler *state,
const int32_t *src_buffer, const int32_t *src_buffer,
size_t src_size, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r); Error &error);
#endif #endif
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "config.h" #include "config.h"
#include "PcmResampleInternal.hxx" #include "PcmResampleInternal.hxx"
#include "conf.h" #include "conf.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h> #include <glib.h>
...@@ -32,11 +34,7 @@ ...@@ -32,11 +34,7 @@
static int lsr_converter = SRC_SINC_FASTEST; static int lsr_converter = SRC_SINC_FASTEST;
static inline GQuark static constexpr Domain libsamplerate_domain("libsamplerate");
libsamplerate_quark(void)
{
return g_quark_from_static_string("libsamplerate");
}
static bool static bool
lsr_parse_converter(const char *s) lsr_parse_converter(const char *s)
...@@ -69,10 +67,10 @@ lsr_parse_converter(const char *s) ...@@ -69,10 +67,10 @@ lsr_parse_converter(const char *s)
} }
bool bool
pcm_resample_lsr_global_init(const char *converter, GError **error_r) pcm_resample_lsr_global_init(const char *converter, Error &error)
{ {
if (!lsr_parse_converter(converter)) { if (!lsr_parse_converter(converter)) {
g_set_error(error_r, libsamplerate_quark(), 0, error.Format(libsamplerate_domain,
"unknown samplerate converter '%s'", converter); "unknown samplerate converter '%s'", converter);
return false; return false;
} }
...@@ -109,7 +107,7 @@ pcm_resample_lsr_reset(PcmResampler *state) ...@@ -109,7 +107,7 @@ pcm_resample_lsr_reset(PcmResampler *state)
static bool static bool
pcm_resample_set(PcmResampler *state, pcm_resample_set(PcmResampler *state,
unsigned channels, unsigned src_rate, unsigned dest_rate, unsigned channels, unsigned src_rate, unsigned dest_rate,
GError **error_r) Error &error_r)
{ {
/* (re)set the state/ratio if the in or out format changed */ /* (re)set the state/ratio if the in or out format changed */
if (channels == state->prev.channels && if (channels == state->prev.channels &&
...@@ -128,7 +126,7 @@ pcm_resample_set(PcmResampler *state, ...@@ -128,7 +126,7 @@ pcm_resample_set(PcmResampler *state,
int error; int error;
state->state = src_new(lsr_converter, channels, &error); state->state = src_new(lsr_converter, channels, &error);
if (!state->state) { if (!state->state) {
g_set_error(error_r, libsamplerate_quark(), state->error, error_r.Format(libsamplerate_domain, error,
"libsamplerate initialization has failed: %s", "libsamplerate initialization has failed: %s",
src_strerror(error)); src_strerror(error));
return false; return false;
...@@ -144,12 +142,12 @@ pcm_resample_set(PcmResampler *state, ...@@ -144,12 +142,12 @@ pcm_resample_set(PcmResampler *state,
} }
static bool static bool
lsr_process(PcmResampler *state, GError **error_r) lsr_process(PcmResampler *state, Error &error)
{ {
if (state->error == 0) if (state->error == 0)
state->error = src_process(state->state, &state->data); state->error = src_process(state->state, &state->data);
if (state->error) { if (state->error) {
g_set_error(error_r, libsamplerate_quark(), state->error, error.Format(libsamplerate_domain, state->error,
"libsamplerate has failed: %s", "libsamplerate has failed: %s",
src_strerror(state->error)); src_strerror(state->error));
return false; return false;
...@@ -164,16 +162,15 @@ pcm_resample_lsr_float(PcmResampler *state, ...@@ -164,16 +162,15 @@ pcm_resample_lsr_float(PcmResampler *state,
unsigned src_rate, unsigned src_rate,
const float *src_buffer, size_t src_size, const float *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r) Error &error)
{ {
SRC_DATA *data = &state->data; SRC_DATA *data = &state->data;
assert((src_size % (sizeof(*src_buffer) * channels)) == 0); assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
if (!pcm_resample_set(state, channels, src_rate, dest_rate, error_r)) if (!pcm_resample_set(state, channels, src_rate, dest_rate, error))
return nullptr; return nullptr;
data->input_frames = src_size / sizeof(*src_buffer) / channels; data->input_frames = src_size / sizeof(*src_buffer) / channels;
data->data_in = const_cast<float *>(src_buffer); data->data_in = const_cast<float *>(src_buffer);
...@@ -181,7 +178,7 @@ pcm_resample_lsr_float(PcmResampler *state, ...@@ -181,7 +178,7 @@ pcm_resample_lsr_float(PcmResampler *state,
size_t data_out_size = data->output_frames * sizeof(float) * channels; size_t data_out_size = data->output_frames * sizeof(float) * channels;
data->data_out = (float *)state->out.Get(data_out_size); data->data_out = (float *)state->out.Get(data_out_size);
if (!lsr_process(state, error_r)) if (!lsr_process(state, error))
return nullptr; return nullptr;
*dest_size_r = data->output_frames_gen * *dest_size_r = data->output_frames_gen *
...@@ -195,14 +192,14 @@ pcm_resample_lsr_16(PcmResampler *state, ...@@ -195,14 +192,14 @@ pcm_resample_lsr_16(PcmResampler *state,
unsigned src_rate, unsigned src_rate,
const int16_t *src_buffer, size_t src_size, const int16_t *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r) Error &error)
{ {
SRC_DATA *data = &state->data; SRC_DATA *data = &state->data;
assert((src_size % (sizeof(*src_buffer) * channels)) == 0); assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
if (!pcm_resample_set(state, channels, src_rate, dest_rate, if (!pcm_resample_set(state, channels, src_rate, dest_rate,
error_r)) error))
return nullptr; return nullptr;
data->input_frames = src_size / sizeof(*src_buffer) / channels; data->input_frames = src_size / sizeof(*src_buffer) / channels;
...@@ -216,7 +213,7 @@ pcm_resample_lsr_16(PcmResampler *state, ...@@ -216,7 +213,7 @@ pcm_resample_lsr_16(PcmResampler *state,
src_short_to_float_array(src_buffer, data->data_in, src_short_to_float_array(src_buffer, data->data_in,
data->input_frames * channels); data->input_frames * channels);
if (!lsr_process(state, error_r)) if (!lsr_process(state, error))
return nullptr; return nullptr;
int16_t *dest_buffer; int16_t *dest_buffer;
...@@ -255,14 +252,14 @@ pcm_resample_lsr_32(PcmResampler *state, ...@@ -255,14 +252,14 @@ pcm_resample_lsr_32(PcmResampler *state,
unsigned src_rate, unsigned src_rate,
const int32_t *src_buffer, size_t src_size, const int32_t *src_buffer, size_t src_size,
unsigned dest_rate, size_t *dest_size_r, unsigned dest_rate, size_t *dest_size_r,
GError **error_r) Error &error)
{ {
SRC_DATA *data = &state->data; SRC_DATA *data = &state->data;
assert((src_size % (sizeof(*src_buffer) * channels)) == 0); assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
if (!pcm_resample_set(state, channels, src_rate, dest_rate, if (!pcm_resample_set(state, channels, src_rate, dest_rate,
error_r)) error))
return nullptr; return nullptr;
data->input_frames = src_size / sizeof(*src_buffer) / channels; data->input_frames = src_size / sizeof(*src_buffer) / channels;
...@@ -276,7 +273,7 @@ pcm_resample_lsr_32(PcmResampler *state, ...@@ -276,7 +273,7 @@ pcm_resample_lsr_32(PcmResampler *state,
src_int_to_float_array(src_buffer, data->data_in, src_int_to_float_array(src_buffer, data->data_in,
data->input_frames * channels); data->input_frames * channels);
if (!lsr_process(state, error_r)) if (!lsr_process(state, error))
return nullptr; return nullptr;
int32_t *dest_buffer; int32_t *dest_buffer;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -208,6 +209,7 @@ asx_open_stream(struct input_stream *is) ...@@ -208,6 +209,7 @@ asx_open_stream(struct input_stream *is)
char buffer[1024]; char buffer[1024];
size_t nbytes; size_t nbytes;
bool success; bool success;
Error error2;
GError *error = NULL; GError *error = NULL;
/* parse the ASX XML file */ /* parse the ASX XML file */
...@@ -218,12 +220,11 @@ asx_open_stream(struct input_stream *is) ...@@ -218,12 +220,11 @@ asx_open_stream(struct input_stream *is)
while (true) { while (true) {
nbytes = input_stream_lock_read(is, buffer, sizeof(buffer), nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
&error); error2);
if (nbytes == 0) { if (nbytes == 0) {
if (error != NULL) { if (error2.IsDefined()) {
g_markup_parse_context_free(context); g_markup_parse_context_free(context);
g_warning("%s", error->message); g_warning("%s", error2.GetMessage());
g_error_free(error);
return NULL; return NULL;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "conf.h" #include "conf.h"
#include "Song.hxx" #include "Song.hxx"
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -92,16 +93,14 @@ static char * ...@@ -92,16 +93,14 @@ static char *
lastfm_get(const char *url, Mutex &mutex, Cond &cond) lastfm_get(const char *url, Mutex &mutex, Cond &cond)
{ {
struct input_stream *input_stream; struct input_stream *input_stream;
GError *error = NULL; Error error;
char buffer[4096]; char buffer[4096];
size_t length = 0, nbytes; size_t length = 0;
input_stream = input_stream_open(url, mutex, cond, &error); input_stream = input_stream_open(url, mutex, cond, error);
if (input_stream == NULL) { if (input_stream == 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;
} }
...@@ -111,13 +110,12 @@ lastfm_get(const char *url, Mutex &mutex, Cond &cond) ...@@ -111,13 +110,12 @@ lastfm_get(const char *url, Mutex &mutex, Cond &cond)
input_stream_wait_ready(input_stream); input_stream_wait_ready(input_stream);
do { do {
nbytes = input_stream_read(input_stream, buffer + length, size_t nbytes =
sizeof(buffer) - length, &error); input_stream_read(input_stream, buffer + length,
sizeof(buffer) - length, error);
if (nbytes == 0) { if (nbytes == 0) {
if (error != NULL) { if (error.IsDefined())
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
}
if (input_stream_eof(input_stream)) if (input_stream_eof(input_stream))
break; break;
...@@ -166,7 +164,6 @@ lastfm_find(const char *response, const char *name) ...@@ -166,7 +164,6 @@ lastfm_find(const char *response, const char *name)
static struct playlist_provider * static struct playlist_provider *
lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond) lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond)
{ {
GError *error = NULL;
char *p, *q, *response, *session; char *p, *q, *response, *session;
/* handshake */ /* handshake */
...@@ -225,15 +222,15 @@ lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond) ...@@ -225,15 +222,15 @@ lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond)
NULL); NULL);
g_free(session); g_free(session);
const auto is = input_stream_open(p, mutex, cond, &error); Error error;
const auto is = input_stream_open(p, mutex, cond, error);
g_free(p); g_free(p);
if (is == nullptr) { if (is == nullptr) {
if (error != NULL) { if (error.IsDefined())
g_warning("Failed to load XSPF playlist: %s", g_warning("Failed to load XSPF playlist: %s",
error->message); error.GetMessage());
g_error_free(error); else
} else
g_warning("Failed to load XSPF playlist"); g_warning("Failed to load XSPF playlist");
return NULL; return NULL;
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -104,6 +105,7 @@ static struct playlist_provider * ...@@ -104,6 +105,7 @@ static struct playlist_provider *
pls_open_stream(struct input_stream *is) pls_open_stream(struct input_stream *is)
{ {
GError *error = NULL; GError *error = NULL;
Error error2;
size_t nbytes; size_t nbytes;
char buffer[1024]; char buffer[1024];
bool success; bool success;
...@@ -113,11 +115,10 @@ pls_open_stream(struct input_stream *is) ...@@ -113,11 +115,10 @@ pls_open_stream(struct input_stream *is)
do { do {
nbytes = input_stream_lock_read(is, buffer, sizeof(buffer), nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
&error); error2);
if (nbytes == 0) { if (nbytes == 0) {
if (error != NULL) { if (error2.IsDefined()) {
g_warning("%s", error->message); g_warning("%s", error2.GetMessage());
g_error_free(error);
return NULL; return NULL;
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -205,6 +206,7 @@ rss_open_stream(struct input_stream *is) ...@@ -205,6 +206,7 @@ rss_open_stream(struct input_stream *is)
char buffer[1024]; char buffer[1024];
size_t nbytes; size_t nbytes;
bool success; bool success;
Error error2;
GError *error = NULL; GError *error = NULL;
/* parse the RSS XML file */ /* parse the RSS XML file */
...@@ -215,12 +217,11 @@ rss_open_stream(struct input_stream *is) ...@@ -215,12 +217,11 @@ rss_open_stream(struct input_stream *is)
while (true) { while (true) {
nbytes = input_stream_lock_read(is, buffer, sizeof(buffer), nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
&error); error2);
if (nbytes == 0) { if (nbytes == 0) {
if (error != NULL) { if (error2.IsDefined()) {
g_markup_parse_context_free(context); g_markup_parse_context_free(context);
g_warning("%s", error->message); g_warning("%s", error2.GetMessage());
g_error_free(error);
return NULL; return NULL;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "Song.hxx" #include "Song.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
#include <yajl/yajl_parse.h> #include <yajl/yajl_parse.h>
...@@ -244,18 +245,15 @@ static int ...@@ -244,18 +245,15 @@ static int
soundcloud_parse_json(const char *url, yajl_handle hand, soundcloud_parse_json(const char *url, yajl_handle hand,
Mutex &mutex, Cond &cond) Mutex &mutex, Cond &cond)
{ {
struct input_stream *input_stream;
GError *error = NULL;
char buffer[4096]; char buffer[4096];
unsigned char *ubuffer = (unsigned char *)buffer; unsigned char *ubuffer = (unsigned char *)buffer;
size_t nbytes;
input_stream = input_stream_open(url, mutex, cond, &error); Error error;
input_stream *input_stream = input_stream_open(url, mutex, cond,
error);
if (input_stream == NULL) { if (input_stream == NULL) {
if (error != NULL) { if (error.IsDefined())
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
}
return -1; return -1;
} }
...@@ -266,12 +264,13 @@ soundcloud_parse_json(const char *url, yajl_handle hand, ...@@ -266,12 +264,13 @@ soundcloud_parse_json(const char *url, yajl_handle hand,
int done = 0; int done = 0;
while (!done) { while (!done) {
nbytes = input_stream_read(input_stream, buffer, sizeof(buffer), &error); const size_t nbytes =
input_stream_read(input_stream, buffer, sizeof(buffer),
error);
if (nbytes == 0) { if (nbytes == 0) {
if (error != NULL) { if (error.IsDefined())
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
}
if (input_stream_eof(input_stream)) { if (input_stream_eof(input_stream)) {
done = true; done = true;
} else { } else {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "MemoryPlaylistProvider.hxx" #include "MemoryPlaylistProvider.hxx"
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -224,6 +225,7 @@ xspf_open_stream(struct input_stream *is) ...@@ -224,6 +225,7 @@ xspf_open_stream(struct input_stream *is)
char buffer[1024]; char buffer[1024];
size_t nbytes; size_t nbytes;
bool success; bool success;
Error error2;
GError *error = NULL; GError *error = NULL;
/* parse the XSPF XML file */ /* parse the XSPF XML file */
...@@ -234,12 +236,11 @@ xspf_open_stream(struct input_stream *is) ...@@ -234,12 +236,11 @@ xspf_open_stream(struct input_stream *is)
while (true) { while (true) {
nbytes = input_stream_lock_read(is, buffer, sizeof(buffer), nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
&error); error2);
if (nbytes == 0) { if (nbytes == 0) {
if (error != NULL) { if (error2.IsDefined()) {
g_markup_parse_context_free(context); g_markup_parse_context_free(context);
g_warning("%s", error->message); g_warning("%s", error2.GetMessage());
g_error_free(error);
return NULL; return NULL;
} }
......
/*
* Copyright (C) 2003-2011 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "Ack.hxx"
#include "util/Domain.hxx"
const Domain ack_domain("ack");
...@@ -20,9 +20,7 @@ ...@@ -20,9 +20,7 @@
#ifndef MPD_ACK_H #ifndef MPD_ACK_H
#define MPD_ACK_H #define MPD_ACK_H
#include "gcc.h" class Domain;
#include <glib.h>
enum ack { enum ack {
ACK_ERROR_NOT_LIST = 1, ACK_ERROR_NOT_LIST = 1,
...@@ -40,14 +38,6 @@ enum ack { ...@@ -40,14 +38,6 @@ enum ack {
ACK_ERROR_EXIST = 56, ACK_ERROR_EXIST = 56,
}; };
/** extern const Domain ack_domain;
* Quark for GError.domain; the code is an enum #ack.
*/
gcc_const
static inline GQuark
ack_quark(void)
{
return g_quark_from_static_string("ack");
}
#endif #endif
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include "gcc.h" #include "gcc.h"
#include "Ack.hxx" #include "Ack.hxx"
#include <stdarg.h>
class Client; class Client;
extern const char *current_command; extern const char *current_command;
......
...@@ -17,7 +17,9 @@ ...@@ -17,7 +17,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "config.h"
#include "FatalError.hxx" #include "FatalError.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -53,6 +55,12 @@ FormatFatalError(const char *fmt, ...) ...@@ -53,6 +55,12 @@ FormatFatalError(const char *fmt, ...)
} }
void void
FatalError(const Error &error)
{
FatalError(error.GetMessage());
}
void
FatalError(GError *error) FatalError(GError *error)
{ {
FatalError(error->message); FatalError(error->message);
......
...@@ -20,9 +20,12 @@ ...@@ -20,9 +20,12 @@
#ifndef MPD_FATAL_ERROR_HXX #ifndef MPD_FATAL_ERROR_HXX
#define MPD_FATAL_ERROR_HXX #define MPD_FATAL_ERROR_HXX
#include "check.h"
#include "gerror.h" #include "gerror.h"
#include "gcc.h" #include "gcc.h"
class Error;
/** /**
* Log the specified message and abort the process. * Log the specified message and abort the process.
*/ */
...@@ -36,6 +39,10 @@ FormatFatalError(const char *fmt, ...); ...@@ -36,6 +39,10 @@ FormatFatalError(const char *fmt, ...);
gcc_noreturn gcc_noreturn
void void
FatalError(const Error &error);
gcc_noreturn
void
FatalError(GError *error); FatalError(GError *error);
gcc_noreturn gcc_noreturn
......
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
#include "config.h" #include "config.h"
#include "Resolver.hxx" #include "Resolver.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h>
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
#include <sys/socket.h> #include <sys/socket.h>
...@@ -30,8 +34,10 @@ ...@@ -30,8 +34,10 @@
#include <string.h> #include <string.h>
const Domain resolver_domain("resolver");
char * char *
sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error) sockaddr_to_string(const struct sockaddr *sa, size_t length, Error &error)
{ {
#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) #if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)sa; const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)sa;
...@@ -59,8 +65,7 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error) ...@@ -59,8 +65,7 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error)
ret = getnameinfo(sa, length, host, sizeof(host), serv, sizeof(serv), ret = getnameinfo(sa, length, host, sizeof(host), serv, sizeof(serv),
NI_NUMERICHOST|NI_NUMERICSERV); NI_NUMERICHOST|NI_NUMERICSERV);
if (ret != 0) { if (ret != 0) {
g_set_error(error, g_quark_from_static_string("netdb"), ret, error.Set(resolver_domain, ret, gai_strerror(ret));
"%s", gai_strerror(ret));
return NULL; return NULL;
} }
...@@ -82,7 +87,7 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error) ...@@ -82,7 +87,7 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error)
struct addrinfo * struct addrinfo *
resolve_host_port(const char *host_port, unsigned default_port, resolve_host_port(const char *host_port, unsigned default_port,
int flags, int socktype, int flags, int socktype,
GError **error_r) Error &error)
{ {
char *p = g_strdup(host_port); char *p = g_strdup(host_port);
const char *host = p, *port = NULL; const char *host = p, *port = NULL;
...@@ -130,7 +135,7 @@ resolve_host_port(const char *host_port, unsigned default_port, ...@@ -130,7 +135,7 @@ resolve_host_port(const char *host_port, unsigned default_port,
int ret = getaddrinfo(host, port, &hints, &ai); int ret = getaddrinfo(host, port, &hints, &ai);
g_free(p); g_free(p);
if (ret != 0) { if (ret != 0) {
g_set_error(error_r, resolver_quark(), ret, error.Format(resolver_domain, ret,
"Failed to look up '%s': %s", "Failed to look up '%s': %s",
host_port, gai_strerror(ret)); host_port, gai_strerror(ret));
return NULL; return NULL;
......
...@@ -22,17 +22,13 @@ ...@@ -22,17 +22,13 @@
#include "gcc.h" #include "gcc.h"
#include <glib.h> #include <stddef.h>
struct sockaddr; struct sockaddr;
struct addrinfo; struct addrinfo;
class Error;
gcc_const extern const class Domain resolver_domain;
static inline GQuark
resolver_quark(void)
{
return g_quark_from_static_string("resolver");
}
/** /**
* Converts the specified socket address into a string in the form * Converts the specified socket address into a string in the form
...@@ -46,7 +42,7 @@ resolver_quark(void) ...@@ -46,7 +42,7 @@ resolver_quark(void)
*/ */
gcc_malloc gcc_malloc
char * char *
sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error); sockaddr_to_string(const struct sockaddr *sa, size_t length, Error &error);
/** /**
* Resolve a specification in the form "host", "host:port", * Resolve a specification in the form "host", "host:port",
...@@ -61,6 +57,6 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error); ...@@ -61,6 +57,6 @@ sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error);
struct addrinfo * struct addrinfo *
resolve_host_port(const char *host_port, unsigned default_port, resolve_host_port(const char *host_port, unsigned default_port,
int flags, int socktype, int flags, int socktype,
GError **error_r); Error &error);
#endif #endif
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "SocketError.hxx"
#include "util/Domain.hxx"
const Domain socket_domain("socket");
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define MPD_SOCKET_ERROR_HXX #define MPD_SOCKET_ERROR_HXX
#include "gcc.h" #include "gcc.h"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -33,15 +34,10 @@ typedef int socket_error_t; ...@@ -33,15 +34,10 @@ typedef int socket_error_t;
#endif #endif
/** /**
* A GQuark for GError for socket I/O errors. The code is an errno * A #Domain for #Error for socket I/O errors. The code is an errno
* value (or WSAGetLastError() on Windows). * value (or WSAGetLastError() on Windows).
*/ */
gcc_const extern const class Domain socket_domain;
static inline GQuark
SocketErrorQuark(void)
{
return g_quark_from_static_string("socket");
}
gcc_pure gcc_pure
static inline socket_error_t static inline socket_error_t
...@@ -121,33 +117,29 @@ public: ...@@ -121,33 +117,29 @@ public:
}; };
static inline void static inline void
SetSocketError(GError **error_r, socket_error_t code) SetSocketError(Error &error, socket_error_t code)
{ {
#ifdef WIN32
if (error_r == NULL)
return;
#endif
const SocketErrorMessage msg(code); const SocketErrorMessage msg(code);
g_set_error_literal(error_r, SocketErrorQuark(), code, msg); error.Set(socket_domain, code, msg);
} }
static inline void static inline void
SetSocketError(GError **error_r) SetSocketError(Error &error)
{ {
SetSocketError(error_r, GetSocketError()); SetSocketError(error, GetSocketError());
} }
gcc_malloc gcc_const
static inline GError * static inline Error
NewSocketError(socket_error_t code) NewSocketError(socket_error_t code)
{ {
const SocketErrorMessage msg(code); Error error;
return g_error_new_literal(SocketErrorQuark(), code, msg); SetSocketError(error, code);
return error;
} }
gcc_malloc gcc_pure
static inline GError * static inline Error
NewSocketError() NewSocketError()
{ {
return NewSocketError(GetSocketError()); return NewSocketError(GetSocketError());
......
...@@ -41,38 +41,38 @@ int ...@@ -41,38 +41,38 @@ int
socket_bind_listen(int domain, int type, int protocol, socket_bind_listen(int domain, int type, int protocol,
const struct sockaddr *address, size_t address_length, const struct sockaddr *address, size_t address_length,
int backlog, int backlog,
GError **error_r) Error &error)
{ {
int fd, ret; int fd, ret;
const int reuse = 1; const int reuse = 1;
fd = socket_cloexec_nonblock(domain, type, protocol); fd = socket_cloexec_nonblock(domain, type, protocol);
if (fd < 0) { if (fd < 0) {
SetSocketError(error_r); SetSocketError(error);
g_prefix_error(error_r, "Failed to create socket: "); error.AddPrefix("Failed to create socket: ");
return -1; return -1;
} }
ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &reuse, sizeof(reuse)); (const char *) &reuse, sizeof(reuse));
if (ret < 0) { if (ret < 0) {
SetSocketError(error_r); SetSocketError(error);
g_prefix_error(error_r, "setsockopt() failed: "); error.AddPrefix("setsockopt() failed: ");
close_socket(fd); close_socket(fd);
return -1; return -1;
} }
ret = bind(fd, address, address_length); ret = bind(fd, address, address_length);
if (ret < 0) { if (ret < 0) {
SetSocketError(error_r); SetSocketError(error);
close_socket(fd); close_socket(fd);
return -1; return -1;
} }
ret = listen(fd, backlog); ret = listen(fd, backlog);
if (ret < 0) { if (ret < 0) {
SetSocketError(error_r); SetSocketError(error);
g_prefix_error(error_r, "listen() failed: "); error.AddPrefix("listen() failed: ");
close_socket(fd); close_socket(fd);
return -1; return -1;
} }
......
...@@ -26,11 +26,10 @@ ...@@ -26,11 +26,10 @@
#ifndef MPD_SOCKET_UTIL_HXX #ifndef MPD_SOCKET_UTIL_HXX
#define MPD_SOCKET_UTIL_HXX #define MPD_SOCKET_UTIL_HXX
#include "gerror.h"
#include <stddef.h> #include <stddef.h>
struct sockaddr; struct sockaddr;
class Error;
/** /**
* Creates a socket listening on the specified address. This is a * Creates a socket listening on the specified address. This is a
...@@ -50,7 +49,7 @@ int ...@@ -50,7 +49,7 @@ int
socket_bind_listen(int domain, int type, int protocol, socket_bind_listen(int domain, int type, int protocol,
const struct sockaddr *address, size_t address_length, const struct sockaddr *address, size_t address_length,
int backlog, int backlog,
GError **error); Error &error);
int int
socket_keepalive(int fd); socket_keepalive(int fd);
......
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_DOMAIN_HXX
#define MPD_DOMAIN_HXX
class Domain {
const char *const name;
public:
constexpr explicit Domain(const char *_name)
:name(_name) {}
Domain(const Domain &) = delete;
Domain &operator=(const Domain &) = delete;
constexpr const char *GetName() const {
return name;
}
bool operator==(const Domain &other) const {
return this == &other;
}
bool operator!=(const Domain &other) const {
return !(*this == other);
}
};
#endif
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "Error.hxx"
#include "Domain.hxx"
#include <glib.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
const Domain errno_domain("errno");
Error::~Error() {}
void
Error::Set(const Domain &_domain, int _code, const char *_message)
{
domain = &_domain;
code = _code;
message.assign(_message);
}
void
Error::Format2(const Domain &_domain, int _code, const char *fmt, ...)
{
char buffer[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
Set(_domain, _code, buffer);
}
void
Error::FormatPrefix(const char *fmt, ...)
{
char buffer[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
AddPrefix(buffer);
}
void
Error::SetErrno(int e)
{
Set(errno_domain, e, g_strerror(e));
}
void
Error::SetErrno()
{
SetErrno(errno);
}
void
Error::SetErrno(int e, const char *prefix)
{
Format(errno_domain, e, "%s: %s", prefix, g_strerror(e));
}
void
Error::SetErrno(const char *prefix)
{
SetErrno(errno, prefix);
}
void
Error::FormatErrno(int e, const char *fmt, ...)
{
char buffer[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
SetErrno(e, buffer);
}
void
Error::FormatErrno(const char *fmt, ...)
{
const int e = errno;
char buffer[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
SetErrno(e, buffer);
}
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_ERROR_HXX
#define MPD_ERROR_HXX
#include "check.h"
#include "gcc.h"
#include <string>
#include <assert.h>
class Domain;
extern const Domain errno_domain;
#ifdef WIN32
/* fuck WIN32! */
#include <windows.h>
#define IgnoreError MPDIgnoreError
#undef GetMessage
#endif
/**
* This class contains information about a runtime error.
*/
class Error {
const Domain *domain;
int code;
std::string message;
public:
Error():domain(nullptr), code(0) {}
Error(const Domain &_domain, int _code, const char *_message)
:domain(&_domain), code(_code), message(_message) {}
Error(const Domain &_domain, const char *_message)
:domain(&_domain), code(0), message(_message) {}
Error(Error &&other)
:domain(other.domain), code(other.code),
message(std::move(other.message)) {}
~Error();
Error(const Error &) = delete;
Error &operator=(const Error &) = delete;
Error &operator=(Error &&other) {
domain = other.domain;
code = other.code;
std::swap(message, other.message);
return *this;
}
bool IsDefined() const {
return domain != nullptr;
}
void Clear() {
domain = nullptr;
}
const Domain &GetDomain() const {
assert(IsDefined());
return *domain;
}
bool IsDomain(const Domain &other) const {
return domain == &other;
}
int GetCode() const {
assert(IsDefined());
return code;
}
const char *GetMessage() const {
assert(IsDefined());
return message.c_str();
}
void Set(const Error &other) {
assert(!IsDefined());
assert(other.IsDefined());
domain = other.domain;
code = other.code;
message = other.message;
}
void Set(const Domain &_domain, int _code, const char *_message);
void Set(const Domain &_domain, const char *_message) {
Set(_domain, 0, _message);
}
private:
void Format2(const Domain &_domain, int _code, const char *fmt, ...);
public:
template<typename... Args>
void Format(const Domain &_domain, int _code,
const char *fmt, Args&&... args) {
Format2(_domain, _code, fmt, std::forward<Args>(args)...);
}
template<typename... Args>
void Format(const Domain &_domain, const char *fmt, Args&&... args) {
Format2(_domain, 0, fmt, std::forward<Args>(args)...);
}
void AddPrefix(const char *prefix) {
message.insert(0, prefix);
}
void FormatPrefix(const char *fmt, ...);
void SetErrno(int e);
void SetErrno();
void SetErrno(int e, const char *prefix);
void SetErrno(const char *prefix);
void FormatErrno(const char *prefix, ...);
void FormatErrno(int e, const char *prefix, ...);
};
/**
* Pass a temporary instance of this class to ignore errors.
*/
class IgnoreError final {
Error error;
public:
operator Error &() {
assert(!error.IsDefined());
return error;
}
};
#endif
...@@ -20,18 +20,15 @@ ...@@ -20,18 +20,15 @@
#include "config.h" #include "config.h"
#include "Tokenizer.hxx" #include "Tokenizer.hxx"
#include "StringUtil.hxx" #include "StringUtil.hxx"
#include "Error.hxx"
#include "Domain.hxx"
#include <glib.h> #include <glib.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
gcc_const static constexpr Domain tokenizer_domain("tokenizer");
static GQuark
tokenizer_quark(void)
{
return g_quark_from_static_string("tokenizer");
}
static inline bool static inline bool
valid_word_first_char(char ch) valid_word_first_char(char ch)
...@@ -46,7 +43,7 @@ valid_word_char(char ch) ...@@ -46,7 +43,7 @@ valid_word_char(char ch)
} }
char * char *
Tokenizer::NextWord(GError **error_r) Tokenizer::NextWord(Error &error)
{ {
char *const word = input; char *const word = input;
...@@ -56,8 +53,7 @@ Tokenizer::NextWord(GError **error_r) ...@@ -56,8 +53,7 @@ Tokenizer::NextWord(GError **error_r)
/* check the first character */ /* check the first character */
if (!valid_word_first_char(*input)) { if (!valid_word_first_char(*input)) {
g_set_error(error_r, tokenizer_quark(), 0, error.Set(tokenizer_domain, "Letter expected");
"Letter expected");
return nullptr; return nullptr;
} }
...@@ -74,8 +70,7 @@ Tokenizer::NextWord(GError **error_r) ...@@ -74,8 +70,7 @@ Tokenizer::NextWord(GError **error_r)
} }
if (!valid_word_char(*input)) { if (!valid_word_char(*input)) {
g_set_error(error_r, tokenizer_quark(), 0, error.Set(tokenizer_domain, "Invalid word character");
"Invalid word character");
return nullptr; return nullptr;
} }
} }
...@@ -93,7 +88,7 @@ valid_unquoted_char(char ch) ...@@ -93,7 +88,7 @@ valid_unquoted_char(char ch)
} }
char * char *
Tokenizer::NextUnquoted(GError **error_r) Tokenizer::NextUnquoted(Error &error)
{ {
char *const word = input; char *const word = input;
...@@ -103,8 +98,7 @@ Tokenizer::NextUnquoted(GError **error_r) ...@@ -103,8 +98,7 @@ Tokenizer::NextUnquoted(GError **error_r)
/* check the first character */ /* check the first character */
if (!valid_unquoted_char(*input)) { if (!valid_unquoted_char(*input)) {
g_set_error(error_r, tokenizer_quark(), 0, error.Set(tokenizer_domain, "Invalid unquoted character");
"Invalid unquoted character");
return nullptr; return nullptr;
} }
...@@ -121,7 +115,7 @@ Tokenizer::NextUnquoted(GError **error_r) ...@@ -121,7 +115,7 @@ Tokenizer::NextUnquoted(GError **error_r)
} }
if (!valid_unquoted_char(*input)) { if (!valid_unquoted_char(*input)) {
g_set_error(error_r, tokenizer_quark(), 0, error.Set(tokenizer_domain,
"Invalid unquoted character"); "Invalid unquoted character");
return nullptr; return nullptr;
} }
...@@ -134,7 +128,7 @@ Tokenizer::NextUnquoted(GError **error_r) ...@@ -134,7 +128,7 @@ Tokenizer::NextUnquoted(GError **error_r)
} }
char * char *
Tokenizer::NextString(GError **error_r) Tokenizer::NextString(Error &error)
{ {
char *const word = input, *dest = input; char *const word = input, *dest = input;
...@@ -145,8 +139,7 @@ Tokenizer::NextString(GError **error_r) ...@@ -145,8 +139,7 @@ Tokenizer::NextString(GError **error_r)
/* check for the opening " */ /* check for the opening " */
if (*input != '"') { if (*input != '"') {
g_set_error(error_r, tokenizer_quark(), 0, error.Set(tokenizer_domain, "'\"' expected");
"'\"' expected");
return nullptr; return nullptr;
} }
...@@ -165,8 +158,7 @@ Tokenizer::NextString(GError **error_r) ...@@ -165,8 +158,7 @@ Tokenizer::NextString(GError **error_r)
difference between "end of line" and difference between "end of line" and
"error" */ "error" */
--input; --input;
g_set_error(error_r, tokenizer_quark(), 0, error.Set(tokenizer_domain, "Missing closing '\"'");
"Missing closing '\"'");
return nullptr; return nullptr;
} }
...@@ -179,7 +171,7 @@ Tokenizer::NextString(GError **error_r) ...@@ -179,7 +171,7 @@ Tokenizer::NextString(GError **error_r)
++input; ++input;
if (*input != 0 && !g_ascii_isspace(*input)) { if (*input != 0 && !g_ascii_isspace(*input)) {
g_set_error(error_r, tokenizer_quark(), 0, error.Set(tokenizer_domain,
"Space expected after closing '\"'"); "Space expected after closing '\"'");
return nullptr; return nullptr;
} }
...@@ -192,10 +184,10 @@ Tokenizer::NextString(GError **error_r) ...@@ -192,10 +184,10 @@ Tokenizer::NextString(GError **error_r)
} }
char * char *
Tokenizer::NextParam(GError **error_r) Tokenizer::NextParam(Error &error)
{ {
if (*input == '"') if (*input == '"')
return NextString(error_r); return NextString(error);
else else
return NextUnquoted(error_r); return NextUnquoted(error);
} }
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#ifndef MPD_TOKENIZER_HXX #ifndef MPD_TOKENIZER_HXX
#define MPD_TOKENIZER_HXX #define MPD_TOKENIZER_HXX
#include "gerror.h" class Error;
class Tokenizer { class Tokenizer {
char *input; char *input;
...@@ -50,23 +50,23 @@ public: ...@@ -50,23 +50,23 @@ public:
/** /**
* Reads the next word. * Reads the next word.
* *
* @param error_r if this function returns nullptr and * @param error if this function returns nullptr and
* **input_p!=0, it optionally provides a GError object in * **input_p!=0, it provides an #Error object in
* this argument * this argument
* @return a pointer to the null-terminated word, or nullptr * @return a pointer to the null-terminated word, or nullptr
* on error or end of line * on error or end of line
*/ */
char *NextWord(GError **error_r); char *NextWord(Error &error);
/** /**
* Reads the next unquoted word from the input string. * Reads the next unquoted word from the input string.
* *
* @param error_r if this function returns nullptr and **input_p!=0, it * @param error_r if this function returns nullptr and **input_p!=0, it
* optionally provides a GError object in this argument * provides an #Error object in this argument
* @return a pointer to the null-terminated word, or nullptr * @return a pointer to the null-terminated word, or nullptr
* on error or end of line * on error or end of line
*/ */
char *NextUnquoted(GError **error_r); char *NextUnquoted(Error &error);
/** /**
* Reads the next quoted string from the input string. A backslash * Reads the next quoted string from the input string. A backslash
...@@ -76,11 +76,11 @@ public: ...@@ -76,11 +76,11 @@ public:
* @param input_p the input string; this function returns a pointer to * @param input_p the input string; this function returns a pointer to
* the first non-whitespace character of the following token * the first non-whitespace character of the following token
* @param error_r if this function returns nullptr and **input_p!=0, it * @param error_r if this function returns nullptr and **input_p!=0, it
* optionally provides a GError object in this argument * provides an #Error object in this argument
* @return a pointer to the null-terminated string, or nullptr on error * @return a pointer to the null-terminated string, or nullptr on error
* or end of line * or end of line
*/ */
char *NextString(GError **error_r); char *NextString(Error &error);
/** /**
* Reads the next unquoted word or quoted string from the * Reads the next unquoted word or quoted string from the
...@@ -88,12 +88,12 @@ public: ...@@ -88,12 +88,12 @@ public:
* NextString(). * NextString().
* *
* @param error_r if this function returns nullptr and * @param error_r if this function returns nullptr and
* **input_p!=0, it optionally provides a GError object in * **input_p!=0, it provides an #Error object in
* this argument * this argument
* @return a pointer to the null-terminated string, or nullptr * @return a pointer to the null-terminated string, or nullptr
* on error or end of line * on error or end of line
*/ */
char *NextParam(GError **error_r); char *NextParam(Error &error);
}; };
#endif #endif
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "conf.h" #include "conf.h"
#include "Tag.hxx" #include "Tag.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/Error.hxx"
#include <iostream> #include <iostream>
using std::cout; using std::cout;
...@@ -46,14 +47,14 @@ my_log_func(const gchar *log_domain, gcc_unused GLogLevelFlags log_level, ...@@ -46,14 +47,14 @@ my_log_func(const gchar *log_domain, gcc_unused GLogLevelFlags log_level,
} }
static bool static bool
DumpDirectory(const Directory &directory, GError **) DumpDirectory(const Directory &directory, Error &)
{ {
cout << "D " << directory.path << endl; cout << "D " << directory.path << endl;
return true; return true;
} }
static bool static bool
DumpSong(Song &song, GError **) DumpSong(Song &song, Error &)
{ {
cout << "S " << song.parent->path << "/" << song.uri << endl; cout << "S " << song.parent->path << "/" << song.uri << endl;
return true; return true;
...@@ -61,7 +62,7 @@ DumpSong(Song &song, GError **) ...@@ -61,7 +62,7 @@ DumpSong(Song &song, GError **)
static bool static bool
DumpPlaylist(const PlaylistInfo &playlist, DumpPlaylist(const PlaylistInfo &playlist,
const Directory &directory, GError **) const Directory &directory, Error &)
{ {
cout << "P " << directory.path << "/" << playlist.name.c_str() << endl; cout << "P " << directory.path << "/" << playlist.name.c_str() << endl;
return true; return true;
...@@ -70,8 +71,6 @@ DumpPlaylist(const PlaylistInfo &playlist, ...@@ -70,8 +71,6 @@ DumpPlaylist(const PlaylistInfo &playlist,
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
GError *error = nullptr;
if (argc != 3) { if (argc != 3) {
cerr << "Usage: DumpDatabase CONFIG PLUGIN" << endl; cerr << "Usage: DumpDatabase CONFIG PLUGIN" << endl;
return 1; return 1;
...@@ -98,9 +97,9 @@ main(int argc, char **argv) ...@@ -98,9 +97,9 @@ main(int argc, char **argv)
config_global_init(); config_global_init();
if (!ReadConfigFile(config_path, &error)) { Error error;
cerr << error->message << endl; if (!ReadConfigFile(config_path, error)) {
g_error_free(error); cerr << error.GetMessage() << endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -113,29 +112,26 @@ main(int argc, char **argv) ...@@ -113,29 +112,26 @@ main(int argc, char **argv)
if (path != nullptr) if (path != nullptr)
param.AddBlockParam("path", path->value, path->line); param.AddBlockParam("path", path->value, path->line);
Database *db = plugin->create(param, &error); Database *db = plugin->create(param, error);
if (db == nullptr) { if (db == nullptr) {
cerr << error->message << endl; cerr << error.GetMessage() << endl;
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!db->Open(&error)) { if (!db->Open(error)) {
delete db; delete db;
cerr << error->message << endl; cerr << error.GetMessage() << endl;
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
const DatabaseSelection selection("", true); const DatabaseSelection selection("", true);
if (!db->Visit(selection, DumpDirectory, DumpSong, DumpPlaylist, if (!db->Visit(selection, DumpDirectory, DumpSong, DumpPlaylist,
&error)) { error)) {
db->Close(); db->Close();
delete db; delete db;
cerr << error->message << endl; cerr << error.GetMessage() << endl;
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "PlaylistRegistry.hxx" #include "PlaylistRegistry.hxx"
#include "PlaylistPlugin.hxx" #include "PlaylistPlugin.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -84,7 +85,8 @@ decoder_read(gcc_unused struct decoder *decoder, ...@@ -84,7 +85,8 @@ decoder_read(gcc_unused struct decoder *decoder,
struct input_stream *is, struct input_stream *is,
void *buffer, size_t length) void *buffer, size_t length)
{ {
return input_stream_lock_read(is, buffer, length, NULL); Error error;
return input_stream_lock_read(is, buffer, length, error);
} }
void void
...@@ -139,7 +141,6 @@ int main(int argc, char **argv) ...@@ -139,7 +141,6 @@ int main(int argc, char **argv)
{ {
const char *uri; const char *uri;
struct input_stream *is = NULL; struct input_stream *is = NULL;
GError *error = NULL;
struct playlist_provider *playlist; struct playlist_provider *playlist;
Song *song; Song *song;
...@@ -162,18 +163,18 @@ int main(int argc, char **argv) ...@@ -162,18 +163,18 @@ int main(int argc, char **argv)
/* initialize MPD */ /* initialize MPD */
config_global_init(); config_global_init();
if (!ReadConfigFile(config_path, &error)) {
g_printerr("%s\n", error->message); Error error;
g_error_free(error); if (!ReadConfigFile(config_path, error)) {
g_printerr("%s\n", error.GetMessage());
return 1; return 1;
} }
io_thread_init(); io_thread_init();
io_thread_start(); io_thread_start();
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 2; return 2;
} }
...@@ -189,12 +190,11 @@ int main(int argc, char **argv) ...@@ -189,12 +190,11 @@ int main(int argc, char **argv)
if (playlist == NULL) { if (playlist == NULL) {
/* open the stream and wait until it becomes ready */ /* open the stream and wait until it becomes ready */
is = input_stream_open(uri, mutex, cond, &error); is = input_stream_open(uri, mutex, 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); else
} else
g_printerr("input_stream_open() failed\n"); g_printerr("input_stream_open() failed\n");
return 2; return 2;
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "replay_gain_info.h" #include "replay_gain_info.h"
#include "conf.h" #include "conf.h"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
#include <id3tag.h> #include <id3tag.h>
...@@ -51,8 +52,6 @@ Tag::~Tag() {} ...@@ -51,8 +52,6 @@ Tag::~Tag() {}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
#ifdef HAVE_LOCALE_H #ifdef HAVE_LOCALE_H
/* initialize locale */ /* initialize locale */
setlocale(LC_CTYPE,""); setlocale(LC_CTYPE,"");
...@@ -65,12 +64,12 @@ int main(int argc, char **argv) ...@@ -65,12 +64,12 @@ int main(int argc, char **argv)
const char *path = argv[1]; const char *path = argv[1];
struct id3_tag *tag = tag_id3_load(path, &error); Error error;
struct id3_tag *tag = tag_id3_load(path, error);
if (tag == NULL) { if (tag == NULL) {
if (error != NULL) { if (error.IsDefined())
g_printerr("%s\n", error->message); g_printerr("%s\n", error.GetMessage());
g_error_free(error); else
} else
g_printerr("No ID3 tag found\n"); g_printerr("No ID3 tag found\n");
return EXIT_FAILURE; return EXIT_FAILURE;
......
/* /*
* Copyright (C) 2003-2011 The Music Player Daemon Project * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "conf.h" #include "conf.h"
#include "stdbin.h" #include "stdbin.h"
#include "TextInputStream.hxx" #include "TextInputStream.hxx"
#include "util/Error.hxx"
#ifdef ENABLE_ARCHIVE #ifdef ENABLE_ARCHIVE
#include "ArchiveList.hxx" #include "ArchiveList.hxx"
...@@ -56,7 +57,7 @@ dump_text_file(TextInputStream &is) ...@@ -56,7 +57,7 @@ dump_text_file(TextInputStream &is)
static int static int
dump_input_stream(struct input_stream *is) dump_input_stream(struct input_stream *is)
{ {
GError *error = NULL; Error error;
input_stream_lock(is); input_stream_lock(is);
...@@ -64,9 +65,8 @@ dump_input_stream(struct input_stream *is) ...@@ -64,9 +65,8 @@ dump_input_stream(struct input_stream *is)
input_stream_wait_ready(is); input_stream_wait_ready(is);
if (!input_stream_check(is, &error)) { if (!input_stream_check(is, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
input_stream_unlock(is); input_stream_unlock(is);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -80,9 +80,8 @@ dump_input_stream(struct input_stream *is) ...@@ -80,9 +80,8 @@ dump_input_stream(struct input_stream *is)
} }
input_stream_lock(is); input_stream_lock(is);
if (!input_stream_check(is, &error)) { if (!input_stream_check(is, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
input_stream_unlock(is); input_stream_unlock(is);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -94,7 +93,6 @@ dump_input_stream(struct input_stream *is) ...@@ -94,7 +93,6 @@ dump_input_stream(struct input_stream *is)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
struct input_stream *is; struct input_stream *is;
int ret; int ret;
...@@ -122,9 +120,9 @@ int main(int argc, char **argv) ...@@ -122,9 +120,9 @@ int main(int argc, char **argv)
archive_plugin_init_all(); archive_plugin_init_all();
#endif #endif
if (!input_stream_global_init(&error)) { Error error;
g_warning("%s", error->message); if (!input_stream_global_init(error)) {
g_error_free(error); g_warning("%s", error.GetMessage());
return 2; return 2;
} }
...@@ -133,15 +131,14 @@ int main(int argc, char **argv) ...@@ -133,15 +131,14 @@ int main(int argc, char **argv)
Mutex mutex; Mutex mutex;
Cond cond; Cond cond;
is = input_stream_open(argv[1], mutex, cond, &error); is = input_stream_open(argv[1], mutex, cond, error);
if (is != NULL) { if (is != NULL) {
ret = dump_input_stream(is); ret = dump_input_stream(is);
input_stream_close(is); input_stream_close(is);
} else { } else {
if (error != NULL) { if (error.IsDefined())
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error); else
} else
g_printerr("input_stream_open() failed\n"); g_printerr("input_stream_open() failed\n");
ret = 2; ret = 2;
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include "conf.h" #include "conf.h"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -50,10 +51,9 @@ int main(int argc, char **argv) ...@@ -50,10 +51,9 @@ int main(int argc, char **argv)
config_global_init(); config_global_init();
GError *error = NULL; Error error;
if (!ReadConfigFile(config_path, &error)) { if (!ReadConfigFile(config_path, error)) {
g_printerr("%s:", error->message); g_printerr("%s:", error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "Main.hxx" #include "Main.hxx"
#include "event/Loop.hxx" #include "event/Loop.hxx"
#include "ConfigData.hxx" #include "ConfigData.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -63,7 +64,7 @@ pulse_output_clear_mixer(gcc_unused PulseOutput *po, ...@@ -63,7 +64,7 @@ pulse_output_clear_mixer(gcc_unused PulseOutput *po,
bool bool
pulse_output_set_volume(gcc_unused PulseOutput *po, pulse_output_set_volume(gcc_unused PulseOutput *po,
gcc_unused const struct pa_cvolume *volume, gcc_unused const struct pa_cvolume *volume,
gcc_unused GError **error_r) gcc_unused Error &error)
{ {
return false; return false;
} }
...@@ -111,8 +112,6 @@ pcm_volume(gcc_unused void *buffer, gcc_unused size_t length, ...@@ -111,8 +112,6 @@ pcm_volume(gcc_unused void *buffer, gcc_unused size_t length,
int main(int argc, gcc_unused char **argv) int main(int argc, gcc_unused char **argv)
{ {
GError *error = NULL;
bool success;
int volume; int volume;
if (argc != 2) { if (argc != 2) {
...@@ -126,23 +125,21 @@ int main(int argc, gcc_unused char **argv) ...@@ -126,23 +125,21 @@ int main(int argc, gcc_unused char **argv)
main_loop = new EventLoop(EventLoop::Default()); main_loop = new EventLoop(EventLoop::Default());
Error error;
Mixer *mixer = mixer_new(&alsa_mixer_plugin, nullptr, Mixer *mixer = mixer_new(&alsa_mixer_plugin, nullptr,
config_param(), &error); config_param(), error);
if (mixer == NULL) { if (mixer == NULL) {
g_printerr("mixer_new() failed: %s\n", error->message); g_printerr("mixer_new() failed: %s\n", error.GetMessage());
g_error_free(error);
return 2; return 2;
} }
success = mixer_open(mixer, &error); if (!mixer_open(mixer, error)) {
if (!success) {
mixer_free(mixer); mixer_free(mixer);
g_printerr("failed to open the mixer: %s\n", error->message); g_printerr("failed to open the mixer: %s\n", error.GetMessage());
g_error_free(error);
return 2; return 2;
} }
volume = mixer_get_volume(mixer, &error); volume = mixer_get_volume(mixer, error);
mixer_close(mixer); mixer_close(mixer);
mixer_free(mixer); mixer_free(mixer);
...@@ -151,10 +148,9 @@ int main(int argc, gcc_unused char **argv) ...@@ -151,10 +148,9 @@ int main(int argc, gcc_unused char **argv)
assert(volume >= -1 && volume <= 100); assert(volume >= -1 && volume <= 100);
if (volume < 0) { if (volume < 0) {
if (error != NULL) { if (error.IsDefined()) {
g_printerr("failed to read volume: %s\n", g_printerr("failed to read volume: %s\n",
error->message); error.GetMessage());
g_error_free(error);
} else } else
g_printerr("failed to read volume\n"); g_printerr("failed to read volume\n");
return 2; return 2;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "TagHandler.hxx" #include "TagHandler.hxx"
#include "TagId3.hxx" #include "TagId3.hxx"
#include "ApeTag.hxx" #include "ApeTag.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -70,7 +71,8 @@ decoder_read(gcc_unused struct decoder *decoder, ...@@ -70,7 +71,8 @@ decoder_read(gcc_unused struct decoder *decoder,
struct input_stream *is, struct input_stream *is,
void *buffer, size_t length) void *buffer, size_t length)
{ {
return input_stream_lock_read(is, buffer, length, NULL); Error error;
return input_stream_lock_read(is, buffer, length, error);
} }
void void
...@@ -140,7 +142,6 @@ static const struct tag_handler print_handler = { ...@@ -140,7 +142,6 @@ static const struct tag_handler print_handler = {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
const char *decoder_name, *path; const char *decoder_name, *path;
const struct decoder_plugin *plugin; const struct decoder_plugin *plugin;
...@@ -164,9 +165,9 @@ int main(int argc, char **argv) ...@@ -164,9 +165,9 @@ int main(int argc, char **argv)
io_thread_init(); io_thread_init();
io_thread_start(); io_thread_start();
if (!input_stream_global_init(&error)) { Error error;
g_warning("%s", error->message); if (!input_stream_global_init(error)) {
g_error_free(error); g_warning("%s", error.GetMessage());
return 2; return 2;
} }
...@@ -185,12 +186,11 @@ int main(int argc, char **argv) ...@@ -185,12 +186,11 @@ int main(int argc, char **argv)
Cond cond; Cond cond;
struct input_stream *is = struct input_stream *is =
input_stream_open(path, mutex, cond, &error); input_stream_open(path, mutex, cond, error);
if (is == NULL) { if (is == NULL) {
g_printerr("Failed to open %s: %s\n", g_printerr("Failed to open %s: %s\n",
path, error->message); path, error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
...@@ -201,13 +201,11 @@ int main(int argc, char **argv) ...@@ -201,13 +201,11 @@ int main(int argc, char **argv)
input_stream_update(is); input_stream_update(is);
} }
if (!input_stream_check(is, &error)) { if (!input_stream_check(is, error)) {
mutex.unlock(); mutex.unlock();
g_printerr("Failed to read %s: %s\n", g_printerr("Failed to read %s: %s\n",
path, error->message); path, error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "pcm/PcmConvert.hxx" #include "pcm/PcmConvert.hxx"
#include "conf.h" #include "conf.h"
#include "util/fifo_buffer.h" #include "util/fifo_buffer.h"
#include "util/Error.hxx"
#include "stdbin.h" #include "stdbin.h"
#include <glib.h> #include <glib.h>
...@@ -56,7 +57,6 @@ config_get_string(gcc_unused enum ConfigOption option, ...@@ -56,7 +57,6 @@ config_get_string(gcc_unused enum ConfigOption option,
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
AudioFormat in_audio_format, out_audio_format; AudioFormat in_audio_format, out_audio_format;
const void *output; const void *output;
ssize_t nbytes; ssize_t nbytes;
...@@ -69,18 +69,19 @@ int main(int argc, char **argv) ...@@ -69,18 +69,19 @@ int main(int argc, char **argv)
g_log_set_default_handler(my_log_func, NULL); g_log_set_default_handler(my_log_func, NULL);
Error error;
if (!audio_format_parse(in_audio_format, argv[1], if (!audio_format_parse(in_audio_format, argv[1],
false, &error)) { false, error)) {
g_printerr("Failed to parse audio format: %s\n", g_printerr("Failed to parse audio format: %s\n",
error->message); error.GetMessage());
return 1; return 1;
} }
AudioFormat out_audio_format_mask; AudioFormat out_audio_format_mask;
if (!audio_format_parse(out_audio_format_mask, argv[2], if (!audio_format_parse(out_audio_format_mask, argv[2],
true, &error)) { true, error)) {
g_printerr("Failed to parse audio format: %s\n", g_printerr("Failed to parse audio format: %s\n",
error->message); error.GetMessage());
return 1; return 1;
} }
...@@ -113,9 +114,9 @@ int main(int argc, char **argv) ...@@ -113,9 +114,9 @@ int main(int argc, char **argv)
fifo_buffer_consume(buffer, length); fifo_buffer_consume(buffer, length);
output = state.Convert(in_audio_format, src, length, output = state.Convert(in_audio_format, src, length,
out_audio_format, &length, &error); out_audio_format, &length, error);
if (output == NULL) { if (output == NULL) {
g_printerr("Failed to convert: %s\n", error->message); g_printerr("Failed to convert: %s\n", error.GetMessage());
return 2; return 2;
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "InputInit.hxx" #include "InputInit.hxx"
#include "InputLegacy.hxx" #include "InputLegacy.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "stdbin.h" #include "stdbin.h"
#include <glib.h> #include <glib.h>
...@@ -91,7 +92,8 @@ decoder_read(gcc_unused struct decoder *decoder, ...@@ -91,7 +92,8 @@ decoder_read(gcc_unused struct decoder *decoder,
struct input_stream *is, struct input_stream *is,
void *buffer, size_t length) void *buffer, size_t length)
{ {
return input_stream_lock_read(is, buffer, length, NULL); Error error;
return input_stream_lock_read(is, buffer, length, error);
} }
void void
...@@ -144,7 +146,6 @@ decoder_mixramp(gcc_unused struct decoder *decoder, ...@@ -144,7 +146,6 @@ decoder_mixramp(gcc_unused struct decoder *decoder,
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
const char *decoder_name; const char *decoder_name;
struct decoder decoder; struct decoder decoder;
...@@ -165,9 +166,9 @@ int main(int argc, char **argv) ...@@ -165,9 +166,9 @@ int main(int argc, char **argv)
io_thread_init(); io_thread_init();
io_thread_start(); io_thread_start();
if (!input_stream_global_init(&error)) { Error error;
g_warning("%s", error->message); if (!input_stream_global_init(error)) {
g_error_free(error); g_warning("%s", error.GetMessage());
return 2; return 2;
} }
...@@ -189,12 +190,11 @@ int main(int argc, char **argv) ...@@ -189,12 +190,11 @@ int main(int argc, char **argv)
Cond cond; Cond cond;
struct input_stream *is = struct input_stream *is =
input_stream_open(decoder.uri, mutex, cond, &error); input_stream_open(decoder.uri, mutex, 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); else
} else
g_printerr("input_stream_open() failed\n"); g_printerr("input_stream_open() failed\n");
return 1; return 1;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "AudioParser.hxx" #include "AudioParser.hxx"
#include "conf.h" #include "conf.h"
#include "util/Error.hxx"
#include "stdbin.h" #include "stdbin.h"
#include <glib.h> #include <glib.h>
...@@ -43,8 +44,6 @@ encoder_to_stdout(Encoder &encoder) ...@@ -43,8 +44,6 @@ encoder_to_stdout(Encoder &encoder)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
bool ret;
const char *encoder_name; const char *encoder_name;
static char buffer[32768]; static char buffer[32768];
...@@ -71,11 +70,11 @@ int main(int argc, char **argv) ...@@ -71,11 +70,11 @@ int main(int argc, char **argv)
config_param param; config_param param;
param.AddBlockParam("quality", "5.0", -1); param.AddBlockParam("quality", "5.0", -1);
const auto encoder = encoder_init(*plugin, param, &error); Error error;
const auto encoder = encoder_init(*plugin, param, error);
if (encoder == NULL) { if (encoder == NULL) {
g_printerr("Failed to initialize encoder: %s\n", g_printerr("Failed to initialize encoder: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
...@@ -83,20 +82,16 @@ int main(int argc, char **argv) ...@@ -83,20 +82,16 @@ int main(int argc, char **argv)
AudioFormat audio_format(44100, SampleFormat::S16, 2); AudioFormat audio_format(44100, SampleFormat::S16, 2);
if (argc > 2) { if (argc > 2) {
ret = audio_format_parse(audio_format, argv[2], if (!audio_format_parse(audio_format, argv[2], false, error)) {
false, &error);
if (!ret) {
g_printerr("Failed to parse audio format: %s\n", g_printerr("Failed to parse audio format: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
} }
if (!encoder_open(encoder, audio_format, &error)) { if (!encoder_open(encoder, audio_format, error)) {
g_printerr("Failed to open encoder: %s\n", g_printerr("Failed to open encoder: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
...@@ -106,22 +101,18 @@ int main(int argc, char **argv) ...@@ -106,22 +101,18 @@ int main(int argc, char **argv)
ssize_t nbytes; ssize_t nbytes;
while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) {
ret = encoder_write(encoder, buffer, nbytes, &error); if (!encoder_write(encoder, buffer, nbytes, error)) {
if (!ret) {
g_printerr("encoder_write() failed: %s\n", g_printerr("encoder_write() failed: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
encoder_to_stdout(*encoder); encoder_to_stdout(*encoder);
} }
ret = encoder_end(encoder, &error); if (!encoder_end(encoder, error)) {
if (!ret) {
g_printerr("encoder_flush() failed: %s\n", g_printerr("encoder_flush() failed: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "pcm/PcmVolume.hxx" #include "pcm/PcmVolume.hxx"
#include "MixerControl.hxx" #include "MixerControl.hxx"
#include "stdbin.h" #include "stdbin.h"
#include "util/Error.hxx"
#include "system/FatalError.hxx"
#include <glib.h> #include <glib.h>
...@@ -37,7 +39,7 @@ ...@@ -37,7 +39,7 @@
bool bool
mixer_set_volume(gcc_unused Mixer *mixer, mixer_set_volume(gcc_unused Mixer *mixer,
gcc_unused unsigned volume, gcc_unused GError **error_r) gcc_unused unsigned volume, gcc_unused Error &error)
{ {
return true; return true;
} }
...@@ -70,7 +72,6 @@ static Filter * ...@@ -70,7 +72,6 @@ static Filter *
load_filter(const char *name) load_filter(const char *name)
{ {
const struct config_param *param; const struct config_param *param;
GError *error = NULL;
param = find_named_config_block(CONF_AUDIO_FILTER, name); param = find_named_config_block(CONF_AUDIO_FILTER, name);
if (param == NULL) { if (param == NULL) {
...@@ -78,10 +79,10 @@ load_filter(const char *name) ...@@ -78,10 +79,10 @@ load_filter(const char *name)
return nullptr; return nullptr;
} }
Filter *filter = filter_configured_new(*param, &error); Error error;
Filter *filter = filter_configured_new(*param, error);
if (filter == NULL) { if (filter == NULL) {
g_printerr("Failed to load filter: %s\n", error->message); g_printerr("Failed to load filter: %s\n", error.GetMessage());
g_error_free(error);
return NULL; return NULL;
} }
...@@ -91,8 +92,7 @@ load_filter(const char *name) ...@@ -91,8 +92,7 @@ load_filter(const char *name)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct audio_format_string af_string; struct audio_format_string af_string;
bool success; Error error2;
GError *error = NULL;
char buffer[4096]; char buffer[4096];
if (argc < 3 || argc > 4) { if (argc < 3 || argc > 4) {
...@@ -115,21 +115,16 @@ int main(int argc, char **argv) ...@@ -115,21 +115,16 @@ int main(int argc, char **argv)
/* read configuration file (mpd.conf) */ /* read configuration file (mpd.conf) */
config_global_init(); config_global_init();
if (!ReadConfigFile(config_path, &error)) { if (!ReadConfigFile(config_path, error2))
g_printerr("%s:", error->message); FatalError(error2);
g_error_free(error);
return 1;
}
/* parse the audio format */ /* parse the audio format */
if (argc > 3) { if (argc > 3) {
success = audio_format_parse(audio_format, argv[3], Error error;
false, &error); if (!audio_format_parse(audio_format, argv[3], false, error)) {
if (!success) {
g_printerr("Failed to parse audio format: %s\n", g_printerr("Failed to parse audio format: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
} }
...@@ -142,11 +137,10 @@ int main(int argc, char **argv) ...@@ -142,11 +137,10 @@ int main(int argc, char **argv)
/* open the filter */ /* open the filter */
const AudioFormat out_audio_format = Error error;
filter->Open(audio_format, &error); const AudioFormat out_audio_format = filter->Open(audio_format, error);
if (!out_audio_format.IsDefined()) { if (!out_audio_format.IsDefined()) {
g_printerr("Failed to open filter: %s\n", error->message); g_printerr("Failed to open filter: %s\n", error.GetMessage());
g_error_free(error);
delete filter; delete filter;
return 1; return 1;
} }
...@@ -166,9 +160,9 @@ int main(int argc, char **argv) ...@@ -166,9 +160,9 @@ int main(int argc, char **argv)
break; break;
dest = filter->FilterPCM(buffer, (size_t)nbytes, dest = filter->FilterPCM(buffer, (size_t)nbytes,
&length, &error); &length, error);
if (dest == NULL) { if (dest == NULL) {
g_printerr("Filter failed: %s\n", error->message); g_printerr("Filter failed: %s\n", error.GetMessage());
filter->Close(); filter->Close();
delete filter; delete filter;
return 1; return 1;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include "InotifySource.hxx" #include "InotifySource.hxx"
#include "event/Loop.hxx" #include "event/Loop.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -51,7 +52,6 @@ my_inotify_callback(gcc_unused int wd, unsigned mask, ...@@ -51,7 +52,6 @@ my_inotify_callback(gcc_unused int wd, unsigned mask,
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
const char *path; const char *path;
if (argc != 2) { if (argc != 2) {
...@@ -63,20 +63,19 @@ int main(int argc, char **argv) ...@@ -63,20 +63,19 @@ int main(int argc, char **argv)
event_loop = new EventLoop(EventLoop::Default()); event_loop = new EventLoop(EventLoop::Default());
Error error;
InotifySource *source = InotifySource::Create(*event_loop, InotifySource *source = InotifySource::Create(*event_loop,
my_inotify_callback, my_inotify_callback,
nullptr, &error); nullptr, error);
if (source == NULL) { if (source == NULL) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return 2; return 2;
} }
int descriptor = source->Add(path, IN_MASK, &error); int descriptor = source->Add(path, IN_MASK, error);
if (descriptor < 0) { if (descriptor < 0) {
delete source; delete source;
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return 2; return 2;
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "InputStream.hxx" #include "InputStream.hxx"
#include "InputInit.hxx" #include "InputInit.hxx"
#include "IOThread.hxx" #include "IOThread.hxx"
#include "util/Error.hxx"
#ifdef ENABLE_ARCHIVE #ifdef ENABLE_ARCHIVE
#include "ArchiveList.hxx" #include "ArchiveList.hxx"
...@@ -49,7 +50,7 @@ my_log_func(const gchar *log_domain, gcc_unused GLogLevelFlags log_level, ...@@ -49,7 +50,7 @@ my_log_func(const gchar *log_domain, gcc_unused GLogLevelFlags log_level,
static int static int
dump_input_stream(struct input_stream *is) dump_input_stream(struct input_stream *is)
{ {
GError *error = NULL; Error error;
char buffer[4096]; char buffer[4096];
size_t num_read; size_t num_read;
ssize_t num_written; ssize_t num_written;
...@@ -60,9 +61,8 @@ dump_input_stream(struct input_stream *is) ...@@ -60,9 +61,8 @@ dump_input_stream(struct input_stream *is)
input_stream_wait_ready(is); input_stream_wait_ready(is);
if (!input_stream_check(is, &error)) { if (!input_stream_check(is, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
input_stream_unlock(is); input_stream_unlock(is);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -83,12 +83,10 @@ dump_input_stream(struct input_stream *is) ...@@ -83,12 +83,10 @@ dump_input_stream(struct input_stream *is)
} }
num_read = input_stream_read(is, buffer, sizeof(buffer), num_read = input_stream_read(is, buffer, sizeof(buffer),
&error); error);
if (num_read == 0) { if (num_read == 0) {
if (error != NULL) { if (error.IsDefined())
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
}
break; break;
} }
...@@ -98,9 +96,8 @@ dump_input_stream(struct input_stream *is) ...@@ -98,9 +96,8 @@ dump_input_stream(struct input_stream *is)
break; break;
} }
if (!input_stream_check(is, &error)) { if (!input_stream_check(is, error)) {
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
input_stream_unlock(is); input_stream_unlock(is);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
...@@ -112,7 +109,7 @@ dump_input_stream(struct input_stream *is) ...@@ -112,7 +109,7 @@ dump_input_stream(struct input_stream *is)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL; Error error;
struct input_stream *is; struct input_stream *is;
int ret; int ret;
...@@ -140,9 +137,8 @@ int main(int argc, char **argv) ...@@ -140,9 +137,8 @@ int main(int argc, char **argv)
archive_plugin_init_all(); archive_plugin_init_all();
#endif #endif
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 2; return 2;
} }
...@@ -151,15 +147,14 @@ int main(int argc, char **argv) ...@@ -151,15 +147,14 @@ int main(int argc, char **argv)
Mutex mutex; Mutex mutex;
Cond cond; Cond cond;
is = input_stream_open(argv[1], mutex, cond, &error); is = input_stream_open(argv[1], mutex, cond, error);
if (is != NULL) { if (is != NULL) {
ret = dump_input_stream(is); ret = dump_input_stream(is);
input_stream_close(is); input_stream_close(is);
} else { } else {
if (error != NULL) { if (error.IsDefined())
g_warning("%s", error->message); g_warning("%s", error.GetMessage());
g_error_free(error); else
} else
g_printerr("input_stream_open() failed\n"); g_printerr("input_stream_open() failed\n");
ret = 2; ret = 2;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "AudioCompress/compress.h" #include "AudioCompress/compress.h"
#include "AudioParser.hxx" #include "AudioParser.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "stdbin.h" #include "stdbin.h"
#include <glib.h> #include <glib.h>
...@@ -37,8 +38,6 @@ ...@@ -37,8 +38,6 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
bool ret;
struct Compressor *compressor; struct Compressor *compressor;
static char buffer[4096]; static char buffer[4096];
ssize_t nbytes; ssize_t nbytes;
...@@ -50,11 +49,10 @@ int main(int argc, char **argv) ...@@ -50,11 +49,10 @@ int main(int argc, char **argv)
AudioFormat audio_format(48000, SampleFormat::S16, 2); AudioFormat audio_format(48000, SampleFormat::S16, 2);
if (argc > 1) { if (argc > 1) {
ret = audio_format_parse(audio_format, argv[1], Error error;
false, &error); if (!audio_format_parse(audio_format, argv[1], false, error)) {
if (!ret) {
g_printerr("Failed to parse audio format: %s\n", g_printerr("Failed to parse audio format: %s\n",
error->message); error.GetMessage());
return 1; return 1;
} }
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "PlayerControl.hxx" #include "PlayerControl.hxx"
#include "stdbin.h" #include "stdbin.h"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -48,21 +49,6 @@ GlobalEvents::Emit(gcc_unused Event event) ...@@ -48,21 +49,6 @@ GlobalEvents::Emit(gcc_unused Event event)
{ {
} }
PcmConvert::PcmConvert() {}
PcmConvert::~PcmConvert() {}
const void *
PcmConvert::Convert(gcc_unused const AudioFormat src_format,
gcc_unused const void *src, gcc_unused size_t src_size,
gcc_unused const AudioFormat dest_format,
gcc_unused size_t *dest_size_r,
gcc_unused GError **error_r)
{
g_set_error(error_r, pcm_convert_quark(), 0,
"Not implemented");
return NULL;
}
const struct filter_plugin * const struct filter_plugin *
filter_plugin_by_name(gcc_unused const char *name) filter_plugin_by_name(gcc_unused const char *name)
{ {
...@@ -92,7 +78,6 @@ static struct audio_output * ...@@ -92,7 +78,6 @@ static struct audio_output *
load_audio_output(const char *name) load_audio_output(const char *name)
{ {
const struct config_param *param; const struct config_param *param;
GError *error = NULL;
param = find_named_config_block(CONF_AUDIO_OUTPUT, name); param = find_named_config_block(CONF_AUDIO_OUTPUT, name);
if (param == NULL) { if (param == NULL) {
...@@ -102,12 +87,11 @@ load_audio_output(const char *name) ...@@ -102,12 +87,11 @@ load_audio_output(const char *name)
static struct player_control dummy_player_control(32, 4); static struct player_control dummy_player_control(32, 4);
Error error;
struct audio_output *ao = struct audio_output *ao =
audio_output_new(*param, &dummy_player_control, &error); audio_output_new(*param, &dummy_player_control, error);
if (ao == NULL) { if (ao == nullptr)
g_printerr("%s\n", error->message); g_printerr("%s\n", error.GetMessage());
g_error_free(error);
}
return ao; return ao;
} }
...@@ -117,19 +101,17 @@ run_output(struct audio_output *ao, AudioFormat audio_format) ...@@ -117,19 +101,17 @@ run_output(struct audio_output *ao, AudioFormat audio_format)
{ {
/* open the audio output */ /* open the audio output */
GError *error = NULL; Error error;
if (!ao_plugin_enable(ao, &error)) { if (!ao_plugin_enable(ao, error)) {
g_printerr("Failed to enable audio output: %s\n", g_printerr("Failed to enable audio output: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return false; return false;
} }
if (!ao_plugin_open(ao, audio_format, &error)) { if (!ao_plugin_open(ao, audio_format, error)) {
ao_plugin_disable(ao); ao_plugin_disable(ao);
g_printerr("Failed to open audio output: %s\n", g_printerr("Failed to open audio output: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return false; return false;
} }
...@@ -157,13 +139,12 @@ run_output(struct audio_output *ao, AudioFormat audio_format) ...@@ -157,13 +139,12 @@ run_output(struct audio_output *ao, AudioFormat audio_format)
if (play_length > 0) { if (play_length > 0) {
size_t consumed = ao_plugin_play(ao, size_t consumed = ao_plugin_play(ao,
buffer, play_length, buffer, play_length,
&error); error);
if (consumed == 0) { if (consumed == 0) {
ao_plugin_close(ao); ao_plugin_close(ao);
ao_plugin_disable(ao); ao_plugin_disable(ao);
g_printerr("Failed to play: %s\n", g_printerr("Failed to play: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return false; return false;
} }
...@@ -182,8 +163,7 @@ run_output(struct audio_output *ao, AudioFormat audio_format) ...@@ -182,8 +163,7 @@ run_output(struct audio_output *ao, AudioFormat audio_format)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
bool success; Error error;
GError *error = NULL;
if (argc < 3 || argc > 4) { if (argc < 3 || argc > 4) {
g_printerr("Usage: run_output CONFIG NAME [FORMAT] <IN\n"); g_printerr("Usage: run_output CONFIG NAME [FORMAT] <IN\n");
...@@ -201,9 +181,8 @@ int main(int argc, char **argv) ...@@ -201,9 +181,8 @@ int main(int argc, char **argv)
/* read configuration file (mpd.conf) */ /* read configuration file (mpd.conf) */
config_global_init(); config_global_init();
if (!ReadConfigFile(config_path, &error)) { if (!ReadConfigFile(config_path, error)) {
g_printerr("%s:", error->message); g_printerr("%s\n", error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
...@@ -221,19 +200,16 @@ int main(int argc, char **argv) ...@@ -221,19 +200,16 @@ int main(int argc, char **argv)
/* parse the audio format */ /* parse the audio format */
if (argc > 3) { if (argc > 3) {
success = audio_format_parse(audio_format, argv[3], if (!audio_format_parse(audio_format, argv[3], false, error)) {
false, &error);
if (!success) {
g_printerr("Failed to parse audio format: %s\n", g_printerr("Failed to parse audio format: %s\n",
error->message); error.GetMessage());
g_error_free(error);
return 1; return 1;
} }
} }
/* do it */ /* do it */
success = run_output(ao, audio_format); bool success = run_output(ao, audio_format);
/* cleanup and exit */ /* cleanup and exit */
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
#include "config.h" #include "config.h"
#include "system/Resolver.hxx" #include "system/Resolver.hxx"
#include "util/Error.hxx"
#include <glib.h>
#ifdef WIN32 #ifdef WIN32
#include <ws2tcpip.h> #include <ws2tcpip.h>
...@@ -37,23 +40,21 @@ int main(int argc, char **argv) ...@@ -37,23 +40,21 @@ int main(int argc, char **argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
GError *error = NULL; Error error;
struct addrinfo *ai = struct addrinfo *ai =
resolve_host_port(argv[1], 80, AI_PASSIVE, SOCK_STREAM, resolve_host_port(argv[1], 80, AI_PASSIVE, SOCK_STREAM,
&error); error);
if (ai == NULL) { if (ai == NULL) {
g_printerr("%s\n", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
for (const struct addrinfo *i = ai; i != NULL; i = i->ai_next) { for (const struct addrinfo *i = ai; i != NULL; i = i->ai_next) {
char *p = sockaddr_to_string(i->ai_addr, i->ai_addrlen, char *p = sockaddr_to_string(i->ai_addr, i->ai_addrlen,
&error); error);
if (p == NULL) { if (p == NULL) {
freeaddrinfo(ai); freeaddrinfo(ai);
g_printerr("%s\n", error->message); g_warning("%s", error.GetMessage());
g_error_free(error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "pcm/PcmVolume.hxx" #include "pcm/PcmVolume.hxx"
#include "AudioParser.hxx" #include "AudioParser.hxx"
#include "AudioFormat.hxx" #include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "stdbin.h" #include "stdbin.h"
#include <glib.h> #include <glib.h>
...@@ -36,8 +37,6 @@ ...@@ -36,8 +37,6 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
GError *error = NULL;
bool ret;
static char buffer[4096]; static char buffer[4096];
ssize_t nbytes; ssize_t nbytes;
...@@ -46,13 +45,12 @@ int main(int argc, char **argv) ...@@ -46,13 +45,12 @@ int main(int argc, char **argv)
return 1; return 1;
} }
Error error;
AudioFormat audio_format(48000, SampleFormat::S16, 2); AudioFormat audio_format(48000, SampleFormat::S16, 2);
if (argc > 1) { if (argc > 1) {
ret = audio_format_parse(audio_format, argv[1], if (!audio_format_parse(audio_format, argv[1], false, error)) {
false, &error);
if (!ret) {
g_printerr("Failed to parse audio format: %s\n", g_printerr("Failed to parse audio format: %s\n",
error->message); error.GetMessage());
return 1; return 1;
} }
} }
......
...@@ -24,8 +24,7 @@ ...@@ -24,8 +24,7 @@
#include "conf.h" #include "conf.h"
#include "stdbin.h" #include "stdbin.h"
#include "Tag.hxx" #include "Tag.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <stddef.h> #include <stddef.h>
#include <unistd.h> #include <unistd.h>
...@@ -56,27 +55,27 @@ main(gcc_unused int argc, gcc_unused char **argv) ...@@ -56,27 +55,27 @@ main(gcc_unused int argc, gcc_unused char **argv)
config_param param; config_param param;
param.AddBlockParam("quality", "5.0", -1); param.AddBlockParam("quality", "5.0", -1);
const auto encoder = encoder_init(*plugin, param, NULL); const auto encoder = encoder_init(*plugin, param, IgnoreError());
assert(encoder != NULL); assert(encoder != NULL);
/* open the encoder */ /* open the encoder */
AudioFormat audio_format(44100, SampleFormat::S16, 2); AudioFormat audio_format(44100, SampleFormat::S16, 2);
success = encoder_open(encoder, audio_format, NULL); success = encoder_open(encoder, audio_format, IgnoreError());
assert(success); assert(success);
encoder_to_stdout(*encoder); encoder_to_stdout(*encoder);
/* write a block of data */ /* write a block of data */
success = encoder_write(encoder, zero, sizeof(zero), NULL); success = encoder_write(encoder, zero, sizeof(zero), IgnoreError());
assert(success); assert(success);
encoder_to_stdout(*encoder); encoder_to_stdout(*encoder);
/* write a tag */ /* write a tag */
success = encoder_pre_tag(encoder, NULL); success = encoder_pre_tag(encoder, IgnoreError());
assert(success); assert(success);
encoder_to_stdout(*encoder); encoder_to_stdout(*encoder);
...@@ -85,19 +84,19 @@ main(gcc_unused int argc, gcc_unused char **argv) ...@@ -85,19 +84,19 @@ main(gcc_unused int argc, gcc_unused char **argv)
tag.AddItem(TAG_ARTIST, "Foo"); tag.AddItem(TAG_ARTIST, "Foo");
tag.AddItem(TAG_TITLE, "Bar"); tag.AddItem(TAG_TITLE, "Bar");
success = encoder_tag(encoder, &tag, NULL); success = encoder_tag(encoder, &tag, IgnoreError());
assert(success); assert(success);
encoder_to_stdout(*encoder); encoder_to_stdout(*encoder);
/* write another block of data */ /* write another block of data */
success = encoder_write(encoder, zero, sizeof(zero), NULL); success = encoder_write(encoder, zero, sizeof(zero), IgnoreError());
assert(success); assert(success);
/* finish */ /* finish */
success = encoder_end(encoder, NULL); success = encoder_end(encoder, IgnoreError());
assert(success); assert(success);
encoder_to_stdout(*encoder); encoder_to_stdout(*encoder);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "ArchiveFile.hxx" #include "ArchiveFile.hxx"
#include "ArchiveVisitor.hxx" #include "ArchiveVisitor.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "util/Error.hxx"
#include <glib.h> #include <glib.h>
...@@ -54,7 +55,7 @@ class MyArchiveVisitor final : public ArchiveVisitor { ...@@ -54,7 +55,7 @@ class MyArchiveVisitor final : public ArchiveVisitor {
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
GError *error = nullptr; Error error;
if (argc != 3) { if (argc != 3) {
fprintf(stderr, "Usage: visit_archive PLUGIN PATH\n"); fprintf(stderr, "Usage: visit_archive PLUGIN PATH\n");
...@@ -81,9 +82,8 @@ main(int argc, char **argv) ...@@ -81,9 +82,8 @@ main(int argc, char **argv)
archive_plugin_init_all(); archive_plugin_init_all();
if (!input_stream_global_init(&error)) { if (!input_stream_global_init(error)) {
g_warning("%s", error->message); fprintf(stderr, "%s", error.GetMessage());
g_error_free(error);
return 2; return 2;
} }
...@@ -97,14 +97,13 @@ main(int argc, char **argv) ...@@ -97,14 +97,13 @@ main(int argc, char **argv)
int result = EXIT_SUCCESS; int result = EXIT_SUCCESS;
ArchiveFile *file = archive_file_open(plugin, path.c_str(), &error); ArchiveFile *file = archive_file_open(plugin, path.c_str(), error);
if (file != nullptr) { if (file != nullptr) {
MyArchiveVisitor visitor; MyArchiveVisitor visitor;
file->Visit(visitor); file->Visit(visitor);
file->Close(); file->Close();
} else { } else {
fprintf(stderr, "%s\n", error->message); fprintf(stderr, "%s", error.GetMessage());
g_error_free(error);
result = EXIT_FAILURE; result = EXIT_FAILURE;
} }
......
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