util/Error: new error passing library

Replaces GLib's GError.
This commit is contained in:
Max Kellermann 2013-08-10 18:02:44 +02:00
parent c9fcc7f148
commit 29030b54c9
256 changed files with 3269 additions and 3371 deletions

View File

@ -91,7 +91,7 @@ src_mpd_SOURCES = \
src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \
src/AudioFormat.cxx src/AudioFormat.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/Result.cxx src/protocol/Result.hxx \
src/CommandError.cxx src/CommandError.hxx \
@ -107,7 +107,7 @@ src_mpd_SOURCES = \
src/CommandLine.cxx src/CommandLine.hxx \
src/CrossFade.cxx src/CrossFade.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/DecoderCommand.hxx \
src/DecoderControl.cxx src/DecoderControl.hxx \
@ -122,7 +122,7 @@ src_mpd_SOURCES = \
src/DatabasePrint.cxx src/DatabasePrint.hxx \
src/DatabaseQueue.cxx src/DatabaseQueue.hxx \
src/DatabasePlaylist.cxx src/DatabasePlaylist.hxx \
src/DatabaseError.hxx \
src/DatabaseError.cxx src/DatabaseError.hxx \
src/DatabaseLock.cxx src/DatabaseLock.hxx \
src/DatabaseSave.cxx src/DatabaseSave.hxx \
src/DatabasePlugin.hxx \
@ -160,7 +160,6 @@ src_mpd_SOURCES = \
src/Listen.cxx src/Listen.hxx \
src/Log.cxx src/Log.hxx \
src/ls.cxx src/ls.hxx \
src/io_error.h \
src/IOThread.cxx src/IOThread.hxx \
src/Main.cxx src/Main.hxx \
src/Instance.cxx src/Instance.hxx \
@ -178,7 +177,7 @@ src_mpd_SOURCES = \
src/PlayerThread.cxx src/PlayerThread.hxx \
src/PlayerControl.cxx src/PlayerControl.hxx \
src/Playlist.cxx \
src/PlaylistError.hxx \
src/PlaylistError.cxx src/PlaylistError.hxx \
src/PlaylistGlobal.cxx src/PlaylistGlobal.hxx \
src/PlaylistControl.cxx \
src/PlaylistEdit.cxx \
@ -261,6 +260,7 @@ endif
# Generic utility library
libutil_a_SOURCES = \
src/util/Error.cxx src/util/Error.hxx \
src/util/ReusableArray.hxx \
src/util/StringUtil.cxx src/util/StringUtil.hxx \
src/util/Tokenizer.cxx src/util/Tokenizer.hxx \
@ -284,7 +284,7 @@ libsystem_a_SOURCES = \
src/system/FatalError.cxx src/system/FatalError.hxx \
src/system/fd_util.c src/system/fd_util.h \
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/EventPipe.cxx src/system/EventPipe.hxx \
src/system/EventFD.cxx src/system/EventFD.hxx \
@ -420,7 +420,7 @@ libconf_a_SOURCES = \
src/ConfigGlobal.cxx src/ConfigGlobal.hxx \
src/ConfigFile.cxx src/ConfigFile.hxx \
src/ConfigTemplates.cxx src/ConfigTemplates.hxx \
src/ConfigQuark.hxx \
src/ConfigError.cxx src/ConfigError.hxx \
src/ConfigOption.hxx
# tag plugins
@ -793,7 +793,7 @@ OUTPUT_API_SRC = \
src/OutputList.cxx src/OutputList.hxx \
src/OutputAll.cxx src/OutputAll.hxx \
src/OutputThread.cxx src/OutputThread.hxx \
src/OutputError.hxx \
src/OutputError.cxx src/OutputError.hxx \
src/OutputControl.cxx src/OutputControl.hxx \
src/OutputState.cxx src/OutputState.hxx \
src/OutputPrint.cxx src/OutputPrint.hxx \
@ -1071,6 +1071,7 @@ test_read_conf_SOURCES = test/read_conf.cxx
test_run_resolver_LDADD = \
libsystem.a \
libutil.a \
$(GLIB_LIBS)
test_run_resolver_SOURCES = test/run_resolver.cxx
@ -1082,6 +1083,7 @@ test_DumpDatabase_LDADD = \
libfs.a \
$(GLIB_LIBS)
test_DumpDatabase_SOURCES = test/DumpDatabase.cxx \
src/DatabaseError.cxx \
src/DatabaseRegistry.cxx \
src/DatabaseSelection.cxx \
src/Directory.cxx src/DirectorySave.cxx \
@ -1217,6 +1219,7 @@ test_read_tags_SOURCES = test/read_tags.cxx \
if HAVE_ID3TAG
test_dump_rva2_LDADD = \
$(ID3TAG_LIBS) \
libutil.a \
$(GLIB_LIBS)
test_dump_rva2_SOURCES = test/dump_rva2.cxx \
src/riff.c src/aiff.c \
@ -1296,6 +1299,7 @@ test_software_volume_SOURCES = test/software_volume.cxx \
src/AudioParser.cxx
test_software_volume_LDADD = \
$(PCM_LIBS) \
libutil.a \
$(GLIB_LIBS)
test_run_normalize_SOURCES = test/run_normalize.cxx \
@ -1304,6 +1308,7 @@ test_run_normalize_SOURCES = test/run_normalize.cxx \
src/AudioParser.cxx \
src/AudioCompress/compress.c
test_run_normalize_LDADD = \
libutil.a \
$(GLIB_LIBS)
test_run_convert_SOURCES = test/run_convert.cxx \
@ -1337,6 +1342,7 @@ test_run_output_SOURCES = test/run_output.cxx \
src/Timer.cxx \
src/Tag.cxx src/TagNames.c src/TagPool.cxx \
src/Page.cxx \
src/OutputError.cxx \
src/OutputInit.cxx src/OutputFinish.cxx src/OutputList.cxx \
src/OutputPlugin.cxx \
src/MixerControl.cxx \

View File

@ -32,6 +32,7 @@
#include "protocol/Result.hxx"
#include "Client.hxx"
#include "util/Tokenizer.hxx"
#include "util/Error.hxx"
#ifdef ENABLE_SQLITE
#include "StickerCommands.hxx"
@ -315,7 +316,7 @@ command_checked_lookup(Client *client, unsigned permission,
enum command_return
command_process(Client *client, unsigned num, char *line)
{
GError *error = NULL;
Error error;
char *argv[COMMAND_ARGV_MAX] = { NULL };
const struct command *cmd;
enum command_return ret = COMMAND_RETURN_ERROR;
@ -325,17 +326,16 @@ command_process(Client *client, unsigned num, char *line)
/* get the command name (first word on the line) */
Tokenizer tokenizer(line);
argv[0] = tokenizer.NextWord(&error);
argv[0] = tokenizer.NextWord(error);
if (argv[0] == NULL) {
current_command = "";
if (tokenizer.IsEnd())
command_error(client, ACK_ERROR_UNKNOWN,
"No command given");
else {
else
command_error(client, ACK_ERROR_UNKNOWN,
"%s", error->message);
g_error_free(error);
}
"%s", error.GetMessage());
current_command = NULL;
return COMMAND_RETURN_ERROR;
@ -347,7 +347,7 @@ command_process(Client *client, unsigned num, char *line)
while (argc < COMMAND_ARGV_MAX &&
(argv[argc] =
tokenizer.NextParam(&error)) != NULL)
tokenizer.NextParam(error)) != NULL)
++argc;
/* some error checks; we have to set current_command because
@ -362,10 +362,8 @@ command_process(Client *client, unsigned num, char *line)
}
if (!tokenizer.IsEnd()) {
command_error(client, ACK_ERROR_ARG,
"%s", error->message);
command_error(client, ACK_ERROR_ARG, "%s", error.GetMessage());
current_command = NULL;
g_error_free(error);
return COMMAND_RETURN_ERROR;
}

View File

@ -20,6 +20,8 @@
#ifndef MPD_ARCHIVE_FILE_HXX
#define MPD_ARCHIVE_FILE_HXX
class Error;
class ArchiveFile {
public:
const struct archive_plugin &plugin;
@ -50,7 +52,7 @@ public:
*/
virtual input_stream *OpenStream(const char *path,
Mutex &mutex, Cond &cond,
GError **error_r) = 0;
Error &error) = 0;
};
#endif

View File

@ -17,27 +17,23 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "ArchivePlugin.hxx"
#include "ArchiveFile.hxx"
#include "util/Error.hxx"
#include <assert.h>
ArchiveFile *
archive_file_open(const struct archive_plugin *plugin, const char *path,
GError **error_r)
Error &error)
{
assert(plugin != NULL);
assert(plugin->open != NULL);
assert(path != NULL);
assert(error_r == NULL || *error_r == NULL);
ArchiveFile *file = plugin->open(path, error_r);
if (file != NULL) {
assert(error_r == NULL || *error_r == NULL);
} else {
assert(error_r == NULL || *error_r != NULL);
}
ArchiveFile *file = plugin->open(path, error);
assert((file == nullptr) == error.IsDefined());
return file;
}

View File

@ -22,11 +22,11 @@
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "gerror.h"
struct input_stream;
class ArchiveFile;
class ArchiveVisitor;
class Error;
struct archive_plugin {
const char *name;
@ -49,7 +49,7 @@ struct archive_plugin {
* returns pointer to handle used is all operations with this archive
* or NULL when opening fails
*/
ArchiveFile *(*open)(const char *path_fs, GError **error_r);
ArchiveFile *(*open)(const char *path_fs, Error &error);
/**
* suffixes handled by this plugin.
@ -60,6 +60,6 @@ struct archive_plugin {
ArchiveFile *
archive_file_open(const struct archive_plugin *plugin, const char *path,
GError **error_r);
Error &error);
#endif

View File

@ -23,6 +23,7 @@
#include "AudioParser.hxx"
#include "conf.h"
#include "mpd_error.h"
#include "util/Error.hxx"
static AudioFormat configured_audio_format;
@ -37,15 +38,13 @@ getOutputAudioFormat(AudioFormat inAudioFormat)
void initAudioConfig(void)
{
const struct config_param *param = config_get_param(CONF_AUDIO_OUTPUT_FORMAT);
GError *error = NULL;
bool ret;
if (param == NULL)
return;
ret = audio_format_parse(configured_audio_format, param->value,
true, &error);
if (!ret)
Error error;
if (!audio_format_parse(configured_audio_format, param->value,
true, error))
MPD_ERROR("error parsing line %i: %s",
param->line, error->message);
param->line, error.GetMessage());
}

View File

@ -26,24 +26,16 @@
#include "AudioParser.hxx"
#include "AudioFormat.hxx"
#include "CheckAudioFormat.hxx"
#include "util/Error.hxx"
#include "gcc.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
/**
* The GLib quark used for errors reported by this library.
*/
static inline GQuark
audio_parser_quark(void)
{
return g_quark_from_static_string("audio_parser");
}
static bool
parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
const char **endptr_r, GError **error_r)
const char **endptr_r, Error &error)
{
unsigned long value;
char *endptr;
@ -56,10 +48,10 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
value = strtoul(src, &endptr, 10);
if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0,
"Failed to parse the sample rate");
error.Set(audio_format_domain,
"Failed to parse the sample rate");
return false;
} else if (!audio_check_sample_rate(value, error_r))
} else if (!audio_check_sample_rate(value, error))
return false;
*sample_rate_r = value;
@ -70,7 +62,7 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
static bool
parse_sample_format(const char *src, bool mask,
SampleFormat *sample_format_r,
const char **endptr_r, GError **error_r)
const char **endptr_r, Error &error)
{
unsigned long value;
char *endptr;
@ -96,8 +88,8 @@ parse_sample_format(const char *src, bool mask,
value = strtoul(src, &endptr, 10);
if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0,
"Failed to parse the sample format");
error.Set(audio_format_domain,
"Failed to parse the sample format");
return false;
}
@ -123,8 +115,8 @@ parse_sample_format(const char *src, bool mask,
break;
default:
g_set_error(error_r, audio_parser_quark(), 0,
"Invalid sample format: %lu", value);
error.Format(audio_format_domain,
"Invalid sample format: %lu", value);
return false;
}
@ -137,7 +129,7 @@ parse_sample_format(const char *src, bool mask,
static bool
parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
const char **endptr_r, GError **error_r)
const char **endptr_r, Error &error)
{
unsigned long value;
char *endptr;
@ -150,10 +142,10 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
value = strtoul(src, &endptr, 10);
if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0,
"Failed to parse the channel count");
error.Set(audio_format_domain,
"Failed to parse the channel count");
return false;
} else if (!audio_check_channel_count(value, error_r))
} else if (!audio_check_channel_count(value, error))
return false;
*channels_r = value;
@ -163,7 +155,7 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
bool
audio_format_parse(AudioFormat &dest, const char *src,
bool mask, GError **error_r)
bool mask, Error &error)
{
uint32_t rate;
SampleFormat sample_format;
@ -178,12 +170,11 @@ audio_format_parse(AudioFormat &dest, const char *src,
rate = 0;
#endif
if (!parse_sample_rate(src, mask, &rate, &src, error_r))
if (!parse_sample_rate(src, mask, &rate, &src, error))
return false;
if (*src++ != ':') {
g_set_error(error_r, audio_parser_quark(), 0,
"Sample format missing");
error.Set(audio_format_domain, "Sample format missing");
return false;
}
@ -194,22 +185,21 @@ audio_format_parse(AudioFormat &dest, const char *src,
sample_format = SampleFormat::UNDEFINED;
#endif
if (!parse_sample_format(src, mask, &sample_format, &src, error_r))
if (!parse_sample_format(src, mask, &sample_format, &src, error))
return false;
if (*src++ != ':') {
g_set_error(error_r, audio_parser_quark(), 0,
"Channel count missing");
error.Set(audio_format_domain, "Channel count missing");
return false;
}
/* parse channel count */
if (!parse_channel_count(src, mask, &channels, &src, error_r))
if (!parse_channel_count(src, mask, &channels, &src, error))
return false;
if (*src != 0) {
g_set_error(error_r, audio_parser_quark(), 0,
error.Format(audio_format_domain,
"Extra data after channel count: %s", src);
return false;
}

View File

@ -25,9 +25,8 @@
#ifndef MPD_AUDIO_PARSER_HXX
#define MPD_AUDIO_PARSER_HXX
#include "gerror.h"
struct AudioFormat;
class Error;
/**
* Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an
@ -42,6 +41,6 @@ struct AudioFormat;
*/
bool
audio_format_parse(AudioFormat &dest, const char *src,
bool mask, GError **error_r);
bool mask, Error &error);
#endif

View File

@ -17,17 +17,22 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "CheckAudioFormat.hxx"
#include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h>
const Domain audio_format_domain("audio_format");
bool
audio_check_sample_rate(unsigned long sample_rate, GError **error_r)
audio_check_sample_rate(unsigned long sample_rate, Error &error)
{
if (!audio_valid_sample_rate(sample_rate)) {
g_set_error(error_r, audio_format_quark(), 0,
"Invalid sample rate: %lu", sample_rate);
error.Format(audio_format_domain,
"Invalid sample rate: %lu", sample_rate);
return false;
}
@ -35,12 +40,12 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r)
}
bool
audio_check_sample_format(SampleFormat sample_format, GError **error_r)
audio_check_sample_format(SampleFormat sample_format, Error &error)
{
if (!audio_valid_sample_format(sample_format)) {
g_set_error(error_r, audio_format_quark(), 0,
"Invalid sample format: %u",
unsigned(sample_format));
error.Format(audio_format_domain,
"Invalid sample format: %u",
unsigned(sample_format));
return false;
}
@ -48,11 +53,11 @@ audio_check_sample_format(SampleFormat sample_format, GError **error_r)
}
bool
audio_check_channel_count(unsigned channels, GError **error_r)
audio_check_channel_count(unsigned channels, Error &error)
{
if (!audio_valid_channel_count(channels)) {
g_set_error(error_r, audio_format_quark(), 0,
"Invalid channel count: %u", channels);
error.Format(audio_format_domain,
"Invalid channel count: %u", channels);
return false;
}
@ -62,11 +67,11 @@ audio_check_channel_count(unsigned channels, GError **error_r)
bool
audio_format_init_checked(AudioFormat &af, unsigned long sample_rate,
SampleFormat sample_format, unsigned channels,
GError **error_r)
Error &error)
{
if (audio_check_sample_rate(sample_rate, error_r) &&
audio_check_sample_format(sample_format, error_r) &&
audio_check_channel_count(channels, error_r)) {
if (audio_check_sample_rate(sample_rate, error) &&
audio_check_sample_format(sample_format, error) &&
audio_check_channel_count(channels, error)) {
af = AudioFormat(sample_rate, sample_format, channels);
assert(af.IsValid());
return true;

View File

@ -22,26 +22,18 @@
#include "AudioFormat.hxx"
#include <glib.h>
class Error;
/**
* The GLib quark used for errors reported by this library.
*/
gcc_const
static inline GQuark
audio_format_quark(void)
{
return g_quark_from_static_string("audio_format");
}
extern const class Domain audio_format_domain;
bool
audio_check_sample_rate(unsigned long sample_rate, GError **error_r);
audio_check_sample_rate(unsigned long sample_rate, Error &error);
bool
audio_check_sample_format(SampleFormat sample_format, GError **error_r);
audio_check_sample_format(SampleFormat sample_format, Error &error);
bool
audio_check_channel_count(unsigned sample_format, GError **error_r);
audio_check_channel_count(unsigned sample_format, Error &error);
/**
* Wrapper for audio_format_init(), which checks all attributes.
@ -49,6 +41,6 @@ audio_check_channel_count(unsigned sample_format, GError **error_r);
bool
audio_format_init_checked(AudioFormat &af, unsigned long sample_rate,
SampleFormat sample_format, unsigned channels,
GError **error_r);
Error &error);
#endif

View File

@ -19,14 +19,14 @@
#include "config.h"
#include "ClientInternal.hxx"
#include "util/Error.hxx"
#include <glib.h>
void
Client::OnSocketError(GError *error)
Client::OnSocketError(Error &&error)
{
g_warning("error on client %d: %s", num, error->message);
g_error_free(error);
g_warning("error on client %d: %s", num, error.GetMessage());
SetExpired();
}

View File

@ -21,9 +21,10 @@
#include "ClientFile.hxx"
#include "Client.hxx"
#include "protocol/Ack.hxx"
#include "io_error.h"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <sys/stat.h>
#include <sys/types.h>
@ -32,14 +33,13 @@
bool
client_allow_file(const Client *client, const Path &path_fs,
GError **error_r)
Error &error)
{
#ifdef WIN32
(void)client;
(void)path_fs;
g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION,
"Access denied");
error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied");
return false;
#else
const int uid = client_get_uid(client);
@ -50,21 +50,19 @@ client_allow_file(const Client *client, const Path &path_fs,
if (uid <= 0) {
/* unauthenticated client */
g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION,
"Access denied");
error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied");
return false;
}
struct stat st;
if (!StatFile(path_fs, st)) {
set_error_errno(error_r);
error.SetErrno();
return false;
}
if (st.st_uid != (uid_t)uid && (st.st_mode & 0444) != 0444) {
/* client is not owner */
g_set_error(error_r, ack_quark(), ACK_ERROR_PERMISSION,
"Access denied");
error.Set(ack_domain, ACK_ERROR_PERMISSION, "Access denied");
return false;
}

View File

@ -20,10 +20,9 @@
#ifndef MPD_CLIENT_FILE_HXX
#define MPD_CLIENT_FILE_HXX
#include "gerror.h"
class Client;
class Path;
class Error;
/**
* Is this client allowed to use the specified local file?
@ -37,6 +36,6 @@ class Path;
*/
bool
client_allow_file(const Client *client, const Path &path_fs,
GError **error_r);
Error &error);
#endif

View File

@ -116,7 +116,7 @@ private:
/* virtual methods from class BufferedSocket */
virtual InputResult OnSocketInput(const void *data,
size_t length) override;
virtual void OnSocketError(GError *error) override;
virtual void OnSocketError(Error &&error) override;
virtual void OnSocketClosed() override;
/* virtual methods from class TimeoutMonitor */

View File

@ -25,6 +25,7 @@
#include "system/fd_util.h"
#include "system/Resolver.hxx"
#include "Permission.hxx"
#include "util/Error.hxx"
#include <assert.h>
#include <sys/types.h>
@ -70,7 +71,8 @@ client_new(EventLoop &loop, Partition &partition,
#ifdef HAVE_LIBWRAP
if (sa->sa_family != AF_UNIX) {
char *hostaddr = sockaddr_to_string(sa, sa_length, NULL);
char *hostaddr = sockaddr_to_string(sa, sa_length,
IgnoreError());
const char *progname = g_get_prgname();
struct request_info req;
@ -107,7 +109,7 @@ client_new(EventLoop &loop, Partition &partition,
client_list.Add(*client);
remote = sockaddr_to_string(sa, sa_length, NULL);
remote = sockaddr_to_string(sa, sa_length, IgnoreError());
g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE,
"[%u] opened from %s", client->num, remote);
g_free(remote);

View File

@ -22,6 +22,8 @@
#include "protocol/Result.hxx"
#include "AllCommands.hxx"
#include <glib.h>
#include <string.h>
#define CLIENT_LIST_MODE_BEGIN "command_list_begin"

View File

@ -20,8 +20,10 @@
#include "config.h"
#include "CommandError.hxx"
#include "DatabaseError.hxx"
#include "io_error.h"
#include "protocol/Result.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <assert.h>
#include <errno.h>
@ -85,50 +87,38 @@ print_playlist_result(Client *client, enum playlist_result result)
return COMMAND_RETURN_ERROR;
}
/**
* Send the GError to the client and free the GError.
*/
enum command_return
print_error(Client *client, GError *error)
print_error(Client *client, const Error &error)
{
assert(client != NULL);
assert(error != NULL);
assert(error.IsDefined());
g_warning("%s", error->message);
g_warning("%s", error.GetMessage());
if (error->domain == playlist_quark()) {
enum playlist_result result = (playlist_result)error->code;
g_error_free(error);
return print_playlist_result(client, result);
} else if (error->domain == ack_quark()) {
command_error(client, (ack)error->code, "%s", error->message);
g_error_free(error);
if (error.IsDomain(playlist_domain)) {
return print_playlist_result(client,
playlist_result(error.GetCode()));
} else if (error.IsDomain(ack_domain)) {
command_error(client, (ack)error.GetCode(),
"%s", error.GetMessage());
return COMMAND_RETURN_ERROR;
} else if (error->domain == db_quark()) {
switch ((enum db_error)error->code) {
} else if (error.IsDomain(db_domain)) {
switch ((enum db_error)error.GetCode()) {
case DB_DISABLED:
command_error(client, ACK_ERROR_NO_EXIST, "%s",
error->message);
g_error_free(error);
error.GetMessage());
return COMMAND_RETURN_ERROR;
case DB_NOT_FOUND:
g_error_free(error);
command_error(client, ACK_ERROR_NO_EXIST, "Not found");
return COMMAND_RETURN_ERROR;
}
} else if (error->domain == errno_quark()) {
} else if (error.IsDomain(errno_domain)) {
command_error(client, ACK_ERROR_SYSTEM, "%s",
g_strerror(error->code));
g_error_free(error);
return COMMAND_RETURN_ERROR;
} else if (error->domain == g_file_error_quark()) {
command_error(client, ACK_ERROR_SYSTEM, "%s", error->message);
g_error_free(error);
g_strerror(error.GetCode()));
return COMMAND_RETURN_ERROR;
}
g_error_free(error);
command_error(client, ACK_ERROR_UNKNOWN, "error");
return COMMAND_RETURN_ERROR;
}

View File

@ -22,17 +22,17 @@
#include "command.h"
#include "PlaylistError.hxx"
#include "gerror.h"
class Client;
class Error;
enum command_return
print_playlist_result(Client *client, enum playlist_result result);
/**
* Send the GError to the client and free the GError.
* Send the #Error to the client.
*/
enum command_return
print_error(Client *client, GError *error);
print_error(Client *client, const Error &error);
#endif

View File

@ -33,6 +33,8 @@
#include "mpd_error.h"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#ifdef ENABLE_ENCODER
#include "EncoderList.hxx"
@ -57,11 +59,7 @@
#define USER_CONFIG_FILE_LOCATION_XDG "mpd/mpd.conf"
#endif
static GQuark
cmdline_quark(void)
{
return g_quark_from_static_string("cmdline");
}
static constexpr Domain cmdline_domain("cmdline");
gcc_noreturn
static void version(void)
@ -147,9 +145,8 @@ PathBuildChecked(const Path &a, Path::const_pointer b)
bool
parse_cmdline(int argc, char **argv, struct options *options,
GError **error_r)
Error &error)
{
GError *error = NULL;
GOptionContext *context;
bool ret;
static gboolean option_version,
@ -183,11 +180,12 @@ parse_cmdline(int argc, char **argv, struct options *options,
g_option_context_set_summary(context, summary);
ret = g_option_context_parse(context, &argc, &argv, &error);
GError *gerror = nullptr;
ret = g_option_context_parse(context, &argc, &argv, &gerror);
g_option_context_free(context);
if (!ret)
MPD_ERROR("option parsing failed: %s\n", error->message);
MPD_ERROR("option parsing failed: %s\n", gerror->message);
if (option_version)
version();
@ -208,7 +206,7 @@ parse_cmdline(int argc, char **argv, struct options *options,
Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()),
CONFIG_FILE_LOCATION);
if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r);
return ReadConfigFile(path, error);
const char *const*system_config_dirs =
g_get_system_config_dirs();
@ -217,38 +215,36 @@ parse_cmdline(int argc, char **argv, struct options *options,
path = PathBuildChecked(Path::FromUTF8(system_config_dirs[i]),
CONFIG_FILE_LOCATION);
if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r);
return ReadConfigFile(path, error);
}
#else /* G_OS_WIN32 */
Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()),
USER_CONFIG_FILE_LOCATION_XDG);
if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r);
return ReadConfigFile(path, error);
path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()),
USER_CONFIG_FILE_LOCATION1);
if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r);
return ReadConfigFile(path, error);
path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()),
USER_CONFIG_FILE_LOCATION2);
if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r);
return ReadConfigFile(path, error);
path = Path::FromUTF8(SYSTEM_CONFIG_FILE_LOCATION);
if (!path.IsNull() && FileExists(path))
return ReadConfigFile(path, error_r);
return ReadConfigFile(path, error);
#endif
g_set_error(error_r, cmdline_quark(), 0,
"No configuration file found");
error.Set(cmdline_domain, "No configuration file found");
return false;
} else if (argc == 2) {
/* specified configuration file */
return ReadConfigFile(Path::FromFS(argv[1]), error_r);
return ReadConfigFile(Path::FromFS(argv[1]), error);
} else {
g_set_error(error_r, cmdline_quark(), 0,
"too many arguments");
error.Set(cmdline_domain, "too many arguments");
return false;
}
}

