stored_playlist: added spl_list()
spl_list() provides an interface for enumerating all stored playlists. This separates the internal playlist logic from the protocol specific function lsPlaylists().
This commit is contained in:
parent
3a164ef8e6
commit
a65e20b50e
86
src/ls.c
86
src/ls.c
|
@ -23,6 +23,7 @@
|
|||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include "list.h"
|
||||
#include "stored_playlist.h"
|
||||
#include "os_compat.h"
|
||||
|
||||
static const char *remoteUrlPrefixes[] = {
|
||||
|
@ -99,84 +100,19 @@ int isRemoteUrl(const char *url)
|
|||
|
||||
int lsPlaylists(struct client *client, const char *utf8path)
|
||||
{
|
||||
DIR *dir;
|
||||
struct stat st;
|
||||
struct dirent *ent;
|
||||
char *duplicated;
|
||||
char *utf8;
|
||||
char s[MPD_PATH_MAX];
|
||||
char path_max_tmp[MPD_PATH_MAX];
|
||||
List *list = NULL;
|
||||
ListNode *node;
|
||||
char *actualPath = rpp2app_r(path_max_tmp,
|
||||
utf8_to_fs_charset(path_max_tmp,
|
||||
utf8path));
|
||||
size_t actlen = strlen(actualPath) + 1;
|
||||
size_t maxlen = MPD_PATH_MAX - actlen;
|
||||
size_t suflen = strlen(PLAYLIST_FILE_SUFFIX) + 1;
|
||||
ssize_t suff;
|
||||
|
||||
if (actlen > MPD_PATH_MAX - 1 || (dir = opendir(actualPath)) == NULL) {
|
||||
GPtrArray *list = spl_list();
|
||||
if (list == NULL)
|
||||
return 0;
|
||||
|
||||
for (unsigned i = 0; i < list->len; ++i) {
|
||||
struct stored_playlist_info *playlist =
|
||||
g_ptr_array_index(list, i);
|
||||
|
||||
client_printf(client, "playlist: %s%s\n",
|
||||
utf8path, playlist->name);
|
||||
}
|
||||
|
||||
s[MPD_PATH_MAX - 1] = '\0';
|
||||
/* this is safe, notice actlen > MPD_PATH_MAX-1 above */
|
||||
strcpy(s, actualPath);
|
||||
strcat(s, "/");
|
||||
|
||||
while ((ent = readdir(dir))) {
|
||||
size_t len = strlen(ent->d_name) + 1;
|
||||
duplicated = ent->d_name;
|
||||
if (mpd_likely(len <= maxlen) &&
|
||||
duplicated[0] != '.' &&
|
||||
(suff = (ssize_t)(strlen(duplicated) - suflen)) > 0 &&
|
||||
duplicated[suff] == '.' &&
|
||||
strcmp(duplicated + suff + 1, PLAYLIST_FILE_SUFFIX) == 0) {
|
||||
memcpy(s + actlen, ent->d_name, len);
|
||||
if (stat(s, &st) == 0) {
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
if (list == NULL)
|
||||
list = makeList(NULL, 1);
|
||||
duplicated[suff] = '\0';
|
||||
utf8 = fs_charset_to_utf8(path_max_tmp,
|
||||
duplicated);
|
||||
if (utf8)
|
||||
insertInList(list, utf8, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
if (list) {
|
||||
int i;
|
||||
sortList(list);
|
||||
|
||||
duplicated = xmalloc(strlen(utf8path) + 2);
|
||||
strcpy(duplicated, utf8path);
|
||||
for (i = strlen(duplicated) - 1;
|
||||
i >= 0 && duplicated[i] == '/';
|
||||
i--) {
|
||||
duplicated[i] = '\0';
|
||||
}
|
||||
if (strlen(duplicated))
|
||||
strcat(duplicated, "/");
|
||||
|
||||
node = list->firstNode;
|
||||
while (node != NULL) {
|
||||
if (!strchr(node->key, '\n')) {
|
||||
client_printf(client, "playlist: %s%s\n",
|
||||
duplicated, node->key);
|
||||
}
|
||||
node = node->nextNode;
|
||||
}
|
||||
|
||||
freeList(list);
|
||||
free(duplicated);
|
||||
}
|
||||
|
||||
spl_list_free(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,85 @@
|
|||
#include "idle.h"
|
||||
#include "os_compat.h"
|
||||
|
||||
static struct stored_playlist_info *
|
||||
load_playlist_info(const char *parent_path_fs, const char *name_fs)
|
||||
{
|
||||
size_t name_length = strlen(name_fs);
|
||||
char buffer[MPD_PATH_MAX], *name, *name_utf8;
|
||||
int ret;
|
||||
struct stat st;
|
||||
struct stored_playlist_info *playlist;
|
||||
|
||||
if (name_length < 1 + sizeof(PLAYLIST_FILE_SUFFIX) ||
|
||||
strlen(parent_path_fs) + name_length >= sizeof(buffer) ||
|
||||
memchr(name_fs, '\n', name_length) != NULL)
|
||||
return NULL;
|
||||
|
||||
if (name_fs[name_length - sizeof(PLAYLIST_FILE_SUFFIX)] != '.' ||
|
||||
memcmp(name_fs + name_length - sizeof(PLAYLIST_FILE_SUFFIX) + 1,
|
||||
PLAYLIST_FILE_SUFFIX,
|
||||
sizeof(PLAYLIST_FILE_SUFFIX) - 1) != 0)
|
||||
return NULL;
|
||||
|
||||
pfx_dir(buffer, name_fs, name_length,
|
||||
parent_path_fs, strlen(parent_path_fs));
|
||||
|
||||
ret = stat(buffer, &st);
|
||||
if (ret < 0 || !S_ISREG(st.st_mode))
|
||||
return NULL;
|
||||
|
||||
name = g_strdup(name_fs);
|
||||
name[name_length - sizeof(PLAYLIST_FILE_SUFFIX)] = 0;
|
||||
name_utf8 = fs_charset_to_utf8(buffer, name);
|
||||
g_free(name);
|
||||
if (name_utf8 == NULL)
|
||||
return NULL;
|
||||
|
||||
playlist = g_new(struct stored_playlist_info, 1);
|
||||
playlist->name = g_strdup(name_utf8);
|
||||
playlist->mtime = st.st_mtime;
|
||||
return playlist;
|
||||
}
|
||||
|
||||
GPtrArray *
|
||||
spl_list(void)
|
||||
{
|
||||
char parent_path_fs[MPD_PATH_MAX];
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
GPtrArray *list;
|
||||
struct stored_playlist_info *playlist;
|
||||
|
||||
rpp2app_r(parent_path_fs, "");
|
||||
dir = opendir(parent_path_fs);
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
|
||||
list = g_ptr_array_new();
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
playlist = load_playlist_info(parent_path_fs, ent->d_name);
|
||||
if (playlist != NULL)
|
||||
g_ptr_array_add(list, playlist);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return list;
|
||||
}
|
||||
|
||||
void
|
||||
spl_list_free(GPtrArray *list)
|
||||
{
|
||||
for (unsigned i = 0; i < list->len; ++i) {
|
||||
struct stored_playlist_info *playlist =
|
||||
g_ptr_array_index(list, i);
|
||||
g_free(playlist->name);
|
||||
g_free(playlist);
|
||||
}
|
||||
|
||||
g_ptr_array_free(list, true);
|
||||
}
|
||||
|
||||
static ListNode *
|
||||
spl_get_index(List *list, int idx)
|
||||
{
|
||||
|
|
|
@ -22,8 +22,26 @@
|
|||
#include "list.h"
|
||||
#include "playlist.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
struct song;
|
||||
|
||||
struct stored_playlist_info {
|
||||
char *name;
|
||||
|
||||
time_t mtime;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a list of stored_playlist_info struct pointers. Returns
|
||||
* NULL if an error occured.
|
||||
*/
|
||||
GPtrArray *
|
||||
spl_list(void);
|
||||
|
||||
void
|
||||
spl_list_free(GPtrArray *list);
|
||||
|
||||
List *
|
||||
spl_load(const char *utf8path);
|
||||
|
||||
|
|
Loading…
Reference in New Issue