db/simple/Save: migrate from class Error to C++ exceptions
This commit is contained in:
parent
dea46e8d5a
commit
90a14e14f4
@ -23,14 +23,11 @@
|
|||||||
#include "fs/io/TextFile.hxx"
|
#include "fs/io/TextFile.hxx"
|
||||||
#include "fs/io/BufferedOutputStream.hxx"
|
#include "fs/io/BufferedOutputStream.hxx"
|
||||||
#include "util/StringUtil.hxx"
|
#include "util/StringUtil.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Domain.hxx"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static constexpr Domain playlist_database_domain("playlist_database");
|
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv)
|
playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv)
|
||||||
{
|
{
|
||||||
@ -41,9 +38,8 @@ playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv)
|
|||||||
pi.name.c_str(), (long)pi.mtime);
|
pi.name.c_str(), (long)pi.mtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
|
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
PlaylistInfo pm(name, 0);
|
PlaylistInfo pm(name, 0);
|
||||||
|
|
||||||
@ -53,24 +49,19 @@ playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
|
|||||||
while ((line = file.ReadLine()) != nullptr &&
|
while ((line = file.ReadLine()) != nullptr &&
|
||||||
strcmp(line, "playlist_end") != 0) {
|
strcmp(line, "playlist_end") != 0) {
|
||||||
colon = strchr(line, ':');
|
colon = strchr(line, ':');
|
||||||
if (colon == nullptr || colon == line) {
|
if (colon == nullptr || colon == line)
|
||||||
error.Format(playlist_database_domain,
|
throw FormatRuntimeError("unknown line in db: %s",
|
||||||
"unknown line in db: %s", line);
|
line);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*colon++ = 0;
|
*colon++ = 0;
|
||||||
value = StripLeft(colon);
|
value = StripLeft(colon);
|
||||||
|
|
||||||
if (strcmp(line, "mtime") == 0)
|
if (strcmp(line, "mtime") == 0)
|
||||||
pm.mtime = strtol(value, nullptr, 10);
|
pm.mtime = strtol(value, nullptr, 10);
|
||||||
else {
|
else
|
||||||
error.Format(playlist_database_domain,
|
throw FormatRuntimeError("unknown line in db: %s",
|
||||||
"unknown line in db: %s", line);
|
line);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pv.UpdateOrInsert(std::move(pm));
|
pv.UpdateOrInsert(std::move(pm));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,10 @@ class Error;
|
|||||||
void
|
void
|
||||||
playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv);
|
playlist_vector_save(BufferedOutputStream &os, const PlaylistVector &pv);
|
||||||
|
|
||||||
bool
|
/**
|
||||||
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name,
|
* Throws #std::runtime_error on error.
|
||||||
Error &error);
|
*/
|
||||||
|
void
|
||||||
|
playlist_metadata_load(TextFile &file, PlaylistVector &pv, const char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,8 +27,7 @@
|
|||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "tag/TagBuilder.hxx"
|
#include "tag/TagBuilder.hxx"
|
||||||
#include "util/StringUtil.hxx"
|
#include "util/StringUtil.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Domain.hxx"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -36,8 +35,6 @@
|
|||||||
#define SONG_MTIME "mtime"
|
#define SONG_MTIME "mtime"
|
||||||
#define SONG_END "song_end"
|
#define SONG_END "song_end"
|
||||||
|
|
||||||
static constexpr Domain song_save_domain("song_save");
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
range_save(BufferedOutputStream &os, unsigned start_ms, unsigned end_ms)
|
range_save(BufferedOutputStream &os, unsigned start_ms, unsigned end_ms)
|
||||||
{
|
{
|
||||||
@ -74,8 +71,7 @@ song_save(BufferedOutputStream &os, const DetachedSong &song)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DetachedSong *
|
DetachedSong *
|
||||||
song_load(TextFile &file, const char *uri,
|
song_load(TextFile &file, const char *uri)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
DetachedSong *song = new DetachedSong(uri);
|
DetachedSong *song = new DetachedSong(uri);
|
||||||
|
|
||||||
@ -88,9 +84,7 @@ song_load(TextFile &file, const char *uri,
|
|||||||
if (colon == nullptr || colon == line) {
|
if (colon == nullptr || colon == line) {
|
||||||
delete song;
|
delete song;
|
||||||
|
|
||||||
error.Format(song_save_domain,
|
throw FormatRuntimeError("unknown line in db: %s", line);
|
||||||
"unknown line in db: %s", line);
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*colon++ = 0;
|
*colon++ = 0;
|
||||||
@ -118,9 +112,7 @@ song_load(TextFile &file, const char *uri,
|
|||||||
} else {
|
} else {
|
||||||
delete song;
|
delete song;
|
||||||
|
|
||||||
error.Format(song_save_domain,
|
throw FormatRuntimeError("unknown line in db: %s", line);
|
||||||
"unknown line in db: %s", line);
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,11 +38,9 @@ song_save(BufferedOutputStream &os, const DetachedSong &song);
|
|||||||
* Loads a song from the input file. Reading stops after the
|
* Loads a song from the input file. Reading stops after the
|
||||||
* "song_end" line.
|
* "song_end" line.
|
||||||
*
|
*
|
||||||
* @param error location to store the error occurring
|
* Throws #std::runtime_error on error.
|
||||||
* @return true on success, false on error
|
|
||||||
*/
|
*/
|
||||||
DetachedSong *
|
DetachedSong *
|
||||||
song_load(TextFile &file, const char *uri,
|
song_load(TextFile &file, const char *uri);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "tag/Settings.hxx"
|
#include "tag/Settings.hxx"
|
||||||
#include "fs/Charset.hxx"
|
#include "fs/Charset.hxx"
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -66,8 +66,8 @@ db_save_internal(BufferedOutputStream &os, const Directory &music_root)
|
|||||||
directory_save(os, music_root);
|
directory_save(os, music_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
db_load_internal(TextFile &file, Directory &music_root, Error &error)
|
db_load_internal(TextFile &file, Directory &music_root)
|
||||||
{
|
{
|
||||||
char *line;
|
char *line;
|
||||||
unsigned format = 0;
|
unsigned format = 0;
|
||||||
@ -76,10 +76,8 @@ db_load_internal(TextFile &file, Directory &music_root, Error &error)
|
|||||||
|
|
||||||
/* get initial info */
|
/* get initial info */
|
||||||
line = file.ReadLine();
|
line = file.ReadLine();
|
||||||
if (line == nullptr || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) {
|
if (line == nullptr || strcmp(DIRECTORY_INFO_BEGIN, line) != 0)
|
||||||
error.Set(db_domain, "Database corrupted");
|
throw std::runtime_error("Database corrupted");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(tags, false, sizeof(tags));
|
memset(tags, false, sizeof(tags));
|
||||||
|
|
||||||
@ -90,67 +88,49 @@ db_load_internal(TextFile &file, Directory &music_root, Error &error)
|
|||||||
if ((p = StringAfterPrefix(line, DB_FORMAT_PREFIX))) {
|
if ((p = StringAfterPrefix(line, DB_FORMAT_PREFIX))) {
|
||||||
format = atoi(p);
|
format = atoi(p);
|
||||||
} else if (StringStartsWith(line, DIRECTORY_MPD_VERSION)) {
|
} else if (StringStartsWith(line, DIRECTORY_MPD_VERSION)) {
|
||||||
if (found_version) {
|
if (found_version)
|
||||||
error.Set(db_domain, "Duplicate version line");
|
throw std::runtime_error("Duplicate version line");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
found_version = true;
|
found_version = true;
|
||||||
} else if ((p = StringAfterPrefix(line, DIRECTORY_FS_CHARSET))) {
|
} else if ((p = StringAfterPrefix(line, DIRECTORY_FS_CHARSET))) {
|
||||||
if (found_charset) {
|
if (found_charset)
|
||||||
error.Set(db_domain, "Duplicate charset line");
|
throw std::runtime_error("Duplicate charset line");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
found_charset = true;
|
found_charset = true;
|
||||||
|
|
||||||
const char *new_charset = p;
|
const char *new_charset = p;
|
||||||
const char *const old_charset = GetFSCharset();
|
const char *const old_charset = GetFSCharset();
|
||||||
if (*old_charset != 0
|
if (*old_charset != 0
|
||||||
&& strcmp(new_charset, old_charset) != 0) {
|
&& strcmp(new_charset, old_charset) != 0)
|
||||||
error.Format(db_domain,
|
throw FormatRuntimeError("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);
|
||||||
new_charset, old_charset);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if ((p = StringAfterPrefix(line, DB_TAG_PREFIX))) {
|
} else if ((p = StringAfterPrefix(line, DB_TAG_PREFIX))) {
|
||||||
const char *name = p;
|
const char *name = p;
|
||||||
TagType tag = tag_name_parse(name);
|
TagType tag = tag_name_parse(name);
|
||||||
if (tag == TAG_NUM_OF_ITEM_TYPES) {
|
if (tag == TAG_NUM_OF_ITEM_TYPES)
|
||||||
error.Format(db_domain,
|
throw FormatRuntimeError("Unrecognized tag '%s', "
|
||||||
"Unrecognized tag '%s', "
|
"discarding database file",
|
||||||
"discarding database file",
|
name);
|
||||||
name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tags[tag] = true;
|
tags[tag] = true;
|
||||||
} else {
|
} else {
|
||||||
error.Format(db_domain, "Malformed line: %s", line);
|
throw FormatRuntimeError("Malformed line: %s", line);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format < OLDEST_DB_FORMAT || format > DB_FORMAT) {
|
if (format < OLDEST_DB_FORMAT || format > DB_FORMAT)
|
||||||
error.Set(db_domain,
|
throw std::runtime_error("Database format mismatch, "
|
||||||
"Database format mismatch, "
|
"discarding database file");
|
||||||
"discarding database file");
|
|
||||||
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 (IsTagEnabled(i) && !tags[i]) {
|
if (IsTagEnabled(i) && !tags[i])
|
||||||
error.Set(db_domain,
|
throw std::runtime_error("Tag list mismatch, "
|
||||||
"Tag list mismatch, "
|
"discarding database file");
|
||||||
"discarding database file");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogDebug(db_domain, "reading DB");
|
LogDebug(db_domain, "reading DB");
|
||||||
|
|
||||||
const ScopeDatabaseLock protect;
|
const ScopeDatabaseLock protect;
|
||||||
return directory_load(file, music_root, error);
|
directory_load(file, music_root);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,10 @@ class Error;
|
|||||||
void
|
void
|
||||||
db_save_internal(BufferedOutputStream &os, const Directory &root);
|
db_save_internal(BufferedOutputStream &os, const Directory &root);
|
||||||
|
|
||||||
bool
|
/**
|
||||||
db_load_internal(TextFile &file, Directory &root, Error &error);
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
db_load_internal(TextFile &file, Directory &root);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,8 +28,7 @@
|
|||||||
#include "fs/io/BufferedOutputStream.hxx"
|
#include "fs/io/BufferedOutputStream.hxx"
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
#include "util/NumberParser.hxx"
|
#include "util/NumberParser.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Domain.hxx"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -39,8 +38,6 @@
|
|||||||
#define DIRECTORY_BEGIN "begin: "
|
#define DIRECTORY_BEGIN "begin: "
|
||||||
#define DIRECTORY_END "end: "
|
#define DIRECTORY_END "end: "
|
||||||
|
|
||||||
static constexpr Domain directory_domain("directory");
|
|
||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
static const char *
|
static const char *
|
||||||
DeviceToTypeString(unsigned device)
|
DeviceToTypeString(unsigned device)
|
||||||
@ -115,49 +112,37 @@ ParseLine(Directory &directory, const char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Directory *
|
static Directory *
|
||||||
directory_load_subdir(TextFile &file, Directory &parent, const char *name,
|
directory_load_subdir(TextFile &file, Directory &parent, const char *name)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
bool success;
|
if (parent.FindChild(name) != nullptr)
|
||||||
|
throw FormatRuntimeError("Duplicate subdirectory '%s'", name);
|
||||||
if (parent.FindChild(name) != nullptr) {
|
|
||||||
error.Format(directory_domain,
|
|
||||||
"Duplicate subdirectory '%s'", name);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory *directory = parent.CreateChild(name);
|
Directory *directory = parent.CreateChild(name);
|
||||||
|
|
||||||
while (true) {
|
try {
|
||||||
const char *line = file.ReadLine();
|
while (true) {
|
||||||
if (line == nullptr) {
|
const char *line = file.ReadLine();
|
||||||
error.Set(directory_domain, "Unexpected end of file");
|
if (line == nullptr)
|
||||||
directory->Delete();
|
throw std::runtime_error("Unexpected end of file");
|
||||||
return nullptr;
|
|
||||||
|
if (StringStartsWith(line, DIRECTORY_BEGIN))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!ParseLine(*directory, line))
|
||||||
|
throw FormatRuntimeError("Malformed line: %s", line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringStartsWith(line, DIRECTORY_BEGIN))
|
directory_load(file, *directory);
|
||||||
break;
|
} catch (...) {
|
||||||
|
|
||||||
if (!ParseLine(*directory, line)) {
|
|
||||||
error.Format(directory_domain,
|
|
||||||
"Malformed line: %s", line);
|
|
||||||
directory->Delete();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
success = directory_load(file, *directory, error);
|
|
||||||
if (!success) {
|
|
||||||
directory->Delete();
|
directory->Delete();
|
||||||
return nullptr;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
directory_load(TextFile &file, Directory &directory, Error &error)
|
directory_load(TextFile &file, Directory &directory)
|
||||||
{
|
{
|
||||||
const char *line;
|
const char *line;
|
||||||
|
|
||||||
@ -165,38 +150,23 @@ directory_load(TextFile &file, Directory &directory, Error &error)
|
|||||||
!StringStartsWith(line, DIRECTORY_END)) {
|
!StringStartsWith(line, DIRECTORY_END)) {
|
||||||
const char *p;
|
const char *p;
|
||||||
if ((p = StringAfterPrefix(line, DIRECTORY_DIR))) {
|
if ((p = StringAfterPrefix(line, DIRECTORY_DIR))) {
|
||||||
Directory *subdir =
|
directory_load_subdir(file, directory, p);
|
||||||
directory_load_subdir(file, directory,
|
|
||||||
p, error);
|
|
||||||
if (subdir == nullptr)
|
|
||||||
return false;
|
|
||||||
} else if ((p = StringAfterPrefix(line, SONG_BEGIN))) {
|
} else if ((p = StringAfterPrefix(line, SONG_BEGIN))) {
|
||||||
const char *name = p;
|
const char *name = p;
|
||||||
|
|
||||||
if (directory.FindSong(name) != nullptr) {
|
if (directory.FindSong(name) != nullptr)
|
||||||
error.Format(directory_domain,
|
throw FormatRuntimeError("Duplicate song '%s'", name);
|
||||||
"Duplicate song '%s'", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DetachedSong *song = song_load(file, name, error);
|
DetachedSong *song = song_load(file, name);
|
||||||
if (song == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
directory.AddSong(Song::NewFrom(std::move(*song),
|
directory.AddSong(Song::NewFrom(std::move(*song),
|
||||||
directory));
|
directory));
|
||||||
delete song;
|
delete song;
|
||||||
} else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) {
|
} else if ((p = StringAfterPrefix(line, PLAYLIST_META_BEGIN))) {
|
||||||
const char *name = p;
|
const char *name = p;
|
||||||
if (!playlist_metadata_load(file, directory.playlists,
|
playlist_metadata_load(file, directory.playlists, name);
|
||||||
name, error))
|
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
error.Format(directory_domain,
|
throw FormatRuntimeError("Malformed line: %s", line);
|
||||||
"Malformed line: %s", line);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,10 @@ class Error;
|
|||||||
void
|
void
|
||||||
directory_save(BufferedOutputStream &os, const Directory &directory);
|
directory_save(BufferedOutputStream &os, const Directory &directory);
|
||||||
|
|
||||||
bool
|
/**
|
||||||
directory_load(TextFile &file, Directory &directory, Error &error);
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
directory_load(TextFile &file, Directory &directory);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -142,22 +142,19 @@ SimpleDatabase::Check() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
SimpleDatabase::Load(Error &error)
|
SimpleDatabase::Load()
|
||||||
{
|
{
|
||||||
assert(!path.IsNull());
|
assert(!path.IsNull());
|
||||||
assert(root != nullptr);
|
assert(root != nullptr);
|
||||||
|
|
||||||
TextFile file(path);
|
TextFile file(path);
|
||||||
|
|
||||||
if (!db_load_internal(file, *root, error))
|
db_load_internal(file, *root);
|
||||||
return false;
|
|
||||||
|
|
||||||
FileInfo fi;
|
FileInfo fi;
|
||||||
if (GetFileInfo(path, fi))
|
if (GetFileInfo(path, fi))
|
||||||
mtime = fi.GetModificationTime();
|
mtime = fi.GetModificationTime();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -173,16 +170,7 @@ SimpleDatabase::Open()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Error error2;
|
Load();
|
||||||
if (!Load(error2)) {
|
|
||||||
LogError(error2);
|
|
||||||
|
|
||||||
delete root;
|
|
||||||
|
|
||||||
Check();
|
|
||||||
|
|
||||||
root = Directory::NewRoot();
|
|
||||||
}
|
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
LogError(e);
|
LogError(e);
|
||||||
|
|
||||||
|
@ -136,7 +136,10 @@ private:
|
|||||||
|
|
||||||
void Check() const;
|
void Check() const;
|
||||||
|
|
||||||
bool Load(Error &error);
|
/**
|
||||||
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
void Load();
|
||||||
|
|
||||||
Database *LockUmountSteal(const char *uri);
|
Database *LockUmountSteal(const char *uri);
|
||||||
};
|
};
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include "fs/io/TextFile.hxx"
|
#include "fs/io/TextFile.hxx"
|
||||||
#include "fs/io/BufferedOutputStream.hxx"
|
#include "fs/io/BufferedOutputStream.hxx"
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -95,10 +94,10 @@ queue_load_song(TextFile &file, const SongLoader &loader,
|
|||||||
if ((p = StringAfterPrefix(line, SONG_BEGIN))) {
|
if ((p = StringAfterPrefix(line, SONG_BEGIN))) {
|
||||||
const char *uri = p;
|
const char *uri = p;
|
||||||
|
|
||||||
Error error;
|
try {
|
||||||
song = song_load(file, uri, error);
|
song = song_load(file, uri);
|
||||||
if (song == nullptr) {
|
} catch (const std::runtime_error &e) {
|
||||||
LogError(error);
|
LogError(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user