View File

@ -22,6 +22,8 @@
#include <glib.h>
class Error;
struct options {
gboolean kill;
gboolean daemon;
@ -31,6 +33,6 @@ struct options {
bool
parse_cmdline(int argc, char **argv, struct options *options,
GError **error_r);
Error &error);
#endif

View File

@ -21,6 +21,7 @@
#include "ConfigData.hxx"
#include "ConfigParser.hxx"
#include "ConfigPath.hxx"
#include "util/Error.hxx"
#include "fs/Path.hxx"
#include "system/FatalError.hxx"
#include "mpd_error.h"
@ -97,10 +98,9 @@ config_param::DupBlockString(const char *name, const char *default_value) const
Path
config_param::GetBlockPath(const char *name, const char *default_value,
GError **error_r) const
Error &error) const
{
assert(error_r != nullptr);
assert(*error_r == nullptr);
assert(!error.IsDefined());
int line2 = line;
const char *s;
@ -112,19 +112,18 @@ config_param::GetBlockPath(const char *name, const char *default_value,
} else
s = default_value;
Path path = ParsePath(s, error_r);
Path path = ParsePath(s, error);
if (gcc_unlikely(path.IsNull()))
g_prefix_error(error_r,
"Invalid path in \"%s\" at line %i: ",
name, line2);
error.FormatPrefix("Invalid path in \"%s\" at line %i: ",
name, line2);
return path;
}
Path
config_param::GetBlockPath(const char *name, GError **error_r) const
config_param::GetBlockPath(const char *name, Error &error) const
{
return GetBlockPath(name, nullptr, error_r);
return GetBlockPath(name, nullptr, error);
}
unsigned

View File

@ -21,7 +21,6 @@
#define MPD_CONFIG_DATA_HXX
#include "ConfigOption.hxx"
#include "gerror.h"
#include "gcc.h"
#include <string>
@ -29,6 +28,7 @@
#include <vector>
class Path;
class Error;
struct block_param {
std::string name;
@ -113,9 +113,9 @@ struct config_param {
* specified block.
*/
Path GetBlockPath(const char *name, const char *default_value,
GError **error_r) const;
Error &error) const;
Path GetBlockPath(const char *name, GError **error_r) const;
Path GetBlockPath(const char *name, Error &error) const;
gcc_pure
unsigned GetBlockValue(const char *name, unsigned default_value) const;

23
src/ConfigError.cxx Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ConfigError.hxx"
#include "util/Domain.hxx"
const Domain config_domain("config");

View File

@ -17,22 +17,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_CONFIG_QUARK_HXX
#define MPD_CONFIG_QUARK_HXX
#ifndef MPD_CONFIG_ERROR_HXX
#define MPD_CONFIG_ERROR_HXX
#include "gcc.h"
#include <glib.h>
/**
* A GQuark for GError instances, resulting from malformed
* configuration.
*/
gcc_const
static inline GQuark
config_quark(void)
{
return g_quark_from_static_string("config");
}
extern const class Domain config_domain;
#endif

View File

@ -19,12 +19,14 @@
#include "config.h"
#include "ConfigFile.hxx"
#include "ConfigQuark.hxx"
#include "ConfigError.hxx"
#include "ConfigData.hxx"
#include "ConfigTemplates.hxx"
#include "conf.h"
#include "util/Tokenizer.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
@ -42,42 +44,41 @@
#define CONF_COMMENT '#'
static constexpr Domain config_file_domain("config_file");
static bool
config_read_name_value(struct config_param *param, char *input, unsigned line,
GError **error_r)
Error &error)
{
Tokenizer tokenizer(input);
const char *name = tokenizer.NextWord(error_r);
const char *name = tokenizer.NextWord(error);
if (name == NULL) {
assert(!tokenizer.IsEnd());
return false;
}
const char *value = tokenizer.NextString(error_r);
const char *value = tokenizer.NextString(error);
if (value == NULL) {
if (tokenizer.IsEnd()) {
assert(error_r == NULL || *error_r == NULL);
g_set_error(error_r, config_quark(), 0,
"Value missing");
error.Set(config_file_domain, "Value missing");
} else {
assert(error_r == NULL || *error_r != NULL);
assert(error.IsDefined());
}
return false;
}
if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0,
"Unknown tokens after value");
error.Set(config_file_domain, "Unknown tokens after value");
return false;
}
const struct block_param *bp = param->GetBlockParam(name);
if (bp != NULL) {
g_set_error(error_r, config_quark(), 0,
"\"%s\" is duplicate, first defined on line %i",
name, bp->line);
error.Format(config_file_domain,
"\"%s\" is duplicate, first defined on line %i",
name, bp->line);
return false;
}
@ -86,10 +87,9 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
}
static struct config_param *
config_read_block(FILE *fp, int *count, char *string, GError **error_r)
config_read_block(FILE *fp, int *count, char *string, Error &error)
{
struct config_param *ret = new config_param(*count);
GError *error = NULL;
while (true) {
char *line;
@ -97,8 +97,8 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r)
line = fgets(string, MAX_STRING_SIZE, fp);
if (line == NULL) {
delete ret;
g_set_error(error_r, config_quark(), 0,
"Expected '}' before end-of-file");
error.Set(config_file_domain,
"Expected '}' before end-of-file");
return NULL;
}
@ -114,9 +114,9 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r)
line = strchug_fast(line + 1);
if (*line != 0 && *line != CONF_COMMENT) {
delete ret;
g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after '}'",
*count);
error.Format(config_file_domain,
"line %i: Unknown tokens after '}'",
*count);
return nullptr;
}
@ -125,11 +125,10 @@ config_read_block(FILE *fp, int *count, char *string, GError **error_r)
/* parse name and value */
if (!config_read_name_value(ret, line, *count, &error)) {
if (!config_read_name_value(ret, line, *count, error)) {
assert(*line != 0);
delete ret;
g_propagate_prefixed_error(error_r, error,
"line %i: ", *count);
error.FormatPrefix("line %i: ", *count);
return NULL;
}
}
@ -149,7 +148,7 @@ Append(config_param *&head, config_param *p)
}
static bool
ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
ReadConfigFile(ConfigData &config_data, FILE *fp, Error &error)
{
assert(fp != nullptr);
@ -160,7 +159,6 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
while (fgets(string, MAX_STRING_SIZE, fp)) {
char *line;
const char *name, *value;
GError *error = NULL;
count++;
@ -172,11 +170,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
by either the value or '{' */
Tokenizer tokenizer(line);
name = tokenizer.NextWord(&error);
name = tokenizer.NextWord(error);
if (name == NULL) {
assert(!tokenizer.IsEnd());
g_propagate_prefixed_error(error_r, error,
"line %i: ", count);
error.FormatPrefix("line %i: ", count);
return false;
}
@ -185,9 +182,9 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
const ConfigOption o = ParseConfigOptionName(name);
if (o == CONF_MAX) {
g_set_error(error_r, config_quark(), 0,
"unrecognized parameter in config file at "
"line %i: %s\n", count, name);
error.Format(config_file_domain,
"unrecognized parameter in config file at "
"line %i: %s\n", count, name);
return false;
}
@ -197,10 +194,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
if (head != nullptr && !option.repeatable) {
param = head;
g_set_error(error_r, config_quark(), 0,
"config parameter \"%s\" is first defined "
"on line %i and redefined on line %i\n",
name, param->line, count);
error.Format(config_file_domain,
"config parameter \"%s\" is first defined "
"on line %i and redefined on line %i\n",
name, param->line, count);
return false;
}
@ -210,47 +207,43 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
/* it's a block, call config_read_block() */
if (tokenizer.CurrentChar() != '{') {
g_set_error(error_r, config_quark(), 0,
"line %i: '{' expected", count);
error.Format(config_file_domain,
"line %i: '{' expected", count);
return false;
}
line = strchug_fast(tokenizer.Rest() + 1);
if (*line != 0 && *line != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after '{'",
count);
error.Format(config_file_domain,
"line %i: Unknown tokens after '{'",
count);
return false;
}
param = config_read_block(fp, &count, string, error_r);
param = config_read_block(fp, &count, string, error);
if (param == NULL) {
return false;
}
} else {
/* a string value */
value = tokenizer.NextString(&error);
value = tokenizer.NextString(error);
if (value == NULL) {
if (tokenizer.IsEnd())
g_set_error(error_r, config_quark(), 0,
"line %i: Value missing",
count);
else {
g_set_error(error_r, config_quark(), 0,
"line %i: %s", count,
error->message);
g_error_free(error);
}
error.Format(config_file_domain,
"line %i: Value missing",
count);
else
error.FormatPrefix("line %i: ", count);
return false;
}
if (!tokenizer.IsEnd() &&
tokenizer.CurrentChar() != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after value",
count);
error.Format(config_file_domain,
"line %i: Unknown tokens after value",
count);
return false;
}
@ -264,7 +257,7 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
}
bool
ReadConfigFile(ConfigData &config_data, const Path &path, GError **error_r)
ReadConfigFile(ConfigData &config_data, const Path &path, Error &error)
{
assert(!path.IsNull());
const std::string path_utf8 = path.ToUTF8();
@ -273,13 +266,11 @@ ReadConfigFile(ConfigData &config_data, const Path &path, GError **error_r)
FILE *fp = FOpen(path, FOpenMode::ReadText);
if (fp == nullptr) {
g_set_error(error_r, config_quark(), errno,
"Failed to open %s: %s",
path_utf8.c_str(), g_strerror(errno));
error.FormatErrno("Failed to open %s", path_utf8.c_str());
return false;
}
bool result = ReadConfigFile(config_data, fp, error_r);
bool result = ReadConfigFile(config_data, fp, error);
fclose(fp);
return result;
}

View File

@ -20,12 +20,11 @@
#ifndef MPD_CONFIG_FILE_HXX
#define MPD_CONFIG_FILE_HXX
#include "gerror.h"
class Error;
class Path;
struct ConfigData;
bool
ReadConfigFile(ConfigData &data, const Path &path, GError **error_r);
ReadConfigFile(ConfigData &data, const Path &path, Error &error);
#endif

View File

