diff --git a/NEWS b/NEWS index e4fa1e995..423c6ed3c 100644 --- a/NEWS +++ b/NEWS @@ -12,7 +12,7 @@ ver 0.15 - (200?/??/??) * failure to read the state file is non-fatal * added Icy-Metadata support * --create-db starts the MPD daemon instead of exiting -* playlist_directory is optional +* playlist_directory and music_directory are optional ver 0.14.1 (2009/01/17) diff --git a/doc/mpd.conf.5 b/doc/mpd.conf.5 index 9ee10b2b7..a40ec9467 100644 --- a/doc/mpd.conf.5 +++ b/doc/mpd.conf.5 @@ -29,9 +29,6 @@ See \fBdocs/mpdconf.example\fP in the source tarball for an example configuration file. .SH REQUIRED PARAMETERS .TP -.B music_directory -This specifies the directory where music is located. -.TP .B follow_outside_symlinks Control if MPD will follow symbolic links pointing outside the music dir. You must recreate the database after changing this option. @@ -54,6 +51,10 @@ The special value "syslog" makes MPD use the local syslog daemon. .B pid_file This specifies the file to save mpd's process ID in. .TP +.B music_directory +This specifies the directory where music is located. +If you do not configure this, you can only play streams. +.TP .B playlist_directory This specifies the directory where saved playlists are stored. If you do not configure this, you cannot save playlists. diff --git a/src/database.c b/src/database.c index 44909aced..6beb84f61 100644 --- a/src/database.c +++ b/src/database.c @@ -49,13 +49,17 @@ db_init(const char *path) { database_path = g_strdup(path); - music_root = directory_new("", NULL); + if (path != NULL) + music_root = directory_new("", NULL); } void db_finish(void) { - directory_free(music_root); + assert((database_path == NULL) == (music_root == NULL)); + + if (music_root != NULL) + directory_free(music_root); g_free(database_path); } @@ -63,6 +67,8 @@ db_finish(void) void db_clear(void) { + assert(music_root != NULL); + directory_free(music_root); music_root = directory_new("", NULL); } @@ -78,6 +84,9 @@ db_get_root(void) struct directory * db_get_directory(const char *name) { + if (music_root == NULL) + return NULL; + if (name == NULL) return music_root; @@ -89,14 +98,20 @@ db_get_song(const char *file) { struct song *song = NULL; struct directory *directory; - char *dir = NULL; - char *duplicated = g_strdup(file); - char *shortname = strrchr(duplicated, '/'); + char *duplicated, *shortname, *dir; + + assert(file != NULL); g_debug("get song: %s", file); + if (music_root == NULL) + return NULL; + + duplicated = g_strdup(file); + shortname = strrchr(duplicated, '/'); if (!shortname) { shortname = duplicated; + dir = NULL; } else { *shortname = '\0'; ++shortname; @@ -121,6 +136,9 @@ db_walk(const char *name, { struct directory *directory; + if (music_root == NULL) + return -1; + if ((directory = db_get_directory(name)) == NULL) { struct song *song; if ((song = db_get_song(name)) && forEachSong) { diff --git a/src/database.h b/src/database.h index bb2ccce70..211cdc619 100644 --- a/src/database.h +++ b/src/database.h @@ -42,6 +42,10 @@ db_finish(void); void db_clear(void); +/** + * Returns the root directory object. Returns NULL if there is no + * configured music directory. + */ struct directory * db_get_root(void); diff --git a/src/main.c b/src/main.c index b7e9e0106..1bcae8f36 100644 --- a/src/main.c +++ b/src/main.c @@ -128,7 +128,16 @@ static void openDB(Options * options, char *argv0) { struct config_param *param; - param = parseConfigFilePath(CONF_DB_FILE, true); + param = parseConfigFilePath(CONF_DB_FILE, + mapper_has_music_directory()); + if (!mapper_has_music_directory()) { + if (param != NULL) + g_message("Found " CONF_DB_FILE " setting without " + CONF_MUSIC_DIR " - disabling database"); + db_init(NULL); + return; + } + db_init(param->value); if (options->createDB > 0 || !db_load()) { diff --git a/src/mapper.c b/src/mapper.c index 2c3e50ab0..a47507bb1 100644 --- a/src/mapper.c +++ b/src/mapper.c @@ -40,6 +40,24 @@ static size_t music_dir_length; static char *playlist_dir; +static void +mapper_set_music_dir(const char *path, int line) +{ + int ret; + struct stat st; + + music_dir = g_strdup(path); + music_dir_length = strlen(music_dir); + + ret = stat(music_dir, &st); + if (ret < 0) + g_warning("failed to stat music directory \"%s\" (config line %i): %s\n", + music_dir, line, g_strerror(errno)); + else if (!S_ISDIR(st.st_mode)) + g_warning("music directory is not a directory: \"%s\" (config line %i)\n", + music_dir, line); +} + static void mapper_set_playlist_dir(const char *path, int line) { @@ -59,34 +77,19 @@ mapper_set_playlist_dir(const char *path, int line) void mapper_init(void) { - struct config_param *music_dir_param = - parseConfigFilePath(CONF_MUSIC_DIR, false); struct config_param *param; - int ret; - struct stat st; - if (music_dir_param != NULL) { - music_dir = g_strdup(music_dir_param->value); - } else { + param = parseConfigFilePath(CONF_MUSIC_DIR, false); + if (param != NULL) + mapper_set_music_dir(param->value, param->line); #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 14) - music_dir = g_strdup(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC)); - if (music_dir == NULL) - /* GLib failed to determine the XDG music - directory - abort */ -#endif - g_error("config parameter \"%s\" not found\n", CONF_MUSIC_DIR); + else { + const char *path = + g_get_user_special_dir(G_USER_DIRECTORY_MUSIC); + if (path != NULL) + mapper_set_music_dir(path, -1); } - - music_dir_length = strlen(music_dir); - - ret = stat(music_dir, &st); - if (ret < 0) - g_warning("failed to stat music directory \"%s\" (config line %i): %s\n", - music_dir_param->value, music_dir_param->line, - strerror(errno)); - else if (!S_ISDIR(st.st_mode)) - g_warning("music directory is not a directory: \"%s\" (config line %i)\n", - music_dir_param->value, music_dir_param->line); +#endif param = parseConfigFilePath(CONF_PLAYLIST_DIR, false); if (param != NULL) @@ -99,6 +102,12 @@ void mapper_finish(void) g_free(playlist_dir); } +bool +mapper_has_music_directory(void) +{ + return music_dir != NULL; +} + char * map_uri_fs(const char *uri) { @@ -107,6 +116,9 @@ map_uri_fs(const char *uri) assert(uri != NULL); assert(*uri != '/'); + if (music_dir == NULL) + return NULL; + uri_fs = utf8_to_fs_charset(uri); if (uri_fs == NULL) return NULL; @@ -120,6 +132,8 @@ map_uri_fs(const char *uri) char * map_directory_fs(const struct directory *directory) { + assert(music_dir != NULL); + if (directory_is_root(directory)) return g_strdup(music_dir); @@ -131,6 +145,8 @@ map_directory_child_fs(const struct directory *directory, const char *name) { char *name_fs, *parent_fs, *path; + assert(music_dir != NULL); + /* check for invalid or unauthorized base names */ if (*name == 0 || strchr(name, '/') != NULL || strcmp(name, ".") == 0 || strcmp(name, "..") == 0) @@ -167,7 +183,8 @@ map_song_fs(const struct song *song) char * map_fs_to_utf8(const char *path_fs) { - if (strncmp(path_fs, music_dir, music_dir_length) == 0 && + if (music_dir != NULL && + strncmp(path_fs, music_dir, music_dir_length) == 0 && path_fs[music_dir_length] == '/') /* remove musicDir prefix */ path_fs += music_dir_length + 1; diff --git a/src/mapper.h b/src/mapper.h index d33a21bbf..874add377 100644 --- a/src/mapper.h +++ b/src/mapper.h @@ -23,6 +23,8 @@ #ifndef MPD_MAPPER_H #define MPD_MAPPER_H +#include + #define PLAYLIST_FILE_SUFFIX "m3u" struct directory; @@ -32,6 +34,12 @@ void mapper_init(void); void mapper_finish(void); +/** + * Returns true if a music directory was configured. + */ +bool +mapper_has_music_directory(void); + /** * Determines the absolute file system path of a relative URI. This * is basically done by converting the URI to the file system charset diff --git a/src/update.c b/src/update.c index f27247628..1edb8cc01 100644 --- a/src/update.c +++ b/src/update.c @@ -680,6 +680,9 @@ directory_update_init(char *path) { assert(g_thread_self() == main_task); + if (!mapper_has_music_directory()) + return 0; + if (progress != UPDATE_PROGRESS_IDLE) { unsigned next_task_id;