From: Andre Noll Date: Tue, 23 Oct 2007 00:23:28 +0000 (+0200) Subject: Remove old audio file selector code. X-Git-Tag: v0.3.0~260 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=8978f426314b107c55a652e0151397fdab2f003e;ds=sidebyside Remove old audio file selector code. --- diff --git a/Makefile.in b/Makefile.in index f6df58e7..fe5bdb61 100644 --- a/Makefile.in +++ b/Makefile.in @@ -63,7 +63,7 @@ PICS := $(wildcard pics/paraslash/*.jpg) gengetopts := $(wildcard *.ggo) gengetopts_c := $(gengetopts:.ggo=.cmdline.c) gengetopts_h := $(gengetopts:.ggo=.cmdline.h) -grutatxt := NEWS README.mysql CREDITS INSTALL README FEATURES +grutatxt := NEWS CREDITS INSTALL README FEATURES grutatxt_html := $(grutatxt:=.html) html_in := $(wildcard web/*.in.html) gen_html := $(subst web/,web/sync/,$(html_in)) @@ -163,9 +163,7 @@ grab_client.cmdline.h grab_client.cmdline.c: grab_client.ggo %_command_list.man: %.cmd ./command_util.sh man < $< > $@ -server_command_lists = server_command_list.man random_selector_command_list.man \ - playlist_selector_command_list.man mysql_selector_command_list.man \ - afs_command_list.man +server_command_lists = server_command_list.man afs_command_list.man man/man1/para_server.1: para_server $(server_command_lists) mkdir -p man/man1 opts="-N `for i in $(server_command_lists); do echo "-i $$i"; done`"; \ @@ -214,9 +212,6 @@ slider.o: slider.c krell.o: krell.c $(CC) -Wall -O -g -fPIC @GTK_CFLAGS@ -c -o $@ krell.c -mysql_selector.o: mysql_selector.c - $(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @mysql_cppflags@ $< - %.cmdline.o: %.cmdline.c $(CC) -c $(CPPFLAGS) $< diff --git a/afs_common.c b/afs_common.c deleted file mode 100644 index c45b3d90..00000000 --- a/afs_common.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2005-2007 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ - - -/** \file afs_common.c Functions common to all audio file selectors. */ - -#include -#include - - -#include "para.h" -#include "error.h" -#include "string.h" -#include "fd.h" -#include "server.cmdline.h" -#include "afh.h" -#include "afs.h" -#include "server.h" -#include "vss.h" -#include /* readdir() */ -#include /* stat */ -#include /* mode_t */ - -/** - * Traverse the given directory recursively. - * - * \param dirname The directory to traverse. - * \param f The function to call for each entry. - * - * For each regular file whose filename ends in .yyy, where yyy is a supported - * audio format, the supplied function \a f is called. The directory and - * filename component of the regular file are passed to \a f. - * - * \return On success, 1 is returned. Otherwise, this function returns a - * negative value which indicates the kind of the error. - */ -int find_audio_files(const char *dirname, int (*f)(const char *, const char *)) -{ - DIR *dir = NULL; - int ret, ret2, cwd_fd; - struct dirent *entry; - - ret = para_opendir(dirname, &dir, &cwd_fd); - if (ret < 0) - return ret; - /* scan cwd recursively */ - while ((entry = readdir(dir))) { - mode_t m; - char *tmp; - struct stat s; - - if (!strcmp(entry->d_name, ".")) - continue; - if (!strcmp(entry->d_name, "..")) - continue; - ret = -E_LSTAT; - if (lstat(entry->d_name, &s) == -1) - continue; - m = s.st_mode; - if (!S_ISREG(m) && !S_ISDIR(m)) /* skip links, sockets, ... */ - continue; - if (S_ISREG(m)) { /* regular file */ - if (guess_audio_format(entry->d_name) < 0) - continue; - ret = f(dirname, entry->d_name); - if (ret < 0) - goto out; - continue; - } - /* directory */ - tmp = make_message("%s/%s", dirname, entry->d_name); - ret = find_audio_files(tmp, f); - free(tmp); - if (ret < 0) - goto out; - } - ret = 1; -out: - if (dir) - closedir(dir); - ret2 = fchdir(cwd_fd); - if (ret2 < 0 && ret >= 0) - ret = ret2; - close(cwd_fd); - if (ret < 0) - PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); - return ret; -} diff --git a/afs_common.h b/afs_common.h deleted file mode 100644 index 82b75d68..00000000 --- a/afs_common.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2005-2007 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ - -/** \file afs_common.h data structures common to all audio file selectors */ - -#include - - -int find_audio_files(const char *dirname, int (*f)(const char *, const char *)); - -/** - * describes one supported audio file selector - * - * There is one such struct for each supported selector. During the startup - * part of para_server the \a init() function of the activated selector gets - * called which fills in all other function pointers. - * - */ -struct audio_file_selector { -/** - * name name of this selector - */ -const char *name; -/** - * the init routine of the selector - * - * It should check its command line options and do all necessary initialization - * like connecting to a database server. - * - * A negative return value indicates an initialization error and means that - * this selector should be ignored for now (it may later be activated again via - * the chs command). - * - * If \a init() returns success (non-negative return value), it must have - * initialized in all non-optional function pointers of the given selector - * struct. Moreover, \a cmd_list must point to a NULL-terminated array which - * holds the list of all commands that are supported by this selector. - */ -int (*init)(struct audio_file_selector *self); -/** - * list of commands supported by this selector - */ -struct server_command *cmd_list; -/** - * pointer to function returning list of at most \a num audio files to be - * streamed next - * - * \a get_audio_file_list() must return a pointer to a array of at most \a num - * char* pointers (terminated by a NULL pointer), or NULL on errors. Both the - * array and its contents must be dynamically allocated and are freed by the - * caller. - * -*/ -char **(*get_audio_file_list)(unsigned int num); -/** - * - * the update hook - * - * The \a update_audio_file pointer is optional and need not be supplied. In this - * case it is not necessary to init this pointer from within init(). If - * \a update_audio_file is non-NULL, the function it points to gets called - * whenever a new audio file was successfully loaded and is going to be - * streamed by any of paraslash's senders. The full path of the audio file is - * passed \a update_audio_file(). - * - */ -void (*update_audio_file)(char *audio_file); -/** - * - * shutdown this selector and free all resources - * - * This gets called whenever the audio file selector changes. The reason for - * this change might be that some user sent the chs command, that para_server - * receives the HUP signal, or that para_server shuts down. It is assumed to - * succeed. - */ -void (*shutdown)(void); -/** - * - * add file descriptors to fd_sets - * - * The pre_select function of the activated selector gets called just before - * para_server enters its main select loop. The selector may add its own file - * descriptors to the \a rfds or the \a wfds set. - * - * \return The highest-numbered file descriptor which was added to either of - * the two fd sets (or -1 if no file descriptors were added). - * - * \sa select(2) - */ -int (*pre_select)(fd_set *rfds, fd_set *wfds); -/** - * handle the file descriptors which are ready for I/O - * - * If the pre_select hook added one ore more file descriptors to the read or write - * set, this is the hook to check the result and do any I/O on those descriptors - * which are ready for reading/writing. - */ -void (*post_select)(fd_set *rfds, fd_set *wfds); -/** - * each selector has its private data pointer */ -void *private_data; -}; - -int mysql_selector_init(struct audio_file_selector*); -int playlist_selector_init(struct audio_file_selector*); -int random_selector_init(struct audio_file_selector*); - diff --git a/command.c b/command.c index 7dba2f90..9d902baf 100644 --- a/command.c +++ b/command.c @@ -15,7 +15,6 @@ #include "para.h" #include "error.h" #include "server.cmdline.h" -#include "afs_common.h" #include "string.h" #include "afh.h" #include "afs.h" diff --git a/configure.ac b/configure.ac index 4d984457..aef9d1ec 100644 --- a/configure.ac +++ b/configure.ac @@ -71,8 +71,8 @@ AC_CHECK_FUNCS([atexit dup2 memchr memmove memset \ strncasecmp strrchr strspn alarm], [], [AC_MSG_ERROR([function not found, cannot live without it])]) -all_errlist_objs="server mp3_afh afh_common vss command net string signal random_selector time -daemon stat crypt http_send afs_common close_on_fork playlist_selector ipc dccp +all_errlist_objs="server mp3_afh afh_common vss command net string signal time +daemon stat crypt http_send close_on_fork ipc dccp dccp_send fd user_list chunk_queue afs osl aft mood score attribute blob ringbuffer playlist sha1 rbtree sched audiod grab_client filter_chain wav compress http_recv dccp_recv recv_common write_common file_write audiod_command @@ -87,7 +87,6 @@ recv_ldflags="" receivers=" http dccp" senders=" http dccp" -selectors=" random playlist" filter_cmdline_objs="filter.cmdline compress_filter.cmdline" filter_errlist_objs="filter_chain wav compress filter string stdin stdout sched fd" @@ -108,10 +107,9 @@ audiod_errlist_objs="audiod signal string daemon stat net audiod_ldflags="" audiod_audio_formats="" -server_cmdline_objs="server.cmdline server_command_list random_selector_command_list - playlist_selector_command_list afs_command_list" -server_errlist_objs="server afh_common mp3_afh vss command net string signal random_selector - time daemon stat crypt http_send afs_common close_on_fork playlist_selector +server_cmdline_objs="server.cmdline server_command_list afs_command_list" +server_errlist_objs="server afh_common mp3_afh vss command net string signal + time daemon stat crypt http_send close_on_fork ipc dccp dccp_send fd user_list chunk_queue afs osl aft mood score attribute blob playlist sha1 rbtree sched" server_ldflags="" @@ -302,44 +300,6 @@ AC_CHECK_LIB([SDL_image], [SDL_Init], [extras="$extras para_sdl_gui"], [ AC_CHECK_HEADER(SDL/SDL.h, [], [AC_MSG_WARN([SDL/SDL.h not found])]) -########################################################################### mysql -have_mysql="yes" -OLD_CPPFLAGS="$CPPFLAGS" -OLD_LD_FLAGS="$LDFLAGS" -OLD_LIBS="$LIBS" -AC_ARG_WITH(mysql_headers, [AC_HELP_STRING(--with-mysql-headers=dir, - [look for mysql.h also in dir])]) -if test -n "$with_mysql_headers"; then - mysql_cppflags="-I$with_mysql_headers" - CPPFLAGS="$CPPFLAGS $mysql_cppflags" -fi -AC_ARG_WITH(mysql_libs, [AC_HELP_STRING(--with-mysql-libs=dir, - [look for libmysqlclient also in dir])]) -if test -n "$with_mysql_libs"; then - mysql_libs="-L$with_mysql_libs" - LDFLAGS="$LDFLAGS $mysql_libs" -fi -AC_CHECK_HEADER(mysql/mysql.h, [], [ - have_mysql="no" -]) -AC_CHECK_LIB([mysqlclient], [mysql_init], [], [ - have_mysql="no" -]) -if test "$have_mysql" = "yes"; then - selectors="$selectors mysql" - server_ldflags="$server_ldflags $mysql_libs -lmysqlclient" - server_errlist_objs="$server_errlist_objs mysql_selector" - all_errlist_objs="$all_errlist_objs mysql_selector" - server_cmdline_objs="$server_cmdline_objs mysql_selector_command_list" - AC_SUBST(mysql_cppflags) - AC_SUBST(mysql_libs) - AC_DEFINE(HAVE_MYSQL, 1, [define to 1 to turn on mysql support]) -else - AC_MSG_WARN([cannot build mysql-based audio file selector]) -fi -CPPFLAGS="$OLD_CPPFLAGS" -LDFLAGS="$OLD_LDFLAGS" -LIBS="$OLD_LIBS" ########################################################################### ogg have_ogg="yes" OLD_CPPFLAGS="$CPPFLAGS" @@ -708,12 +668,11 @@ AC_DEFINE_UNQUOTED(AUDIOD_AUDIO_FORMAT_ARRAY, $names, array of audio formats sup AC_OUTPUT AC_MSG_NOTICE([creating Makefile.deps]) -gcc -MM -MG $mysql_cppflags $faad_cppflags $mad_cppflags $ortp_cppflags $oggvorbis_cppflags *.c > Makefile.deps +gcc -MM -MG $faad_cppflags $mad_cppflags $ortp_cppflags $oggvorbis_cppflags *.c > Makefile.deps AC_MSG_NOTICE([ paraslash configuration: ~~~~~~~~~~~~~~~~~~~~~~~~ unix socket credentials: $have_ucred -audio file selectors supported by para_server: $selectors audio formats supported by para_server: $server_audio_formats senders supported by para_server/para_send: $senders receivers supported by para_audiod/para_recv: $receivers diff --git a/error.h b/error.h index 9d1f7bb0..56b26d78 100644 --- a/error.h +++ b/error.h @@ -316,10 +316,6 @@ extern const char **para_errlist[]; PARA_ERROR(BAD_AFS_CODE, "received junk from afs"), \ -#define AFS_COMMON_ERRORS \ - PARA_ERROR(LSTAT, "lstat error"), \ - - #define CRYPT_ERRORS \ PARA_ERROR(PRIVATE_KEY, "can not read private key"), \ PARA_ERROR(PUBLIC_KEY, "can not read public key"), \ @@ -334,33 +330,6 @@ extern const char **para_errlist[]; PARA_ERROR(SEND_QUEUED_CHUNK, "failed to send queued chunk"), \ -#define RANDOM_SELECTOR_ERRORS \ - PARA_ERROR(NOTHING_FOUND, "no audio files found"), \ - - -#define MYSQL_SELECTOR_ERRORS \ - PARA_ERROR(MYSQL_SYNTAX, "mysql syntax error"), \ - PARA_ERROR(NOTCONN, "not connected to mysql server"), \ - PARA_ERROR(TOOBIG, "mysql: file too large"), \ - PARA_ERROR(NAMETOOLONG, "mysql: name too long"), \ - PARA_ERROR(QFAILED, "mysql query failed"), \ - PARA_ERROR(NOROW, "row is NULL"), \ - PARA_ERROR(NOATTS, "can not get attributes from mysql table"), \ - PARA_ERROR(NORESULT, "error while fetching mysql result"), \ - PARA_ERROR(EMPTY_RESULT, "result is empty"), \ - PARA_ERROR(ESCAPE, "can not escape string"), \ - PARA_ERROR(GET_AUDIO_FILE, "can not get current audio file"), \ - PARA_ERROR(GET_STREAM, "can not get current stream"), \ - PARA_ERROR(NO_STREAM, "no such stream"), \ - PARA_ERROR(AUDIO_FILE, "no such audio file"), \ - PARA_ERROR(GET_QUERY, "can not get query for specified stream"), \ - PARA_ERROR(TMPFILE, "error while writing temporary file"), \ - PARA_ERROR(META, "can not get meta data"), \ - PARA_ERROR(MYSQL_INIT, "can not initialize mysql connection"), \ - PARA_ERROR(NO_MYSQL_PASSWD, "fatal: no mysql passord given"), \ - PARA_ERROR(NO_AF_DIR, "fatal: audio file directory not given"), \ - - #define COMMAND_ERRORS \ PARA_ERROR(COMMAND_SYNTAX, "syntax error in command"), \ PARA_ERROR(AUTH, "did not receive auth request"), \ @@ -374,10 +343,6 @@ extern const char **para_errlist[]; PARA_ERROR(BAD_USER, "you don't exist. Go away."), \ -#define PLAYLIST_SELECTOR_ERRORS \ - PARA_ERROR(LOAD_PLAYLIST, "failed to load playlist"), \ - - #define IPC_ERRORS \ PARA_ERROR(SEM_GET, "failed to create semaphore"), \ PARA_ERROR(SEM_REMOVE, "can not remove semaphore"), \ diff --git a/mysql_selector.c b/mysql_selector.c deleted file mode 100644 index 5b145dca..00000000 --- a/mysql_selector.c +++ /dev/null @@ -1,2325 +0,0 @@ -/* - * Copyright (C) 1999-2007 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ - -/** \file mysql_selector.c para_server's mysql-based audio file selector */ - -/** \cond some internal constants */ -#define MEDIUM_BLOB_SIZE 16777220 /* (2**24 + 4) */ -#define BLOB_SIZE 65539 /* (2**16 + 3) */ -/** \endcond */ - -#include "para.h" -#include "error.h" -#include "string.h" -#include "server.cmdline.h" -#include "afh.h" -#include "afs.h" -#include "server.h" -#include "vss.h" -#include "afs_common.h" -#include -#include -#include -#include "net.h" -#include "list.h" -#include "user_list.h" -#include "mysql_selector_command_list.h" -#include "ipc.h" - -/** pointer to the shared memory area */ -extern struct misc_meta_data *mmd; - -static void *mysql_ptr = NULL; -static int mysql_lock; - -/** - * contains name/replacement pairs used by s_a_r_list() - * - * \sa s_a_r() - */ -struct para_macro { - /** the name of the macro */ - const char *name; - /** the replacement text */ - const char *replacement; -}; - -static const struct para_macro mysql_macro_list[] = { - { .name = "IS_N_SET", - .replacement = "(data.%s != '1')" - }, { - .name = "IS_SET", - .replacement = "(data.%s = '1')" - }, { - .name = "PICID", - .replacement = "%sdata.Pic_Id" - }, { - .name = "NAME_LIKE", - .replacement = "(data.name like '%s')" - }, { - .name = "LASTPLAYED", - .replacement = "%sFLOOR((UNIX_TIMESTAMP(now())" - "-UNIX_TIMESTAMP(data.Lastplayed))/60)" - }, { - .name = "NUMPLAYED", - .replacement = "%sdata.Numplayed" - }, { - .name = NULL, - } -}; - -/** - * Simple search and replace routine. - * - * \param src Source String. - * \param macro_name The name of the macro. - * \param replacement The replacement format string. - * - * In \p src, replace each occurence of \p macro_name(arg) by the string - * determined by the \p replacement format string. \p replacement may (but - * needs not) contain a single string conversion specifier (%s) which gets - * replaced by \p arg. - * - * \return A string in which all matches in \p src are replaced, or \p NULL if - * an error was encountered. Caller must free the result. - * - * \sa regcomp(3) - */ -__must_check __malloc static char *s_a_r(const char *src, const char* macro_name, - const char *replacement) -{ - regex_t preg; - size_t nmatch = 1; - regmatch_t pmatch[1]; - int eflags = 0; - char *dest = NULL; - const char *bufptr = src; - - if (!macro_name || !replacement || !src) - return para_strdup(src); - if (regcomp(&preg, macro_name, 0) != 0) - return NULL; - while (regexec(&preg, bufptr, nmatch, pmatch, eflags) - != REG_NOMATCH) { - char *tmp, *arg, *o_bracket, *c_bracket; - - o_bracket = strchr(bufptr + pmatch[0].rm_so, '('); - c_bracket = o_bracket? strchr(o_bracket, ')') : NULL; - if (!c_bracket) - goto out; - tmp = para_strdup(bufptr); - tmp[pmatch[0].rm_so] = '\0'; - dest = para_strcat(dest, tmp); - free(tmp); - - arg = para_strdup(o_bracket + 1); - arg[c_bracket - o_bracket - 1] = '\0'; - tmp = make_message(replacement, arg); - free(arg); - dest = para_strcat(dest, tmp); - free(tmp); - bufptr = c_bracket; - bufptr++; - } - dest = para_strcat(dest, bufptr); -// PARA_DEBUG_LOG("%s: returning %s\n", __func__, dest); -out: - regfree(&preg); - return dest; -} - -/** - * replace a string according to a list of macros - * - * \param macro_list the array containing a macro/replacement pairs. - * \param src the source string - * - * This function just calls s_a_r() for each element of \p macro_list. - * - * \return \p NULL if one of the underlying calls to \p s_a_r returned \p NULL. - * Otherwise the completely expanded version of \p src is returned. - */ -__must_check __malloc static char *s_a_r_list(const struct para_macro *macro_list, - char *src) -{ - const struct para_macro *mp = macro_list; - char *ret = NULL, *tmp = para_strdup(src); - - while (mp->name) { - ret = s_a_r(tmp, mp->name, mp->replacement); - free(tmp); - if (!ret) /* syntax error */ - return NULL; - tmp = ret; - mp++; - } - //PARA_DEBUG_LOG("%s: returning %s\n", __func__, dest); - return ret; -} - -static int lockless_real_query(const char *query) -{ - if (!mysql_ptr) - return -E_NOTCONN; - PARA_DEBUG_LOG("%s\n", query); - if (mysql_real_query(mysql_ptr, query, strlen(query))) { - PARA_ERROR_LOG("real_query error (%s)\n", - mysql_error(mysql_ptr)); - return -E_QFAILED; - } - return 1; -} - -static int real_query(const char *query) -{ - int ret; - - mutex_lock(mysql_lock); - ret = lockless_real_query(query); - mutex_unlock(mysql_lock); - return ret; -} - -/* - * Use open connection given by mysql_ptr to query server. Returns a - * result pointer on succes and NULL on errors - */ -static struct MYSQL_RES *get_result(const char *query) -{ - void *result = NULL; - - mutex_lock(mysql_lock); - if (lockless_real_query(query) < 0) - goto out; - result = mysql_store_result(mysql_ptr); - if (!result) - PARA_ERROR_LOG("%s", "store_result error\n"); -out: - mutex_unlock(mysql_lock); - return result; -} -/* - * write input from fd to dynamically allocated char array, - * but maximal max_size byte. Return size. - */ -static int fd2buf(int fd, char **buf_ptr, size_t max_size) -{ - const size_t chunk_size = 1024; - size_t size = 2048; - char *buf = para_malloc(size * sizeof(char)), *p = buf; - int ret; - - while ((ret = recv_bin_buffer(fd, p, chunk_size)) > 0) { - p += ret; - if ((p - buf) + chunk_size >= size) { - char *tmp; - - size *= 2; - if (size > max_size) { - ret = -E_TOOBIG; - goto out; - } - tmp = para_realloc(buf, size); - p = (p - buf) + tmp; - buf = tmp; - } - } - if (ret < 0) - goto out; - *buf_ptr = buf; - ret = p - buf; -out: - if (ret < 0 && buf) - free(buf); - return ret; -} - -static char *escape_blob(const char* old, size_t size) -{ - char *new; - - if (!mysql_ptr) - return NULL; - new = para_malloc(2 * size * sizeof(char) + 1); - mysql_real_escape_string(mysql_ptr, new, old, size); - return new; -} - -static char *escape_str(const char* old) -{ - return escape_blob(old, strlen(old)); -} - -static char *escaped_basename(const char *name) -{ - char *esc, *bn = para_basename(name); - - if (!bn) - return NULL; - esc = escape_str(bn); - free(bn); - return esc; -} - -/* - * new attribute - */ -int com_na(__a_unused int fd, int argc, char * const * argv) -{ - char *q, *tmp; - int ret; - - if (argc < 2) - return -E_MYSQL_SYNTAX; - tmp = escape_str(argv[1]); - if (!tmp) - return -E_ESCAPE; - q = make_message("alter table data add %s char(1) " - "not null default 0", tmp); - free(tmp); - ret = real_query(q); - free(q); - return ret; -} - -/* - * delete attribute - */ -int com_da(__a_unused int fd, int argc, char * const * argv) -{ - char *q, *tmp; - int ret; - - if (argc < 2) - return -E_MYSQL_SYNTAX; - tmp = escape_str(argv[1]); - if (!tmp) - return -E_ESCAPE; - q = make_message("alter table data drop %s", tmp); - free(tmp); - ret = real_query(q); - free(q); - return ret; -} - -/* stradd/pic_add */ -static int com_stradd_picadd(int fd, int argc, char * const * argv) -{ - char *blob = NULL, *esc_blob = NULL, *q = NULL, *tmp = NULL; - const char *fmt, *del_fmt; - int ret, stradd = strcmp(argv[0], "picadd"); - size_t size; - - if (argc < 2) - return -E_MYSQL_SYNTAX; - if (strlen(argv[1]) >= MAXLINE - 1) - return -E_NAMETOOLONG; - if (!mysql_ptr) - return -E_NOTCONN; - if (stradd) { - size = BLOB_SIZE; - fmt = "insert into streams (name, def) values ('%s','%s')"; - del_fmt="delete from streams where name='%s'"; - } else { - size = MEDIUM_BLOB_SIZE; - fmt = "insert into pics (name, pic) values ('%s','%s')"; - del_fmt="delete from pics where pic='%s'"; - } - tmp = escape_str(argv[1]); - if (!tmp) - return -E_ESCAPE; - q = make_message(del_fmt, tmp); - free(tmp); - ret = real_query(q); - free(q); - if (ret < 0) - return ret; - if ((ret = send_buffer(fd, AWAITING_DATA_MSG) < 0)) - return ret; - if ((ret = fd2buf(fd, &blob, size)) < 0) - return ret; - size = ret; - if (stradd) - blob[size] = '\0'; - ret = -E_ESCAPE; - esc_blob = escape_blob(blob, size); - if (!esc_blob) - goto out; - tmp = escape_str(argv[1]); - if (!tmp) - goto out; - q = make_message(fmt, tmp, esc_blob); - ret = real_query(q); -out: - free(blob); - free(esc_blob); - free(tmp); - free(q); - return ret; -} - -/* stradd */ -int com_stradd(int fd, int argc, char * const * argv) -{ - return com_stradd_picadd(fd, argc, argv); -} - -/* pic_add */ -int com_picadd(int fd, int argc, char * const * argv) -{ - return com_stradd_picadd(fd, argc, argv); -} - -/* - * print results to fd - */ -static int print_results(int fd, void *result, - my_ulonglong top, my_ulonglong left, - my_ulonglong bottom, my_ulonglong right) -{ - unsigned int i,j; - int ret; - MYSQL_ROW row; - - for (i = top; i <= bottom; i++) { - row = mysql_fetch_row(result); - if (!row || !row[0]) - return -E_NOROW; - for (j = left; j <= right; j++) { - ret = send_va_buffer(fd, j == left? "%s" : "\t%s", - row[j]? row[j] : "NULL"); - if (ret < 0) - return ret; - } - ret = send_buffer(fd, "\n"); - if (ret < 0) - return ret; - } - return 0; -} - -/* - * verbatim - */ -int com_verb(int fd, int argc, char * const * argv) -{ - void *result = NULL; - int ret; - my_ulonglong num_rows, num_fields, top = 0, left = 0; - char *tmp; - - if (argc < 2) - return -E_MYSQL_SYNTAX; - tmp = escape_str(argv[1]); - if (!tmp) - return -E_ESCAPE; - result = get_result(tmp); - free(tmp); - if (!result) - /* return success, because it's ok to have no results */ - return 1; - num_fields = mysql_field_count(mysql_ptr); - num_rows = mysql_num_rows(result); - ret = 1; - if (num_fields && num_rows) - ret = print_results(fd, result, top, left, num_rows - 1, - num_fields - 1); - mysql_free_result(result); - return ret; -} - -/* returns NULL on errors or if there are no atts defined yet */ -static void *get_all_attributes(void) -{ - void *result = get_result("desc data"); - unsigned int num_rows; - - if (!result) - return NULL; - num_rows = mysql_num_rows(result); - if (num_rows < 5) { - mysql_free_result(result); - return NULL; - } - mysql_data_seek(result, (my_ulonglong)4); /* skip Lastplayed, Numplayed... */ - return result; -} - -/* - * list all attributes - */ -int com_laa(int fd, int argc, __a_unused char * const * argv) -{ - void *result; - int ret; - my_ulonglong top = 0, left = 0, bottom, right = 0; - - if (argc != 1) - return -E_MYSQL_SYNTAX; - result = get_all_attributes(); - if (!result) - return -E_NOATTS; - bottom = mysql_num_rows(result); - if (bottom < 5) - return -E_MYSQL_SYNTAX; - bottom -= 5; - ret = print_results(fd, result, top, left, bottom, right); - mysql_free_result(result); - return ret; -} - -/* - * history - */ -int com_hist(int fd, int argc, char * const * argv) -{ - int ret; - void *result = NULL; - char *q, *atts; - my_ulonglong num_rows, top = 0, left = 0, right = 1; - - if (argc > 3) - return -E_MYSQL_SYNTAX; - if (argc > 1) { - char *tmp = escape_str(argv[1]); - if (!tmp) - return -E_ESCAPE; - atts = make_message("where %s = '1'", tmp); - free(tmp); - } else - atts = para_strdup(NULL); - - q = make_message("select name, to_days(now()) - to_days(lastplayed) from " - "data %s order by lastplayed", atts); - free(atts); - result = get_result(q); - free(q); - if (!result) - return -E_NORESULT; - num_rows = mysql_num_rows(result); - ret = 1; - if (num_rows) - ret = print_results(fd, result, top, left, num_rows - 1, right); - mysql_free_result(result); - return ret; -} - -/* - * get last num audio files - */ -int com_last(int fd, int argc, char * const * argv) -{ - void *result = NULL; - char *q; - int num, ret; - my_ulonglong top = 0, left = 0, right = 0; - - if (argc < 2) - num = 10; - else - num = atoi(argv[1]); - if (!num) - return -E_MYSQL_SYNTAX; - q = make_message("select name from data order by lastplayed desc " - "limit %u", num); - result = get_result(q); - free(q); - if (!result) - return -E_NORESULT; - ret = print_results(fd, result, top, left, mysql_num_rows(result) - 1, - right); - mysql_free_result(result); - return ret; -} - -int com_mbox(int fd, int argc, char * const * argv) -{ - void *result; - MYSQL_ROW row; - int ret; - my_ulonglong num_rows, num_fields, top = 0, left = 0; - char *query = para_strdup("select concat('From foo@localhost ', " - "date_format(Lastplayed, '%a %b %e %T %Y'), " - "'\nReceived: from\nTo: bar\n"); - - ret = -E_NOATTS; - result = get_all_attributes(); - if (!result) - goto out; - ret = -E_NOROW; - while ((row = mysql_fetch_row(result))) { - char *tmp; - - if (!row[0]) - goto out; - tmp = make_message("%sX-Attribute-%s: ', %s, '\n", query, - row[0], row[0]); - free(query); - query = tmp; - } - query = para_strcat(query, - "From: a\n" - "Subject: " - "', name, '" - "\n\n\n" - "') from data" - ); - if (argc >= 2) { - char *esc = escape_str(argv[1]), *tmp; - ret = -E_ESCAPE; - if (!esc) - goto out; - tmp = make_message("%s where name LIKE '%s'", query, esc); - free(esc); - free(query); - query = tmp; - } - mysql_free_result(result); - ret = -E_NORESULT; - result = get_result(query); - if (!result) - goto out; - ret = -E_EMPTY_RESULT; - num_fields = mysql_field_count(mysql_ptr); - num_rows = mysql_num_rows(result); - if (!num_fields || !num_rows) - goto out; - ret = print_results(fd, result, top, left, num_rows - 1, - num_fields - 1); -out: - free(query); - if (result) - mysql_free_result(result); - return ret; -} - -/* - * get attributes by name. If verbose is not 0, this function returns a string - * of the form 'att1="0",att2="1"'... which is used in com_cam() for - * constructing a mysql update query. Otherwise the space-separated list of all - * attributes which are set in the audio file given by name is returned. Never - * returns NULL in *NON VERBOSE* mode. - */ -static char *get_atts(char *name, int verbose) -{ - char *atts = NULL, *buf, *ebn; - void *result = NULL, *result2 = NULL; - MYSQL_ROW row, row2; - int i; - my_ulonglong num_fields, offset = 4; /* skip Lastplayed, Numplayed... */ - - - result2 = get_all_attributes(); - if (!result2) - goto out; - ebn = escaped_basename(name); - if (!ebn) - goto out; - buf = make_message("select * from data where name='%s'", ebn); - free(ebn); - result = get_result(buf); - free(buf); - if (!result) - goto out; - num_fields = mysql_num_fields(result); - if (num_fields < 5) - goto out; - mysql_data_seek(result2, offset); - row = mysql_fetch_row(result); - if (!row) - goto out; - for (i = 4; i < num_fields; i++) { - int is_set = row[i] && !strcmp(row[i], "1"); - row2 = mysql_fetch_row(result2); - if (!row2 || !row2[0]) - goto out; - if (atts && (verbose || is_set)) - atts = para_strcat(atts, verbose? "," : " "); - if (is_set || verbose) - atts = para_strcat(atts, row2[0]); - if (verbose) - atts = para_strcat(atts, is_set? "=\"1\"" : "=\"0\""); - } -out: - if (result2) - mysql_free_result(result2); - if (result) - mysql_free_result(result); - if (!atts && !verbose) - atts = para_strdup("(none)"); - return atts; -} - -/* never returns NULL in verbose mode */ -static char *get_meta(char *name, int verbose) -{ - MYSQL_ROW row; - void *result = NULL; - char *ebn, *q, *ret = NULL; - const char *verbose_fmt = - "select concat('lastplayed: ', " - "(to_days(now()) - to_days(lastplayed))," - "' day(s). numplayed: ', numplayed, " - "', pic: ', pic_id) " - "from data where name = '%s'"; - /* is that really needed? */ - const char *fmt = "select concat('lastplayed=\\'', lastplayed, " - "'\\', numplayed=\\'', numplayed, " - "'\\', pic_id=\\'', pic_id, '\\'') " - "from data where name = '%s'"; - - if (!(ebn = escaped_basename(name))) - goto out; - q = make_message(verbose? verbose_fmt : fmt, ebn); - free(ebn); - result = get_result(q); - free(q); - if (!result) - goto out; - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto out; - ret = para_strdup(row[0]); -out: - if (result) - mysql_free_result(result); - if (!ret && verbose) - ret = para_strdup("(not yet played)"); - return ret; -} - -static char *get_dir(char *name) -{ - char *ret = NULL, *q, *ebn; - void *result; - MYSQL_ROW row; - - if (!(ebn = escaped_basename(name))) - return NULL; - q = make_message("select dir from dir where name = '%s'", ebn); - free(ebn); - result = get_result(q); - free(q); - if (!result) - return NULL; - row = mysql_fetch_row(result); - if (row && row[0]) - ret = para_strdup(row[0]); - mysql_free_result(result); - return ret; -} - -/* never returns NULL */ -static char *get_current_stream(void) -{ - char *ret; - MYSQL_ROW row; - void *result = get_result("select def from streams where " - "name = 'current_stream'"); - - if (!result) - goto err_out; - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto err_out; - ret = para_strdup(row[0]); - mysql_free_result(result); - return ret; -err_out: - if (result) - mysql_free_result(result); - return para_strdup("(none)"); -} - -/* - * Read stream definition of stream streamname and construct mysql - * query. Return NULL on errors. If streamname is NULL, use current - * stream. If that is also NULL, use query that selects everything. - * If filename is NULL, query will list everything, otherwise only - * the score of given file. - */ -static char *get_query(const char *streamname, char *filename, int with_path) -{ - char *accept_opts = NULL, *deny_opts = NULL, *score = NULL; - char *where_clause, *order, *query; - char command[255] = ""; /* buffer for sscanf */ - void *result; - MYSQL_ROW row; - char *end, *tmp; - char *select_clause = NULL; - if (!streamname) - tmp = get_current_stream(); - else { - tmp = escape_str(streamname); - if (!tmp) - return NULL; - } - if (!strcmp(tmp, "(none)")) { - free(tmp); - if (filename) { - char *ret, *ebn = escaped_basename(filename); - if (!ebn) - return NULL; - ret = make_message("select to_days(now()) - " - "to_days(lastplayed) from data " - "where name = '%s'", ebn); - free(ebn); - return ret; - } - if (with_path) - return make_message( - "select concat(dir.dir, '/', dir.name) " - "from data, dir where dir.name = data.name " - "order by data.lastplayed" - ); - return make_message( - "select name from data where name is not NULL " - "order by lastplayed" - ); - } - free(tmp); - query = make_message("select def from streams where name = '%s'", - streamname); - result = get_result(query); - free(query); - query = NULL; - if (!result) - goto out; - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto out; - end = row[0]; - while (*end) { - int n; - char *arg, *line = end; - - if (!(end = strchr(line, '\n'))) - break; - *end = '\0'; - end++; - if (sscanf(line, "%200s%n", command, &n) < 1) - continue; - arg = line + n; - if (!strcmp(command, "accept:")) { - char *tmp2 = s_a_r_list(mysql_macro_list, arg); - if (accept_opts) - accept_opts = para_strcat( - accept_opts, " or "); - accept_opts = para_strcat(accept_opts, tmp2); - free(tmp2); - continue; - } - if (!strcmp(command, "deny:")) { - char *tmp2 = s_a_r_list(mysql_macro_list, arg); - if (deny_opts) - deny_opts = para_strcat(deny_opts, " or "); - deny_opts = para_strcat(deny_opts, tmp2); - free(tmp2); - continue; - } - if (!score && !strcmp(command, "score:")) - score = s_a_r_list(mysql_macro_list, arg); - } - if (!score) { - score = s_a_r_list(mysql_macro_list, conf.mysql_default_score_arg); - if (!score) - goto out; - } - if (filename) { - char *ebn = escaped_basename(filename); - if (!ebn) - goto out; - select_clause = make_message("select %s from data ", score); - free(score); - where_clause = make_message( "where name = '%s' ", ebn); - free(ebn); - order = para_strdup(""); - goto write_query; - } - select_clause = para_strdup(with_path? - "select concat(dir.dir, '/', dir.name) from data, dir " - "where dir.name = data.name " - : - "select name from data where name is not NULL"); - order = make_message("order by -(%s)", score); - free(score); - if (accept_opts && deny_opts) { - where_clause = make_message("and ((%s) and not (%s)) ", - accept_opts, deny_opts); - goto write_query; - } - if (accept_opts && !deny_opts) { - where_clause = make_message("and (%s) ", accept_opts); - goto write_query; - } - if (!accept_opts && deny_opts) { - where_clause = make_message("and not (%s) ", deny_opts); - goto write_query; - } - where_clause = para_strdup(""); -write_query: - query = make_message("%s %s %s", select_clause, where_clause, order); - free(order); - free(select_clause); - free(where_clause); -out: - if (accept_opts) - free(accept_opts); - if (deny_opts) - free(deny_opts); - if (result) - mysql_free_result(result); - return query; -} - - - -/* - * This is called from server and from some commands. Name must not be NULL - * Never returns NULL. - */ -static char *get_selector_info(char *name) -{ - char *meta, *atts, *info, *dir, *query, *stream; - void *result = NULL; - MYSQL_ROW row = NULL; - - if (!name) - return para_strdup("(none)"); - stream = get_current_stream(); - meta = get_meta(name, 1); - atts = get_atts(name, 0); - dir = get_dir(name); - /* get score */ - query = get_query(stream, name, 0); /* FIXME: pass stream == NULL instead? */ - if (!query) - goto write; - result = get_result(query); - free(query); - if (result) - row = mysql_fetch_row(result); -write: - info = make_message("dbinfo1:dir: %s\n" - "dbinfo2:stream: %s, %s, score: %s\n" - "dbinfo3:%s\n", - dir? dir : "(not contained in table)", - stream, meta, - (result && row && row[0])? row[0] : "(no score)", - atts); - free(dir); - free(meta); - free(atts); - free(stream); - if (result) - mysql_free_result(result); - return info; -} - -/* might return NULL */ -static char *get_current_audio_file(void) -{ - char *name; - mmd_lock(); - name = para_basename(mmd->filename); - mmd_unlock(); - return name; -} - -/* If called as child, mmd_lock must be held */ -static void update_mmd(char *info) -{ - PARA_DEBUG_LOG("%s", "updating shared memory area\n"); - strncpy(mmd->selector_info, info, MMD_INFO_SIZE - 1); - mmd->selector_info[MMD_INFO_SIZE - 1] = '\0'; -} - -static void refresh_selector_info(void) -{ - char *name = get_current_audio_file(); - char *info; - - if (!name) - return; - info = get_selector_info(name); - free(name); - mmd_lock(); - update_mmd(info); - mmd_unlock(); - free(info); -} - -/* list attributes / print database info */ -static int com_la_info(int fd, int argc, char * const * argv) -{ - char *name = NULL, *meta = NULL, *atts = NULL, *dir = NULL; - int ret, la = strcmp(argv[0], "info"); - - if (argc < 2) { - ret = -E_GET_AUDIO_FILE; - if (!(name = get_current_audio_file())) - goto out; - ret = send_va_buffer(fd, "%s\n", name); - if (ret < 0) - goto out; - } else { - ret = -E_ESCAPE; - if (!(name = escaped_basename(argv[1]))) - goto out; - } - meta = get_meta(name, 1); - atts = get_atts(name, 0); - dir = get_dir(name); - if (la) - ret = send_va_buffer(fd, "%s\n", atts); - else - ret = send_va_buffer(fd, "dir: %s\n" "%s\n" "attributes: %s\n", - dir? dir : "(not contained in table)", meta, atts); -out: - free(meta); - free(atts); - free(dir); - free(name); - return ret; -} - -/* list attributes */ -int com_la(int fd, int argc, char * const * argv) -{ - return com_la_info(fd, argc, argv); -} - -/* print database info */ -int com_info(int fd, int argc, char * const * argv) -{ - return com_la_info(fd, argc, argv); -} - -static int change_stream(const char *stream) -{ - char *query; - int ret; - query = make_message("update streams set def='%s' " - "where name = 'current_stream'", stream); - ret = real_query(query); - free(query); - return ret; -} - -static int get_pic_id_by_name(char *name) -{ - char *q, *ebn; - void *result = NULL; - int ret; - MYSQL_ROW row; - - if (!(ebn = escaped_basename(name))) - return -E_ESCAPE; - q = make_message("select pic_id from data where name = '%s'", ebn); - free(ebn); - result = get_result(q); - free(q); - if (!result) - return -E_NORESULT; - row = mysql_fetch_row(result); - ret = -E_NOROW; - if (row && row[0]) - ret = atoi(row[0]); - mysql_free_result(result); - return ret; -} - -static int remove_entry(const char *name) -{ - char *q, *ebn = escaped_basename(name); - int ret = -E_ESCAPE; - - if (!ebn) - goto out; - q = make_message("delete from data where name = '%s'", ebn); - real_query(q); /* ignore errors */ - free(q); - q = make_message("delete from dir where name = '%s'", ebn); - real_query(q); /* ignore errors */ - free(q); - ret = 1; -out: - free(ebn); - return ret; -} - -static int add_entry(const char *name) -{ - char *q, *dn, *ebn = NULL, *edn = NULL; - int ret; - - if (!name || !*name) - return -E_MYSQL_SYNTAX; - ebn = escaped_basename(name); - if (!ebn) - return -E_ESCAPE; - ret = -E_MYSQL_SYNTAX; - dn = para_dirname(name); - if (!dn) - goto out; - ret = -E_ESCAPE; - edn = escape_str(dn); - free(dn); - if (!edn || !*edn) - goto out; - q = make_message("insert into data (name, pic_id) values " - "('%s', '%s')", ebn, "1"); - ret = real_query(q); -// ret = 1; PARA_DEBUG_LOG("q: %s\n", q); - free(q); - if (ret < 0) - goto out; - q = make_message("insert into dir (name, dir) values " - "('%s', '%s')", ebn, edn); -// ret = 1; PARA_DEBUG_LOG("q: %s\n", q); - ret = real_query(q); - free(q); -out: - if (ebn) - free(ebn); - if (edn) - free(edn); - return ret; -} - -/* - * remove/add entries - */ -static int com_rm_ne(__a_unused int fd, int argc, char * const * argv) -{ - int ne = !strcmp(argv[0], "ne"); - int i, ret; - if (argc < 2) - return -E_MYSQL_SYNTAX; - for (i = 1; i < argc; i++) { - ret = remove_entry(argv[i]); - if (ret < 0) - return ret; - if (!ne) - continue; - ret = add_entry(argv[i]); - if (ret < 0) - return ret; - } - return 1; -} - -/* - * rm - */ -int com_rm(int fd, int argc, char * const * argv) -{ - return com_rm_ne(fd, argc, argv); -} - -/* - * ne - */ -int com_ne(int fd, int argc, char * const * argv) -{ - return com_ne(fd, argc, argv); -} - -/* - * mv: rename entry - */ -int com_mv(__a_unused int fd, int argc, char * const * argv) -{ - char *q, *dn, *ebn1 = NULL, *ebn2 = NULL, *edn = NULL; - int ret; - - if (argc != 3) - return -E_MYSQL_SYNTAX; - ret = -E_ESCAPE; - ebn1 = escaped_basename(argv[1]); - ebn2 = escaped_basename(argv[2]); - if (!ebn1 || !ebn2 || !*ebn1 || !*ebn2) - goto out; - ret = -E_MYSQL_SYNTAX; - if (!strcmp(ebn1, ebn2)) - goto update_dir; - remove_entry(argv[2]); /* no need to escape, ignore error */ - q = make_message("update data set name = '%s' where name = '%s'", - ebn2, ebn1); - ret = real_query(q); - free(q); - if (ret < 0) - goto out; - ret = -E_AUDIO_FILE; - if (!mysql_affected_rows(mysql_ptr)) - goto out; - q = make_message("update dir set name = '%s' where name = '%s'", - ebn2, ebn1); - ret = real_query(q); - free(q); - if (ret < 0) - goto out; -update_dir: - ret = 1; - dn = para_dirname(argv[2]); - if (!dn) - goto out; - ret = -E_ESCAPE; - edn = escape_str(dn); - free(dn); - if (!edn) - goto out; - ret = 1; - if (!*edn) - goto out; - q = make_message("update dir set dir = '%s' where name = '%s'", - edn, ebn2); - ret = real_query(q); - free(q); -out: - free(edn); - free(ebn1); - free(ebn2); - return ret; -} - -/* - * set field - */ -static int com_set(__a_unused int fd, int argc, char * const * argv) -{ - char *q, *ebn; - long unsigned id; - int i, ret; - const char *field = strcmp(argv[0], "picass")? "numplayed" : "pic_id"; - - if (argc < 3) - return -E_MYSQL_SYNTAX; - id = atol(argv[1]); - for (i = 2; i < argc; i++) { - ebn = escaped_basename(argv[i]); - if (!ebn) - return -E_ESCAPE; - q = make_message("update data set %s = %lu " - "where name = '%s'", field, id, ebn); - free(ebn); - ret = real_query(q); - free(q); - if (ret < 0) - return ret; - } - return 1; -} - -/* - * snp: set numplayed - */ -int com_picass(int fd, int argc, char * const * argv) -{ - return com_set(fd, argc, argv); -} - -/* - * snp: set numplayed - */ -int com_snp(int fd, int argc, char * const * argv) -{ - int ret = com_set(fd, argc, argv); - if (ret >= 0) - refresh_selector_info(); - return ret; -} - -/* - * picch: change entry's name in pics table - */ -int com_picch(__a_unused int fd, int argc, char * const * argv) -{ - int ret; - long unsigned id; - char *q, *tmp; - - if (argc != 3) - return -E_MYSQL_SYNTAX; - id = atol(argv[1]); - ret = -E_ESCAPE; - tmp = escape_str(argv[2]); - if (!tmp) - return -E_ESCAPE; - q = make_message("update pics set name = '%s' where id = %lu", tmp, id); - free(tmp); - ret = real_query(q); - free(q); - return ret; -} - -/* - * piclist: print list of pics in db - */ -int com_piclist(__a_unused int fd, int argc, __a_unused char * const * argv) -{ - void *result = NULL; - MYSQL_ROW row; - unsigned long *length; - int ret; - - if (argc != 1) - return -E_MYSQL_SYNTAX; - result = get_result("select id,name,pic from pics order by id"); - if (!result) - return -E_NORESULT; - while ((row = mysql_fetch_row(result))) { - length = mysql_fetch_lengths(result); - if (!row || !row[0] || !row[1] || !row[2]) - continue; - ret = send_va_buffer(fd, "%s\t%lu\t%s\n", row[0], length[2], row[1]); - if (ret < 0) - goto out; - } - ret = 1; -out: - mysql_free_result(result); - return ret; -} - -/* - * picdel: delete picture from database - */ -int com_picdel(int fd, int argc, char * const * argv) -{ - char *q; - long unsigned id; - my_ulonglong aff; - int i, ret; - - if (argc < 2) - return -E_MYSQL_SYNTAX; - for (i = 1; i < argc; i++) { - id = atol(argv[i]); - q = make_message("delete from pics where id = %lu", id); - ret = real_query(q); - free(q); - if (ret < 0) - return ret; - aff = mysql_affected_rows(mysql_ptr); - if (!aff) { - ret = send_va_buffer(fd, "No such id: %lu\n", id); - if (ret < 0) - return ret; - continue; - } - q = make_message("update data set pic_id = 1 where pic_id = %lu", id); - ret = real_query(q); - free(q); - } - return 1; -} -/* - * pic: get picture by name or by number - */ -int com_pic(int fd, int argc, char * const * argv) -{ - void *result = NULL; - MYSQL_ROW row; - unsigned long *length, id; - int ret; - char *q, *name = NULL; - - if (argc < 2) { - ret = -E_GET_AUDIO_FILE; - name = get_current_audio_file(); - } else { - ret = -E_ESCAPE; - name = escaped_basename(argv[1]); - } - if (!name) - return ret; - if (*name == '#') - id = atoi(name + 1); - else - id = get_pic_id_by_name(name); - free(name); - if (id <= 0) - return id; - q = make_message("select pic from pics where id = '%lu'", id); - result = get_result(q); - free(q); - if (!result) - return -E_NORESULT; - row = mysql_fetch_row(result); - ret = -E_NOROW; - if (!row || !row[0]) - goto out; - length = mysql_fetch_lengths(result); - ret = send_bin_buffer(fd, row[0], *length); -out: - mysql_free_result(result); - return ret; -} - -/* strdel */ -int com_strdel(__a_unused int fd, int argc, char * const * argv) -{ - char *q, *tmp; - int ret; - - if (argc < 2) - return -E_MYSQL_SYNTAX; - tmp = escape_str(argv[1]); - if (!tmp) - return -E_ESCAPE; - q = make_message("delete from streams where name='%s'", tmp); - free(tmp); - ret = real_query(q); - free(q); - return ret; -} - -/* - * ls - */ -int com_ls(int fd, int argc, char * const * argv) -{ - char *q; - void *result; - int ret; - my_ulonglong num_rows, top = 0, left = 0, right = 0; - - if (argc > 2) - return -E_MYSQL_SYNTAX; - if (argc > 1) { - char *tmp = escape_str(argv[1]); - if (!tmp) - return -E_ESCAPE; - q = make_message("select name from data where name like '%s'", - tmp); - free(tmp); - } else - q = para_strdup("select name from data"); - result = get_result(q); - free(q); - if (!result) - return -E_NORESULT; - num_rows = mysql_num_rows(result); - ret = 1; - if (num_rows) - ret = print_results(fd, result, top, left, num_rows - 1, right); - mysql_free_result(result); - return ret; -} - -/* - * summary - */ -int com_summary(__a_unused int fd, int argc, __a_unused char * const * argv) -{ - MYSQL_ROW row; - MYSQL_ROW row2; - void *result; - void *result2 = NULL; - const char *fmt = "select count(name) from data where %s='1'"; - int ret = -E_NORESULT; - - if (argc != 1) - return -E_MYSQL_SYNTAX; - result = get_all_attributes(); - if (!result) - goto out; - while ((row = mysql_fetch_row(result))) { - char *buf; - - ret = -E_NOROW; - if (!row[0]) - goto out; - ret = -E_NORESULT; - buf = make_message(fmt, row[0]); - result2 = get_result(buf); - free(buf); - if (!result2) - goto out; - ret = -E_NOROW; - row2 = mysql_fetch_row(result2); - if (!row2 || !row2[0]) - goto out; - ret = send_va_buffer(fd, "%s\t%s\n", row[0], row2[0]); - if (ret < 0) - goto out; - } - ret = 1; -out: - if (result2) - mysql_free_result(result2); - if (result) - mysql_free_result(result); - return ret; -} - -static int get_numplayed(char *name) -{ - void *result; - MYSQL_ROW row; - const char *fmt = "select numplayed from data where name = '%s'"; - char *buf = make_message(fmt, name); - int ret = -E_NORESULT; - - result = get_result(buf); - free(buf); - if (!result) - goto out; - ret = -E_NOROW; - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto out; - ret = atoi(row[0]); -out: - if (result) - mysql_free_result(result); - return ret; -} - -static int update_audio_file(const char *name) -{ - int ret; - const char *fmt1 = "update data set lastplayed = now() where name = '%s'"; - const char *fmt2 = "update data set numplayed = %i where name = '%s'"; - char *q; - char *ebn = escaped_basename(name); - - ret = -E_ESCAPE; - if (!ebn) - goto out; - q = make_message(fmt1, ebn); - ret = real_query(q); - free(q); - if (ret < 0) - goto out; - ret = get_numplayed(ebn); - if (ret < 0) - goto out; - q = make_message(fmt2, ret + 1, ebn); - ret = real_query(q); - free(q); -out: - free(ebn); - return ret; -} - -static void update_audio_file_server_handler(char *name) -{ - char *info; - info = get_selector_info(name); - update_mmd(info); - free(info); - update_audio_file(name); -} - -int com_us(__a_unused int fd, int argc, char * const * argv) -{ - char *tmp; - int ret; - - if (argc != 2) - return -E_MYSQL_SYNTAX; - tmp = escape_str(argv[1]); - if (!tmp) - return -E_ESCAPE; - ret = update_audio_file(argv[1]); - free(tmp); - if (ret >= 0) - refresh_selector_info(); - return ret; -} - -/* select previous / next stream */ -static int com_ps_ns(__a_unused int fd, int argc, char * const * argv) -{ - char *query, *stream = get_current_stream(); - void *result = get_result("select name from streams"); - MYSQL_ROW row; - int ret; - my_ulonglong num_rows, match, i; - - ret = -E_MYSQL_SYNTAX; - if (argc != 1) - goto out; - ret = -E_NORESULT; - if (!result) - goto out; - num_rows = mysql_num_rows(result); - ret = -E_EMPTY_RESULT; - if (num_rows < 2) - goto out; - ret = -E_NOROW; - for (i = 0; i < num_rows; i++) { - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto out; - if (!strcmp(row[0], "current_stream")) - continue; - if (!strcmp(row[0], stream)) - break; - } - ret = -E_NO_STREAM; - if (i == num_rows) - goto out; - match = i; - if (!strcmp(argv[0], "ps")) - i = match > 0? match - 1 : num_rows - 1; - else - i = match < num_rows - 1? match + 1 : 0; - ret = -E_NOROW; - mysql_data_seek(result, i); - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto out; - if (!strcmp(row[0], "current_stream")) { - if (!strcmp(argv[0], "ps")) { - i = match < 2? match + num_rows - 2 : match - 2; - } else { - i = match + 2; - i = i > num_rows - 1? i - num_rows : i; - } - mysql_data_seek(result, i); - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto out; - } - query = make_message("update streams set def='%s' where name = " - "'current_stream'", row[0]); - ret = real_query(query); - free(query); - refresh_selector_info(); -out: - free(stream); - if (result) - mysql_free_result(result); - return ret; -} - -/* select previous stream */ -int com_ps(int fd, int argc, char * const * argv) -{ - return com_ps_ns(fd, argc, argv); -} - -/* select next stream */ -int com_ns(int fd, int argc, char * const * argv) -{ - return com_ps_ns(fd, argc, argv); -} - -/* streams */ -int com_streams(int fd, int argc, __a_unused char * const * argv) -{ - unsigned int num_rows; - int i, ret = -E_NORESULT; - void *result; - MYSQL_ROW row; - - if (argc > 1 && strcmp(argv[1], "current_stream")) - return -E_MYSQL_SYNTAX; - if (argc > 1) { - char *cs = get_current_stream(); - ret = send_va_buffer(fd, "%s\n", cs); - free(cs); - return ret; - } - result = get_result("select name from streams"); - if (!result) - goto out; - num_rows = mysql_num_rows(result); - ret = 1; - if (!num_rows) - goto out; - ret = -E_NOROW; - for (i = 0; i < num_rows; i++) { - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto out; - if (strcmp(row[0], "current_stream")) - send_va_buffer(fd, "%s\n", row[0]); - } - ret = 1; -out: - if (result) - mysql_free_result(result); - return ret; -} - -/* query stream definition */ -int com_strq(int fd, int argc, char * const * argv) -{ - MYSQL_ROW row; - char *query, *name; - void *result; - int ret; - - if (argc < 2) { - ret = -E_GET_STREAM; - name = get_current_stream(); - } else { - ret = -E_ESCAPE; - name = escaped_basename(argv[1]); - } - if (!name) - return ret; - ret = -E_NORESULT; - query = make_message("select def from streams where name='%s'", name); - free(name); - result = get_result(query); - free(query); - if (!result) - goto out; - ret = -E_NOROW; - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto out; - /* no '\n' needed */ - ret = send_buffer(fd, row[0]); -out: - if (result) - mysql_free_result(result); - return ret; -} - -/* change stream / change stream and play */ -static int com_cs_csp(int fd, int argc, char * const * argv) -{ - int ret, stream_change; - char *query, *stream = NULL; - char *old_stream = get_current_stream(); - int csp = !strcmp(argv[0], "csp"); - - ret = -E_MYSQL_SYNTAX; - if (argc > 2) - goto out; - if (argc == 1) { - if (csp) - goto out; - ret = send_va_buffer(fd, "%s\n", old_stream); - goto out; - } - ret = -E_GET_QUERY; - /* test if stream is valid, no need to escape argv[1] */ - query = get_query(argv[1], NULL, 0); - if (!query) - goto out; - free(query); - /* stream is ok */ - stream = escape_str(argv[1]); - if (!stream) - goto out; - stream_change = strcmp(stream, old_stream); - if (stream_change) { - ret = change_stream(stream); - if (ret < 0) - goto out; - refresh_selector_info(); - } - if (csp) { - mmd_lock(); - mmd->new_vss_status_flags |= VSS_PLAYING; - if (stream_change) - mmd->new_vss_status_flags |= VSS_NEXT; - mmd_unlock(); - } - ret = 1; -out: - free(old_stream); - free(stream); - return ret; -} - -/* change stream */ -int com_cs(int fd, int argc, char * const * argv) -{ - return com_cs_csp(fd, argc, argv); -} - -/* change stream and play */ -int com_csp(int fd, int argc, char * const * argv) -{ - return com_cs_csp(fd, argc, argv); -} - -/* score list / skip */ -static int com_sl_skip(int fd, int argc, char * const * argv) -{ - void *result = NULL; - MYSQL_ROW row; - int ret, i, skip = !strcmp(argv[0], "skip"); - char *query, *stream, *tmp; - unsigned int num_rows, num; - - if (argc < 2) - return -E_MYSQL_SYNTAX; - num = atoi(argv[1]); - if (!num) - return -E_MYSQL_SYNTAX; - if (argc == 2) { - stream = get_current_stream(); - if (!stream) - return -E_GET_STREAM; - } else { - stream = escape_str(argv[2]); - if (!stream) - return -E_ESCAPE; - } - tmp = get_query(stream, NULL, 0); - free(stream); - if (!tmp) - return -E_GET_QUERY; - query = make_message("%s limit %d", tmp, num); - free(tmp); - ret = -E_NORESULT; - result = get_result(query); - free(query); - if (!result) - goto out; - ret = -E_EMPTY_RESULT; - num_rows = mysql_num_rows(result); - if (!num_rows) - goto out; - for (i = 0; i < num_rows && i < num; i++) { - row = mysql_fetch_row(result); - if (skip) { - send_va_buffer(fd, "Skipping %s\n", row[0]); - update_audio_file(row[0]); - } else - send_va_buffer(fd, "%s\n", row[0]? row[0]: "BUG"); - } - ret = 1; -out: - if (result) - mysql_free_result(result); - return ret; -} - -/* score list */ -int com_sl(int fd, int argc, char * const * argv) -{ - return com_sl_skip(fd, argc, argv); -} - -/* skip */ -int com_skip(int fd, int argc, char * const * argv) -{ - return com_sl_skip(fd, argc, argv); -} - -/* - * update attributes of name - */ -static int update_atts(int fd, const char *name, char *atts) -{ - int ret; - char *ebn, *q, *old, *new = NULL; - - if (!mysql_ptr) - return -E_NOTCONN; - ebn = escaped_basename(name); - if (!ebn) - return -E_ESCAPE; - q = make_message("update data set %s where name = '%s'", atts, ebn); - old = get_atts(ebn, 0); - send_va_buffer(fd, "old: %s\n", old); - free(old); - ret = real_query(q); - free(q); - if (ret < 0) - goto out; - new = get_atts(ebn, 0); - ret = send_va_buffer(fd, "new: %s\n", new); - free(new); -out: - free(ebn); - return ret; -} - -/* - * set attributes - */ -int com_sa(int fd, int argc, char * const * argv) -{ - int i, ret; - char *atts = NULL, *name; - - if (argc < 2) - return -E_MYSQL_SYNTAX; - for (i = 1; i < argc; i++) { - int unset = 0; - char *esc, *tmp, *p; - int len = strlen(argv[i]); - - if (!len) - continue; - switch (argv[i][len - 1]) { - case '+': - unset = 0; - break; - case '-': - unset = 1; - break; - default: - goto no_more_atts; - } - p = para_strdup(argv[i]); - p[len - 1] = '\0'; - esc = escape_str(p); - free(p); - if (!esc) - return -E_ESCAPE; - tmp = make_message("%s%s='%s'", atts? "," : "", esc, - unset? "0" : "1"); - free(esc); - atts = para_strcat(atts, tmp); - free(tmp); - } -no_more_atts: - if (!atts) - return -E_NOATTS; - if (i >= argc) { /* no name given, use current af */ - ret = -E_GET_AUDIO_FILE; - if (!(name = get_current_audio_file())) - goto out; - ret = update_atts(fd, name, atts); - free(name); - } else { - ret = 1; - for (; argv[i] && ret >= 0; i++) - ret = update_atts(fd, argv[i], atts); - } - refresh_selector_info(); -out: - free(atts); - return ret; -} - -/* - * copy attributes - */ -int com_cam(int fd, int argc, char * const * argv) -{ - char *name = NULL, *meta = NULL, *atts = NULL; - int i, ret; - - if (argc < 3) - return -E_MYSQL_SYNTAX; - if (!(name = escaped_basename(argv[1]))) - return -E_ESCAPE; - ret = -E_NOATTS; - if (!(atts = get_atts(name, 1))) - goto out; - ret = -E_META; - if (!(meta = get_meta(name, 0))) - goto out; - for (i = 2; i < argc; i++) { - char *ebn, *q; - ret = -E_ESCAPE; - if (!(ebn = escaped_basename(argv[i]))) - goto out; - ret = send_va_buffer(fd, "updating %s\n", ebn); - if (ret < 0) { - free(ebn); - goto out; - } - q = make_message("update data set %s where name = '%s'", - meta, ebn); - if ((ret = update_atts(fd, ebn, atts)) >= 0) - ret = real_query(q); - free(ebn); - free(q); - if (ret < 0) - goto out; - } - ret = 1; -out: - if (name) - free(name); - if (meta) - free(meta); - if (atts) - free(atts); - return ret; -} - -/* - * verify / clean - */ -static int com_vrfy_clean(int fd, int argc, __a_unused char * const * argv) -{ - char *query; - int ret, vrfy_mode = strcmp(argv[0], "clean"); - void *result = NULL; - MYSQL_ROW row; - char *escaped_name; - my_ulonglong num_rows, top = 0, left = 0, right = 0; - - if (argc != 1) - return -E_MYSQL_SYNTAX; - ret = -E_NORESULT; - result = get_result("select data.name from data left join dir on " - "dir.name = data.name where dir.name is NULL"); - if (!result) - goto out; - num_rows = mysql_num_rows(result); - if (!num_rows) { - ret = send_buffer(fd, "No invalid entries\n"); - goto out; - } - if (vrfy_mode) { - send_va_buffer(fd, "found %lli invalid entr%s\n", num_rows, - num_rows == 1? "y" : "ies"); - ret = print_results(fd, result, top, left, num_rows - 1, right); - goto out; - } - while ((row = mysql_fetch_row(result))) { - ret = -E_NOROW; - if (!row[0]) - goto out; - ret = -E_ESCAPE; - escaped_name = escape_str(row[0]); - if (!escaped_name) - goto out; - send_va_buffer(fd, "deleting %s\n", escaped_name); - query = make_message("delete from data where name = '%s'", - escaped_name); - ret = real_query(query); - free(query); - if (ret < 0) - goto out; - } - -out: - if (result) - mysql_free_result(result); - return ret; -} - -/* - * verify - */ -int com_vrfy(int fd, int argc, char * const * argv) -{ - return com_vrfy_clean(fd, argc, argv); -} - -/* - * clean - */ -int com_clean(int fd, int argc, char * const * argv) -{ - return com_vrfy_clean(fd, argc, argv); -} - -static FILE *out_file; - -static int mysql_write_tmp_file(const char *dir, const char *name) -{ - int ret = -E_TMPFILE; - char *msg = make_message("%s\t%s\n", dir, name); - if (fputs(msg, out_file) != EOF) - ret = 1; - free(msg); - return ret; -} - -/* - * update database - */ -int com_upd(int fd, int argc, __a_unused char * const * argv) -{ - char *tempname = NULL, *query = NULL; - int ret, out_fd = -1, num = 0; - void *result = NULL; - unsigned int num_rows; - MYSQL_ROW row; - - if (argc != 1) - return -E_MYSQL_SYNTAX; - out_file = NULL; - tempname = para_strdup("/tmp/mysql.tmp.XXXXXX"); - ret = para_mkstemp(tempname, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (ret < 0) - goto out; - out_fd = ret; - out_file = fdopen(out_fd, "w"); - if (!out_file) { - close(out_fd); - goto out; - } - if (find_audio_files(conf.mysql_audio_file_dir_arg, mysql_write_tmp_file) < 0) - goto out; - num = ftell(out_file); - /* - * we have to make sure the file hit the disk before we call - * real_query - */ - fclose(out_file); - out_file = NULL; - PARA_DEBUG_LOG("wrote tempfile %s (%d bytes)\n", tempname, num); - if (!num) - goto out; - if ((ret = real_query("delete from dir")) < 0) - goto out; - query = make_message("load data infile '%s' ignore into table dir " - "fields terminated by '\t' lines terminated by '\n' " - "(dir, name)", tempname); - ret = real_query(query); - free(query); - if (ret < 0) - goto out; - result = get_result("select dir.name from dir left join data on " - "data.name = dir.name where data.name is NULL"); - ret = -E_NORESULT; - if (!result) - goto out; - num_rows = mysql_num_rows(result); - if (!num_rows) { - ret = send_buffer(fd, "no new entries\n"); - goto out; - } - while ((row = mysql_fetch_row(result))) { - char *erow; - ret = -E_NOROW; - if (!row[0]) - goto out; - send_va_buffer(fd, "new entry: %s\n", row[0]); - erow = escape_str(row[0]); - if (!erow) - goto out; - query = make_message("insert into data (name, pic_id) values " - "('%s','%s')", erow, "1"); - free(erow); - ret = real_query(query); - free(query); - if (ret < 0) - goto out; - } - ret = 1; -out: - if (out_fd >= 0) - unlink(tempname); - free(tempname); - if (out_file) - fclose(out_file); - if (result) - mysql_free_result(result); - return ret; -} - -static char **server_get_audio_file_list(unsigned int num) -{ - char **list = para_malloc((num + 1) * sizeof(char *)); - char *tmp, *query, *stream = get_current_stream(); - void *result = NULL; - unsigned int num_rows; - int i = 0; - MYSQL_ROW row; - - tmp = get_query(stream, NULL, 1); - free(stream); - if (!tmp) - goto err_out; - query = make_message("%s limit %d", tmp, num); - free(tmp); - result = get_result(query); - free(query); - if (!result) - goto err_out; - num_rows = mysql_num_rows(result); - if (!num_rows) - goto err_out; - for (i = 0; i < num_rows && i < num; i++) { - row = mysql_fetch_row(result); - if (!row || !row[0]) - goto err_out; - list[i] = para_strdup(row[0]); - } - list[i] = NULL; - goto success; -err_out: - while (i > 0) { - i--; - free(list[i]); - } - free(list); - list = NULL; -success: - if (result) - mysql_free_result(result); - return list; -} - -/* - * connect to mysql server, return mysql pointer on success, -E_NOTCONN - * on errors. Called from parent on startup and also from com_cdb(). - */ -static int init_mysql_server(void) -{ - char *u = conf.mysql_user_arg? conf.mysql_user_arg : para_logname(); - unsigned int port; - - mysql_ptr = mysql_init(NULL); - if (!mysql_ptr) { - PARA_CRIT_LOG("%s", "mysql init error\n"); - return -E_NOTCONN; - } - if (conf.mysql_port_arg < 0) - return -E_MYSQL_SYNTAX; - port = conf.mysql_port_arg; - PARA_DEBUG_LOG("connecting: %s@%s:%d\n", u, conf.mysql_host_arg, port); - if (!conf.mysql_user_arg) - free(u); - /* - * If host is NULL a connection to the local host is assumed, - * If user is NULL, the current user is assumed - */ - if (!(mysql_ptr = mysql_real_connect(mysql_ptr, - conf.mysql_host_arg, - conf.mysql_user_arg, - conf.mysql_passwd_arg, - conf.mysql_database_arg, - port, NULL, 0))) { - PARA_CRIT_LOG("%s", "connect error\n"); - return -E_NOTCONN; - } - PARA_INFO_LOG("%s", "success\n"); - return 1; -} - -/* mmd lock must be held */ -static void write_msg2mmd(int success) -{ - sprintf(mmd->selector_info, "dbinfo1:%s\ndbinfo2:mysql-%s\ndbinfo3:\n", - success < 0? PARA_STRERROR(-success) : - "successfully connected to mysql server", - success < 0? "" : mysql_get_server_info(mysql_ptr)); -} - -/* create database */ -int com_cdb(int fd, int argc, char * const * argv) -{ - char *query; - int ret; - - if (mysql_ptr) { - PARA_INFO_LOG("%s", "closing database\n"); - mysql_close(mysql_ptr); - } - /* dont use any database */ - conf.mysql_database_arg = NULL; /* leak? */ - ret = -E_MYSQL_INIT; - if (init_mysql_server() < 0 || !mysql_ptr) - goto out; - if (argc < 2) - conf.mysql_database_arg = para_strdup("paraslash"); - else { - ret = -E_ESCAPE; - conf.mysql_database_arg = escape_str(argv[1]); - if (!conf.mysql_database_arg) - goto out; - } - query = make_message("create database %s", conf.mysql_database_arg); - ret = real_query(query); - free(query); - if (ret < 0) - goto out; - /* reconnect with database just created */ - mysql_close(mysql_ptr); - ret = -E_MYSQL_INIT; - if (init_mysql_server() < 0 || !mysql_ptr) - goto out; - mmd_lock(); - write_msg2mmd(1); - mmd_unlock(); - ret = -E_QFAILED; - if (real_query("create table data (name varchar(255) binary not null " - "primary key, " - "lastplayed datetime not null default " - "'1970-01-01', " - "numplayed int not null default 0, " - "pic_id bigint unsigned not null default 1)") < 0) - goto out; - if (real_query("create table dir (name varchar(255) binary not null " - "primary key, dir varchar(255) default null)") < 0) - goto out; - if (real_query("create table pics (" - "id bigint(20) unsigned not null primary key " - "auto_increment, " - "name varchar(255) binary not null, " - "pic mediumblob not null)") < 0) - goto out; - if (real_query("create table streams (" - "name varchar(255) binary not null primary key, " - "def blob not null)") < 0) - goto out; - if (real_query("insert into streams (name, def) values " - "('current_stream', '(none)')") < 0) - goto out; - ret = send_va_buffer(fd, "successfully created database %s\n", - conf.mysql_database_arg); -out: - return ret; -} - -static void shutdown_connection(void) -{ - int ret; - - if (mysql_ptr) { - PARA_NOTICE_LOG("%s", "shutting down mysql connection\n"); - mysql_close(mysql_ptr); - mysql_ptr = NULL; - } - if (mysql_lock) { - ret = mutex_destroy(mysql_lock); - if (ret < 0) - PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); - mysql_lock = 0; - } -} - -/** - * the init function of the mysql-based audio file selector - * - * \param db pointer to the struct to initialize - * - * Check the command line options and initialize all function pointers of \a - * db. Connect to the mysql server and initialize the info string. - * - * \return This function returns success even if it could not connect - * to the mysql server. This is because the connect is expected to fail - * if there the paraslash database is not yet created. This gives the - * user a chance to send the "cdb" to create the database. - * - * \sa struct audio_file_selector, misc_meta_data::selector_info, - * random_selector.c - */ -int mysql_selector_init(struct audio_file_selector *db) -{ - int ret; - - if (!conf.mysql_passwd_given) - return -E_NO_MYSQL_PASSWD; - if (!conf.mysql_audio_file_dir_given) - return -E_NO_AF_DIR; - db->name = "mysql"; - db->cmd_list = mysql_selector_cmds; - db->get_audio_file_list = server_get_audio_file_list; - db->update_audio_file = update_audio_file_server_handler; - db->shutdown = shutdown_connection; - ret = mutex_new(); - if (ret < 0) - return ret; - mysql_lock = ret; - ret = init_mysql_server(); - if (ret < 0) - PARA_WARNING_LOG("%s\n", PARA_STRERROR(-ret)); - write_msg2mmd(ret); - return 1; /* return success even if connect failed to give the - * user the chance to exec com_cdb - */ -} diff --git a/mysql_selector.cmd b/mysql_selector.cmd deleted file mode 100644 index a49d6d1e..00000000 --- a/mysql_selector.cmd +++ /dev/null @@ -1,324 +0,0 @@ -OF: mysql_selector_command_list -SF: mysql_selector.c -HC: prototypes for the commands of the mysql audio file selector -CC: array of commands for the mysql audio file selector -AT: server_command -IN: para error string afh afs server list user_list -SN: list of mysql selector commands ---- -N: cam -P: AFS_READ | AFS_WRITE -D: copy all metadata -U: cam source dest1 [dest2 ...] -H: Copy attributes and other meta data from source file to destination -H: file(s). Useful for files that have been renamed. ---- -N: cdb -P: AFS_READ | AFS_WRITE -D: create database -U: cdb [name] -H: -H: Create database name containing the initial columns for basic -H: interoperation with server. This command has to be used only once -H: when you use the mysql audio file selector for the very first time. -H: -H: The optional name defaults to 'paraslash' if not given. ---- -N: clean -P: AFS_READ | AFS_WRITE -D: nuke invalid entries in database -U: clean -H: If the vrfy command shows you any invalid entries in your database, -H: you can get rid of them with clean. Always run 'upd' and 'vrfy' -H: before running this command. Use with caution! ---- -N: cs -P: VSS_WRITE | AFS_READ | AFS_WRITE -D: change stream -U: cs [s] -H: Selects stream s or prints current stream when s was not given. ---- -N: csp -P: VSS_WRITE | AFS_READ -D: change stream and play -U: csp s -H: Select stream s and start playing. If this results in a -H: stream-change, skip rest of current audio file. ---- -N: da -P: AFS_READ | AFS_WRITE -D: drop attribute from database -U: da att -H: Use with caution. All info on attribute att will be lost. ---- -N: hist -P: AFS_READ -D: print history -U: hist -H: Print list of all audio files together with number of days since -H: each file was last played. ---- -N: info -P: AFS_READ -D: print database info -U: info [af] -H: print database informations for audio file af. Current audio file -H: is used if af is not given. ---- -N: la -P: AFS_READ -D: list attributes -U: la [af] -H: List attributes of audio file af or of current audio file when -H: invoked without arguments. ---- -N: laa -P: AFS_READ -D: list available attributes -U: laa -H: print list of all attributes defined in the database ---- -N: last -P: AFS_READ -D: print list of audio files, ordered by lastplayed time -U: last [n] -H: The optional number n defaults to 10 if not specified. ---- -N: ls -P: AFS_READ -D: list all audio files that match a LIKE pattern -U: ls [pattern] -H: If pattern was not given, print list of all audio files known -H: to the mysql selector. See the documentation of mysql -H: for the definition of LIKE patterns. ---- -N: mbox -P: AFS_READ -D: dump audio file list in mbox format -U: mbox [p] -H: Dump list of audio files in mbox format (email) to stdout. If -H: the optional pattern p is given, only those audio files, -H: whose basename match p are going to be included. Otherwise, -H: all files are selected. -H: -H: EXAMPLE -H: The mbox command can be used together with your favorite -H: mailer (this example uses mutt) for browsing the audio file -H: collection: -H: -H: para_client mbox > ~/para_mbox -H: -H: mutt -F ~/.muttrc.para -f ~/para_mbox -H: -H: For playlists, you can use mutt's powerful pattern matching -H: language to select files. If you like to tag all files -H: containing the pattern 'foo', type 'T', then '~s foo'. -H: -H: When ready with the list, type ';|' (i.e., hit the semicolon -H: key to apply the next mutt command to all tagged messages, -H: then the pipe key) to pipe the selected mails to a -H: suitable script which adds a paraslash stream where exactly -H: these files are admissable or does whatever thou wilt. ---- -N: mv -P: AFS_READ | AFS_WRITE -D: rename entry in database -U: mv oldname newname -H: Rename oldname to newname. This updates the data table to reflect -H: the new name. All internal data (numplayed, lastplayed, picid,..) -H: is kept. If newname is a full path, the dir table is updated as -H: well. ---- -N: na -P: AFS_READ | AFS_WRITE -D: add new attribute to database -U: na att -H: This adds a column named att to your mysql database. att should -H: only contain letters and numbers, in paricular, '+' and '-' are -H: not allowed. ---- -N: ne -P: AFS_READ | AFS_WRITE -D: add new database entries -U: ne file1 [file2 [...]] -H: Add the given filename(s) to the database, where file1,... must -H: be full path names. This command might be much faster than 'upd' -H: if the number of given files is small. ---- -N: ns -P: VSS_WRITE | AFS_READ | AFS_WRITE -D: change to next stream -U: ns -H: Cycle forwards through stream list. ---- -N: pic -P: AFS_READ -D: get picture by name or by identifier -U: pic [name] -H: Dump jpg image that is associated to given audio file (current -H: audio file if not specified) to stdout. If name starts with -H: '#' it is interpreted as an identifier instead and the picture -H: having that identifier is dumped to stdout. -H: -H: EXAMPLE -H: -H: para_client pic '#123' > pic123.jpg ---- -N: picadd -P: AFS_READ | AFS_WRITE -D: add picture to database -U: picadd [picname] -H: Read jpeg file from stdin and store it as picname in database. -H: -H: EXAMPLE -H: -H: para_client picadd foo.jpg < foo.jpg ---- -N: picass -P: AFS_READ | AFS_WRITE -D: associate a picture to file(s) -U: picass pic_id file1 [file2...] -H: Associate the picture given by pic_id to all given files. ---- -N: picch -P: AFS_READ | AFS_WRITE -D: change name of picture -U: picch id new_name -H: Asign new_name to picture with identifier id. ---- -N: picdel -P: AFS_READ | AFS_WRITE -D: delete picture from database -U: picdel id1 [id2...] -H: Delete each given picture from database. ---- -N: piclist -P: AFS_READ -D: print list of pictures -U: piclist -H: Print id, name and length of each picture contained in the -H: database. ---- -N: ps -P: VSS_WRITE | AFS_READ | AFS_WRITE -D: change to previous stream -U: ps -H: Cycle backwards through stream list. ---- -N: rm -P: AFS_READ | AFS_WRITE -D: remove entries from database -U: rm name1 [name2 [...]] -H: Remove name1, name2, ... from the data table. Use with caution. ---- -N: sa -P: AFS_READ | AFS_WRITE -D: set/unset attributes -U: sa at1<'+' | '-'> [at2<'+' | '-'> ] [af1 ...] -H: Set ('+') or unset ('-') attribute at1, at2 etc. for given list of -H: audio files. If no audio files were given the current audio file is -H: used. Example: -H: -H: sa rock+ punk+ classic- LZ__Waldsterben.mp3 -H: -H: sets the 'rock' and the 'punk' attribute but unsets the 'classic' -H: attribute. ---- -N: skip -P: AFS_READ | AFS_WRITE -D: skip subsequent audio files(s) -U: skip n [s] -H: Skip the next n audio files of stream s. This is equivalent to the -H: command 'sl n s', followed by 'us name' for each name the output of -H: sl. ---- -N: sl -P: AFS_READ -D: print score list -U: sl n [s] -H: Print sorted list of maximal n lines. Each line is an admissible -H: entry with respect to stream s. The list is sorted by score-value -H: which is given by the definition of s. If s is not given, the -H: current stream is used. Example: -H: -H: sl 1 -H: -H: shows you the audio file the server would select right now. ---- -N: snp -P: AFS_READ | AFS_WRITE -D: set numplayed -U: snp number af1 [af2 ...] -H: Update the numplayed field in the data table for all given audio -H: files. ---- -N: stradd -P: AFS_READ | AFS_WRITE -D: add stream -U: stradd s -H: Add stream s to the list of available streams. The stream -H: definition for s is read from stdin and is then sent to -H: para_server. Example: -H: -H: echo 'deny: NAME_LIKE(%Madonna%)' | para_client stradd no_madonna -H: -H: adds the new stream 'no_madonna' to the list of available streams. -H: A given audio file is admissible for this stream iff its basename -H: does not contain the string 'Madonna'. ---- -N: strdel -P: AFS_READ | AFS_WRITE -D: delete stream -U: strdel s -H: Remove stream s from database. ---- -N: streams -P: AFS_READ -D: list streams -U: streams -H: Print list of available streams. Use 'cs' to switch to any of -H: these. ---- -N: strq -P: AFS_READ -D: query stream definition -U: strq [s] -H: Print definition of stream s to stdout. Use current stream if s was -H: not given. ---- -N: summary -P: AFS_READ -D: list attributes -U: summary -H: Print a list of attributes together with number of audio -H: files having that attribute set. ---- -N: upd -P: AFS_READ | AFS_WRITE -D: update database -U: upd -H: This command uses the --audio_file_dir option of para_server to -H: locate your audio files. New files are then added to the mysql -H: database. Use this command if you got new files or if you have -H: moved some files around. ---- -N: us -P: AFS_READ | AFS_WRITE -D: update lastplayed time -U: us name -H: Update lastplayed time without actually playing the thing. ---- -N: verb -P: AFS_READ | AFS_WRITE -D: send verbatim sql query -U: verb cmd -H: Send cmd to mysql server. For expert/debugging only. Note that cmd -H: usually must be escaped. Use only if you know what you are doing! ---- -N: vrfy -P: AFS_READ -D: list invalid entries in database -U: vrfy -H: Show what clean would delete. Run 'upd' before this command to make -H: sure your database is up to date. ---- 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; -} diff --git a/playlist_selector.cmd b/playlist_selector.cmd deleted file mode 100644 index b8190258..00000000 --- a/playlist_selector.cmd +++ /dev/null @@ -1,21 +0,0 @@ -OF: playlist_selector_command_list -SF: playlist_selector.c -HC: prototypes for the commands of the playlist audio file selector -CC: array of commands for the playlist audio file selector -AT: server_command -IN: para error string afh afs server list user_list -SN: list of playlist selector commands ---- -N: ppl -P: AFS_READ -D: print playlist -U: ppl -H: Print out the current playlist ---- -N: lpl -P: AFS_WRITE -D: load playlist -U: lpl -H: Read a new playlist from stdin. Example: -H: find /audio -name '*.mp3' | para_client lpl ---- diff --git a/random_selector.c b/random_selector.c deleted file mode 100644 index ac82058d..00000000 --- a/random_selector.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2004-2007 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ - -/** \file random_selector.c An audio file selector which chooses files by random */ - -#include /* gettimeofday */ -#include "para.h" -#include "error.h" -#include "string.h" -#include "server.cmdline.h" -#include "afh.h" -#include "afs.h" -#include "server.h" -#include "afs_common.h" -#include "net.h" -#include "random_selector_command_list.h" - -extern struct misc_meta_data *mmd; - -static unsigned int num_audio_files, audio_file_count; -static char **audio_file_list; - -static int count_audio_files(__a_unused const char *dir, __a_unused const char *name) -{ - num_audio_files++; - return 1; -} - -static int remember_file(const char *dir, const char *name) -{ - if (audio_file_count < num_audio_files) { - audio_file_list[audio_file_count] = - make_message("%s/%s", dir, name); - audio_file_count++; - } - return 1; -} - -int com_random_info(int fd, __a_unused int argc, __a_unused char * const * const argv) -{ - return send_buffer(fd, "Don't use for huge directories as it is " - "very inefficient in this case.\n"); -} - -/* - * Load a list of all audio files into memory and chose num of them randomly. - * Called by server to determine next audio file to be streamed. - */ -static char **random_get_audio_file_list(unsigned int num) -{ - int i, ret; - unsigned int len; - char **ret_list = NULL; /* what we are going to return */ - - audio_file_list = NULL; - num_audio_files = 0; - /* first run, just count all audio files. dopey */ - ret = find_audio_files(conf.random_dir_arg, count_audio_files); - if (ret < 0) - goto out; - ret = -E_NOTHING_FOUND; - if (!num_audio_files) - goto out; - /* yeah, that doesn't scale, also dopey */ - audio_file_list = para_malloc(num_audio_files * sizeof(char *)); - audio_file_count = 0; - /* second run (hot dentry cache, hopefully), fill audio_file_list */ - ret = find_audio_files(conf.random_dir_arg, remember_file); - if (ret < 0) - goto out; - /* careful, files might got deleted underneath */ - num_audio_files = audio_file_count; /* can only decrease */ - len = PARA_MIN(num, num_audio_files); - ret = -E_NOTHING_FOUND; - if (!len) /* nothing found, return NULL */ - goto out; - /* success, return NULL-terminated list */ - ret_list = para_calloc((len + 1) * sizeof(char *)); - for (i = 0; i < len; i++) { /* choose randomly */ - int r = (int) ((num_audio_files + 0.0) * (rand() - / (RAND_MAX + 1.0))); - ret_list[i] = para_strdup(audio_file_list[r]); - } - ret = 1; -out: - if (audio_file_list) { - for (i = 0; i < num_audio_files; i++) - free(audio_file_list[i]); - free(audio_file_list); - } - if (ret > 0) { - } else - sprintf(mmd->selector_info, "dbinfo1:%s\n", PARA_STRERROR(-ret)); - return ret_list; -} - -static void random_update_audio_file(char *audio_file) -{ - char *dn = para_dirname(audio_file); - snprintf(mmd->selector_info, MMD_INFO_SIZE - 1, - "dbinfo1:current dir: %s\n" - "dbinfo2:random_dir: %s\n" - "dbinfo3:%d files available\n", - dn, conf.random_dir_arg, num_audio_files); - free(dn); - mmd->selector_info[MMD_INFO_SIZE - 1] = '\0'; -} -static void random_shutdown(void) -{ -} - -/** - * the init function for the random audio file selector - * - * \param s pointer ro the struct to iniitalize - * - * Init all function pointers of \a s, init the info text and seed the PRNG. - * - * \sa struct audio_file_selector, misc_meta_data::selector_info, mysql.c - */ -int random_selector_init(struct audio_file_selector *s) -{ - struct timeval now; - unsigned int seed; - - PARA_INFO_LOG("%s", "registering random handlers ;)\n"); - gettimeofday(&now, NULL); - seed = now.tv_usec; - srand(seed); - s->cmd_list = random_selector_cmds; - s->get_audio_file_list = random_get_audio_file_list; - s->shutdown = random_shutdown; - s->update_audio_file = random_update_audio_file; - snprintf(mmd->selector_info, MMD_INFO_SIZE - 1, - "dbinfo1: Welcome to the random selector\n" - "dbinfo2: random_dir: %s\n", conf.random_dir_arg); - mmd->selector_info[MMD_INFO_SIZE - 1] = '\0'; - return 1; -} diff --git a/random_selector.cmd b/random_selector.cmd deleted file mode 100644 index 67f07db1..00000000 --- a/random_selector.cmd +++ /dev/null @@ -1,13 +0,0 @@ -OF: random_selector_command_list -SF: random_selector.c -HC: prototypes for the commands of the random audio file selector -CC: array of commands for the random audio file selector -AT: server_command -IN: para error string afh afs server list user_list -SN: list of random selector commands ---- -N: random_info -P: 0 -D: about the random audio file selector -U: random_info -H: The random selector chooses files randomly out of the given directory. diff --git a/server.c b/server.c index ab88b07f..bf4ed37c 100644 --- a/server.c +++ b/server.c @@ -22,7 +22,6 @@ #include "para.h" #include "error.h" #include "server.cmdline.h" -#include "afs_common.h" #include "afh.h" #include "string.h" #include "afs.h" diff --git a/server.ggo b/server.ggo index b64aaa3c..f6ebc172 100644 --- a/server.ggo +++ b/server.ggo @@ -169,88 +169,6 @@ loads the playlist named 'foo'." string typestr="name" optional -section "mysql selector" -#~~~~~~~~~~~~~~~~~~~~~~~ - - -option "mysql_host" - -#~~~~~~~~~~~~~~~~~~~~ - -"mysql server" - - string typestr="ip or hostname" - default="localhost" - optional - -option "mysql_port" - -#~~~~~~~~~~~~~~~~~~~~ - -"where mysql is listening" - - int typestr="portnumber" - default="3306" - optional - - -option "mysql_user" - -#~~~~~~~~~~~~~~~~~~~~ - -"default value: username from /etc/passwd" - - string typestr="username" - optional - -option "mysql_passwd" - -#~~~~~~~~~~~~~~~~~~~~~~ - -"(required)" - - string - optional - -option "mysql_database" - -#~~~~~~~~~~~~~~~~~~~~~~~~ - -"name of mysql database" - - string - default="paraslash" - optional - -option "mysql_audio_file_dir" - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -"dir to search for audio files (required)" - - string typestr="dirname" - optional - -option "mysql_default_score" - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -"scoring rule to use if stream definition -does not contain explicit score definition" - - string - default="(LASTPLAYED() / 1440 - 1000 / (LASTPLAYED() + 1) - sqrt(NUMPLAYED()))" - optional - - - - -section "random selector" -#~~~~~~~~~~~~~~~~~~~~~~~~ - - -option "random_dir" - -#~~~~~~~~~~~~~~~~~~~~ - -"dir to search for audio files" - string typestr="dirname" - default="/home/music" - optional - - section "http sender" diff --git a/vss.c b/vss.c index ab5cd1b1..0bef15d0 100644 --- a/vss.c +++ b/vss.c @@ -24,7 +24,6 @@ #include "server.h" #include "net.h" #include "server.cmdline.h" -#include "afs_common.h" #include "vss.h" #include "send.h" #include "ipc.h"