@ -24,6 +24,7 @@
#include "ConfigFile.hxx"
#include "ConfigPath.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "mpd_error.h"
#include <glib.h>
@ -47,9 +48,9 @@ void config_global_init(void)
}
bool
ReadConfigFile(const Path &path, GError **error_r)
ReadConfigFile(const Path &path, Error &error)
{
return ReadConfigFile(config_data, path, error_r);
return ReadConfigFile(config_data, path, error);
}
static void
@ -98,20 +99,16 @@ config_get_string(ConfigOption option, const char *default_value)
}
Path
config_get_path(ConfigOption option, GError **error_r)
config_get_path(ConfigOption option, Error &error)
{
assert(error_r != NULL);
assert(*error_r == NULL);
const struct config_param *param = config_get_param(option);
if (param == NULL)
return Path::Null();
Path path = ParsePath(param->value, error_r);
Path path = ParsePath(param->value, error);
if (gcc_unlikely(path.IsNull()))
g_prefix_error(error_r,
"Invalid path at line %i: ",
param->line);
error.FormatPrefix("Invalid path at line %i: ",
param->line);
return path;
}

View File

@ -21,7 +21,6 @@
#define MPD_CONFIG_GLOBAL_HXX
#include "ConfigOption.hxx"
#include "gerror.h"
#include "gcc.h"
#include <stdbool.h>
@ -30,6 +29,7 @@
#define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16)
#define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS false
class Error;
class Path;
void config_global_init(void);
@ -42,7 +42,7 @@ void config_global_finish(void);
void config_global_check(void);
bool
ReadConfigFile(const Path &path, GError **error_r);
ReadConfigFile(const Path &path, Error &error);
/* don't free the returned value
set _last_ to NULL to get first entry */
@ -76,7 +76,7 @@ config_get_string(enum ConfigOption option, const char *default_value);
* could not be parsed, returns Path::Null() and sets the error.
*/
Path
config_get_path(enum ConfigOption option, GError **error_r);
config_get_path(enum ConfigOption option, Error &error);
gcc_pure
unsigned

View File

@ -20,6 +20,8 @@
#include "config.h"
#include "ConfigPath.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "conf.h"
#include <glib.h>
@ -46,31 +48,25 @@
#include <windows.h>
#endif
gcc_const
static inline GQuark
parse_path_quark(void)
{
return g_quark_from_static_string("path");
}
static constexpr Domain path_domain("path");
Path
ParsePath(const char *path, GError **error_r)
ParsePath(const char *path, Error &error)
{
assert(path != nullptr);
assert(error_r == nullptr || *error_r == nullptr);
Path path2 = Path::FromUTF8(path);
if (path2.IsNull()) {
g_set_error(error_r, parse_path_quark(), 0,
"Failed to convert path to file system charset: %s",
path);
error.Format(path_domain,
"Failed to convert path to file system charset: %s",
path);
return Path::Null();
}
#ifndef WIN32
if (!g_path_is_absolute(path) && path[0] != '~') {
g_set_error(error_r, parse_path_quark(), 0,
"not an absolute path: %s", path);
error.Format(path_domain,
"not an absolute path: %s", path);
return Path::Null();
} else if (path[0] == '~') {
const char *home;
@ -80,8 +76,8 @@ ParsePath(const char *path, GError **error_r)
if (user != nullptr) {
struct passwd *passwd = getpwnam(user);
if (!passwd) {
g_set_error(error_r, parse_path_quark(), 0,
"no such user: %s", user);
error.Format(path_domain,
"no such user: %s", user);
return Path::Null();
}
@ -89,9 +85,9 @@ ParsePath(const char *path, GError **error_r)
} else {
home = g_get_home_dir();
if (home == nullptr) {
g_set_error_literal(error_r, parse_path_quark(), 0,
"problems getting home "
"for current user");
error.Set(path_domain,
"problems getting home "
"for current user");
return Path::Null();
}
}
@ -107,8 +103,8 @@ ParsePath(const char *path, GError **error_r)
struct passwd *passwd = getpwnam(user);
if (!passwd) {
g_set_error(error_r, parse_path_quark(), 0,
"no such user: %s", user);
error.Format(path_domain,
"no such user: %s", user);
g_free(user);
return Path::Null();
}

View File

@ -20,11 +20,10 @@
#ifndef MPD_CONFIG_PATH_HXX
#define MPD_CONFIG_PATH_HXX
#include "gerror.h"
class Path;
class Error;
Path
ParsePath(const char *path, GError **error_r);
ParsePath(const char *path, Error &error);
#endif

View File

@ -27,6 +27,7 @@
#include "ClientInternal.hxx"
#include "Tag.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "SongFilter.hxx"
#include "protocol/Result.hxx"
@ -46,8 +47,8 @@ handle_lsinfo2(Client *client, int argc, char *argv[])
const DatabaseSelection selection(uri, false);
GError *error = NULL;
if (!db_selection_print(client, selection, true, &error))
Error error;
if (!db_selection_print(client, selection, true, error))
return print_error(client, error);
return COMMAND_RETURN_OK;
@ -64,8 +65,8 @@ handle_match(Client *client, int argc, char *argv[], bool fold_case)
const DatabaseSelection selection("", true, &filter);
GError *error = NULL;
return db_selection_print(client, selection, true, &error)
Error error;
return db_selection_print(client, selection, true, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -92,8 +93,8 @@ handle_match_add(Client *client, int argc, char *argv[], bool fold_case)
}
const DatabaseSelection selection("", true, &filter);
GError *error = NULL;
return AddFromDatabase(client->partition, selection, &error)
Error error;
return AddFromDatabase(client->partition, selection, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -121,8 +122,8 @@ handle_searchaddpl(Client *client, int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
GError *error = NULL;
return search_add_to_playlist("", playlist, &filter, &error)
Error error;
return search_add_to_playlist("", playlist, &filter, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -136,8 +137,8 @@ handle_count(Client *client, int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
GError *error = NULL;
return searchStatsForSongsIn(client, "", &filter, &error)
Error error;
return searchStatsForSongsIn(client, "", &filter, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -150,8 +151,8 @@ handle_listall(Client *client, gcc_unused int argc, char *argv[])
if (argc == 2)
directory = argv[1];
GError *error = NULL;
return printAllIn(client, directory, &error)
Error error;
return printAllIn(client, directory, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -194,9 +195,9 @@ handle_list(Client *client, int argc, char *argv[])
} else
filter = nullptr;
GError *error = NULL;
Error error;
enum command_return ret =
listAllUniqueTags(client, tagType, filter, &error)
listAllUniqueTags(client, tagType, filter, error)
? COMMAND_RETURN_OK
: print_error(client, error);
@ -213,8 +214,8 @@ handle_listallinfo(Client *client, gcc_unused int argc, char *argv[])
if (argc == 2)
directory = argv[1];
GError *error = NULL;
return printInfoForAllIn(client, directory, &error)
Error error;
return printInfoForAllIn(client, directory, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}

24
src/DatabaseError.cxx Normal file
View File

@ -0,0 +1,24 @@
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "DatabaseError.hxx"
#include "util/Domain.hxx"
const Domain db_domain("db");

View File

@ -20,9 +20,7 @@
#ifndef MPD_DB_ERROR_HXX
#define MPD_DB_ERROR_HXX
#include "gcc.h"
#include <glib.h>
class Domain;
enum db_error {
/**
@ -34,14 +32,6 @@ enum db_error {
DB_NOT_FOUND,
};
/**
* Quark for GError.domain; the code is an enum #db_error.
*/
gcc_const
static inline GQuark
db_quark(void)
{
return g_quark_from_static_string("db");
}
extern const Domain db_domain;
#endif

View File

@ -24,6 +24,7 @@
#include "DatabaseSave.hxx"
#include "DatabaseError.hxx"
#include "Directory.hxx"
#include "util/Error.hxx"
#include "conf.h"
extern "C" {
@ -50,7 +51,7 @@ static bool db_is_open;
static bool is_simple;
bool
DatabaseGlobalInit(const config_param &param, GError **error_r)
DatabaseGlobalInit(const config_param &param, Error &error)
{
assert(db == NULL);
assert(!db_is_open);
@ -61,12 +62,12 @@ DatabaseGlobalInit(const config_param &param, GError **error_r)
const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name);
if (plugin == NULL) {
g_set_error(error_r, db_quark(), 0,
"No such database plugin: %s", plugin_name);
error.Format(db_domain,
"No such database plugin: %s", plugin_name);
return false;
}
db = plugin->create(param, error_r);
db = plugin->create(param, error);
return db != NULL;
}
@ -89,13 +90,12 @@ GetDatabase()
}
const Database *
GetDatabase(GError **error_r)
GetDatabase(Error &error)
{
assert(db == nullptr || db_is_open);
if (db == nullptr)
g_set_error_literal(error_r, db_quark(), DB_DISABLED,
"No database");
error.Set(db_domain, DB_DISABLED, "No database");
return db;
}
@ -131,17 +131,17 @@ db_get_directory(const char *name)
}
bool
db_save(GError **error_r)
db_save(Error &error)
{
assert(db != NULL);
assert(db_is_open);
assert(db_is_simple());
return ((SimpleDatabase *)db)->Save(error_r);
return ((SimpleDatabase *)db)->Save(error);
}
bool
DatabaseGlobalOpen(GError **error)
DatabaseGlobalOpen(Error &error)
{
assert(db != NULL);
assert(!db_is_open);

View File

@ -21,10 +21,10 @@
#define MPD_DATABASE_GLUE_HXX
#include "gcc.h"
#include "gerror.h"
struct config_param;
class Database;
class Error;
/**
* Initialize the database library.
@ -32,13 +32,13 @@ class Database;
* @param param the database configuration block
*/
bool
DatabaseGlobalInit(const config_param &param, GError **error_r);
DatabaseGlobalInit(const config_param &param, Error &error);
void
DatabaseGlobalDeinit(void);
bool
DatabaseGlobalOpen(GError **error);
DatabaseGlobalOpen(Error &error);
/**
* Returns the global #Database instance. May return NULL if this MPD
@ -54,6 +54,6 @@ GetDatabase();
*/
gcc_pure
const Database *
GetDatabase(GError **error_r);
GetDatabase(Error &error);
#endif

View File

@ -61,17 +61,17 @@ bool
VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
enum tag_type tag_type,
VisitString visit_string,
GError **error_r)
Error &error)
{
StringSet set;
using namespace std::placeholders;
const auto f = std::bind(CollectTags, std::ref(set), tag_type, _1);
if (!db.Visit(selection, f, error_r))
if (!db.Visit(selection, f, error))
return false;
for (auto value : set)
if (!visit_string(value, error_r))
if (!visit_string(value, error))
return false;
return true;
@ -116,7 +116,7 @@ StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
bool
GetStats(const Database &db, const DatabaseSelection &selection,
DatabaseStats &stats, GError **error_r)
DatabaseStats &stats, Error &error)
{
stats.Clear();
@ -125,7 +125,7 @@ GetStats(const Database &db, const DatabaseSelection &selection,
const auto f = std::bind(StatsVisitSong,
std::ref(stats), std::ref(artists),
std::ref(albums), _1);
if (!db.Visit(selection, f, error_r))
if (!db.Visit(selection, f, error))
return false;
stats.artist_count = artists.size();

View File

@ -24,6 +24,7 @@
#include "TagType.h"
#include "gcc.h"
class Error;
class Database;
struct DatabaseSelection;
struct DatabaseStats;
@ -32,10 +33,10 @@ bool
VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
enum tag_type tag_type,
VisitString visit_string,
GError **error_r);
Error &error);
bool
GetStats(const Database &db, const DatabaseSelection &selection,
DatabaseStats &stats, GError **error_r);
DatabaseStats &stats, Error &error);
#endif

View File

@ -28,17 +28,17 @@
static bool
AddSong(const char *playlist_path_utf8,
Song &song, GError **error_r)
Song &song, Error &error)
{
return spl_append_song(playlist_path_utf8, &song, error_r);
return spl_append_song(playlist_path_utf8, &song, error);
}
bool
search_add_to_playlist(const char *uri, const char *playlist_path_utf8,
const SongFilter *filter,
GError **error_r)
Error &error)
{
const Database *db = GetDatabase(error_r);
const Database *db = GetDatabase(error);
if (db == nullptr)
return false;
@ -46,5 +46,5 @@ search_add_to_playlist(const char *uri, const char *playlist_path_utf8,
using namespace std::placeholders;
const auto f = std::bind(AddSong, playlist_path_utf8, _1, _2);
return db->Visit(selection, f, error_r);
return db->Visit(selection, f, error);
}

View File

@ -21,14 +21,14 @@
#define MPD_DATABASE_PLAYLIST_HXX
#include "gcc.h"
#include "gerror.h"
class SongFilter;
class Error;
gcc_nonnull(1,2)
bool
search_add_to_playlist(const char *uri, const char *path_utf8,
const SongFilter *filter,
GError **error_r);
Error &error);
#endif

View File

@ -34,6 +34,7 @@ struct config_param;
struct DatabaseSelection;
struct db_visitor;
struct Song;
class Error;
struct DatabaseStats {
/**
@ -73,7 +74,7 @@ public:
/**
* Open the database. Read it into memory if applicable.
*/
virtual bool Open(gcc_unused GError **error_r) {
virtual bool Open(gcc_unused Error &error) {
return true;
}
@ -90,7 +91,7 @@ public:
* directory (UTF-8)
*/
virtual Song *GetSong(const char *uri_utf8,
GError **error_r) const = 0;
Error &error) const = 0;
/**
* Mark the song object as "unused". Call this on objects
@ -105,19 +106,19 @@ public:
VisitDirectory visit_directory,
VisitSong visit_song,
VisitPlaylist visit_playlist,
GError **error_r) const = 0;
Error &error) const = 0;
bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory,
VisitSong visit_song,
GError **error_r) const {
Error &error) const {
return Visit(selection, visit_directory, visit_song,
VisitPlaylist(), error_r);
VisitPlaylist(), error);
}
bool Visit(const DatabaseSelection &selection, VisitSong visit_song,
GError **error_r) const {
return Visit(selection, VisitDirectory(), visit_song, error_r);
Error &error) const {
return Visit(selection, VisitDirectory(), visit_song, error);
}
/**
@ -126,11 +127,11 @@ public:
virtual bool VisitUniqueTags(const DatabaseSelection &selection,
enum tag_type tag_type,
VisitString visit_string,
GError **error_r) const = 0;
Error &error) const = 0;
virtual bool GetStats(const DatabaseSelection &selection,
DatabaseStats &stats,
GError **error_r) const = 0;
Error &error) const = 0;
};
struct DatabasePlugin {
@ -140,7 +141,7 @@ struct DatabasePlugin {
* Allocates and configures a database.
*/
Database *(*create)(const config_param &param,
GError **error_r);
Error &error);
};
#endif

View File

@ -118,9 +118,9 @@ PrintPlaylistFull(Client *client,
bool
db_selection_print(Client *client, const DatabaseSelection &selection,
bool full, GError **error_r)
bool full, Error &error)
{
const Database *db = GetDatabase(error_r);
const Database *db = GetDatabase(error);
if (db == nullptr)
return false;
@ -136,7 +136,7 @@ db_selection_print(Client *client, const DatabaseSelection &selection,
client, _1, _2)
: VisitPlaylist();
return db->Visit(selection, d, s, p, error_r);
return db->Visit(selection, d, s, p, error);
}
struct SearchStats {
@ -162,9 +162,9 @@ stats_visitor_song(SearchStats &stats, Song &song)
bool
searchStatsForSongsIn(Client *client, const char *name,
const SongFilter *filter,
GError **error_r)
Error &error)
{
const Database *db = GetDatabase(error_r);
const Database *db = GetDatabase(error);
if (db == nullptr)
return false;
@ -177,7 +177,7 @@ searchStatsForSongsIn(Client *client, const char *name,
using namespace std::placeholders;
const auto f = std::bind(stats_visitor_song, std::ref(stats),
_1);
if (!db->Visit(selection, f, error_r))
if (!db->Visit(selection, f, error))
return false;
printSearchStats(client, &stats);
@ -185,18 +185,18 @@ searchStatsForSongsIn(Client *client, const char *name,
}
bool
printAllIn(Client *client, const char *uri_utf8, GError **error_r)
printAllIn(Client *client, const char *uri_utf8, Error &error)
{
const DatabaseSelection selection(uri_utf8, true);
return db_selection_print(client, selection, false, error_r);
return db_selection_print(client, selection, false, error);
}
bool
printInfoForAllIn(Client *client, const char *uri_utf8,
GError **error_r)
Error &error)
{
const DatabaseSelection selection(uri_utf8, true);
return db_selection_print(client, selection, true, error_r);
return db_selection_print(client, selection, true, error);
}
static bool
@ -218,9 +218,9 @@ PrintUniqueTag(Client *client, enum tag_type tag_type,
bool
listAllUniqueTags(Client *client, int type,
const SongFilter *filter,
GError **error_r)
Error &error)
{
const Database *db = GetDatabase(error_r);
const Database *db = GetDatabase(error);
if (db == nullptr)
return false;
@ -229,12 +229,12 @@ listAllUniqueTags(Client *client, int type,
if (type == LOCATE_TAG_FILE_TYPE) {
using namespace std::placeholders;
const auto f = std::bind(PrintSongURIVisitor, client, _1);
return db->Visit(selection, f, error_r);
return db->Visit(selection, f, error);
} else {
using namespace std::placeholders;
const auto f = std::bind(PrintUniqueTag, client,
(enum tag_type)type, _1);
return db->VisitUniqueTags(selection, (enum tag_type)type,
f, error_r);
f, error);
}
}

View File

@ -21,37 +21,37 @@
#define MPD_DB_PRINT_H
#include "gcc.h"
#include "gerror.h"
class SongFilter;
struct DatabaseSelection;
struct db_visitor;
class Client;
class Error;
gcc_nonnull(1)
bool
db_selection_print(Client *client, const DatabaseSelection &selection,
bool full, GError **error_r);
bool full, Error &error);
gcc_nonnull(1,2)
bool
printAllIn(Client *client, const char *uri_utf8, GError **error_r);
printAllIn(Client *client, const char *uri_utf8, Error &error);
gcc_nonnull(1,2)
bool
printInfoForAllIn(Client *client, const char *uri_utf8,
GError **error_r);
Error &error);
gcc_nonnull(1,2)
bool
searchStatsForSongsIn(Client *client, const char *name,
const SongFilter *filter,
GError **error_r);
Error &error);
gcc_nonnull(1)
bool
listAllUniqueTags(Client *client, int type,
const SongFilter *filter,
GError **error_r);
Error &error);
#endif

View File

