X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=playlist_selector.c;fp=playlist_selector.c;h=0000000000000000000000000000000000000000;hp=2d076ee63728e4383892d93a0daba96dceb8baed;hb=8978f426314b107c55a652e0151397fdab2f003e;hpb=08a1de75a3a83c728d97a3c4ff182553adbda8cc diff --git a/playlist_selector.c b/playlist_selector.c deleted file mode 100644 index 2d076ee6..00000000 --- a/playlist_selector.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2006-2007 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ - -/** \file playlist_selector.c The playlist audio file selector of paraslash */ - -#include -#include "para.h" -#include "error.h" -#include "string.h" -#include "afh.h" -#include "afs.h" -#include "server.h" -#include "afs_common.h" -#include "net.h" -#include "ipc.h" -#include "list.h" -#include "user_list.h" -#include "playlist_selector_command_list.h" - -/** - * structure used for transmission of the playlist - * - * There's one such struct which gets initialized during startup. It lives in - * shared memory and is used by com_lpl(). - */ -struct pls_client_data { -/** allocated and set by com_lpl() (child) */ - int shm_id; -/** the size of the shared memory area identified by \a shm_id */ - size_t size; -/** initially locked, gets unlocked by parent when it is done */ - int mutex; -/** return value, set by parent */ - int retval; -}; - -/** data specific to the playlist selector */ -struct private_pls_data { -/** guards against concurrent client access */ - int client_mutex; -/** guards against concurrent parent-child access */ - int server_mutex; -/** pointer to the client data */ - struct pls_client_data *client_data; -/** id of the shm corresponding to \a client_data */ - int client_data_shm_id; -}; - -/** we refuse to load playlists bigger than that */ -#define MAX_PLAYLIST_BYTES (1024 * 1024) - -static unsigned playlist_len, playlist_size, current_playlist_entry; -static char **playlist; -static struct audio_file_selector *self; - -extern struct misc_meta_data *mmd; - -static int playlist_add(char *path, __a_unused void *data) -{ - if (playlist_len >= playlist_size) { - playlist_size = 2 * playlist_size + 1; - playlist = para_realloc(playlist, playlist_size * sizeof(char *)); - } - PARA_DEBUG_LOG("adding #%d/%d: %s\n", playlist_len, playlist_size, path); - playlist[playlist_len++] = para_strdup(path); - return 1; -} - -static int send_playlist_to_server(const char *buf, size_t size) -{ - struct private_pls_data *ppd = self->private_data; - int ret, shm_mutex = -1, shm_id = -1; - void *shm = NULL; - - PARA_DEBUG_LOG("new playlist (%zd bytes)\n", size); - - ret = mutex_new(); - if (ret < 0) - return ret; - shm_mutex = ret; - - ret = shm_new(size); - if (ret < 0) - goto out; - shm_id = ret; - - ret = shm_attach(shm_id, ATTACH_RW, &shm); - if (ret < 0) - goto out; - mutex_lock(shm_mutex); - memcpy(shm, buf, size); - mutex_lock(ppd->client_mutex); - mutex_lock(ppd->server_mutex); - ppd->client_data->size = size; - ppd->client_data->shm_id = shm_id; - ppd->client_data->mutex = shm_mutex; - kill(getppid(), SIGUSR1); /* wake up the server */ - mutex_unlock(ppd->server_mutex); - mutex_lock(shm_mutex); /* wait until server is done */ - mutex_unlock(shm_mutex); - ret = ppd->client_data->retval; - mutex_unlock(ppd->client_mutex); - shm_detach(shm); -out: - if (shm_id >= 0) - shm_destroy(shm_id); - mutex_destroy(shm_mutex); - PARA_DEBUG_LOG("returning %d\n", ret); - return ret; -} - -int com_lpl(int fd, __a_unused int argc, __a_unused char * const * const argv) -{ - unsigned loaded = 0; - size_t bufsize = 4096; /* guess that's enough */ - char *buf = para_malloc(bufsize); - ssize_t ret; - ret = send_buffer(fd, AWAITING_DATA_MSG); - if (ret < 0) - goto out; -again: - ret = recv_bin_buffer(fd, buf + loaded, bufsize - loaded); - if (ret < 0) - goto out; - if (!ret) { - ret = send_playlist_to_server(buf, loaded); - goto out; - } - loaded += ret; - ret = -E_LOAD_PLAYLIST; - if (loaded >= MAX_PLAYLIST_BYTES) - goto out; - if (loaded >= bufsize) { - bufsize *= 2; - buf = para_realloc(buf, bufsize); - } - goto again; -out: - free(buf); - return ret; -} - -int com_ppl(int fd, __a_unused int argc, __a_unused char * const * const argv) -{ - unsigned i; - - PARA_DEBUG_LOG("sending playlist to client (%d entries)\n", playlist_len); - for (i = 0; i < playlist_len; i++) { - int ret = send_va_buffer(fd, "%s\n", playlist[ - (i + current_playlist_entry) % playlist_len]); - if (ret < 0) - return ret; - } - return 1; -} - -static char **pls_get_audio_file_list(unsigned int num) -{ - char **file_list; - unsigned i; - - num = PARA_MIN(num, playlist_len); - if (!num) - return NULL; - file_list = para_malloc((num + 1) * sizeof(char *)); - for (i = 0; i < num; i++) { - unsigned j = (current_playlist_entry + i + 1) % playlist_len; - file_list[i] = para_strdup(playlist[j]); - } - file_list[i] = NULL; - return file_list; -} - -static void free_playlist_contents(void) -{ - int i; - - PARA_DEBUG_LOG("freeing playlist (%d entries)\n", playlist_len); - for (i = 0; i < playlist_len; i++) - free(playlist[i]); - current_playlist_entry = 0; - playlist_len = 0; -} - -static void pls_shutdown(void) -{ - struct private_pls_data *ppd = self->private_data; - - shm_detach(ppd->client_data); - shm_destroy(ppd->client_data_shm_id); - mutex_destroy(ppd->server_mutex); - mutex_destroy(ppd->client_mutex); - free(ppd); - free_playlist_contents(); - free(playlist); - playlist = NULL; - playlist_len = 0; - playlist_size = 0; -} - -static void pls_post_select(__a_unused fd_set *rfds, __a_unused fd_set *wfds) -{ - struct private_pls_data *ppd = self->private_data; - struct pls_client_data *pcd = ppd->client_data; - int ret; - void *shm; - - mutex_lock(ppd->server_mutex); - if (!pcd->size) - goto out; - free_playlist_contents(); - ret = shm_attach(pcd->shm_id, ATTACH_RW, &shm); - if (ret < 0) { - PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); - goto out; - } - PARA_DEBUG_LOG("loading new playlist (%zd bytes)\n", pcd->size); - ret = for_each_line((char *)shm, pcd->size, &playlist_add, NULL); - shm_detach(shm); - PARA_NOTICE_LOG("new playlist (%d entries)\n", playlist_len); - sprintf(mmd->selector_info, "dbinfo1:new playlist: %d files\n" - "dbinfo2:\ndbinfo3:\n", playlist_len); - pcd->retval = 1; - pcd->size = 0; - mutex_unlock(pcd->mutex); -out: - mutex_unlock(ppd->server_mutex); -} - -static size_t string_offset(const char *str, size_t max) -{ - size_t l = strlen(str); - - if (l <= max) - return 0; - return l - max; -} - -static void pls_update_audio_file(char *audio_file) -{ - unsigned i; - char *dir = para_dirname(audio_file), - *prev = playlist[current_playlist_entry % playlist_len]; - size_t dir_off = string_offset(dir, 50), - prev_off = string_offset(prev, 70); - - for (i = 1; i <= playlist_len; i++) { - char *next; - size_t next_off; - unsigned j = (current_playlist_entry + i) % playlist_len; - if (strcmp(playlist[j], audio_file)) - continue; - current_playlist_entry = j; - next = playlist[(j + 1) %playlist_len]; - next_off = string_offset(next, 70); - snprintf(mmd->selector_info, MMD_INFO_SIZE, - "dbinfo1: %d files, current dir: %s%s\n" - "dbinfo2: prev: %s%s\n" - "dbinfo3: next: %s%s\n", - playlist_len, - dir_off? "... " : "", dir + dir_off, - prev_off? "... " : "", prev + prev_off, - next_off? "... " : "", next + next_off - ); - break; - } - free(dir); -} - -/** - * the init function for the playlist selector - * - * \param afs pointer to the struct to initialize - * - * Init all function pointers of \a afs - * - * \sa struct audio_file_selector, misc_meta_data::selector_info, mysql.c - * random_selector.c. - */ -int playlist_selector_init(struct audio_file_selector *afs) -{ - int ret; - struct private_pls_data *ppd = NULL; - void *shm = NULL; - - self = afs; - afs->cmd_list = playlist_selector_cmds; - afs->get_audio_file_list = pls_get_audio_file_list; - afs->shutdown = pls_shutdown; - afs->post_select = pls_post_select; - afs->update_audio_file = pls_update_audio_file; - ppd = para_calloc(sizeof(struct private_pls_data)); - afs->private_data = ppd; - - ppd->client_mutex = -1; - ppd->server_mutex = -1; - ppd->client_data_shm_id = -1; - ppd->client_data = NULL; - - ret = mutex_new(); - if (ret < 0) - goto err_out; - ppd->client_mutex = ret; - - ret = mutex_new(); - if (ret < 0) - goto err_out; - ppd->server_mutex = ret; - - ret = shm_new(sizeof(struct pls_client_data)); - if (ret < 0) - goto err_out; - ppd->client_data_shm_id = ret; - - ret = shm_attach(ppd->client_data_shm_id, ATTACH_RW, &shm); - if (ret < 0) - goto err_out; - ppd->client_data = shm; - ppd->client_data->size = 0; - sprintf(mmd->selector_info, "dbinfo1: Welcome to the playlist " - "selector\ndbinfo2: no playlist loaded\ndbinfo3:\n"); - return 1; -err_out: - if (ppd->client_data_shm_id >= 0) - shm_destroy(ppd->client_data_shm_id); - if (ppd->client_mutex >= 0) - mutex_destroy(ppd->client_mutex); - if (ppd->server_mutex >= 0) - mutex_destroy(ppd->server_mutex); - free(ppd); - return ret; -}