aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/decoder_thread.c21
-rw-r--r--src/mapper.c77
-rw-r--r--src/mapper.h74
-rw-r--r--src/playlist.c1
-rw-r--r--src/playlist_save.c22
-rw-r--r--src/song.c5
-rw-r--r--src/storedPlaylist.c26
-rw-r--r--src/update.c66
9 files changed, 241 insertions, 53 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ca6f8f5a..2151daa7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -79,6 +79,7 @@ mpd_headers = \
os_compat.h \
outputBuffer.h \
path.h \
+ mapper.h \
pcm_utils.h \
permission.h \
player_thread.h \
@@ -158,6 +159,7 @@ mpd_SOURCES = \
compress.c \
outputBuffer.c \
path.c \
+ mapper.c \
pcm_utils.c \
permission.c \
player_thread.c \
diff --git a/src/decoder_thread.c b/src/decoder_thread.c
index 594bfbc7..f0f315f3 100644
--- a/src/decoder_thread.c
+++ b/src/decoder_thread.c
@@ -22,27 +22,28 @@
#include "decoder_internal.h"
#include "player_control.h"
#include "song.h"
-
+#include "mapper.h"
#include "path.h"
#include "log.h"
#include "ls.h"
static void decodeStart(void)
{
+ struct song *song = dc.next_song;
struct decoder decoder;
int ret;
bool close_instream = true;
InputStream inStream;
struct decoder_plugin *plugin = NULL;
char path_max_fs[MPD_PATH_MAX];
- char path_max_utf8[MPD_PATH_MAX];
- song_get_url(dc.next_song, path_max_utf8);
- if (!isRemoteUrl(path_max_utf8)) {
- rmp2amp_r(path_max_fs,
- utf8_to_fs_charset(path_max_fs, path_max_utf8));
- } else
+ if (song_is_file(song))
+ map_song_fs(song, path_max_fs);
+ else {
+ char path_max_utf8[MPD_PATH_MAX];
+ song_get_url(song, path_max_utf8);
pathcpy_trunc(path_max_fs, path_max_utf8);
+ }
dc.current_song = dc.next_song; /* NEED LOCK */
if (openInputStream(&inStream, path_max_fs) < 0) {
@@ -74,7 +75,7 @@ static void decodeStart(void)
goto stop;
ret = DECODE_ERROR_UNKTYPE;
- if (isRemoteUrl(path_max_utf8)) {
+ if (!song_is_file(song)) {
unsigned int next = 0;
/* first we try mime types: */
@@ -92,7 +93,7 @@ static void decodeStart(void)
/* if that fails, try suffix matching the URL: */
if (plugin == NULL) {
- const char *s = getSuffix(path_max_utf8);
+ const char *s = getSuffix(path_max_fs);
next = 0;
while (ret && (plugin = decoder_plugin_from_suffix(s, next++))) {
if (plugin->stream_decode == NULL)
@@ -123,7 +124,7 @@ static void decodeStart(void)
}
} else {
unsigned int next = 0;
- const char *s = getSuffix(path_max_utf8);
+ const char *s = getSuffix(path_max_fs);
while (ret && (plugin = decoder_plugin_from_suffix(s, next++))) {
if (!plugin->stream_types & INPUT_PLUGIN_STREAM_FILE)
continue;
diff --git a/src/mapper.c b/src/mapper.c
new file mode 100644
index 00000000..39221121
--- /dev/null
+++ b/src/mapper.c
@@ -0,0 +1,77 @@
+/* the Music Player Daemon (MPD)
+ * Copyright (C) 2008 Max Kellermann <max@duempel.org>
+ * This project's homepage is: 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Maps directory and song objects to file system paths.
+ */
+
+#include "mapper.h"
+#include "directory.h"
+#include "song.h"
+#include "path.h"
+
+const char *
+map_directory_fs(const struct directory *directory, char *buffer)
+{
+ const char *dirname = directory_get_path(directory);
+ if (isRootDirectory(dirname))
+ return musicDir;
+
+ return rmp2amp_r(buffer, utf8_to_fs_charset(buffer, dirname));
+}
+
+const char *
+map_directory_child_fs(const struct directory *directory, const char *name,
+ char *buffer)
+{
+ char buffer2[MPD_PATH_MAX];
+ const char *parent_fs;
+
+ parent_fs = map_directory_fs(directory, buffer2);
+ if (parent_fs == NULL)
+ return NULL;
+
+ utf8_to_fs_charset(buffer, name);
+ pfx_dir(buffer, name, strlen(name),
+ parent_fs, strlen(parent_fs));
+ return buffer;
+}
+
+const char *
+map_song_fs(const struct song *song, char *buffer)
+{
+ assert(song->parent != NULL);
+
+ return map_directory_child_fs(song->parent, song->url, buffer);
+}
+
+const char *
+map_fs_to_utf8(const char *path_fs, char *buffer)
+{
+ size_t music_path_length = strlen(musicDir);
+
+ if (strncmp(path_fs, musicDir, music_path_length) == 0 &&
+ path_fs[music_path_length] == '/')
+ /* remove musicDir prefix */
+ path_fs += music_path_length;
+ else if (path_fs[0] == '/')
+ /* not within musicDir */
+ return NULL;
+
+ return fs_charset_to_utf8(buffer, path_fs);
+}
diff --git a/src/mapper.h b/src/mapper.h
new file mode 100644
index 00000000..2c21a68e
--- /dev/null
+++ b/src/mapper.h
@@ -0,0 +1,74 @@
+/* the Music Player Daemon (MPD)
+ * Copyright (C) 2008 Max Kellermann <max@duempel.org>
+ * This project's homepage is: 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Maps directory and song objects to file system paths.
+ */
+
+#ifndef MAPPER_H
+#define MAPPER_H
+
+struct directory;
+struct song;
+
+/**
+ * Determines the file system path of a directory object.
+ *
+ * @param directory the directory object
+ * @param a buffer which is MPD_PATH_MAX bytes long
+ * @return the path in file system encoding, or NULL if mapping failed
+ */
+const char *
+map_directory_fs(const struct directory *directory, char *buffer);
+
+/**
+ * Determines the file system path of a directory's child (may be a
+ * sub directory or a song).
+ *
+ * @param directory the parent directory object
+ * @param name the child's name in UTF-8
+ * @param a buffer which is MPD_PATH_MAX bytes long
+ * @return the path in file system encoding, or NULL if mapping failed
+ */
+const char *
+map_directory_child_fs(const struct directory *directory, const char *name,
+ char *buffer);
+
+/**
+ * Determines the file system path of a song. This must not be a
+ * remote song.
+ *
+ * @param song the song object
+ * @param a buffer which is MPD_PATH_MAX bytes long
+ * @return the path in file system encoding, or NULL if mapping failed
+ */
+const char *
+map_song_fs(const struct song *song, char *buffer);
+
+/**
+ * Maps a file system path (relative to the music directory or
+ * absolute) to a relative path in UTF-8 encoding.
+ *
+ * @param path_fs a path in file system encoding
+ * @param buffer a buffer which is MPD_PATH_MAX bytes long
+ * @return the relative path in UTF-8, or NULL if mapping failed
+ */
+const char *
+map_fs_to_utf8(const char *path_fs, char *buffer);
+
+#endif
diff --git a/src/playlist.c b/src/playlist.c
index 65e7d639..b160202b 100644
--- a/src/playlist.c
+++ b/src/playlist.c
@@ -28,6 +28,7 @@
#include "conf.h"
#include "database.h"
#include "log.h"
+#include "mapper.h"
#include "path.h"
#include "utils.h"
#include "state_file.h"
diff --git a/src/playlist_save.c b/src/playlist_save.c
index 98979e2a..55cd6bd8 100644
--- a/src/playlist_save.c
+++ b/src/playlist_save.c
@@ -19,21 +19,25 @@
#include "playlist_save.h"
#include "playlist.h"
#include "song.h"
+#include "mapper.h"
#include "path.h"
#include "ls.h"
+#include "database.h"
void
playlist_print_song(FILE *file, const struct song *song)
{
char tmp1[MPD_PATH_MAX], tmp2[MPD_PATH_MAX];
- song_get_url(song, tmp1);
- utf8_to_fs_charset(tmp2, tmp1);
-
- if (playlist_saveAbsolutePaths && song_is_file(song))
- fprintf(file, "%s\n", rmp2amp_r(tmp2, tmp2));
- else
+ if (playlist_saveAbsolutePaths && song_is_file(song)) {
+ const char *path = map_song_fs(song, tmp1);
+ if (path != NULL)
+ fprintf(file, "%s\n", path);
+ } else {
+ song_get_url(song, tmp1);
+ utf8_to_fs_charset(tmp2, tmp1);
fprintf(file, "%s\n", tmp2);
+ }
}
void
@@ -42,8 +46,10 @@ playlist_print_uri(FILE *file, const char *uri)
char tmp[MPD_PATH_MAX];
const char *s;
- s = utf8_to_fs_charset(tmp, uri);
if (playlist_saveAbsolutePaths && !isValidRemoteUtf8Url(s))
- s = rmp2amp_r(tmp, s);
+ s = map_directory_child_fs(db_get_root(), uri, tmp);
+ else
+ s = utf8_to_fs_charset(tmp, uri);
+
fprintf(file, "%s\n", s);
}
diff --git a/src/song.c b/src/song.c
index 2de9e52c..b4ab28ca 100644
--- a/src/song.c
+++ b/src/song.c
@@ -21,6 +21,7 @@
#include "directory.h"
#include "utils.h"
#include "log.h"
+#include "mapper.h"
#include "path.h"
#include "playlist.h"
#include "decoder_list.h"
@@ -95,14 +96,12 @@ song_file_update(struct song *song)
{
struct decoder_plugin *plugin;
unsigned int next = 0;
- char path_max_tmp[MPD_PATH_MAX];
char abs_path[MPD_PATH_MAX];
struct stat st;
assert(song_is_file(song));
- utf8_to_fs_charset(abs_path, song_get_url(song, path_max_tmp));
- rmp2amp_r(abs_path, abs_path);
+ map_song_fs(song, abs_path);
if (song->tag != NULL) {
tag_free(song->tag);
diff --git a/src/storedPlaylist.c b/src/storedPlaylist.c
index 4e20a6de..3d5b8286 100644
--- a/src/storedPlaylist.c
+++ b/src/storedPlaylist.c
@@ -19,6 +19,7 @@
#include "storedPlaylist.h"
#include "playlist_save.h"
#include "song.h"
+#include "mapper.h"
#include "path.h"
#include "utils.h"
#include "ls.h"
@@ -91,7 +92,6 @@ List *loadStoredPlaylist(const char *utf8path)
FILE *file;
char buffer[MPD_PATH_MAX];
char path_max_tmp[MPD_PATH_MAX];
- const size_t musicDir_len = strlen(musicDir);
if (!is_valid_playlist_name(utf8path))
return NULL;
@@ -105,19 +105,27 @@ List *loadStoredPlaylist(const char *utf8path)
while (myFgets(buffer, sizeof(buffer), file)) {
char *s = buffer;
- struct song *song;
+ const char *path_utf8;
if (*s == PLAYLIST_COMMENT)
continue;
- if (s[musicDir_len] == '/' &&
- !strncmp(s, musicDir, musicDir_len))
- memmove(s, s + musicDir_len + 1,
- strlen(s + musicDir_len + 1) + 1);
- if ((song = db_get_song(s))) {
+
+ if (isValidRemoteUtf8Url(s))
+ insertInListWithoutKey(list, xstrdup(s));
+ else {
+ struct song *song;
+
+ path_utf8 = map_fs_to_utf8(s, path_max_tmp);
+ if (path_utf8 == NULL)
+ continue;
+
+ song = db_get_song(path_utf8);
+ if (song == NULL)
+ continue;
+
song_get_url(song, path_max_tmp);
insertInListWithoutKey(list, xstrdup(path_max_tmp));
- } else if (isValidRemoteUtf8Url(s))
- insertInListWithoutKey(list, xstrdup(s));
+ }
if (list->numberOfNodes >= playlist_max_length)
break;
diff --git a/src/update.c b/src/update.c
index 93ba1668..e36a980d 100644
--- a/src/update.c
+++ b/src/update.c
@@ -23,6 +23,7 @@
#include "song.h"
#include "log.h"
#include "ls.h"
+#include "mapper.h"
#include "path.h"
#include "playlist.h"
#include "utils.h"
@@ -150,11 +151,11 @@ static int
delete_song_if_removed(struct song *song, void *_data)
{
struct delete_data *data = _data;
+ const char *path;
+ struct stat st;
- data->tmp = song_get_url(song, data->tmp);
- assert(data->tmp);
-
- if (!isFile(data->tmp, NULL)) {
+ if ((path = map_song_fs(song, data->tmp)) == NULL ||
+ stat(data->tmp, &st) < 0 || !S_ISREG(st.st_mode)) {
delete_song(data->dir, song);
modified = true;
}
@@ -169,7 +170,12 @@ removeDeletedFromDirectory(char *path_max_tmp, struct directory *directory)
struct delete_data data;
for (i = dv->nr; --i >= 0; ) {
- if (isDir(dv->base[i]->path))
+ const char *path_fs;
+ struct stat st;
+
+ path_fs = map_directory_fs(dv->base[i], path_max_tmp);
+ if (path_fs == NULL || (stat(path_fs, &st) == 0 &&
+ S_ISDIR(st.st_mode)))
continue;
LOG("removing directory: %s\n", dv->base[i]->path);
dirvec_delete(dv, dv->base[i]);
@@ -181,12 +187,26 @@ removeDeletedFromDirectory(char *path_max_tmp, struct directory *directory)
songvec_for_each(&directory->songs, delete_song_if_removed, &data);
}
-static const char *opendir_path(char *path_max_tmp, const char *dirname)
+static int
+stat_directory(const struct directory *directory, struct stat *st)
{
- if (*dirname != '\0')
- return rmp2amp_r(path_max_tmp,
- utf8_to_fs_charset(path_max_tmp, dirname));
- return musicDir;
+ char buffer[MPD_PATH_MAX];
+ const char *path_fs;
+
+ path_fs = map_directory_fs(directory, buffer);
+ if (path_fs == NULL)
+ return -1;
+ return stat(path_fs, st);
+}
+
+static int
+stat_directory_child(const struct directory *parent, const char *name,
+ struct stat *st)
+{
+ char path_fs[MPD_PATH_MAX];
+
+ map_directory_child_fs(parent, name, path_fs);
+ return stat(path_fs, st);
}
static int
@@ -194,7 +214,7 @@ statDirectory(struct directory *dir)
{
struct stat st;
- if (myStat(directory_get_path(dir), &st) < 0)
+ if (stat_directory(dir, &st) < 0)
return -1;
directory_set_stat(dir, &st);
@@ -296,15 +316,19 @@ static bool
updateDirectory(struct directory *directory, const struct stat *st)
{
DIR *dir;
- const char *dirname = directory_get_path(directory);
struct dirent *ent;
char path_max_tmp[MPD_PATH_MAX];
+ const char *path_fs;
assert(S_ISDIR(st->st_mode));
directory_set_stat(directory, st);
- dir = opendir(opendir_path(path_max_tmp, dirname));
+ path_fs = map_directory_fs(directory, path_max_tmp);
+ if (path_fs == NULL)
+ return false;
+
+ dir = opendir(path_fs);
if (!dir)
return false;
@@ -321,15 +345,11 @@ updateDirectory(struct directory *directory, const struct stat *st)
if (!utf8)
continue;
- if (!isRootDirectory(directory->path))
- utf8 = pfx_dir(path_max_tmp, utf8, strlen(utf8),
- dirname, strlen(dirname));
-
- if (myStat(path_max_tmp, &st2) == 0)
+ if (stat_directory_child(directory, utf8, &st2) == 0)
updateInDirectory(directory,
- mpd_basename(path_max_tmp), &st2);
+ path_max_tmp, &st2);
else
- delete_name_in(directory, mpd_basename(path_max_tmp));
+ delete_name_in(directory, path_max_tmp);
}
closedir(dir);
@@ -348,7 +368,7 @@ directory_make_child_checked(struct directory *parent, const char *path)
if (directory != NULL)
return directory;
- if (myStat(path, &st) < 0 ||
+ if (stat_directory_child(parent, mpd_basename(path), &st) < 0 ||
inodeFoundInParent(parent, st.st_ino, st.st_dev))
return NULL;
@@ -398,7 +418,7 @@ updatePath(const char *path)
name = mpd_basename(path);
- if (myStat(path, &st) == 0)
+ if (stat_directory_child(parent, name, &st) == 0)
updateInDirectory(parent, name, &st);
else
delete_name_in(parent, name);
@@ -413,7 +433,7 @@ static void * update_task(void *_path)
struct directory *directory = db_get_root();
struct stat st;
- if (myStat(directory_get_path(directory), &st) == 0)
+ if (stat_directory(directory, &st) == 0)
updateDirectory(directory, &st);
}