@ -23,17 +23,17 @@
#include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx"
#include "Partition.hxx"
#include "util/Error.hxx"
#include <functional>
static bool
AddToQueue(Partition &partition, Song &song, GError **error_r)
AddToQueue(Partition &partition, Song &song, Error &error)
{
enum playlist_result result =
partition.playlist.AppendSong(partition.pc, &song, NULL);
if (result != PLAYLIST_RESULT_SUCCESS) {
g_set_error(error_r, playlist_quark(), result,
"Playlist error");
error.Set(playlist_domain, result, "Playlist error");
return false;
}
@ -42,13 +42,13 @@ AddToQueue(Partition &partition, Song &song, GError **error_r)
bool
AddFromDatabase(Partition &partition, const DatabaseSelection &selection,
GError **error_r)
Error &error)
{
const Database *db = GetDatabase(error_r);
const Database *db = GetDatabase(error);
if (db == nullptr)
return false;
using namespace std::placeholders;
const auto f = std::bind(AddToQueue, std::ref(partition), _1, _2);
return db->Visit(selection, f, error_r);
return db->Visit(selection, f, error);
}

View File

@ -20,13 +20,12 @@
#ifndef MPD_DATABASE_QUEUE_HXX
#define MPD_DATABASE_QUEUE_HXX
#include "gerror.h"
struct Partition;
struct DatabaseSelection;
class Error;
bool
AddFromDatabase(Partition &partition, const DatabaseSelection &selection,
GError **error_r);
Error &error);
#endif

View File

@ -28,6 +28,7 @@
#include "TagInternal.hxx"
#include "Tag.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include <glib.h>
@ -69,7 +70,7 @@ db_save_internal(FILE *fp, const Directory *music_root)
}
bool
db_load_internal(TextFile &file, Directory *music_root, GError **error)
db_load_internal(TextFile &file, Directory *music_root, Error &error)
{
char *line;
int format = 0;
@ -82,7 +83,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
/* get initial info */
line = file.ReadLine();
if (line == NULL || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) {
g_set_error(error, db_quark(), 0, "Database corrupted");
error.Set(db_domain, "Database corrupted");
return false;
}
@ -94,8 +95,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1);
} else if (g_str_has_prefix(line, DIRECTORY_MPD_VERSION)) {
if (found_version) {
g_set_error(error, db_quark(), 0,
"Duplicate version line");
error.Set(db_domain, "Duplicate version line");
return false;
}
@ -104,8 +104,7 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
const char *new_charset;
if (found_charset) {
g_set_error(error, db_quark(), 0,
"Duplicate charset line");
error.Set(db_domain, "Duplicate charset line");
return false;
}
@ -115,44 +114,43 @@ db_load_internal(TextFile &file, Directory *music_root, GError **error)
const std::string &old_charset = Path::GetFSCharset();
if (!old_charset.empty()
&& strcmp(new_charset, old_charset.c_str())) {
g_set_error(error, db_quark(), 0,
"Existing database has charset "
"\"%s\" instead of \"%s\"; "
"discarding database file",
new_charset, old_charset.c_str());
error.Format(db_domain,
"Existing database has charset "
"\"%s\" instead of \"%s\"; "
"discarding database file",
new_charset, old_charset.c_str());
return false;
}
} else if (g_str_has_prefix(line, DB_TAG_PREFIX)) {
const char *name = line + sizeof(DB_TAG_PREFIX) - 1;
enum tag_type tag = tag_name_parse(name);
if (tag == TAG_NUM_OF_ITEM_TYPES) {
g_set_error(error, db_quark(), 0,
"Unrecognized tag '%s', "
"discarding database file",
name);
error.Format(db_domain,
"Unrecognized tag '%s', "
"discarding database file",
name);
return false;
}
tags[tag] = true;
} else {
g_set_error(error, db_quark(), 0,
"Malformed line: %s", line);
error.Format(db_domain, "Malformed line: %s", line);
return false;
}
}
if (format != DB_FORMAT) {
g_set_error(error, db_quark(), 0,
"Database format mismatch, "
"discarding database file");
error.Set(db_domain,
"Database format mismatch, "
"discarding database file");
return false;
}
for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) {
if (!ignore_tag_items[i] && !tags[i]) {
g_set_error(error, db_quark(), 0,
"Tag list mismatch, "
"discarding database file");
error.Set(db_domain,
"Tag list mismatch, "
"discarding database file");
return false;
}
}

View File

@ -20,17 +20,16 @@
#ifndef MPD_DATABASE_SAVE_HXX
#define MPD_DATABASE_SAVE_HXX
#include "gerror.h"
#include <stdio.h>
struct Directory;
class TextFile;
class Error;
void
db_save_internal(FILE *file, const Directory *root);
bool
db_load_internal(TextFile &file, Directory *root, GError **error);
db_load_internal(TextFile &file, Directory *root, Error &error);
#endif

View File

