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