0.?.? (to be announced) "neural discharge"
------------------------------------------
+ - fix a bug in para_filter that caused decoding of aac files
+ to start only after a few seconds.
+
-----------------------------------------
0.2.15 (2007-02-16) "inductive resonance"
-----------------------------------------
--- /dev/null
+/*
+ * Copyright (C) 2005-2007 Andre Noll <maan@systemlinux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ */
+
+
+/** \file afs.c functions common to all audio file selectors */
+
+#include "server.cmdline.h"
+#include "server.h"
+#include "vss.h"
+#include <dirent.h> /* readdir() */
+#include <sys/stat.h> /* stat */
+#include <sys/types.h> /* mode_t */
+#include "error.h"
+#include "string.h"
+
+/**
+ * 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;
+ struct dirent *entry;
+ /*
+ * Opening the current directory (".") and calling fchdir() to return
+ * is usually faster and more reliable than saving cwd in some buffer
+ * and calling chdir() afterwards (see man 3 getcwd).
+ */
+ int cwd_fd = open(".", O_RDONLY);
+ struct stat s;
+ int ret = -1;
+
+// PARA_DEBUG_LOG("dirname: %s\n", dirname);
+ if (cwd_fd < 0)
+ return -E_GETCWD;
+ ret = -E_CHDIR;
+ if (chdir(dirname) < 0)
+ goto out;
+ ret = -E_OPENDIR;
+ dir = opendir(".");
+ if (!dir)
+ goto out;
+ /* scan cwd recursively */
+ while ((entry = readdir(dir))) {
+ mode_t m;
+ char *tmp;
+
+ 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);
+ if (fchdir(cwd_fd) < 0)
+ ret = -E_CHDIR;
+ close(cwd_fd);
+ if (ret < 0)
+ PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2005-2007 Andre Noll <maan@systemlinux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ */
+
+/** \file afs.h data structures common to all audio file selectors */
+
+#include <sys/select.h>
+
+
+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 neccessary 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*);
+
#include <sys/time.h> /* gettimeofday */
#include "server.cmdline.h"
-#include "db.h"
+#include "afs.h"
#include "server.h"
#include "vss.h"
#include "send.h"
server_cmdline_objs="server.cmdline server_command_list random_selector_command_list
playlist_selector_command_list"
server_errlist_objs="server mp3_afh vss command net string signal random_selector
- time daemon stat crypt http_send db close_on_fork playlist_selector
+ time daemon stat crypt http_send afs close_on_fork playlist_selector
ipc dccp dccp_send fd user_list"
server_ldflags=""
server_audio_formats=" mp3"
write_errlist_objs="write write_common file_write time fd string sched stdin"
write_ldflags=""
writers=" file"
+default_writer="FILE_WRITE"
client_cmdline_objs="client.cmdline"
client_errlist_objs="client net string crypt fd sched stdin stdout client_common"
write_cmdline_objs="$write_cmdline_objs osx_write.cmdline"
write_ldflags="$write_ldflags $f"
writers="$writers osx"
+ default_writer="OSX_WRITE"
AC_DEFINE(HAVE_CORE_AUDIO, 1, define to 1 on Mac Os X)
fi
########################################################################### gtk2
write_cmdline_objs="$write_cmdline_objs alsa_write.cmdline"
write_ldflags="$write_ldflags -lasound"
writers="$writers alsa"
+ default_writer="ALSA_WRITE"
fi
CPPFLAGS="$OLD_CPPFLAGS"
LDFLAGS="$OLD_LDFLAGS"
enum="$(for i in $writers; do printf "${i}_WRITE, " | tr '[a-z]' '[A-Z]'; done)"
AC_DEFINE_UNQUOTED(WRITER_ENUM, $enum NUM_SUPPORTED_WRITERS,
enum of supported writers)
+AC_DEFINE_UNQUOTED(DEFAULT_WRITER, $default_writer, use this writer if none was specified)
names="$(for i in $writers; do printf \"$i\",' ' ; done)"
AC_DEFINE_UNQUOTED(WRITER_NAMES, $names, supported writer names)
inits="$(for i in $writers; do printf 'extern void '$i'_write_init(struct writer *); '; done)"
+++ /dev/null
-/*
- * Copyright (C) 2005-2007 Andre Noll <maan@systemlinux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- */
-
-
-/** \file db.c functions common to all audio file selectors */
-
-#include "server.cmdline.h"
-#include "server.h"
-#include "vss.h"
-#include <dirent.h> /* readdir() */
-#include <sys/stat.h> /* stat */
-#include <sys/types.h> /* mode_t */
-#include "error.h"
-#include "string.h"
-
-/**
- * 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;
- struct dirent *entry;
- /*
- * Opening the current directory (".") and calling fchdir() to return
- * is usually faster and more reliable than saving cwd in some buffer
- * and calling chdir() afterwards (see man 3 getcwd).
- */
- char cwd_fd = open(".", O_RDONLY);
- struct stat s;
- int ret = -1;
-
-// PARA_DEBUG_LOG("dirname: %s\n", dirname);
- if (cwd_fd < 0)
- return -E_GETCWD;
- ret = -E_CHDIR;
- if (chdir(dirname) < 0)
- goto out;
- ret = -E_OPENDIR;
- dir = opendir(".");
- if (!dir)
- goto out;
- /* scan cwd recursively */
- while ((entry = readdir(dir))) {
- mode_t m;
- char *tmp;
-
- 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);
- if (fchdir(cwd_fd) < 0)
- ret = -E_CHDIR;
- close(cwd_fd);
- if (ret < 0)
- PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (C) 2005-2006 Andre Noll <maan@systemlinux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- */
-
-/** \file db.h data structures common to all audio file selectors */
-
-#include <sys/select.h>
-
-
-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 neccessary 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*);
-
size = PARA_MIN(1024, len - written);
ret = write(fd, buf + written, size);
if (ret < 0) {
- if (errno != EAGAIN || !retries++ > DCCP_WRITE_RETRIES)
+ if (errno != EAGAIN || retries++ > DCCP_WRITE_RETRIES)
goto err_out;
PARA_DEBUG_LOG("EAGAIN #%d@%zd/%zd\n", retries, written, len);
goto again;
SS_CRYPT,
SS_HTTP_SEND,
SS_ORTP_SEND,
- SS_DB,
+ SS_AFS,
SS_OGG_AFH,
SS_MP3_AFH,
SS_AAC_AFH,
PARA_ERROR(FSTAT, "failed to fstat() audio file"), \
-#define DB_ERRORS \
+#define AFS_ERRORS \
PARA_ERROR(GETCWD, "can not get current working directory"), \
PARA_ERROR(CHDIR, "can not change directory"), \
PARA_ERROR(OPENDIR, "can not open directory"), \
SS_ENUM(CRYPT);
SS_ENUM(HTTP_SEND);
SS_ENUM(ORTP_SEND);
-SS_ENUM(DB);
+SS_ENUM(AFS);
SS_ENUM(MYSQL_SELECTOR);
SS_ENUM(IPC);
SS_ENUM(DCCP);
sot->loaded = fc->out_loaded;
sot->input_eof = &fc->eof;
- register_task(&sot->task);
- register_task(&fc->task);
register_task(&sit->task);
+ register_task(&fc->task);
+ register_task(&sot->task);
s.default_timeout.tv_sec = 1;
s.default_timeout.tv_usec = 0;
ret = sched(&s);
rn->private_data = para_calloc(sizeof(struct private_http_recv_data));
phd = rn->private_data;
ret = get_host_info(conf->host_arg, &he);
- if (!ret < 0)
+ if (ret < 0)
goto err_out;
/* get new socket */
ret = get_socket();
#include "server.cmdline.h"
#include "server.h"
#include "vss.h"
-#include "db.h"
+#include "afs.h"
#include <mysql/mysql.h>
#include <mysql/mysql_version.h>
#include <regex.h>
return ret;
}
-/* get attributes by name. If verbose is not 0, get_a writes a string
- * into atts of the form 'att1="0",att2="1"', which is used in com_cam
- * for contructing a mysql update query.
- * never returns NULL in *NON VERBOSE* mode
+/*
+ * 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, ret;
- unsigned int num_fields;
+ int i;
+ unsigned num_fields;
- ret = -E_NOATTS;
result2 = get_all_attributes();
if (!result2)
goto out;
- ret = -E_ESCAPE;
- if (!(ebn = escaped_basename(name)))
+ ebn = escaped_basename(name);
+ if (!ebn)
goto out;
buf = make_message("select * from data where name='%s'", ebn);
free(ebn);
- ret = -E_NORESULT;
result = get_result(buf);
free(buf);
if (!result)
goto out;
- ret = -E_EMPTY_RESULT;
num_fields = mysql_num_fields(result);
if (num_fields < 5)
goto out;
mysql_data_seek(result2, 4); /* skip Lastplayed, Numplayed... */
row = mysql_fetch_row(result);
- ret = -E_NOROW;
if (!row)
goto out;
for (i = 4; i < num_fields; i++) {
if (verbose)
atts = para_strcat(atts, is_set? "=\"1\"" : "=\"0\"");
}
- ret = 1;
out:
if (result2)
mysql_free_result(result2);
/** \file playlist_selector.c The playlist audio file selector of paraslash */
#include "server.h"
-#include "db.h"
+#include "afs.h"
#include "error.h"
#include "net.h"
#include "string.h"
#include <sys/time.h> /* gettimeofday */
#include "server.cmdline.h"
#include "server.h"
-#include "db.h"
+#include "afs.h"
#include "error.h"
#include "net.h"
#include "string.h"
#include "server.cmdline.h"
-#include "db.h"
+#include "afs.h"
#include "server.h"
#include "vss.h"
#include "config.h"
struct stdout_task {
/** pointer to the data buffer */
char *buf;
- /** the size of \a buf */
- size_t *bufsize;
/** number of bytes loaded in \a buf */
size_t *loaded;
/** pointer to the eof flag of the feeding task */
#include "server.h"
#include <sys/time.h> /* gettimeofday */
#include "server.cmdline.h"
-#include "db.h"
+#include "afs.h"
#include "afh.h"
#include "vss.h"
#include "send.h"
struct writer_node_group *setup_default_wng(void)
{
struct writer_node_group *wng = wng_new(1);
- enum writer_enum default_writer;
-
- if (NUM_SUPPORTED_WRITERS == 1)
- default_writer = FILE_WRITE;
- else
- default_writer = 1;
- wng->writer_nodes[0].writer = &writers[default_writer];
+ wng->writer_nodes[0].writer = &writers[DEFAULT_WRITER];
PARA_INFO_LOG("using default writer: %s %p\n",
- writer_names[default_writer], writers[default_writer].parse_config);
- wng->writer_nodes[0].conf = writers[default_writer].parse_config("");
+ writer_names[DEFAULT_WRITER], writers[DEFAULT_WRITER].parse_config);
+ wng->writer_nodes[0].conf = writers[DEFAULT_WRITER].parse_config("");
return wng;
}