@ -21,7 +21,6 @@
#define MPD_DATABASE_SIMPLE_HXX
#include "gcc.h"
#include "gerror.h"
#include <sys/time.h>
@ -29,6 +28,7 @@ struct config_param;
struct Directory;
struct db_selection;
struct db_visitor;
class Error;
/**
* Check whether the default #SimpleDatabasePlugin is used. This
@ -60,7 +60,7 @@ db_get_directory(const char *name);
* May only be used if db_is_simple() returns true.
*/
bool
db_save(GError **error_r);
db_save(Error &error);
/**
* May only be used if db_is_simple() returns true.

View File

@ -20,19 +20,18 @@
#ifndef MPD_DATABASE_VISITOR_HXX
#define MPD_DATABASE_VISITOR_HXX
#include "gerror.h"
#include <functional>
struct Directory;
struct Song;
struct PlaylistInfo;
class Error;
typedef std::function<bool(const Directory &, GError **)> VisitDirectory;
typedef std::function<bool(struct Song &, GError **)> VisitSong;
typedef std::function<bool(const Directory &, Error &)> VisitDirectory;
typedef std::function<bool(struct Song &, Error &)> VisitSong;
typedef std::function<bool(const PlaylistInfo &, const Directory &,
GError **)> VisitPlaylist;
Error &)> VisitPlaylist;
typedef std::function<bool(const char *, GError **)> VisitString;
typedef std::function<bool(const char *, Error &)> VisitString;
#endif

View File

@ -28,6 +28,7 @@
#include "DecoderInternal.hxx"
#include "Song.hxx"
#include "InputStream.hxx"
#include "util/Error.hxx"
#include <glib.h>
@ -257,8 +258,6 @@ size_t decoder_read(struct decoder *decoder,
void *buffer, size_t length)
{
/* XXX don't allow decoder==NULL */
GError *error = NULL;
size_t nbytes;
assert(decoder == NULL ||
decoder->dc->state == DECODE_STATE_START ||
@ -283,14 +282,13 @@ size_t decoder_read(struct decoder *decoder,
is->cond.wait(is->mutex);
}
nbytes = input_stream_read(is, buffer, length, &error);
assert(nbytes == 0 || error == NULL);
assert(nbytes > 0 || error != NULL || input_stream_eof(is));
Error error;
size_t nbytes = input_stream_read(is, buffer, length, error);
assert(nbytes == 0 || !error.IsDefined());
assert(nbytes > 0 || error.IsDefined() || input_stream_eof(is));
if (gcc_unlikely(nbytes == 0 && error != nullptr)) {
g_warning("%s", error->message);
g_error_free(error);
}
if (gcc_unlikely(nbytes == 0 && error.IsDefined()))
g_warning("%s", error.GetMessage());
input_stream_unlock(is);
@ -364,7 +362,6 @@ decoder_data(struct decoder *decoder,
uint16_t kbit_rate)
{
struct decoder_control *dc = decoder->dc;
GError *error = NULL;
enum decoder_command cmd;
assert(dc->state == DECODE_STATE_DECODE);
@ -397,16 +394,17 @@ decoder_data(struct decoder *decoder,
}
if (dc->in_audio_format != dc->out_audio_format) {
Error error;
data = decoder->conv_state.Convert(dc->in_audio_format,
data, length,
dc->out_audio_format,
&length,
&error);
error);
if (data == NULL) {
/* the PCM conversion has failed - stop
playback, since we have no better way to
bail out */
g_warning("%s", error->message);
g_warning("%s", error.GetMessage());
return DECODE_COMMAND_STOP;
}
}

View File

@ -24,6 +24,7 @@
#include "AudioFormat.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "util/Error.hxx"
#include <glib.h>
@ -77,7 +78,7 @@ struct decoder_control {
* The object must be freed when this object transitions to
* any other state (usually #DECODE_STATE_START).
*/
GError *error;
Error error;
bool quit;
bool seek_error;
@ -218,38 +219,41 @@ struct decoder_control {
}
/**
* Checks whether an error has occurred, and if so, returns a newly
* allocated copy of the #GError object.
* Checks whether an error has occurred, and if so, returns a
* copy of the #Error object.
*
* Caller must lock the object.
*/
GError *GetError() const {
gcc_pure
Error GetError() const {
assert(command == DECODE_COMMAND_NONE);
assert(state != DECODE_STATE_ERROR || error != nullptr);
assert(state != DECODE_STATE_ERROR || error.IsDefined());
return state == DECODE_STATE_ERROR
? g_error_copy(error)
: nullptr;
Error result;
if (state == DECODE_STATE_ERROR)
result.Set(error);
return result;
}
/**
* Like dc_get_error(), but locks and unlocks the object.
*/
GError *LockGetError() const {
gcc_pure
Error LockGetError() const {
Lock();
GError *result = GetError();
Error result = GetError();
Unlock();
return result;
}
/**
* Clear the error condition and free the #GError object (if any).
* Clear the error condition and free the #Error object (if any).
*
* Caller must lock the object.
*/
void ClearError() {
if (state == DECODE_STATE_ERROR) {
g_error_free(error);
error.Clear();
state = DECODE_STATE_STOP;
}
}

23
src/DecoderError.cxx Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "DecoderError.hxx"
#include "util/Domain.hxx"
const Domain decoder_domain("decoder");

View File

@ -20,18 +20,6 @@
#ifndef MPD_DECODER_ERROR_HXX
#define MPD_DECODER_ERROR_HXX
#include "gcc.h"
#include <glib.h>
/**
* Quark for GError.domain.
*/
gcc_pure
static inline GQuark
decoder_quark(void)
{
return g_quark_from_static_string("decoder");
}
extern const class Domain decoder_domain;
#endif

View File

@ -32,6 +32,7 @@
#include "InputStream.hxx"
#include "DecoderList.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "ApeReplayGain.hxx"
#include <glib.h>
@ -72,15 +73,12 @@ decoder_command_finished_locked(struct decoder_control *dc)
static struct input_stream *
decoder_input_stream_open(struct decoder_control *dc, const char *uri)
{
GError *error = NULL;
struct input_stream *is;
Error error;
is = input_stream_open(uri, dc->mutex, dc->cond, &error);
input_stream *is = input_stream_open(uri, dc->mutex, dc->cond, error);
if (is == NULL) {
if (error != NULL) {
g_warning("%s", error->message);
g_error_free(error);
}
if (error.IsDefined())
g_warning("%s", error.GetMessage());
return NULL;
}
@ -98,12 +96,10 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri)
input_stream_update(is);
}
if (!input_stream_check(is, &error)) {
if (!input_stream_check(is, error)) {
dc->Unlock();
g_warning("%s", error->message);
g_error_free(error);
g_warning("%s", error.GetMessage());
return NULL;
}
@ -132,7 +128,10 @@ decoder_stream_decode(const struct decoder_plugin *plugin,
return true;
/* rewind the stream, so each plugin gets a fresh start */
input_stream_seek(input_stream, 0, SEEK_SET, NULL);
{
Error error;
input_stream_seek(input_stream, 0, SEEK_SET, error);
}
decoder->dc->Unlock();
@ -411,8 +410,8 @@ decoder_run_song(struct decoder_control *dc,
if (allocated != NULL)
error_uri = allocated;
dc->error = g_error_new(decoder_quark(), 0,
"Failed to decode %s", error_uri);
dc->error.Format(decoder_domain,
"Failed to decode %s", error_uri);
g_free(allocated);
}
@ -436,8 +435,7 @@ decoder_run(struct decoder_control *dc)
if (uri == NULL) {
dc->state = DECODE_STATE_ERROR;
dc->error = g_error_new(decoder_quark(), 0,
"Failed to map song");
dc->error.Set(decoder_domain, "Failed to map song");
decoder_command_finished_locked(dc);
return;

View File

@ -24,6 +24,7 @@
#include "DatabaseLock.hxx"
#include "SongSort.hxx"
#include "Song.hxx"
#include "util/Error.hxx"
extern "C" {
#include "util/list_sort.h"
@ -300,34 +301,34 @@ bool
Directory::Walk(bool recursive, const SongFilter *filter,
VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist,
GError **error_r) const
Error &error) const
{
assert(error_r == NULL || *error_r == NULL);
assert(!error.IsDefined());
if (visit_song) {
Song *song;
directory_for_each_song(song, this)
if ((filter == nullptr || filter->Match(*song)) &&
!visit_song(*song, error_r))
!visit_song(*song, error))
return false;
}
if (visit_playlist) {
for (const PlaylistInfo &p : playlists)
if (!visit_playlist(p, *this, error_r))
if (!visit_playlist(p, *this, error))
return false;
}
Directory *child;
directory_for_each_child(child, this) {
if (visit_directory &&
!visit_directory(*child, error_r))
!visit_directory(*child, error))
return false;
if (recursive &&
!child->Walk(recursive, filter,
visit_directory, visit_song, visit_playlist,
error_r))
error))
return false;
}

View File

@ -25,7 +25,6 @@
#include "gcc.h"
#include "DatabaseVisitor.hxx"
#include "PlaylistVector.hxx"
#include "gerror.h"
#include <sys/types.h>
@ -47,6 +46,7 @@
struct Song;
struct db_visitor;
class SongFilter;
class Error;
struct Directory {
/**
@ -251,7 +251,7 @@ public:
bool Walk(bool recursive, const SongFilter *match,
VisitDirectory visit_directory, VisitSong visit_song,
VisitPlaylist visit_playlist,
GError **error_r) const;
Error &error) const;
};
static inline bool

View File

@ -24,6 +24,8 @@
#include "SongSave.hxx"
#include "PlaylistDatabase.hxx"
#include "TextFile.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h>
#include <string.h>
@ -33,14 +35,7 @@
#define DIRECTORY_BEGIN "begin: "
#define DIRECTORY_END "end: "
/**
* The quark used for GError.domain.
*/
static inline GQuark
directory_quark(void)
{
return g_quark_from_static_string("directory");
}
static constexpr Domain directory_domain("directory");
void
directory_save(FILE *fp, const Directory *directory)
@ -77,13 +72,13 @@ directory_save(FILE *fp, const Directory *directory)
static Directory *
directory_load_subdir(TextFile &file, Directory *parent, const char *name,
GError **error_r)
Error &error)
{
bool success;
if (parent->FindChild(name) != nullptr) {
g_set_error(error_r, directory_quark(), 0,
"Duplicate subdirectory '%s'", name);
error.Format(directory_domain,
"Duplicate subdirectory '%s'", name);
return NULL;
}
@ -91,8 +86,7 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name,
const char *line = file.ReadLine();
if (line == NULL) {
g_set_error(error_r, directory_quark(), 0,
"Unexpected end of file");
error.Set(directory_domain, "Unexpected end of file");
directory->Delete();
return NULL;
}
@ -104,21 +98,19 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name,
line = file.ReadLine();
if (line == NULL) {
g_set_error(error_r, directory_quark(), 0,
"Unexpected end of file");
error.Set(directory_domain, "Unexpected end of file");
directory->Delete();
return NULL;
}
}
if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) {
g_set_error(error_r, directory_quark(), 0,
"Malformed line: %s", line);
error.Format(directory_domain, "Malformed line: %s", line);
directory->Delete();
return NULL;
}
success = directory_load(file, directory, error_r);
success = directory_load(file, directory, error);
if (!success) {
directory->Delete();
return NULL;
@ -128,7 +120,7 @@ directory_load_subdir(TextFile &file, Directory *parent, const char *name,
}
bool
directory_load(TextFile &file, Directory *directory, GError **error)
directory_load(TextFile &file, Directory *directory, Error &error)
{
const char *line;
@ -146,8 +138,8 @@ directory_load(TextFile &file, Directory *directory, GError **error)
Song *song;
if (directory->FindSong(name) != nullptr) {
g_set_error(error, directory_quark(), 0,
"Duplicate song '%s'", name);
error.Format(directory_domain,
"Duplicate song '%s'", name);
return false;
}
@ -170,8 +162,8 @@ directory_load(TextFile &file, Directory *directory, GError **error)
g_free(name);
} else {
g_set_error(error, directory_quark(), 0,
"Malformed line: %s", line);
error.Format(directory_domain,
"Malformed line: %s", line);
return false;
}
}

View File

@ -20,17 +20,16 @@
#ifndef MPD_DIRECTORY_SAVE_HXX
#define MPD_DIRECTORY_SAVE_HXX
#include "gerror.h"
#include <stdio.h>
struct Directory;
class TextFile;
class Error;
void
directory_save(FILE *fp, const Directory *directory);
bool
directory_load(TextFile &file, Directory *directory, GError **error);
directory_load(TextFile &file, Directory *directory, Error &error);
#endif

View File

@ -20,8 +20,6 @@
#ifndef MPD_ENCODER_PLUGIN_HXX
#define MPD_ENCODER_PLUGIN_HXX
#include "gerror.h"
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
@ -30,6 +28,7 @@ struct EncoderPlugin;
struct AudioFormat;
struct config_param;
struct Tag;
class Error;
struct Encoder {
const EncoderPlugin &plugin;
@ -50,28 +49,28 @@ struct EncoderPlugin {
const char *name;
Encoder *(*init)(const config_param &param,
GError **error);
Error &error);
void (*finish)(Encoder *encoder);
bool (*open)(Encoder *encoder,
AudioFormat &audio_format,
GError **error);
Error &error);
void (*close)(Encoder *encoder);
bool (*end)(Encoder *encoder, GError **error);
bool (*end)(Encoder *encoder, Error &error);
bool (*flush)(Encoder *encoder, GError **error);
bool (*flush)(Encoder *encoder, Error &error);
bool (*pre_tag)(Encoder *encoder, GError **error);
bool (*pre_tag)(Encoder *encoder, Error &error);
bool (*tag)(Encoder *encoder, const Tag *tag,
GError **error);
Error &error);
bool (*write)(Encoder *encoder,
const void *data, size_t length,
GError **error);
Error &error);
size_t (*read)(Encoder *encoder, void *dest, size_t length);
@ -88,7 +87,7 @@ struct EncoderPlugin {
*/
static inline Encoder *
encoder_init(const EncoderPlugin &plugin, const config_param &param,
GError **error_r)
Error &error_r)
{
return plugin.init(param, error_r);
}
@ -123,7 +122,7 @@ encoder_finish(Encoder *encoder)
*/
static inline bool
encoder_open(Encoder *encoder, AudioFormat &audio_format,
GError **error)
Error &error)
{
assert(!encoder->open);
@ -168,7 +167,7 @@ encoder_close(Encoder *encoder)
* @return true on success
*/
static inline bool
encoder_end(Encoder *encoder, GError **error)
encoder_end(Encoder *encoder, Error &error)
{
assert(encoder->open);
assert(!encoder->end);
@ -192,7 +191,7 @@ encoder_end(Encoder *encoder, GError **error)
* @return true on success
*/
static inline bool
encoder_flush(Encoder *encoder, GError **error)
encoder_flush(Encoder *encoder, Error &error)
{
assert(encoder->open);
assert(!encoder->pre_tag);
@ -216,7 +215,7 @@ encoder_flush(Encoder *encoder, GError **error)
* @return true on success
*/
static inline bool
encoder_pre_tag(Encoder *encoder, GError **error)
encoder_pre_tag(Encoder *encoder, Error &error)
{
assert(encoder->open);
assert(!encoder->pre_tag);
@ -246,7 +245,7 @@ encoder_pre_tag(Encoder *encoder, GError **error)
* @return true on success
*/
static inline bool
encoder_tag(Encoder *encoder, const Tag *tag, GError **error)
encoder_tag(Encoder *encoder, const Tag *tag, Error &error)
{
assert(encoder->open);
assert(!encoder->pre_tag);
@ -274,7 +273,7 @@ encoder_tag(Encoder *encoder, const Tag *tag, GError **error)
*/
static inline bool
encoder_write(Encoder *encoder, const void *data, size_t length,
GError **error)
Error &error)
{
assert(encoder->open);
assert(!encoder->pre_tag);

View File

@ -24,35 +24,31 @@
#include "FilterPlugin.hxx"
#include "FilterInternal.hxx"
#include "FilterRegistry.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include <glib.h>
#include <string.h>
static GQuark
filter_quark(void)
{
return g_quark_from_static_string("filter");
}
/**
* Find the "filter" configuration block for the specified name.
*
* @param filter_template_name the name of the filter template
* @param error_r space to return an error description
* @param error space to return an error description
* @return the configuration block, or NULL if none was configured
*/
static const struct config_param *
filter_plugin_config(const char *filter_template_name, GError **error_r)
filter_plugin_config(const char *filter_template_name, Error &error)
{
const struct config_param *param = NULL;
while ((param = config_get_next_param(CONF_AUDIO_FILTER, param)) != NULL) {
const char *name = param->GetBlockValue("name");
if (name == NULL) {
g_set_error(error_r, filter_quark(), 1,
"filter configuration without 'name' name in line %d",
param->line);
error.Format(config_domain,
"filter configuration without 'name' name in line %d",
param->line);
return NULL;
}
@ -60,10 +56,9 @@ filter_plugin_config(const char *filter_template_name, GError **error_r)
return param;
}
g_set_error(error_r, filter_quark(), 1,
"filter template not found: %s",
filter_template_name);
error.Format(config_domain,
"filter template not found: %s",
filter_template_name);
return NULL;
}
@ -73,11 +68,11 @@ filter_plugin_config(const char *filter_template_name, GError **error_r)
* configured filter sections.
* @param chain the chain to append filters on
* @param spec the filter chain specification
* @param error_r space to return an error description
* @param error space to return an error description
* @return the number of filters which were successfully added
*/
unsigned int
filter_chain_parse(Filter &chain, const char *spec, GError **error_r)
filter_chain_parse(Filter &chain, const char *spec, Error &error)
{
// Split on comma
@ -92,14 +87,14 @@ filter_chain_parse(Filter &chain, const char *spec, GError **error_r)
g_strstrip(*template_names);
const struct config_param *cfg =
filter_plugin_config(*template_names, error_r);
filter_plugin_config(*template_names, error);
if (cfg == NULL) {
// The error has already been set, just stop.
break;
}
// Instantiate one of those filter plugins with the template name as a hint
Filter *f = filter_configured_new(*cfg, error_r);
Filter *f = filter_configured_new(*cfg, error);
if (f == NULL) {
// The error has already been set, just stop.
break;

View File

@ -25,9 +25,8 @@
#ifndef MPD_FILTER_CONFIG_HXX
#define MPD_FILTER_CONFIG_HXX
#include "gerror.h"
class Filter;
class Error;
/**
* Builds a filter chain from a configuration string on the form
@ -39,6 +38,6 @@ class Filter;
* @return the number of filters which were successfully added
*/
unsigned int
filter_chain_parse(Filter &chain, const char *spec, GError **error_r);
filter_chain_parse(Filter &chain, const char *spec, Error &error);
#endif

View File

@ -25,7 +25,10 @@
#ifndef MPD_FILTER_INTERNAL_HXX
#define MPD_FILTER_INTERNAL_HXX
#include <stddef.h>
struct AudioFormat;
class Error;
class Filter {
public:
@ -43,7 +46,7 @@ public:
* @return the format of outgoing data or
* AudioFormat::Undefined() on error
*/
virtual AudioFormat Open(AudioFormat &af, GError **error_r) = 0;
virtual AudioFormat Open(AudioFormat &af, Error &error) = 0;
/**
* Closes the filter. After that, you may call Open() again.
@ -65,7 +68,7 @@ public:
*/
virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r,
GError **error_r) = 0;
Error &error) = 0;
};
#endif

View File

@ -22,40 +22,38 @@
#include "FilterInternal.hxx"
#include "FilterRegistry.hxx"
#include "conf.h"
#include "ConfigQuark.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include <assert.h>
Filter *
filter_new(const struct filter_plugin *plugin,
const config_param &param, GError **error_r)
const config_param &param, Error &error)
{
assert(plugin != NULL);
assert(error_r == NULL || *error_r == NULL);
assert(!error.IsDefined());
return plugin->init(param, error_r);
return plugin->init(param, error);
}
Filter *
filter_configured_new(const config_param &param, GError **error_r)
filter_configured_new(const config_param &param, Error &error)
{
const struct filter_plugin *plugin;
assert(error_r == NULL || *error_r == NULL);
assert(!error.IsDefined());
const char *plugin_name = param.GetBlockValue("plugin");
if (plugin_name == NULL) {
g_set_error(error_r, config_quark(), 0,
"No filter plugin specified");
error.Set(config_domain, "No filter plugin specified");
return NULL;
}
plugin = filter_plugin_by_name(plugin_name);
const filter_plugin *plugin = filter_plugin_by_name(plugin_name);
if (plugin == NULL) {
g_set_error(error_r, config_quark(), 0,
"No such filter plugin: %s", plugin_name);
error.Format(config_domain,
"No such filter plugin: %s", plugin_name);
return NULL;
}
return filter_new(plugin, param, error_r);
return filter_new(plugin, param, error);
}

View File

@ -26,12 +26,9 @@
#ifndef MPD_FILTER_PLUGIN_HXX
#define MPD_FILTER_PLUGIN_HXX
#include "gerror.h"
#include <stddef.h>
struct config_param;
class Filter;
class Error;
struct filter_plugin {
const char *name;
@ -39,7 +36,7 @@ struct filter_plugin {
/**
* Allocates and configures a filter.
*/
Filter *(*init)(const config_param &param, GError **error_r);
Filter *(*init)(const config_param &param, Error &error);
};
/**
@ -53,7 +50,7 @@ struct filter_plugin {
*/
Filter *
filter_new(const struct filter_plugin *plugin,
const config_param &param, GError **error_r);
const config_param &param, Error &error);
/**
* Creates a new filter, loads configuration and the plugin name from
@ -65,6 +62,6 @@ filter_new(const struct filter_plugin *plugin,
* @return a new filter object, or NULL on error
*/
Filter *
filter_configured_new(const config_param &param, GError **error_r);
filter_configured_new(const config_param &param, Error &error);
#endif

View File

@ -20,6 +20,7 @@
#include "config.h"
#include "InotifySource.hxx"
#include "util/fifo_buffer.h"
#include "util/Error.hxx"
#include "system/fd_util.h"
#include "system/FatalError.hxx"
@ -32,15 +33,6 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "inotify"
/**
* A GQuark for GError instances.
*/
static inline GQuark
mpd_inotify_quark(void)
{
return g_quark_from_static_string("inotify");
}
bool
InotifySource::OnSocketReady(gcc_unused unsigned flags)
{
@ -97,13 +89,11 @@ InotifySource::InotifySource(EventLoop &_loop,
InotifySource *
InotifySource::Create(EventLoop &loop,
mpd_inotify_callback_t callback, void *callback_ctx,
GError **error_r)
Error &error)
{
int fd = inotify_init_cloexec();
if (fd < 0) {
g_set_error(error_r, mpd_inotify_quark(), errno,
"inotify_init() has failed: %s",
g_strerror(errno));
error.SetErrno("inotify_init() has failed");
return NULL;
}
@ -116,13 +106,11 @@ InotifySource::~InotifySource()
}
int
InotifySource::Add(const char *path_fs, unsigned mask, GError **error_r)
InotifySource::Add(const char *path_fs, unsigned mask, Error &error)
{
int wd = inotify_add_watch(Get(), path_fs, mask);
if (wd < 0)
g_set_error(error_r, mpd_inotify_quark(), errno,
"inotify_add_watch() has failed: %s",
g_strerror(errno));
error.SetErrno("inotify_add_watch() has failed");
return wd;
}

View File

@ -21,9 +21,10 @@
#define MPD_INOTIFY_SOURCE_HXX
#include "event/SocketMonitor.hxx"
#include "gerror.h"
#include "gcc.h"
class Error;
typedef void (*mpd_inotify_callback_t)(int wd, unsigned mask,
const char *name, void *ctx);
@ -46,7 +47,7 @@ public:
static InotifySource *Create(EventLoop &_loop,
mpd_inotify_callback_t callback,
void *ctx,
GError **error_r);
Error &error);
~InotifySource();
@ -56,7 +57,7 @@ public:
*
* @return a watch descriptor or -1 on error
*/
int Add(const char *path_fs, unsigned mask, GError **error_r);
int Add(const char *path_fs, unsigned mask, Error &error);
/**
* Removes a path from the notify list.

View File

@ -24,6 +24,7 @@
#include "Mapper.hxx"
#include "Main.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include <glib.h>
@ -162,7 +163,7 @@ static void
recursive_watch_subdirectories(WatchDirectory *directory,
const char *path_fs, unsigned depth)
{
GError *error = NULL;
Error error;
DIR *dir;
struct dirent *ent;
@ -204,12 +205,11 @@ recursive_watch_subdirectories(WatchDirectory *directory,
continue;
}
ret = inotify_source->Add(child_path_fs, IN_MASK, &error);
ret = inotify_source->Add(child_path_fs, IN_MASK, error);
if (ret < 0) {
g_warning("Failed to register %s: %s",
child_path_fs, error->message);
g_error_free(error);
error = NULL;
child_path_fs, error.GetMessage());
error.Clear();
g_free(child_path_fs);
continue;
}
@ -309,8 +309,6 @@ mpd_inotify_callback(int wd, unsigned mask,
void
mpd_inotify_init(unsigned max_depth)
{
GError *error = NULL;
g_debug("initializing inotify");
const Path &path = mapper_get_music_directory_fs();
@ -319,21 +317,20 @@ mpd_inotify_init(unsigned max_depth)
return;
}
Error error;
inotify_source = InotifySource::Create(*main_loop,
mpd_inotify_callback, nullptr,
&error);
error);
if (inotify_source == NULL) {
g_warning("%s", error->message);
g_error_free(error);
g_warning("%s", error.GetMessage());
return;
}
inotify_max_depth = max_depth;
int descriptor = inotify_source->Add(path.c_str(), IN_MASK, &error);
int descriptor = inotify_source->Add(path.c_str(), IN_MASK, error);
if (descriptor < 0) {
g_warning("%s", error->message);
g_error_free(error);
g_warning("%s", error.GetMessage());
delete inotify_source;
inotify_source = NULL;
return;

View File

@ -21,16 +21,14 @@
#include "InputInit.hxx"
#include "InputRegistry.hxx"
#include "InputPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "conf.h"
#include <assert.h>
#include <string.h>
static inline GQuark
input_quark(void)
{
return g_quark_from_static_string("input");
}
extern constexpr Domain input_domain("input");
/**
* Find the "input" configuration block for the specified plugin.
@ -39,16 +37,16 @@ input_quark(void)
* @return the configuration block, or NULL if none was configured
*/
static const struct config_param *
input_plugin_config(const char *plugin_name, GError **error_r)
input_plugin_config(const char *plugin_name, Error &error)
{
const struct config_param *param = NULL;
while ((param = config_get_next_param(CONF_INPUT, param)) != NULL) {
const char *name = param->GetBlockValue("plugin");
if (name == NULL) {
g_set_error(error_r, input_quark(), 0,
"input configuration without 'plugin' name in line %d",
param->line);
error.Format(input_domain,
"input configuration without 'plugin' name in line %d",
param->line);
return NULL;
}
@ -60,12 +58,10 @@ input_plugin_config(const char *plugin_name, GError **error_r)
}
bool
input_stream_global_init(GError **error_r)
input_stream_global_init(Error &error)
{
const config_param empty;
GError *error = NULL;
for (unsigned i = 0; input_plugins[i] != NULL; ++i) {
const struct input_plugin *plugin = input_plugins[i];
@ -74,24 +70,21 @@ input_stream_global_init(GError **error_r)
assert(plugin->open != NULL);
const struct config_param *param =
input_plugin_config(plugin->name, &error);
input_plugin_config(plugin->name, error);
if (param == nullptr) {
if (error != nullptr) {
g_propagate_error(error_r, error);
if (error.IsDefined())
return false;
}
param = &empty;
} else if (!param->GetBlockValue("enabled", true))
/* the plugin is disabled in mpd.conf */
continue;
if (plugin->init == NULL || plugin->init(*param, &error))
if (plugin->init == NULL || plugin->init(*param, error))
input_plugins_enabled[i] = true;
else {
g_propagate_prefixed_error(error_r, error,
"Failed to initialize input plugin '%s': ",
plugin->name);
error.FormatPrefix("Failed to initialize input plugin '%s': ",
plugin->name);
return false;
}
}

View File

@ -20,7 +20,7 @@
#ifndef MPD_INPUT_INIT_HXX
#define MPD_INPUT_INIT_HXX
#include "gerror.h"
class Error;
/**
* Initializes this library and all input_stream implementations.
@ -29,7 +29,7 @@
* ignore errors
*/
bool
input_stream_global_init(GError **error_r);
input_stream_global_init(Error &error);
/**
* Deinitializes this library and all input_stream implementations.

View File

@ -31,6 +31,7 @@
struct Tag;
struct input_stream;
class Error;
/**
* Opens a new input stream. You may not access it until the "ready"
@ -48,7 +49,7 @@ gcc_malloc
struct input_stream *
input_stream_open(const char *uri,
Mutex &mutex, Cond &cond,
GError **error_r);
Error &error);
/**
* Close the input stream and free resources.
@ -66,7 +67,7 @@ input_stream_close(struct input_stream *is);
*/
gcc_nonnull(1)
bool
input_stream_check(struct input_stream *is, GError **error_r);
input_stream_check(struct input_stream *is, Error &error);
/**
* Update the public attributes. Call before accessing attributes
@ -133,7 +134,7 @@ input_stream_cheap_seeking(const struct input_stream *is);
gcc_nonnull(1)
bool
input_stream_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r);
Error &error);
/**
* Wrapper for input_stream_seek() which locks and unlocks the
@ -142,7 +143,7 @@ input_stream_seek(struct input_stream *is, goffset offset, int whence,
gcc_nonnull(1)
bool
input_stream_lock_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r);
Error &error);
/**
* Returns true if the stream has reached end-of-file.
@ -210,7 +211,7 @@ input_stream_available(struct input_stream *is);
gcc_nonnull(1, 2)
size_t
input_stream_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r);
Error &error);
/**
* Wrapper for input_stream_tag() which locks and unlocks the
@ -219,6 +220,6 @@ input_stream_read(struct input_stream *is, void *ptr, size_t size,
gcc_nonnull(1, 2)
size_t
input_stream_lock_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r);
Error &error);
#endif

View File

@ -23,10 +23,10 @@
#include "InputLegacy.hxx"
#include <stddef.h>
#include <sys/types.h>
struct config_param;
struct input_stream;
class Error;
struct input_plugin {
const char *name;
@ -39,7 +39,7 @@ struct input_plugin {
* @return true on success, false if the plugin should be
* disabled
*/
bool (*init)(const config_param &param, GError **error_r);
bool (*init)(const config_param &param, Error &error);
/**
* Global deinitialization. Called once before MPD shuts
@ -49,7 +49,7 @@ struct input_plugin {
struct input_stream *(*open)(const char *uri,
Mutex &mutex, Cond &cond,
GError **error_r);
Error &error);
void (*close)(struct input_stream *is);
/**
@ -58,7 +58,7 @@ struct input_plugin {
*
* @return false on error
*/
bool (*check)(struct input_stream *is, GError **error_r);
bool (*check)(struct input_stream *is, Error &error);
/**
* Update the public attributes. Call before access. Can be
@ -79,10 +79,10 @@ struct input_plugin {
bool (*available)(struct input_stream *is);
size_t (*read)(struct input_stream *is, void *ptr, size_t size,
GError **error_r);
Error &error);
bool (*eof)(struct input_stream *is);
bool (*seek)(struct input_stream *is, goffset offset, int whence,
GError **error_r);
Error &error);
};
#endif

View File

@ -23,29 +23,22 @@
#include "InputPlugin.hxx"
#include "input/RewindInputPlugin.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h>
#include <assert.h>
static inline GQuark
input_quark(void)
{
return g_quark_from_static_string("input");
}
static constexpr Domain input_domain("input");
struct input_stream *
input_stream_open(const char *url,
Mutex &mutex, Cond &cond,
GError **error_r)
Error &error)
{
GError *error = NULL;
assert(error_r == NULL || *error_r == NULL);
input_plugins_for_each_enabled(plugin) {
struct input_stream *is;
is = plugin->open(url, mutex, cond, &error);
is = plugin->open(url, mutex, cond, error);
if (is != NULL) {
assert(is->plugin.close != NULL);
assert(is->plugin.read != NULL);
@ -55,23 +48,21 @@ input_stream_open(const char *url,
is = input_rewind_open(is);
return is;
} else if (error != NULL) {
g_propagate_error(error_r, error);
} else if (error.IsDefined())
return NULL;
}
}
g_set_error(error_r, input_quark(), 0, "Unrecognized URI");
error.Set(input_domain, "Unrecognized URI");
return NULL;
}
bool
input_stream_check(struct input_stream *is, GError **error_r)
input_stream_check(struct input_stream *is, Error &error)
{
assert(is != NULL);
return is->plugin.check == NULL ||
is->plugin.check(is, error_r);
is->plugin.check(is, error);
}
void
@ -159,19 +150,19 @@ input_stream_cheap_seeking(const struct input_stream *is)
bool
input_stream_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r)
Error &error)
{
assert(is != NULL);
if (is->plugin.seek == NULL)
return false;
return is->plugin.seek(is, offset, whence, error_r);
return is->plugin.seek(is, offset, whence, error);
}
bool
input_stream_lock_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r)
Error &error)
{
assert(is != NULL);
@ -179,7 +170,7 @@ input_stream_lock_seek(struct input_stream *is, goffset offset, int whence,
return false;
const ScopeLock protect(is->mutex);
return input_stream_seek(is, offset, whence, error_r);
return input_stream_seek(is, offset, whence, error);
}
Tag *
@ -216,23 +207,23 @@ input_stream_available(struct input_stream *is)
size_t
input_stream_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
Error &error)
{
assert(ptr != NULL);
assert(size > 0);
return is->plugin.read(is, ptr, size, error_r);
return is->plugin.read(is, ptr, size, error);
}
size_t
input_stream_lock_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
Error &error)
{
assert(ptr != NULL);
assert(size > 0);
const ScopeLock protect(is->mutex);
return input_stream_read(is, ptr, size, error_r);
return input_stream_read(is, ptr, size, error);
}
void input_stream_close(struct input_stream *is)

View File

@ -24,6 +24,7 @@
#include "Client.hxx"
#include "conf.h"
#include "event/ServerSocket.hxx"
#include "util/Error.hxx"
#include <string.h>
#include <assert.h>
@ -55,7 +56,7 @@ int listen_port;
static bool
listen_add_config_param(unsigned int port,
const struct config_param *param,
GError **error_r)
Error &error_r)
{
assert(param != NULL);
@ -69,7 +70,7 @@ listen_add_config_param(unsigned int port,
}
static bool
listen_systemd_activation(GError **error_r)
listen_systemd_activation(Error &error_r)
{
#ifdef ENABLE_SYSTEMD_DAEMON
int n = sd_listen_fds(true);
@ -93,7 +94,7 @@ listen_systemd_activation(GError **error_r)
}
bool
listen_global_init(GError **error_r)
listen_global_init(Error &error)
{
assert(main_loop != nullptr);
@ -101,29 +102,24 @@ listen_global_init(GError **error_r)
const struct config_param *param =
config_get_next_param(CONF_BIND_TO_ADDRESS, NULL);
bool success;
GError *error = NULL;
listen_socket = new ClientListener();
if (listen_systemd_activation(&error))
if (listen_systemd_activation(error))
return true;
if (error != NULL) {
g_propagate_error(error_r, error);
if (error.IsDefined())
return false;
}
if (param != NULL) {
/* "bind_to_address" is configured, create listeners
for all values */
do {
success = listen_add_config_param(port, param, &error);
if (!success) {
if (!listen_add_config_param(port, param, error)) {
delete listen_socket;
g_propagate_prefixed_error(error_r, error,
"Failed to listen on %s (line %i): ",
param->value, param->line);
error.FormatPrefix("Failed to listen on %s (line %i): ",
param->value, param->line);
return false;
}
@ -134,17 +130,15 @@ listen_global_init(GError **error_r)
/* no "bind_to_address" configured, bind the
configured port on all interfaces */
success = listen_socket->AddPort(port, error_r);
success = listen_socket->AddPort(port, error);
if (!success) {
delete listen_socket;
g_propagate_prefixed_error(error_r, error,
"Failed to listen on *:%d: ",
port);
error.FormatPrefix("Failed to listen on *:%d: ", port);
return false;
}
}
if (!listen_socket->Open(error_r)) {
if (!listen_socket->Open(error)) {
delete listen_socket;
return false;
}

View File

@ -20,12 +20,12 @@
#ifndef MPD_LISTEN_HXX
#define MPD_LISTEN_HXX
#include "gerror.h"
class Error;
extern int listen_port;
bool
listen_global_init(GError **error_r);
listen_global_init(Error &error);
void listen_global_finish(void);

View File

@ -25,6 +25,8 @@
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include "mpd_error.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h>
#include <sys/types.h>
@ -51,6 +53,8 @@
#define LOG_DATE_BUF_SIZE 16
#define LOG_DATE_LEN (LOG_DATE_BUF_SIZE - 1)
static constexpr Domain log_domain("log");
static GLogLevelFlags log_threshold = G_LOG_LEVEL_MESSAGE;
static const char *log_charset;
@ -92,7 +96,7 @@ chomp_length(const char *p)
}
static void
file_log_func(const gchar *log_domain,
file_log_func(const gchar *domain,
GLogLevelFlags log_level,
const gchar *message, gcc_unused gpointer user_data)
{
@ -110,12 +114,12 @@ file_log_func(const gchar *log_domain,
} else
converted = NULL;
if (log_domain == NULL)
log_domain = "";
if (domain == nullptr)
domain = "";
fprintf(stderr, "%s%s%s%.*s\n",
stdout_mode ? "" : log_date(),
log_domain, *log_domain == 0 ? "" : ": ",
domain, *domain == 0 ? "" : ": ",
chomp_length(message), message);
g_free(converted);
@ -136,16 +140,15 @@ open_log_file(void)
}
static bool
log_init_file(unsigned line, GError **error_r)
log_init_file(unsigned line, Error &error)
{
assert(!out_path.IsNull());
out_fd = open_log_file();
if (out_fd < 0) {
const std::string out_path_utf8 = out_path.ToUTF8();
g_set_error(error_r, log_quark(), errno,
"failed to open log file \"%s\" (config line %u): %s",
out_path_utf8.c_str(), line, g_strerror(errno));
error.FormatErrno("failed to open log file \"%s\" (config line %u)",
out_path_utf8.c_str(), line);
return false;
}
@ -181,14 +184,14 @@ glib_to_syslog_level(GLogLevelFlags log_level)
}
static void
syslog_log_func(const gchar *log_domain,
syslog_log_func(const gchar *domain,
GLogLevelFlags log_level, const gchar *message,
gcc_unused gpointer user_data)
{
if (stdout_mode) {
/* fall back to the file log function during
startup */
file_log_func(log_domain, log_level,
file_log_func(domain, log_level,
message, user_data);
return;
}
@ -196,11 +199,11 @@ syslog_log_func(const gchar *log_domain,
if (log_level > log_threshold)
return;
if (log_domain == NULL)
log_domain = "";
if (domain == nullptr)
domain = "";
syslog(glib_to_syslog_level(log_level), "%s%s%.*s",
log_domain, *log_domain == 0 ? "" : ": ",
domain, *domain == 0 ? "" : ": ",
chomp_length(message), message);
}
@ -241,7 +244,7 @@ log_early_init(bool verbose)
}
bool
log_init(bool verbose, bool use_stdout, GError **error_r)
log_init(bool verbose, bool use_stdout, Error &error)
{
const struct config_param *param;
@ -264,8 +267,8 @@ log_init(bool verbose, bool use_stdout, GError **error_r)
log_init_syslog();
return true;
#else
g_set_error(error_r, log_quark(), 0,
"config parameter 'log_file' not found");
error.Set(log_domain,
"config parameter 'log_file' not found");
return false;
#endif
#ifdef HAVE_SYSLOG
@ -274,9 +277,9 @@ log_init(bool verbose, bool use_stdout, GError **error_r)
return true;
#endif
} else {
out_path = config_get_path(CONF_LOG_FILE, error_r);
out_path = config_get_path(CONF_LOG_FILE, error);
return !out_path.IsNull() &&
log_init_file(param->line, error_r);
log_init_file(param->line, error);
}
}
}

View File

@ -20,16 +20,7 @@
#ifndef MPD_LOG_HXX
#define MPD_LOG_HXX
#include "gcc.h"
#include <glib.h>
gcc_const
static inline GQuark
log_quark(void)
{
return g_quark_from_static_string("log");
}
class Error;
/**
* Configure a logging destination for daemon startup, before the
@ -43,7 +34,7 @@ void
log_early_init(bool verbose);
bool
log_init(bool verbose, bool use_stdout, GError **error_r);
log_init(bool verbose, bool use_stdout, Error &error);
void
log_deinit(void);

View File

@ -56,6 +56,7 @@
#include "pcm/PcmResample.hxx"
#include "Daemon.hxx"
#include "system/FatalError.hxx"
#include "util/Error.hxx"
extern "C" {
#include "stats.h"
@ -107,15 +108,11 @@ static inline GQuark main_quark()
}
static bool
glue_daemonize_init(const struct options *options, GError **error_r)
glue_daemonize_init(const struct options *options, Error &error)
{
GError *error = NULL;
Path pid_file = config_get_path(CONF_PID_FILE, &error);
if (pid_file.IsNull() && error != NULL) {
g_propagate_error(error_r, error);
Path pid_file = config_get_path(CONF_PID_FILE, error);
if (pid_file.IsNull() && error.IsDefined())
return false;
}
daemonize_init(config_get_string(CONF_USER, NULL),
config_get_string(CONF_GROUP, NULL),
@ -128,20 +125,15 @@ glue_daemonize_init(const struct options *options, GError **error_r)
}
static bool
glue_mapper_init(GError **error_r)
glue_mapper_init(Error &error)
{
GError *error = NULL;
Path music_dir = config_get_path(CONF_MUSIC_DIR, &error);
if (music_dir.IsNull() && error != NULL) {
g_propagate_error(error_r, error);
Path music_dir = config_get_path(CONF_MUSIC_DIR, error);
if (music_dir.IsNull() && error.IsDefined())
return false;
}
Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, &error);
if (playlist_dir.IsNull() && error != NULL) {
g_propagate_error(error_r, error);
Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, error);
if (playlist_dir.IsNull() && error.IsDefined())
return false;
}
if (music_dir.IsNull())
music_dir = Path::FromUTF8(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC));
@ -164,9 +156,6 @@ glue_db_init_and_load(void)
if (param != NULL && path != NULL)
g_message("Found both 'database' and 'db_file' setting - ignoring the latter");
GError *error = NULL;
bool ret;
if (!mapper_has_music_directory()) {
if (param != NULL)
g_message("Found database setting without "
@ -185,13 +174,13 @@ glue_db_init_and_load(void)
param = allocated;
}
if (!DatabaseGlobalInit(*param, &error))
Error error;
if (!DatabaseGlobalInit(*param, error))
FatalError(error);
delete allocated;
ret = DatabaseGlobalOpen(&error);
if (!ret)
if (!DatabaseGlobalOpen(error))
FatalError(error);
/* run database update after daemonization? */
@ -205,36 +194,22 @@ static void
glue_sticker_init(void)
{
#ifdef ENABLE_SQLITE
GError *error = NULL;
Path sticker_file = config_get_path(CONF_STICKER_FILE, &error);
if (sticker_file.IsNull() && error != NULL)
Error error;
Path sticker_file = config_get_path(CONF_STICKER_FILE, error);
if (sticker_file.IsNull() && error.IsDefined())
FatalError(error);
if (!sticker_global_init(std::move(sticker_file), &error))
if (!sticker_global_init(std::move(sticker_file), error))
FatalError(error);
#endif
}
static bool
glue_state_file_init(GError **error_r)
glue_state_file_init(Error &error)
{
GError *error = NULL;
Path path_fs = config_get_path(CONF_STATE_FILE, &error);
if (path_fs.IsNull()) {
if (error != nullptr) {
g_propagate_error(error_r, error);
return false;
}
return true;
}
if (path_fs.IsNull()) {
g_set_error(error_r, main_quark(), 0,
"Failed to convert state file path to FS encoding");
return false;
}
Path path_fs = config_get_path(CONF_STATE_FILE, error);
if (path_fs.IsNull())
return !error.IsDefined();
state_file = new StateFile(std::move(path_fs),
*instance->partition, *main_loop);
@ -364,7 +339,7 @@ int mpd_main(int argc, char *argv[])
struct options options;
clock_t start;
bool create_db;
GError *error = NULL;
Error error;
bool success;
daemonize_close_stdin();
@ -385,25 +360,22 @@ int mpd_main(int argc, char *argv[])
winsock_init();
config_global_init();
success = parse_cmdline(argc, argv, &options, &error);
success = parse_cmdline(argc, argv, &options, error);
if (!success) {
g_warning("%s", error->message);
g_error_free(error);
g_warning("%s", error.GetMessage());
return EXIT_FAILURE;
}
if (!glue_daemonize_init(&options, &error)) {
g_warning("%s", error->message);
g_error_free(error);
if (!glue_daemonize_init(&options, error)) {
g_printerr("%s\n", error.GetMessage());
return EXIT_FAILURE;
}
stats_global_init();
tag_lib_init();
if (!log_init(options.verbose, options.log_stderr, &error)) {
g_warning("%s", error->message);
g_error_free(error);
if (!log_init(options.verbose, options.log_stderr, error)) {
g_warning("%s", error.GetMessage());
return EXIT_FAILURE;
}
@ -415,10 +387,9 @@ int mpd_main(int argc, char *argv[])
const unsigned max_clients = config_get_positive(CONF_MAX_CONN, 10);
instance->client_list = new ClientList(max_clients);
success = listen_global_init(&error);
success = listen_global_init(error);
if (!success) {
g_warning("%s", error->message);
g_error_free(error);
g_warning("%s", error.GetMessage());
return EXIT_FAILURE;
}
@ -432,9 +403,8 @@ int mpd_main(int argc, char *argv[])
Path::GlobalInit();
if (!glue_mapper_init(&error)) {
g_warning("%s", error->message);
g_error_free(error);
if (!glue_mapper_init(error)) {
g_printerr("%s\n", error.GetMessage());
return EXIT_FAILURE;
}
@ -445,9 +415,8 @@ int mpd_main(int argc, char *argv[])
archive_plugin_init_all();
#endif
if (!pcm_resample_global_init(&error)) {
g_warning("%s", error->message);
g_error_free(error);
if (!pcm_resample_global_init(error)) {
g_warning("%s", error.GetMessage());
return EXIT_FAILURE;
}
@ -466,9 +435,8 @@ int mpd_main(int argc, char *argv[])
client_manager_init();
replay_gain_global_init();
if (!input_stream_global_init(&error)) {
g_warning("%s", error->message);
g_error_free(error);
if (!input_stream_global_init(error)) {
g_warning("%s", error.GetMessage());
return EXIT_FAILURE;
}
@ -494,9 +462,8 @@ int mpd_main(int argc, char *argv[])
FatalError("directory update failed");
}
if (!glue_state_file_init(&error)) {
g_warning("%s", error->message);
g_error_free(error);
if (!glue_state_file_init(error)) {
g_printerr("%s\n", error.GetMessage());
return EXIT_FAILURE;
}

View File

@ -25,7 +25,6 @@
#define MPD_MAPPER_HXX
#include "gcc.h"
#include "gerror.h"
#define PLAYLIST_FILE_SUFFIX ".m3u"

View File

@ -25,6 +25,7 @@
#include "OutputAll.hxx"
#include "pcm/PcmVolume.hxx"
#include "OutputInternal.hxx"
#include "util/Error.hxx"
#include <glib.h>
@ -38,7 +39,6 @@ output_mixer_get_volume(unsigned i)
{
struct audio_output *output;
int volume;
GError *error = NULL;
assert(i < audio_output_count());
@ -50,12 +50,11 @@ output_mixer_get_volume(unsigned i)
if (mixer == NULL)
return -1;
volume = mixer_get_volume(mixer, &error);
if (volume < 0 && error != NULL) {
Error error;
volume = mixer_get_volume(mixer, error);
if (volume < 0 && error.IsDefined())
g_warning("Failed to read mixer for '%s': %s",
output->name, error->message);
g_error_free(error);
}
output->name, error.GetMessage());
return volume;
}
@ -85,7 +84,6 @@ output_mixer_set_volume(unsigned i, unsigned volume)
{
struct audio_output *output;
bool success;
GError *error = NULL;
assert(i < audio_output_count());
assert(volume <= 100);
@ -98,12 +96,11 @@ output_mixer_set_volume(unsigned i, unsigned volume)
if (mixer == NULL)
return false;
success = mixer_set_volume(mixer, volume, &error);
if (!success && error != NULL) {
Error error;
success = mixer_set_volume(mixer, volume, error);
if (!success && error.IsDefined())
g_warning("Failed to set mixer for '%s': %s",
output->name, error->message);
g_error_free(error);
}
output->name, error.GetMessage());
return success;
}
@ -138,7 +135,7 @@ output_mixer_get_software_volume(unsigned i)
if (mixer == NULL || !mixer->IsPlugin(software_mixer_plugin))
return -1;
return mixer_get_volume(mixer, NULL);
return mixer_get_volume(mixer, IgnoreError());
}
int
@ -172,6 +169,6 @@ mixer_all_set_software_volume(unsigned volume)
struct audio_output *output = audio_output_get(i);
if (output->mixer != NULL &&
output->mixer->plugin == &software_mixer_plugin)
mixer_set_volume(output->mixer, volume, NULL);
mixer_set_volume(output->mixer, volume, IgnoreError());
}
}

View File

@ -20,8 +20,7 @@
#include "config.h"
#include "MixerControl.hxx"
#include "MixerInternal.hxx"
#include <glib.h>
#include "util/Error.hxx"
#include <assert.h>
#include <stddef.h>
@ -32,13 +31,13 @@
Mixer *
mixer_new(const struct mixer_plugin *plugin, void *ao,
const config_param &param,
GError **error_r)
Error &error)
{
Mixer *mixer;
assert(plugin != NULL);
mixer = plugin->init(ao, param, error_r);
mixer = plugin->init(ao, param, error);
assert(mixer == NULL || mixer->IsPlugin(*plugin));
@ -59,7 +58,7 @@ mixer_free(Mixer *mixer)
}
bool
mixer_open(Mixer *mixer, GError **error_r)
mixer_open(Mixer *mixer, Error &error)
{
bool success;
@ -73,7 +72,7 @@ mixer_open(Mixer *mixer, GError **error_r)
else if (mixer->plugin->open == NULL)
success = mixer->open = true;
else
success = mixer->open = mixer->plugin->open(mixer, error_r);
success = mixer->open = mixer->plugin->open(mixer, error);
mixer->failed = !success;
@ -127,26 +126,22 @@ mixer_failed(Mixer *mixer)
}
int
mixer_get_volume(Mixer *mixer, GError **error_r)
mixer_get_volume(Mixer *mixer, Error &error)
{
int volume;
assert(mixer != NULL);
if (mixer->plugin->global && !mixer->failed &&
!mixer_open(mixer, error_r))
!mixer_open(mixer, error))
return -1;
const ScopeLock protect(mixer->mutex);
if (mixer->open) {
GError *error = NULL;
volume = mixer->plugin->get_volume(mixer, &error);
if (volume < 0 && error != NULL) {
g_propagate_error(error_r, error);
volume = mixer->plugin->get_volume(mixer, error);
if (volume < 0 && error.IsDefined())
mixer_failed(mixer);
}
} else
volume = -1;
@ -154,17 +149,17 @@ mixer_get_volume(Mixer *mixer, GError **error_r)
}
bool
mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r)
mixer_set_volume(Mixer *mixer, unsigned volume, Error &error)
{
assert(mixer != NULL);
assert(volume <= 100);
if (mixer->plugin->global && !mixer->failed &&
!mixer_open(mixer, error_r))
!mixer_open(mixer, error))
return false;
const ScopeLock protect(mixer->mutex);
return mixer->open &&
mixer->plugin->set_volume(mixer, volume, error_r);
mixer->plugin->set_volume(mixer, volume, error);
}

View File

@ -25,8 +25,7 @@
#ifndef MPD_MIXER_CONTROL_HXX
#define MPD_MIXER_CONTROL_HXX
#include "gerror.h"
class Error;
class Mixer;
struct mixer_plugin;
struct config_param;
@ -34,13 +33,13 @@ struct config_param;
Mixer *
mixer_new(const struct mixer_plugin *plugin, void *ao,
const config_param &param,
GError **error_r);
Error &error);
void
mixer_free(Mixer *mixer);
bool
mixer_open(Mixer *mixer, GError **error_r);
mixer_open(Mixer *mixer, Error &error);
void
mixer_close(Mixer *mixer);
@ -53,9 +52,9 @@ void
mixer_auto_close(Mixer *mixer);
int
mixer_get_volume(Mixer *mixer, GError **error_r);
mixer_get_volume(Mixer *mixer, Error &error);
bool
mixer_set_volume(Mixer *mixer, unsigned volume, GError **error_r);
mixer_set_volume(Mixer *mixer, unsigned volume, Error &error);
#endif

View File

@ -27,10 +27,9 @@
#ifndef MPD_MIXER_PLUGIN_HXX
#define MPD_MIXER_PLUGIN_HXX
#include "gerror.h"
struct config_param;
class Mixer;
class Error;
struct mixer_plugin {
/**
@ -43,7 +42,7 @@ struct mixer_plugin {
* @return a mixer object, or NULL on error
*/
Mixer *(*init)(void *ao, const config_param &param,
GError **error_r);
Error &error);
/**
* Finish and free mixer data
@ -57,7 +56,7 @@ struct mixer_plugin {
* NULL to ignore errors
* @return true on success, false on error
*/
bool (*open)(Mixer *data, GError **error_r);
bool (*open)(Mixer *data, Error &error);
/**
* Close mixer device
@ -70,9 +69,9 @@ struct mixer_plugin {
* @param error_r location to store the error occurring, or
* NULL to ignore errors
* @return the current volume (0..100 including) or -1 if
* unavailable or on error (error_r set, mixer will be closed)
* unavailable or on error (error set, mixer will be closed)
*/
int (*get_volume)(Mixer *mixer, GError **error_r);
int (*get_volume)(Mixer *mixer, Error &error);
/**
* Sets the volume.
@ -83,7 +82,7 @@ struct mixer_plugin {
* @return true on success, false on error
*/
bool (*set_volume)(Mixer *mixer, unsigned volume,
GError **error_r);
Error &error);
/**
* If true, then the mixer is automatically opened, even if

View File

@ -34,6 +34,7 @@
#include "ls.hxx"
#include "Volume.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "fs/Path.hxx"
extern "C" {
@ -126,8 +127,8 @@ handle_lsinfo(Client *client, int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
GError *error = NULL;
if (!client_allow_file(client, path_fs, &error))
Error error;
if (!client_allow_file(client, path_fs, error))
return print_error(client, error);
Song *song = Song::LoadFile(path_utf8, nullptr);
@ -147,7 +148,8 @@ handle_lsinfo(Client *client, int argc, char *argv[])
return result;
if (isRootDirectory(uri)) {
const auto &list = ListPlaylistFiles(NULL);
Error error;
const auto &list = ListPlaylistFiles(error);
print_spl_list(client, list);
}

View File

@ -27,6 +27,7 @@
#include "MusicPipe.hxx"
#include "MusicChunk.hxx"
#include "system/FatalError.hxx"
#include "util/Error.hxx"
#include "conf.h"
#include "notify.hxx"
@ -104,7 +105,7 @@ audio_output_all_init(struct player_control *pc)
{
const struct config_param *param = NULL;
unsigned int i;
GError *error = NULL;
Error error;
num_audio_outputs = audio_output_config_count();
audio_outputs = g_new(struct audio_output *, num_audio_outputs);
@ -125,11 +126,12 @@ audio_output_all_init(struct player_control *pc)
param = &empty;
}
struct audio_output *output = audio_output_new(*param, pc, &error);
audio_output *output = audio_output_new(*param, pc, error);
if (output == NULL) {
if (param != NULL)
FormatFatalError("line %i: %s",
param->line, error->message);
param->line,
error.GetMessage());
else
FatalError(error);
}
@ -271,7 +273,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode)
}
bool
audio_output_all_play(struct music_chunk *chunk, GError **error_r)
audio_output_all_play(struct music_chunk *chunk, Error &error)
{
bool ret;
unsigned int i;
@ -284,8 +286,7 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r)
ret = audio_output_all_update();
if (!ret) {
/* TODO: obtain real error */
g_set_error(error_r, output_quark(), 0,
"Failed to open audio output");
error.Set(output_domain, "Failed to open audio output");
return false;
}
@ -300,7 +301,7 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r)
bool
audio_output_all_open(const AudioFormat audio_format,
struct music_buffer *buffer,
GError **error_r)
Error &error)
{
bool ret = false, enabled = false;
unsigned int i;
@ -338,12 +339,10 @@ audio_output_all_open(const AudioFormat audio_format,
}
if (!enabled)
g_set_error(error_r, output_quark(), 0,
"All audio outputs are disabled");
error.Set(output_domain, "All audio outputs are disabled");
else if (!ret)
/* TODO: obtain real error */
g_set_error(error_r, output_quark(), 0,
"Failed to open audio output");
error.Set(output_domain, "Failed to open audio output");
if (!ret)
/* close all devices if there was an error */

View File

@ -27,12 +27,12 @@
#define OUTPUT_ALL_H
#include "replay_gain_info.h"
#include "gerror.h"
struct AudioFormat;
struct music_buffer;
struct music_chunk;
struct player_control;
class Error;
/**
* Global initialization: load audio outputs from the configuration
@ -84,7 +84,7 @@ audio_output_all_enable_disable(void);
bool
audio_output_all_open(AudioFormat audio_format,
struct music_buffer *buffer,
GError **error_r);
Error &error);
/**
* Closes all audio outputs.
@ -111,7 +111,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode);
* (all closed then)
*/
bool
audio_output_all_play(struct music_chunk *chunk, GError **error_r);
audio_output_all_play(struct music_chunk *chunk, Error &error);
/**
* Checks if the output devices have drained their music pipe, and

View File

@ -27,6 +27,7 @@
#include "notify.hxx"
#include "filter/ReplayGainFilterPlugin.hxx"
#include "FilterPlugin.hxx"
#include "util/Error.hxx"
#include <assert.h>
#include <stdlib.h>
@ -187,13 +188,10 @@ audio_output_open(struct audio_output *ao,
open = ao->open;
if (open && ao->mixer != NULL) {
GError *error = NULL;
if (!mixer_open(ao->mixer, &error)) {
Error error;
if (!mixer_open(ao->mixer, error))
g_warning("Failed to open mixer for '%s': %s",
ao->name, error->message);
g_error_free(error);
}
ao->name, error.GetMessage());
}
return open;

23
src/OutputError.cxx Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "OutputError.hxx"
#include "util/Domain.hxx"
const Domain output_domain("output");

View File

@ -20,18 +20,6 @@
#ifndef MPD_OUTPUT_ERROR_HXX
#define MPD_OUTPUT_ERROR_HXX
#include "gcc.h"
#include <glib.h>
/**
* Quark for GError.domain.
*/
gcc_const
static inline GQuark
output_quark(void)
{
return g_quark_from_static_string("output");
}
extern const class Domain output_domain;
#endif

View File

@ -34,6 +34,8 @@
#include "filter/AutoConvertFilterPlugin.hxx"
#include "filter/ReplayGainFilterPlugin.hxx"
#include "filter/ChainFilterPlugin.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include <glib.h>
@ -49,7 +51,7 @@
#define AUDIO_FILTERS "filters"
static const struct audio_output_plugin *
audio_output_detect(GError **error)
audio_output_detect(Error &error)
{
g_warning("Attempt to detect audio output device");
@ -63,8 +65,7 @@ audio_output_detect(GError **error)
return plugin;
}
g_set_error(error, output_quark(), 0,
"Unable to detect an audio device");
error.Set(output_domain, "Unable to detect an audio device");
return NULL;
}
@ -99,7 +100,7 @@ audio_output_load_mixer(struct audio_output *ao,
const config_param &param,
const struct mixer_plugin *plugin,
Filter &filter_chain,
GError **error_r)
Error &error)
{
Mixer *mixer;
@ -112,12 +113,12 @@ audio_output_load_mixer(struct audio_output *ao,
if (plugin == NULL)
return NULL;
return mixer_new(plugin, ao, param, error_r);
return mixer_new(plugin, ao, param, error);
case MIXER_TYPE_SOFTWARE:
mixer = mixer_new(&software_mixer_plugin, nullptr,
config_param(),
nullptr);
IgnoreError());
assert(mixer != NULL);
filter_chain_append(filter_chain, "software_mixer",
@ -132,7 +133,7 @@ audio_output_load_mixer(struct audio_output *ao,
bool
ao_base_init(struct audio_output *ao,
const struct audio_output_plugin *plugin,
const config_param &param, GError **error_r)
const config_param &param, Error &error)
{
assert(ao != NULL);
assert(plugin != NULL);
@ -141,13 +142,11 @@ ao_base_init(struct audio_output *ao,
assert(plugin->close != NULL);
assert(plugin->play != NULL);
GError *error = NULL;
if (!param.IsNull()) {
ao->name = param.GetBlockValue(AUDIO_OUTPUT_NAME);
if (ao->name == NULL) {
g_set_error(error_r, output_quark(), 0,
"Missing \"name\" configuration");
error.Set(config_domain,
"Missing \"name\" configuration");
return false;
}
@ -155,7 +154,7 @@ ao_base_init(struct audio_output *ao,
if (p != NULL) {
bool success =
audio_format_parse(ao->config_audio_format,
p, true, error_r);
p, true, error);
if (!success)
return false;
} else
@ -186,25 +185,23 @@ ao_base_init(struct audio_output *ao,
if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) {
Filter *normalize_filter =
filter_new(&normalize_filter_plugin, config_param(),
nullptr);
IgnoreError());
assert(normalize_filter != NULL);
filter_chain_append(*ao->filter, "normalize",
autoconvert_filter_new(normalize_filter));
}
Error filter_error;
filter_chain_parse(*ao->filter,
param.GetBlockValue(AUDIO_FILTERS, ""),
&error
);
filter_error);
// It's not really fatal - Part of the filter chain has been set up already
// and even an empty one will work (if only with unexpected behaviour)
if (error != NULL) {
if (filter_error.IsDefined())
g_warning("Failed to initialize filter chain for '%s': %s",
ao->name, error->message);
g_error_free(error);
}
ao->name, filter_error.GetMessage());
ao->thread = NULL;
ao->command = AO_COMMAND_NONE;
@ -220,7 +217,7 @@ ao_base_init(struct audio_output *ao,
static bool
audio_output_setup(struct audio_output *ao, const config_param &param,
GError **error_r)
Error &error)
{
/* create the replay_gain filter */
@ -230,13 +227,14 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
if (strcmp(replay_gain_handler, "none") != 0) {
ao->replay_gain_filter = filter_new(&replay_gain_filter_plugin,
param, NULL);
param, IgnoreError());
assert(ao->replay_gain_filter != NULL);
ao->replay_gain_serial = 0;
ao->other_replay_gain_filter = filter_new(&replay_gain_filter_plugin,
param, NULL);
param,
IgnoreError());
assert(ao->other_replay_gain_filter != NULL);
ao->other_replay_gain_serial = 0;
@ -247,15 +245,13 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
/* set up the mixer */
GError *error = NULL;
Error mixer_error;
ao->mixer = audio_output_load_mixer(ao, param,
ao->plugin->mixer_plugin,
*ao->filter, &error);
if (ao->mixer == NULL && error != NULL) {
*ao->filter, mixer_error);
if (ao->mixer == NULL && mixer_error.IsDefined())
g_warning("Failed to initialize hardware mixer for '%s': %s",
ao->name, error->message);
g_error_free(error);
}
ao->name, mixer_error.GetMessage());
/* use the hardware mixer for replay gain? */
@ -267,15 +263,15 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
g_warning("No such mixer for output '%s'", ao->name);
} else if (strcmp(replay_gain_handler, "software") != 0 &&
ao->replay_gain_filter != NULL) {
g_set_error(error_r, output_quark(), 0,
"Invalid \"replay_gain_handler\" value");
error.Set(config_domain,
"Invalid \"replay_gain_handler\" value");
return false;
}
/* the "convert" filter must be the last one in the chain */
ao->convert_filter = filter_new(&convert_filter_plugin, config_param(),
nullptr);
IgnoreError());
assert(ao->convert_filter != NULL);
filter_chain_append(*ao->filter, "convert", ao->convert_filter);
@ -286,7 +282,7 @@ audio_output_setup(struct audio_output *ao, const config_param &param,
struct audio_output *
audio_output_new(const config_param &param,
struct player_control *pc,
GError **error_r)
Error &error)
{
const struct audio_output_plugin *plugin;
@ -295,21 +291,21 @@ audio_output_new(const config_param &param,
p = param.GetBlockValue(AUDIO_OUTPUT_TYPE);
if (p == NULL) {
g_set_error(error_r, output_quark(), 0,
"Missing \"type\" configuration");
error.Set(config_domain,
"Missing \"type\" configuration");
return nullptr;
}
plugin = audio_output_plugin_get(p);
if (plugin == NULL) {
g_set_error(error_r, output_quark(), 0,
"No such audio output plugin: %s", p);
error.Format(config_domain,
"No such audio output plugin: %s", p);
return nullptr;
}
} else {
g_warning("No 'audio_output' defined in config file\n");
plugin = audio_output_detect(error_r);
plugin = audio_output_detect(error);
if (plugin == NULL)
return nullptr;
@ -317,11 +313,11 @@ audio_output_new(const config_param &param,
plugin->name);
}
struct audio_output *ao = ao_plugin_init(plugin, param, error_r);
struct audio_output *ao = ao_plugin_init(plugin, param, error);
if (ao == NULL)
return NULL;
if (!audio_output_setup(ao, param, error_r)) {
if (!audio_output_setup(ao, param, error)) {
ao_plugin_finish(ao);
return NULL;
}

View File

@ -29,6 +29,7 @@
#include <time.h>
class Error;
class Filter;
struct config_param;
@ -263,12 +264,12 @@ audio_output_command_is_finished(const struct audio_output *ao)
struct audio_output *
audio_output_new(const config_param &param,
struct player_control *pc,
GError **error_r);
Error &error);
bool
ao_base_init(struct audio_output *ao,
const struct audio_output_plugin *plugin,
const config_param &param, GError **error_r);
const config_param &param, Error &error);
void
ao_base_finish(struct audio_output *ao);

