Was cooking in next since 2015-10-25.
* refs/heads/t/para_play_fixes:
i9e: Avoid key binding macros.
play: Fix off-by-one in jmp 100.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
-SEARCHENGINE = YES
+SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
+# Implicit rules are implemented in make as suffix rules. The following rule
+# empties the suffix list to disable the predefined implicit rules. This
+# increases performance and avoids hard-to-debug behaviour.
+.SUFFIXES:
+MAKEFLAGS += -Rr
+ifeq ("$(origin CC)", "default")
+ CC := cc
+endif
+
vardir := /var/paraslash
mandir := $(datarootdir)/man/man1
STRIP := $(CROSS_COMPILE)strip
uname_rs := $(shell uname -rs)
cc_version := $(shell $(CC) --version | head -n 1)
GIT_VERSION := $(shell ./GIT-VERSION-GEN git-version.h)
+build_date := $(shell date)
ifeq ("$(origin O)", "command line")
build_dir := $(O)
$(subst z,Z,$1))))))))))))))))))))))))))
CPPFLAGS += -DBINDIR='"$(bindir)"'
-CPPFLAGS += -DBUILD_DATE='"$(shell date)"'
-CPPFLAGS += -DUNAME_RS='"$(shell uname -rs)"'
-CPPFLAGS += -DCC_VERSION='"$(shell $(CC) --version | head -n 1)"'
+CPPFLAGS += -DBUILD_DATE='"$(build_date)"'
+CPPFLAGS += -DUNAME_RS='"$(uname_rs)"'
+CPPFLAGS += -DCC_VERSION='"$(cc_version)"'
CPPFLAGS += -DMAIN_INPUT_FILE_IS_$(*F)
-CPPFLAGS += $(arch_cppflags)
CPPFLAGS += -I/usr/local/include
CPPFLAGS += -I$(cmdline_dir)
CPPFLAGS += -I$(cmdlist_dir)
$(cmdlist_dir)/afs.completion.h \
: afs.c aft.c attribute.c
-$(cmdlist_dir)/audiod,command_list.h \
-$(cmdlist_dir)/audiod,command_list.man \
-$(cmdlist_dir)/audiod,completion.h \
+$(cmdlist_dir)/audiod.command_list.h \
+$(cmdlist_dir)/audiod.command_list.man \
+$(cmdlist_dir)/audiod.completion.h \
: audiod_command.c
server_command_lists := $(cmdlist_dir)/server.command_list.man \
- The check command now also checks the attribute table for
inconsistencies.
- New -v flag for the version command (print verbose version string)
+ - New option --priority for para_server and para_audiod.
--------------------------------------
static int atom_cmp(const unsigned char *buf1, const char *buf2)
{
- const unsigned char *b2 = (unsigned char *)buf2;
-
- if (buf1[0] != b2[0])
- return 1;
- if (buf1[1] != b2[1])
- return 1;
- if (buf1[2] != b2[2])
- return 1;
- if (buf1[3] != b2[3])
- return 1;
- return 0;
+ return memcmp(buf1, buf2, 4)? 1 : 0;
}
static int read_atom_header(unsigned char *buf, uint64_t *subsize, unsigned char type[5])
{
int i;
- uint64_t size = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
+ uint64_t size = aac_read_int32(buf);
memcpy(type, buf + 4, 4);
type[4] = '\0';
if (ret < 0)
return ret;
afhi->chunks_total = ret;
- PARA_DEBUG_LOG("sz table has %lu entries\n", afhi->chunks_total);
+ PARA_DEBUG_LOG("sz table has %" PRIu32 " entries\n", afhi->chunks_total);
afhi->chunk_table = para_malloc((afhi->chunks_total + 1) * sizeof(size_t));
for (i = 1; i <= afhi->chunks_total; i++) {
if (skip + 4 > numbytes)
}
static int aac_set_chunk_tv(struct afh_info *afhi,
- mp4AudioSpecificConfig *mp4ASC, long unsigned *seconds)
+ mp4AudioSpecificConfig *mp4ASC, uint32_t *seconds)
{
float tmp = mp4ASC->sbr_present_flag == 1? 2047 : 1023;
struct timeval total;
ms = 1000.0 * afhi->chunks_total * tmp / mp4ASC->samplingFrequency;
ms2tv(ms, &total);
tv_divide(afhi->chunks_total, &total, &afhi->chunk_tv);
- PARA_INFO_LOG("%luHz, %lus (%lu x %lums)\n",
+ PARA_INFO_LOG("%luHz, %lus (%" PRIu32 " x %lums)\n",
mp4ASC->samplingFrequency, ms / 1000,
afhi->chunks_total, tv2ms(&afhi->chunk_tv));
if (ms < 1000)
/** Audio format dependent information. */
struct afh_info {
/** The number of chunks this audio file contains. */
- long unsigned chunks_total;
+ uint32_t chunks_total;
/** The length of the audio file in seconds. */
- long unsigned seconds_total;
+ uint32_t seconds_total;
/** Audio handler specific info about the file. */
char *techinfo;
/** Id3 tags, vorbis comments, aac tags. */
"%s: %s\n" /* format */
"%s: %dHz\n" /* frequency */
"%s: %d\n" /* channels */
- "%s: %lu\n" /* seconds total */
+ "%s: %" PRIu32 "\n" /* seconds total */
"%s: %lu: %lu\n" /* chunk time */
- "%s: %lu\n" /* num chunks */
+ "%s: %" PRIu32 "\n" /* num chunks */
"%s: %s\n" /* techinfo */
"%s: %s\n" /* artist */
"%s: %s\n" /* title */
*result = NULL;
if (!strcmp(cmd, "seconds_total")) {
- *result = make_message("%lu", pard->afhi.seconds_total);
+ *result = make_message("%" PRIu32, pard->afhi.seconds_total);
return 1;
}
if (!strcmp(cmd, "chunks_total")) {
- *result = make_message("%lu", pard->afhi.chunks_total);
+ *result = make_message("%" PRIu32, pard->afhi.chunks_total);
return 1;
}
if (!strcmp(cmd, "afhi")) {
/**
* A random number used to "authenticate" the connection.
*
- * para_server picks this number by random before forking the afs process. The
- * command handlers write this number together with the id of the shared memory
- * area containing the query. This way, a malicious local user has to know this
- * number to be able to cause the afs process to crash by sending fake queries.
+ * para_server picks this number by random before it forks the afs process. The
+ * command handlers know this number as well and write it to the afs socket,
+ * together with the id of the shared memory area which contains the payload of
+ * the afs command. A local process has to know this number to abuse the afs
+ * service provided by the local socket.
*/
extern uint32_t afs_socket_cookie;
get_database_dir();
ret = para_mkdir(database_dir, 0777);
- if (ret >= 0 || is_errno(-ret, EEXIST))
+ if (ret >= 0 || ret == -ERRNO_TO_PARA_ERROR(EEXIST))
return 1;
return ret;
}
/** \file afs.h Exported symbols of the audio file selector. */
-#include <regex.h>
-
/** Audio file selector data stored in the audio file table. */
struct afs_info {
/** Seconds since the epoch. */
static int get_local_time(uint64_t *seconds, char *buf, size_t size,
time_t current_time, enum ls_listing_mode lm)
{
- struct tm t;
+ struct tm *tm;
+ /*
+ * Omit year but show time if the given value is closer to the current
+ * time than this many seconds.
+ */
+ const time_t m = 6 * 30 * 24 * 3600; /* six months */
- if (!localtime_r((time_t *)seconds, &t))
+ tm = localtime((time_t *)seconds);
+ if (!tm)
return -E_LOCALTIME;
if (lm == LS_MODE_MBOX) {
- if (!strftime(buf, size, "%c", &t))
+ if (!strftime(buf, size, "%c", tm))
return -E_STRFTIME;
return 1;
}
- if (*seconds + 6 * 30 * 24 * 3600 > current_time) {
- if (!strftime(buf, size, "%b %e %k:%M", &t))
+ if (*seconds > current_time - m && *seconds < current_time + m) {
+ if (!strftime(buf, size, "%b %e %k:%M", tm))
return -E_STRFTIME;
return 1;
}
- if (!strftime(buf, size, "%b %e %Y", &t))
+ if (!strftime(buf, size, "%b %e %Y", tm))
return -E_STRFTIME;
return 1;
}
WRITE_STATUS_ITEM(b, SI_FREQUENCY, "%dHz\n", afhi->frequency);
WRITE_STATUS_ITEM(b, SI_CHANNELS, "%d\n", afhi->channels);
WRITE_STATUS_ITEM(b, SI_DURATION, "%s\n", duration_buf);
- WRITE_STATUS_ITEM(b, SI_SECONDS_TOTAL, "%lu\n", afhi->seconds_total);
+ WRITE_STATUS_ITEM(b, SI_SECONDS_TOTAL, "%" PRIu32 "\n",
+ afhi->seconds_total);
WRITE_STATUS_ITEM(b, SI_LAST_PLAYED, "%s\n", last_played_time);
WRITE_STATUS_ITEM(b, SI_NUM_PLAYED, "%d\n", afsi->num_played);
WRITE_STATUS_ITEM(b, SI_AMPLIFICATION, "%u\n", afsi->amp);
WRITE_STATUS_ITEM(b, SI_CHUNK_TIME, "%lu\n", tv2ms(&afhi->chunk_tv));
- WRITE_STATUS_ITEM(b, SI_NUM_CHUNKS, "%lu\n", afhi->chunks_total);
+ WRITE_STATUS_ITEM(b, SI_NUM_CHUNKS, "%" PRIu32 "\n",
+ afhi->chunks_total);
WRITE_STATUS_ITEM(b, SI_TECHINFO, "%s\n", afhi->techinfo);
WRITE_STATUS_ITEM(b, SI_ARTIST, "%s\n", afhi->tags.artist);
WRITE_STATUS_ITEM(b, SI_TITLE, "%s\n", afhi->tags.title);
objs[AFTCOL_AFSI].size = AFSI_SIZE;
save_afsi(&default_afsi, &objs[AFTCOL_AFSI]);
ret = osl(osl_add_and_get_row(audio_file_table, objs, &aft_row));
+ if (ret < 0)
+ goto out;
ret = afs_event(AUDIO_FILE_ADD, &aca->pbout, aft_row);
out:
if (ret < 0)
return;
for (i = a->num_filters - 1; i >= 0; i--) {
struct filter_node *fn = s->fns + i;
- struct filter *f;
+ const struct filter *f;
if (!fn)
continue;
- f = filters + fn->filter_num;
+ f = filter_get(fn->filter_num);
if (f->close)
f->close(fn);
btr_remove_node(&fn->btrn);
parent = s->receiver_node->btrn;
for (i = 0; i < nf; i++) {
char buf[20];
- struct filter *f = filters + a->filter_nums[i];
+ const struct filter *f = filter_get(a->filter_nums[i]);
fn = s->fns + i;
fn->filter_num = a->filter_nums[i];
fn->conf = a->filter_conf[i];
a->filter_conf[nf] = cfg;
a->num_filters++;
PARA_INFO_LOG("%s filter %d: %s\n", audio_formats[format], nf,
- filters[filter_num].name);
+ filter_get(filter_num)->name);
return filter_num;
}
}
/* add "dec" to audio format name */
tmp = make_message("%sdec", audio_formats[i]);
- for (j = 0; filters[j].name; j++)
- if (!strcmp(tmp, filters[j].name))
+ for (j = 0; filter_get(j); j++)
+ if (!strcmp(tmp, filter_get(j)->name))
break;
free(tmp);
ret = -E_UNSUPPORTED_FILTER;
- if (!filters[j].name)
+ if (!filter_get(j))
goto out;
- tmp = para_strdup(filters[j].name);
+ tmp = para_strdup(filter_get(j)->name);
ret = add_filter(i, tmp);
free(tmp);
if (ret < 0)
goto out;
PARA_INFO_LOG("%s -> default filter: %s\n", audio_formats[i],
- filters[j].name);
+ filter_get(j)->name);
}
out:
return ret;
writer_init();
if (conf.help_given || conf.detailed_help_given)
print_help_and_die();
+ daemon_set_priority(conf.priority_arg);
daemon_drop_privileges_or_die(conf.user_arg, conf.group_arg);
parse_config_or_die();
daemon_init_colors_or_die(conf.color_arg, color_arg_auto, color_arg_no,
btr_consume(ct->btrn[1], sz);
}
}
- /* fall though */
+ /* fall through */
case CL_EXECUTING:
if (ct->btrn[0]) {
ret = btr_node_status(ct->btrn[0], 0, BTR_NT_ROOT);
{
}
-static void mmd_dup(struct misc_meta_data *new_mmd)
-{
- mutex_lock(mmd_mutex);
- *new_mmd = *mmd;
- mutex_unlock(mmd_mutex);
-}
-
/*
- * Compute human readable string containing vss status for given integer value.
+ * Compute human readable vss status text.
*
- * We don't want to use vss_playing() and friends here because we take a
- * snapshot of the mmd struct and use the copy for computing the state of the
- * vss. If the real data were used, we would take the mmd lock for a rather
- * long time or risk to get an inconsistent view.
+ * We can't call vss_playing() and friends here because those functions read
+ * the flags from the primary mmd structure, so calling them from command
+ * handler context would require to take the mmd lock. At the time the function
+ * is called we already took a copy of the mmd structure and want to use the
+ * flags value of the copy for computing the vss status text.
*/
static char *vss_status_tohuman(unsigned int flags)
{
if (i != cc->argc)
return -E_COMMAND_SYNTAX;
for (;;) {
- mmd_dup(nmmd);
+ /*
+ * Copy the mmd structure to minimize the time we hold the mmd
+ * lock.
+ */
+ mutex_lock(mmd_mutex);
+ *nmmd = *mmd;
+ mutex_unlock(mmd_mutex);
ret = get_status(nmmd, parser_friendly, &s);
ret = send_sb(&cc->scc, s, ret, SBD_OUTPUT, false);
if (ret < 0)
AC_SUBST($1_ldflags)
])
-AC_PATH_PROG(UNAMEPATH, uname, no)
-if test "$UNAMEPATH" = "no"; then
- AC_MSG_ERROR(unable to determine system type)
-fi
-AC_MSG_CHECKING(os type)
-OSTYPE="`$UNAMEPATH -s`"
-AC_MSG_RESULT("$OSTYPE")
-
-if test "$OSTYPE" = "SunOS"; then
- # needed on SunOS for socket magic
- arch_cppflags="-D_XOPEN_SOURCE=500 -D__EXTENSIONS__"
- AC_SUBST(arch_cppflags)
-fi
-
AC_C_BIGENDIAN()
AC_PATH_PROG([GENGETOPT], [gengetopt])
#include <sys/types.h> /* getgrnam() */
#include <grp.h>
#include <signal.h>
+#include <sys/resource.h>
#include "para.h"
#include "daemon.h"
PARA_INFO_LOG("welcome to para_%s-" PACKAGE_VERSION " \n", name);
}
+/**
+ * Renice the calling process.
+ *
+ * \param prio The priority value to set.
+ *
+ * Errors are not considered fatal, but a warning message is logged if the
+ * underlying call to setpriority(2) fails.
+ */
+void daemon_set_priority(int prio)
+{
+ if (setpriority(PRIO_PROCESS, 0, prio) < 0)
+ PARA_WARNING_LOG("could not set priority to %d: %s\n", prio,
+ strerror(errno));
+}
+
/**
* Give up superuser privileges.
*
void daemon_open_log_or_die(void);
void daemon_close_log(void);
void daemon_log_welcome(const char *whoami);
+void daemon_set_priority(int prio);
void daemon_drop_privileges_or_die(const char *username, const char *groupname);
void daemon_set_start_time(void);
time_t daemon_get_uptime(const struct timeval *current_time);
PARA_ERROR(SIZE_PREFIX, "bad size prefix"), \
PARA_ERROR(REGEX, "regular expression error"), \
PARA_ERROR(ARG_NOT_FOUND, "argument not found in arg vector"), \
+ PARA_ERROR(BAD_LL, "invalid loglevel"), \
#define EXEC_ERRORS \
/** Set the osl error bit for the given number. */
#define OSL_ERRNO_TO_PARA_ERROR(num) ((num) | (1 << OSL_ERROR_BIT))
-/** Check whether a given number is a system error number.
- *
- * \param num The value to be checked.
- * \param _errno The system error number.
- *
- * \return True if \a num is paraslash's representation of the system
- * error identified by \a _errno.
- */
-_static_inline_ bool is_errno(int num, int _errno)
-{
- assert(num > 0 && _errno > 0);
- return ERRNO_TO_PARA_ERROR(_errno) == num;
-}
+static const char *weak_osl_strerror(int) __attribute__ ((weakref("osl_strerror")));
/**
* Paraslash's version of strerror(3).
*
_static_inline_ const char *para_strerror(int num)
{
assert(num > 0);
-#ifdef _OSL_H
- if (IS_OSL_ERROR(num))
- return osl_strerror(num & ((1 << OSL_ERROR_BIT) - 1));
-#endif
+ if (IS_OSL_ERROR(num)) {
+ assert(weak_osl_strerror);
+ return weak_osl_strerror(num & ~(1U << OSL_ERROR_BIT));
+ }
if (IS_SYSTEM_ERROR(num))
- return strerror(num & ((1 << SYSTEM_ERROR_BIT) - 1));
+ return strerror(num & ~(1U << SYSTEM_ERROR_BIT));
return para_errlist[ERRNUM_TO_SS(num)][ERRNUM_TO_INDEX(num)];
}
{
static struct sched s;
int i, ret;
- struct filter *f;
+ const struct filter *f;
struct btr_node *parent;
struct filter_node **fns;
goto out_cleanup;
}
fn->filter_num = ret;
- f = filters + fn->filter_num;
+ f = filter_get(fn->filter_num);
PARA_DEBUG_LOG("filter #%d: %s\n", i, f->name);
fn->btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = f->name, .parent = parent,
for (i--; i >= 0; i--) {
struct filter_node *fn = fns[i];
- f = filters + fn->filter_num;
+ f = filter_get(fn->filter_num);
if (f->close)
f->close(fn);
btr_remove_node(&fn->btrn);
/**
* Set scheduler timeout and add file descriptors to fd sets.
*
- * This function is used to control the timeout value for select. It
- * only allowed to decrease the current value. The second purpose of
- * this function is to set file descriptors to be watched by the
- * subsequent select call to the two fd sets.
+ * This function controls the timeout value for the next call to
+ * select(2). It may decrease the current timeout but shall never
+ * increase it. The second purpose of this function is to add file
+ * descriptors to the two fd sets of the sched structure. The
+ * descriptors in these sets will be watched by the subsequent
+ * select(2) call.
*/
void (*pre_select)(struct sched *s, void *context);
/**
DECLARE_FILTER_INITS
-/** Iterate over the array of supported filters. */
-#define FOR_EACH_SUPPORTED_FILTER(j) for (j = 0; j < NUM_SUPPORTED_FILTERS; j++)
-
/** The filter array, one structure for each supported filter. */
-extern struct filter filters[NUM_SUPPORTED_FILTERS];
+const struct filter *filter_get(int filter_num);
#include "error.h"
#include "string.h"
+/** Iterate over the array of supported filters. */
+#define FOR_EACH_SUPPORTED_FILTER(j) for (j = 0; j < NUM_SUPPORTED_FILTERS; j++)
+
/** The array of supported filters. */
-struct filter filters[NUM_SUPPORTED_FILTERS] = {FILTER_ARRAY};
+static struct filter filters[NUM_SUPPORTED_FILTERS] = {FILTER_ARRAY};
+
+const struct filter *filter_get(int filter_num)
+{
+ assert(filter_num >= 0);
+ assert(filter_num < NUM_SUPPORTED_FILTERS);
+ return filters + filter_num;
+}
/**
* Call the init function of each supported filter.
int i;
FOR_EACH_SUPPORTED_FILTER(i)
- filters[i].init(filters + i);
+ filter_get(i)->init((struct filter *)filter_get(i));
}
/*
*/
static int parse_filter_args(int filter_num, char *options, void **conf)
{
- struct filter *f = &filters[filter_num];
+ const struct filter *f = filter_get(filter_num);
int ret, argc;
char **argv;
*conf = NULL;
// PARA_DEBUG_LOG("arg: %s\n", fa);
FOR_EACH_SUPPORTED_FILTER(j) {
- const char *name = filters[j].name;
+ const char *name = filter_get(j)->name;
size_t len = strlen(name);
char c;
if (strlen(fa) < len)
c = fa[len];
if (c && c != ' ')
continue;
- if (c && !filters[j].parse_config)
+ if (c && !filter_get(j)->parse_config)
return -E_BAD_FILTER_OPTIONS;
return parse_filter_args(j, c? fa + len + 1 :
fa + strlen(fa), conf);
printf_or_die("\n ");
num = 0;
}
- num += printf_or_die("%s%s", i? " " : "", filters[i].name);
+ num += printf_or_die("%s%s", i? " " : "", filter_get(i)->name);
}
printf_or_die("\n");
FOR_EACH_SUPPORTED_FILTER(i) {
- struct filter *f = filters + i;
+ struct filter *f = (struct filter *)filter_get(i);
if (!f->help.short_help)
continue;
option "begin-chunk" b
#~~~~~~~~~~~~~~~~~~~~~
-"skip a number of chunks"
+"skip the beginning of the file"
int typestr = "chunk_num"
default = "0"
optional
details = "
The chunk_num argument must be between -num_chunks and
- num_chunks - 1 inclusively where num_chunks is the total number
- of chunks which is printed when using the --info option. If
- chunk_num is negative, the given number of chunks are counted
- backwards from the end of the file. For example --begin-chunk
- -100 instructs para_afh to start output at chunk num_chunks
- - 100. This is mainly useful for cutting off the end of an
- audio file.
+ num_chunks - 1, inclusively, where num_chunks is the total
+ number of chunks of the audio file given by the argument to
+ --filename. If chunk_num is negative, the given number of
+ chunks are counted backwards from the end of the file. For
+ example --begin-chunk -100 instructs the afh receiver to
+ start output at chunk num_chunks - 100. This is useful for
+ selecting the last part of an audio file.
"
option "end-chunk" e
include(daemon.m4)
include(user.m4)
include(group.m4)
+include(priority.m4)
<qu>
########################
--- /dev/null
+option "priority" -
+#~~~~~~~~~~~~~~~~~~
+"adjust scheduling priority"
+int typestr = "prio"
+default = "0"
+optional
+details = "
+ The priority (also known as nice value) is a value in the range -20
+ to 19. Lower priorities cause more favorable scheduling. Since only
+ privileged processes may request a negative priority, specifying
+ a negative value works only if the daemon is started with root
+ privileges.
+
+ Failure to set the given priority value is not considered an error
+ but a log message is printed in this case.
+"
include(daemon.m4)
include(user.m4)
include(group.m4)
+include(priority.m4)
<qu>
option "port" p
afhi->channels = header_channels(&header);
afhi->seconds_total = (tv2ms(&total_time) + 500) / 1000;
tv_divide(afhi->chunks_total, &total_time, &afhi->chunk_tv);
- PARA_DEBUG_LOG("%lu chunks, each %lums\n", afhi->chunks_total,
+ PARA_DEBUG_LOG("%" PRIu32 "chunks, each %lums\n", afhi->chunks_total,
tv2ms(&afhi->chunk_tv));
ret = mp3_get_id3(map, numbytes, fd, &afhi->tags);
afhi->techinfo = make_message("%cbr, %s, %s tags", vbr? 'v' : 'c',
afhi->seconds_total = num_frames / afhi->frequency;
/* use roughly one page per chunk */
frames_per_chunk = num_frames / i;
- PARA_INFO_LOG("%lu seconds, %d frames/chunk\n",
+ PARA_INFO_LOG("%" PRIu32 "seconds, %d frames/chunk\n",
afhi->seconds_total, frames_per_chunk);
ct_size = 250;
afhi->chunk_table = para_malloc(ct_size * sizeof(uint32_t));
*
* 2. The wav header (para_write only).
*
- * 3. The --format option of para_write.
+ * 3. The --sample-format option of para_write.
*/
#define SAMPLE_FORMATS \
SAMPLE_FORMAT(SF_S8, "8 bit signed"), \
loglevel = get_loglevel_by_name(conf.loglevel_arg);
}
for (i = 0; i < conf.key_map_given; i++) {
- char *s = strchr(conf.key_map_arg[i] + 1, ':');
- if (s)
+ char *kma = conf.key_map_arg[i];
+ if (*kma && strchr(kma + 1, ':'))
continue;
- PARA_EMERG_LOG("invalid key map arg: %s\n", conf.key_map_arg[i]);
+ PARA_EMERG_LOG("invalid key map arg: %s\n", kma);
goto err;
}
free(config_file);
static int eof_cleanup(struct play_task *pt)
{
struct writer *w = writers + DEFAULT_WRITER;
- struct filter *decoder = filters + pt->fn.filter_num;
+ const struct filter *decoder = filter_get(pt->fn.filter_num);
int ret;
ret = get_playback_error(pt);
const char *af;
char *tmp, buf[20];
int ret;
- struct filter *decoder;
+ const struct filter *decoder;
btr_remove_node(&pt->rn.btrn);
if (!pt->rn.receiver || pt->next_file != pt->current_file) {
if (ret < 0)
goto fail;
pt->fn.filter_num = ret;
- decoder = filters + ret;
+ decoder = filter_get(ret);
pt->fn.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = decoder->name, .parent = pt->rn.btrn,
.handler = decoder->execute, .context = &pt->fn));
* stderr. Once the i9e subsystem has been initialized, we switch to the i9e
* log facility.
*/
-static void session_open(__a_unused struct play_task *pt)
+static void session_open(struct play_task *pt)
{
int ret;
char *history_file;
* \param \ra string of the form receiver_name:options
* \param receiver_num contains the number of the receiver upon success
*
- * This function checks whether \a ra starts with the name of a supported
- * paraslash receiver, optionally followed by a colon and any options for that
- * receiver. If a valid receiver name was found the remaining part of \a ra is
- * passed to the receiver's config parser.
+ * This function checks whether \a ra starts with the name of a receiver,
+ * optionally followed by options for that receiver. If a valid receiver name
+ * was found the remaining part of \a ra is passed to the receiver's config
+ * parser.
*
* \return On success, a pointer to the receiver-specific gengetopt args info
* struct is returned and \a receiver_num contains the number of the receiver.
version_handle_flag("server", conf.version_given);
if (conf.help_given || conf.detailed_help_given)
print_help_and_die();
+ daemon_set_priority(conf.priority_arg);
daemon_drop_privileges_or_die(conf.user_arg, conf.group_arg);
/* parse config file, open log and set defaults */
parse_config_or_die(0);
return LL_CRIT;
if (loglevel_equal(txt, "emerg"))
return LL_EMERG;
- return -1;
+ return -E_BAD_LL;
}
static int get_next_word(const char *buf, const char *delim, char **word)
-RM ?= rm -f
+RM = rm -f
results_dir := $(test_dir)/test-results
trash_dir := $(test_dir)/trashes
let i++
commands[$i]="ls_ogg"
required_objects[$i]='ogg_afh'
-cmdline[$i]="ls -lv ${oggs_base[@]}"
+cmdline[$i]="ls -l=v ${oggs_base[@]}"
good[$i]='^basename:'
let i++
if [[ -n "$result" ]]; then
test_skip 'para_audiod' "missing object(s): $result"
else
- test_expect_success 'para_audiod: recv/filter/writer options' \
- "grep_man '$regex' audiod"
+ test_expect_success 'para_audiod: receivers' \
+ "grep_man 'Options for the http receiver' audiod"
+ test_expect_success 'para_audiod: filters' \
+ "grep_man 'Options for the compress filter' audiod"
+ test_expect_success 'para_audiod: writers' \
+ "grep_man 'Options for the file writer' audiod"
fi
# check various command lists
# para_play is always built
regex='LIST OF COMMANDS.\{100,\}'
test_expect_success 'para_play: play commands' "grep_man '$regex' play"
-regex="$rfw_regex"
test_done
return -ERRNO_TO_PARA_ERROR(errno);
}
-static void udp_init_session(struct sender_client *sc)
-{
- PARA_NOTICE_LOG("sending to udp %s\n", sc->name);
-}
-
static void udp_shutdown_targets(void)
{
struct sender_client *sc, *tmp;
{
int mps;
- udp_init_session(sc);
+ PARA_NOTICE_LOG("sending to udp %s\n", sc->name);
mps = generic_max_transport_msg_size(sc->fd) - sizeof(struct udphdr);
PARA_INFO_LOG("current MPS = %d bytes\n", mps);
return mps;
~~~~~~~
Doxygen is a documentation system for various programming
-languages. The paraslash project uses Doxygen for generating the API
-reference on the web pages, but good source code documentation is
-also beneficial to people trying to understand the code structure
-and the interactions between the various source files.
+languages. The API reference on the paraslash web page is generated
+by doxygen.
It is more illustrative to look at the source code for examples than
-to describe the conventions for documenting the source in this manual,
-so we only describe which parts of the code need doxygen comments,
-but leave out details on documentation conventions.
+to describe the conventions in this manual, so we only describe which
+parts of the code need doxygen comments, but leave out details on
+documentation conventions.
As a rule, only the public part of the C source is documented with
Doxygen. This includes structures, defines and enumerations in header
files as well as public (non-static) C functions. These should be
-documented completely. For example each parameter and the return
-value of a public function should get a descriptive comment.
+documented completely. For example, each parameter and the return
+value of a public function should get a descriptive doxygen comment.
No doxygen comments are necessary for static functions and for
structures and enumerations in C files (which are used only within