View File

@ -24,7 +24,7 @@
struct audio_output *
ao_plugin_init(const struct audio_output_plugin *plugin,
const config_param &param,
GError **error)
Error &error)
{
assert(plugin != NULL);
assert(plugin->init != NULL);
@ -39,7 +39,7 @@ ao_plugin_finish(struct audio_output *ao)
}
bool
ao_plugin_enable(struct audio_output *ao, GError **error_r)
ao_plugin_enable(struct audio_output *ao, Error &error_r)
{
return ao->plugin->enable != NULL
? ao->plugin->enable(ao, error_r)
@ -55,7 +55,7 @@ ao_plugin_disable(struct audio_output *ao)
bool
ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error)
Error &error)
{
return ao->plugin->open(ao, audio_format, error);
}
@ -83,7 +83,7 @@ ao_plugin_send_tag(struct audio_output *ao, const Tag *tag)
size_t
ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
Error &error)
{
return ao->plugin->play(ao, chunk, size, error);
}

View File

@ -21,13 +21,13 @@
#define MPD_OUTPUT_PLUGIN_HXX
#include "gcc.h"
#include "gerror.h"
#include <stddef.h>
struct config_param;
struct AudioFormat;
struct Tag;
class Error;
/**
* A plugin which controls an audio output device.
@ -56,7 +56,7 @@ struct audio_output_plugin {
* data
*/
struct audio_output *(*init)(const config_param &param,
GError **error);
Error &error);
/**
* Free resources allocated by this device.
@ -73,7 +73,7 @@ struct audio_output_plugin {
* NULL to ignore errors
* @return true on success, false on error
*/
bool (*enable)(struct audio_output *data, GError **error_r);
bool (*enable)(struct audio_output *data, Error &error);
/**
* Disables the device. It is closed before this method is
@ -90,7 +90,7 @@ struct audio_output_plugin {
* to ignore errors
*/
bool (*open)(struct audio_output *data, AudioFormat &audio_format,
GError **error);
Error &error);
/**
* Close the device.
@ -122,7 +122,7 @@ struct audio_output_plugin {
*/
size_t (*play)(struct audio_output *data,
const void *chunk, size_t size,
GError **error);
Error &error);
/**
* Wait until the device has finished playing.
@ -169,20 +169,20 @@ gcc_malloc
struct audio_output *
ao_plugin_init(const struct audio_output_plugin *plugin,
const config_param &param,
GError **error);
Error &error);
void
ao_plugin_finish(struct audio_output *ao);
bool
ao_plugin_enable(struct audio_output *ao, GError **error_r);
ao_plugin_enable(struct audio_output *ao, Error &error);
void
ao_plugin_disable(struct audio_output *ao);
bool
ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error);
Error &error);
void
ao_plugin_close(struct audio_output *ao);
@ -196,7 +196,7 @@ ao_plugin_send_tag(struct audio_output *ao, const Tag *tag);
size_t
ao_plugin_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error);
Error &error);
void
ao_plugin_drain(struct audio_output *ao);

View File

@ -30,6 +30,7 @@
#include "MusicPipe.hxx"
#include "MusicChunk.hxx"
#include "system/FatalError.hxx"
#include "util/Error.hxx"
#include "gcc.h"
#include <glib.h>
@ -55,19 +56,18 @@ static void ao_command_finished(struct audio_output *ao)
static bool
ao_enable(struct audio_output *ao)
{
GError *error = NULL;
Error error;
bool success;
if (ao->really_enabled)
return true;
ao->mutex.unlock();
success = ao_plugin_enable(ao, &error);
success = ao_plugin_enable(ao, error);
ao->mutex.lock();
if (!success) {
g_warning("Failed to enable \"%s\" [%s]: %s\n",
ao->name, ao->plugin->name, error->message);
g_error_free(error);
ao->name, ao->plugin->name, error.GetMessage());
return false;
}
@ -95,7 +95,7 @@ ao_disable(struct audio_output *ao)
static AudioFormat
ao_filter_open(struct audio_output *ao, AudioFormat &format,
GError **error_r)
Error &error_r)
{
assert(format.IsValid());
@ -131,7 +131,7 @@ static void
ao_open(struct audio_output *ao)
{
bool success;
GError *error = NULL;
Error error;
struct audio_format_string af_string;
assert(!ao->open);
@ -157,11 +157,10 @@ ao_open(struct audio_output *ao)
/* open the filter */
const AudioFormat filter_audio_format =
ao_filter_open(ao, ao->in_audio_format, &error);
ao_filter_open(ao, ao->in_audio_format, error);
if (!filter_audio_format.IsDefined()) {
g_warning("Failed to open filter for \"%s\" [%s]: %s",
ao->name, ao->plugin->name, error->message);
g_error_free(error);
ao->name, ao->plugin->name, error.GetMessage());
ao->fail_timer = g_timer_new();
return;
@ -173,15 +172,14 @@ ao_open(struct audio_output *ao)
ao->out_audio_format.ApplyMask(ao->config_audio_format);
ao->mutex.unlock();
success = ao_plugin_open(ao, ao->out_audio_format, &error);
success = ao_plugin_open(ao, ao->out_audio_format, error);
ao->mutex.lock();
assert(!ao->open);
if (!success) {
g_warning("Failed to open \"%s\" [%s]: %s",
ao->name, ao->plugin->name, error->message);
g_error_free(error);
ao->name, ao->plugin->name, error.GetMessage());
ao_filter_close(ao);
ao->fail_timer = g_timer_new();
@ -231,15 +229,14 @@ ao_close(struct audio_output *ao, bool drain)
static void
ao_reopen_filter(struct audio_output *ao)
{
GError *error = NULL;
Error error;
ao_filter_close(ao);
const AudioFormat filter_audio_format =
ao_filter_open(ao, ao->in_audio_format, &error);
ao_filter_open(ao, ao->in_audio_format, error);
if (!filter_audio_format.IsDefined()) {
g_warning("Failed to open filter for \"%s\" [%s]: %s",
ao->name, ao->plugin->name, error->message);
g_error_free(error);
ao->name, ao->plugin->name, error.GetMessage());
/* this is a little code duplication fro ao_close(),
but we cannot call this function because we must
@ -333,13 +330,12 @@ ao_chunk_data(struct audio_output *ao, const struct music_chunk *chunk,
*replay_gain_serial_p = chunk->replay_gain_serial;
}
GError *error = NULL;
Error error;
data = replay_gain_filter->FilterPCM(data, length,
&length, &error);
&length, error);
if (data == NULL) {
g_warning("\"%s\" [%s] failed to filter: %s",
ao->name, ao->plugin->name, error->message);
g_error_free(error);
ao->name, ao->plugin->name, error.GetMessage());
return NULL;
}
}
@ -352,8 +348,6 @@ static const void *
ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
size_t *length_r)
{
GError *error = NULL;
size_t length;
const void *data = ao_chunk_data(ao, chunk, ao->replay_gain_filter,
&ao->replay_gain_serial, &length);
@ -407,11 +401,11 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
/* apply filter chain */
data = ao->filter->FilterPCM(data, length, &length, &error);
Error error;
data = ao->filter->FilterPCM(data, length, &length, error);
if (data == NULL) {
g_warning("\"%s\" [%s] failed to filter: %s",
ao->name, ao->plugin->name, error->message);
g_error_free(error);
ao->name, ao->plugin->name, error.GetMessage());
return NULL;
}
@ -422,8 +416,6 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
static bool
ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
{
GError *error = NULL;
assert(ao != NULL);
assert(ao->filter != NULL);
@ -448,6 +440,8 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
return false;
}
Error error;
while (size > 0 && ao->command == AO_COMMAND_NONE) {
size_t nbytes;
@ -455,13 +449,13 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
break;
ao->mutex.unlock();
nbytes = ao_plugin_play(ao, data, size, &error);
nbytes = ao_plugin_play(ao, data, size, error);
ao->mutex.lock();
if (nbytes == 0) {
/* play()==0 means failure */
g_warning("\"%s\" [%s] failed to play: %s",
ao->name, ao->plugin->name, error->message);
g_error_free(error);
ao->name, ao->plugin->name,
error.GetMessage());
ao_close(ao, false);

View File

@ -40,7 +40,6 @@ player_control::player_control(unsigned _buffer_chunks,
command(PLAYER_COMMAND_NONE),
state(PLAYER_STATE_STOP),
error_type(PLAYER_ERROR_NONE),
error(nullptr),
next_song(nullptr),
cross_fade_seconds(0),
mixramp_db(0),
@ -216,16 +215,13 @@ player_control::GetStatus()
}
void
player_control::SetError(player_error type, GError *_error)
player_control::SetError(player_error type, Error &&_error)
{
assert(type != PLAYER_ERROR_NONE);
assert(_error != NULL);
if (error_type != PLAYER_ERROR_NONE)
g_error_free(error);
assert(_error.IsDefined());
error_type = type;
error = _error;
error = std::move(_error);
}
void
@ -235,7 +231,7 @@ player_control::ClearError()
if (error_type != PLAYER_ERROR_NONE) {
error_type = PLAYER_ERROR_NONE;
g_error_free(error);
error.Clear();
}
Unlock();
@ -246,7 +242,7 @@ player_control::GetErrorMessage() const
{
Lock();
char *message = error_type != PLAYER_ERROR_NONE
? g_strdup(error->message)
? g_strdup(error.GetMessage())
: NULL;
Unlock();
return message;

View File

@ -23,6 +23,7 @@
#include "AudioFormat.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "util/Error.hxx"
#include <glib.h>
@ -127,7 +128,7 @@ struct player_control {
* #PLAYER_ERROR_NONE. The object must be freed when this
* object transitions back to #PLAYER_ERROR_NONE.
*/
GError *error;
Error error;
uint16_t bit_rate;
AudioFormat audio_format;
@ -262,10 +263,9 @@ struct player_control {
* Caller must lock the object.
*
* @param type the error type; must not be #PLAYER_ERROR_NONE
* @param error detailed error information; must not be NULL; the
* #player_control takes over ownership of this #GError instance
* @param error detailed error information; must be defined.
*/
void SetError(player_error type, GError *error);
void SetError(player_error type, Error &&error);
void ClearError();

View File

@ -251,10 +251,10 @@ player_wait_for_decoder(struct player *player)
player->queued = false;
GError *error = dc->LockGetError();
if (error != NULL) {
Error error = dc->LockGetError();
if (error.IsDefined()) {
pc->Lock();
pc->SetError(PLAYER_ERROR_DECODER, error);
pc->SetError(PLAYER_ERROR_DECODER, std::move(error));
pc->next_song->Free();
pc->next_song = NULL;
@ -327,9 +327,9 @@ player_open_output(struct player *player)
assert(pc->state == PLAYER_STATE_PLAY ||
pc->state == PLAYER_STATE_PAUSE);
GError *error = NULL;
Error error;
if (audio_output_all_open(player->play_audio_format, player_buffer,
&error)) {
error)) {
player->output_open = true;
player->paused = false;
@ -341,7 +341,7 @@ player_open_output(struct player *player)
return true;
} else {
g_warning("%s", error->message);
g_warning("%s", error.GetMessage());
player->output_open = false;
@ -350,7 +350,7 @@ player_open_output(struct player *player)
player->paused = true;
pc->Lock();
pc->SetError(PLAYER_ERROR_OUTPUT, error);
pc->SetError(PLAYER_ERROR_OUTPUT, std::move(error));
pc->state = PLAYER_STATE_PAUSE;
pc->Unlock();
@ -377,13 +377,13 @@ player_check_decoder_startup(struct player *player)
dc->Lock();
GError *error = dc->GetError();
if (error != NULL) {
Error error = dc->GetError();
if (error.IsDefined()) {
/* the decoder failed */
dc->Unlock();
pc->Lock();
pc->SetError(PLAYER_ERROR_DECODER, error);
pc->SetError(PLAYER_ERROR_DECODER, std::move(error));
pc->Unlock();
return false;
@ -460,11 +460,9 @@ player_send_silence(struct player *player)
chunk->length = num_frames * frame_size;
memset(chunk->data, 0, chunk->length);
GError *error = NULL;
if (!audio_output_all_play(chunk, &error)) {
g_warning("%s", error->message);
g_error_free(error);
Error error;
if (!audio_output_all_play(chunk, error)) {
g_warning("%s", error.GetMessage());
music_buffer_return(player_buffer, chunk);
return false;
}
@ -689,7 +687,7 @@ static bool
play_chunk(struct player_control *pc,
Song *song, struct music_chunk *chunk,
const AudioFormat format,
GError **error_r)
Error &error)
{
assert(chunk->CheckFormat(format));
@ -707,7 +705,7 @@ play_chunk(struct player_control *pc,
/* send the chunk to the audio outputs */
if (!audio_output_all_play(chunk, error_r))
if (!audio_output_all_play(chunk, error))
return false;
pc->total_play_time += (double)chunk->length /
@ -822,16 +820,16 @@ play_next_chunk(struct player *player)
/* play the current chunk */
GError *error = NULL;
Error error;
if (!play_chunk(player->pc, player->song, chunk,
player->play_audio_format, &error)) {
g_warning("%s", error->message);
player->play_audio_format, error)) {
g_warning("%s", error.GetMessage());
music_buffer_return(player_buffer, chunk);
pc->Lock();
pc->SetError(PLAYER_ERROR_OUTPUT, error);
pc->SetError(PLAYER_ERROR_OUTPUT, std::move(error));
/* pause: the user may resume playback as soon as an
audio output becomes available */

View File

@ -22,6 +22,7 @@
#include "PlaylistMapper.hxx"
#include "PlaylistRegistry.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "InputLegacy.hxx"
#include <assert.h>
@ -39,14 +40,12 @@ playlist_open_remote(const char *uri, Mutex &mutex, Cond &cond,
return playlist;
}
GError *error = NULL;
struct input_stream *is = input_stream_open(uri, mutex, cond, &error);
Error error;
input_stream *is = input_stream_open(uri, mutex, cond, error);
if (is == NULL) {
if (error != NULL) {
if (error.IsDefined())
g_warning("Failed to open %s: %s",
uri, error->message);
g_error_free(error);
}
uri, error.GetMessage());
return NULL;
}

View File

@ -33,6 +33,7 @@
#include "ls.hxx"
#include "Playlist.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include <assert.h>
#include <stdlib.h>
@ -64,7 +65,7 @@ handle_load(Client *client, int argc, char *argv[])
if (argc < 3) {
start_index = 0;
end_index = G_MAXUINT;
end_index = unsigned(-1);
} else if (!check_range(client, &start_index, &end_index, argv[2]))
return COMMAND_RETURN_ERROR;
@ -77,19 +78,22 @@ handle_load(Client *client, int argc, char *argv[])
if (result != PLAYLIST_RESULT_NO_SUCH_LIST)
return print_playlist_result(client, result);
GError *error = NULL;
Error error;
if (playlist_load_spl(&client->playlist, client->player_control,
argv[1], start_index, end_index,
&error))
error))
return COMMAND_RETURN_OK;
if (error->domain == playlist_quark() &&
error->code == PLAYLIST_RESULT_BAD_NAME)
if (error.IsDomain(playlist_domain) &&
error.GetCode() == PLAYLIST_RESULT_BAD_NAME) {
/* the message for BAD_NAME is confusing when the
client wants to load a playlist file from the music
directory; patch the GError object to show "no such
directory; patch the Error object to show "no such
playlist" instead */
error->code = PLAYLIST_RESULT_NO_SUCH_LIST;
Error error2(playlist_domain, PLAYLIST_RESULT_NO_SUCH_LIST,
error.GetMessage());
error = std::move(error2);
}
return print_error(client, error);
}
@ -100,8 +104,8 @@ handle_listplaylist(Client *client, gcc_unused int argc, char *argv[])
if (playlist_file_print(client, argv[1], false))
return COMMAND_RETURN_OK;
GError *error = NULL;
return spl_print(client, argv[1], false, &error)
Error error;
return spl_print(client, argv[1], false, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -113,8 +117,8 @@ handle_listplaylistinfo(Client *client,
if (playlist_file_print(client, argv[1], true))
return COMMAND_RETURN_OK;
GError *error = NULL;
return spl_print(client, argv[1], true, &error)
Error error;
return spl_print(client, argv[1], true, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -122,8 +126,8 @@ handle_listplaylistinfo(Client *client,
enum command_return
handle_rm(Client *client, gcc_unused int argc, char *argv[])
{
GError *error = NULL;
return spl_delete(argv[1], &error)
Error error;
return spl_delete(argv[1], error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -131,8 +135,8 @@ handle_rm(Client *client, gcc_unused int argc, char *argv[])
enum command_return
handle_rename(Client *client, gcc_unused int argc, char *argv[])
{
GError *error = NULL;
return spl_rename(argv[1], argv[2], &error)
Error error;
return spl_rename(argv[1], argv[2], error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -146,8 +150,8 @@ handle_playlistdelete(Client *client,
if (!check_unsigned(client, &from, argv[2]))
return COMMAND_RETURN_ERROR;
GError *error = NULL;
return spl_remove_index(playlist, from, &error)
Error error;
return spl_remove_index(playlist, from, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -163,8 +167,8 @@ handle_playlistmove(Client *client, gcc_unused int argc, char *argv[])
if (!check_unsigned(client, &to, argv[3]))
return COMMAND_RETURN_ERROR;
GError *error = NULL;
return spl_move_index(playlist, from, to, &error)
Error error;
return spl_move_index(playlist, from, to, error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -172,8 +176,8 @@ handle_playlistmove(Client *client, gcc_unused int argc, char *argv[])
enum command_return
handle_playlistclear(Client *client, gcc_unused int argc, char *argv[])
{
GError *error = NULL;
return spl_clear(argv[1], &error)
Error error;
return spl_clear(argv[1], error)
? COMMAND_RETURN_OK
: print_error(client, error);
}
@ -185,7 +189,7 @@ handle_playlistadd(Client *client, gcc_unused int argc, char *argv[])
char *uri = argv[2];
bool success;
GError *error = NULL;
Error error;
if (uri_has_scheme(uri)) {
if (!uri_supported_scheme(uri)) {
command_error(client, ACK_ERROR_NO_EXIST,
@ -193,12 +197,12 @@ handle_playlistadd(Client *client, gcc_unused int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
success = spl_append_uri(uri, playlist, &error);
success = spl_append_uri(uri, playlist, error);
} else
success = search_add_to_playlist(uri, playlist, nullptr,
&error);
error);
if (!success && error == NULL) {
if (!success && !error.IsDefined()) {
command_error(client, ACK_ERROR_NO_EXIST,
"directory or file not found");
return COMMAND_RETURN_ERROR;
@ -211,9 +215,9 @@ enum command_return
handle_listplaylists(Client *client,
gcc_unused int argc, gcc_unused char *argv[])
{
GError *error = NULL;
const auto list = ListPlaylistFiles(&error);
if (list.empty() && error != NULL)
Error error;
const auto list = ListPlaylistFiles(error);
if (list.empty() && error.IsDefined())
return print_error(client, error);
print_spl_list(client, list);

View File

@ -22,15 +22,13 @@
#include "PlaylistVector.hxx"
#include "TextFile.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <string.h>
#include <stdlib.h>
static GQuark
playlist_database_quark(void)
{
return g_quark_from_static_string("playlist_database");
}
static constexpr Domain playlist_database_domain("playlist_database");
void
playlist_vector_save(FILE *fp, const PlaylistVector &pv)
@ -44,7 +42,7 @@ playlist_vector_save(FILE *fp, const PlaylistVector &pv)
bool
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
GError **error_r)
Error &error)
{
PlaylistInfo pm(name, 0);
@ -55,8 +53,8 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
strcmp(line, "playlist_end") != 0) {
colon = strchr(line, ':');
if (colon == NULL || colon == line) {
g_set_error(error_r, playlist_database_quark(), 0,
"unknown line in db: %s", line);
error.Format(playlist_database_domain,
"unknown line in db: %s", line);
return false;
}
@ -66,8 +64,8 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
if (strcmp(line, "mtime") == 0)
pm.mtime = strtol(value, NULL, 10);
else {
g_set_error(error_r, playlist_database_quark(), 0,
"unknown line in db: %s", line);
error.Format(playlist_database_domain,
"unknown line in db: %s", line);
return false;
}
}

View File

@ -21,7 +21,6 @@
#define MPD_PLAYLIST_DATABASE_HXX
#include "check.h"
#include "gerror.h"
#include <stdio.h>
@ -29,12 +28,13 @@
class PlaylistVector;
class TextFile;
class Error;
void
playlist_vector_save(FILE *fp, const PlaylistVector &pv);
bool
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
GError **error_r);
Error &error);
#endif

View File

@ -27,6 +27,7 @@
#include "Playlist.hxx"
#include "PlayerControl.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "Song.hxx"
#include "Idle.hxx"
#include "DatabaseGlue.hxx"
@ -110,11 +111,11 @@ playlist::AppendURI(struct player_control &pc,
if (uri_has_scheme(uri)) {
song = Song::NewRemote(uri);
} else {
db = GetDatabase(nullptr);
db = GetDatabase(IgnoreError());
if (db == nullptr)
return PLAYLIST_RESULT_NO_SUCH_SONG;
song = db->GetSong(uri, nullptr);
song = db->GetSong(uri, IgnoreError());
if (song == nullptr)
return PLAYLIST_RESULT_NO_SUCH_SONG;
}

Some files were not shown because too many files have changed in this diff Show More