$(audiod_objs) $(audioc_objs) $(fade_objs) $(server_objs) \
$(write_objs) $(afh_objs) $(play_objs))
deps := $(addprefix $(dep_dir)/, $(filter-out %.cmdline.d, $(all_objs:.o=.d)))
-converted_executables := audioc client fade play recv write filter gui afh
+converted_executables := audioc client fade play recv write filter gui afh audiod
unconverted_executables := $(filter-out $(converted_executables), $(executables))
afh_objs += afh.lsg.o
audioc_objs += audioc.lsg.o
-audiod_objs += $(addsuffix _cmd.lsg.o, recv filter audiod write) client.lsg.o
+audiod_objs += $(addsuffix _cmd.lsg.o, recv filter audiod write) \
+ client.lsg.o audiod.lsg.o
client_objs += client.lsg.o
fade_objs += fade.lsg.o
filter_objs += filter_cmd.lsg.o filter.lsg.o
#include <pwd.h>
#include <lopsub.h>
+#include "audiod.lsg.h"
#include "recv_cmd.lsg.h"
-#include "client.lsg.h"
#include "para.h"
#include "error.h"
#include "crypt.h"
-#include "audiod.cmdline.h"
#include "list.h"
#include "sched.h"
-#include "ggo.h"
#include "buffer_tree.h"
#include "recv.h"
#include "filter.h"
/** Array of error strings. */
DEFINE_PARA_ERRLIST;
+static struct lls_parse_result *lpr;
+#define CMD_PTR (lls_cmd(0, audiod_suite))
+#define OPT_RESULT(_name) (lls_opt_result(LSG_AUDIOD_PARA_AUDIOD_OPT_ ## _name, lpr))
+#define OPT_GIVEN(_name) (lls_opt_given(OPT_RESULT(_name)))
+#define OPT_STRING_VAL(_name) (lls_string_val(0, OPT_RESULT(_name)))
+#define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name)))
+#define ENUM_STRING_VAL(_name) (lls_enum_string_val(OPT_UINT32_VAL(_name), \
+ lls_opt(LSG_AUDIOD_PARA_AUDIOD_OPT_ ## _name, CMD_PTR)))
+
__printf_2_3 void (*para_log)(int, const char*, ...) = daemon_log;
/** define the array containing all supported audio formats */
const char *audio_formats[] = {AUDIOD_AUDIO_FORMAT_ARRAY NULL};
*/
int audiod_status = AUDIOD_ON;
-/**
- * the gengetopt args_info struct that holds information on all command line
- * arguments
- */
-static struct audiod_args_info conf;
-
static char *socket_name;
static struct audio_format_info afi[NUM_AUDIO_FORMATS];
-
static struct signal_task *signal_task;
-
static struct status_task status_task_struct;
-
static uid_t *uid_whitelist;
/**
static void parse_config_or_die(void)
{
- int ret, i;
- char *config_file;
- struct audiod_cmdline_parser_params params = {
- .override = 0,
- .initialize = 0,
- .check_required = 1,
- .check_ambiguity = 0,
- .print_errors = 1
- };
-
- if (conf.config_file_given)
- config_file = para_strdup(conf.config_file_arg);
+ int ret;
+ char *cf, *errctx = NULL;
+ void *map;
+ size_t sz;
+
+ if (OPT_GIVEN(CONFIG_FILE))
+ cf = para_strdup(OPT_STRING_VAL(CONFIG_FILE));
else {
char *home = para_homedir();
- config_file = make_message("%s/.paraslash/audiod.conf", home);
+ cf = make_message("%s/.paraslash/audiod.conf", home);
free(home);
}
- ret = file_exists(config_file);
- if (conf.config_file_given && !ret) {
- PARA_EMERG_LOG("can not read config file %s\n", config_file);
- free(config_file);
- goto err;
- }
- if (ret) {
- audiod_cmdline_parser_config_file(config_file, &conf, ¶ms);
- daemon_set_loglevel(conf.loglevel_arg);
+ ret = mmap_full_file(cf, O_RDONLY, &map, &sz, NULL);
+ if (ret < 0) {
+ if (ret != -E_EMPTY && ret != -ERRNO_TO_PARA_ERROR(ENOENT))
+ goto free_cf;
+ if (ret == -ERRNO_TO_PARA_ERROR(ENOENT) && OPT_GIVEN(CONFIG_FILE))
+ goto free_cf;
+ } else {
+ int cf_argc;
+ char **cf_argv;
+ struct lls_parse_result *cf_lpr, *merged_lpr;
+ ret = lls(lls_convert_config(map, sz, NULL, &cf_argv, &errctx));
+ para_munmap(map, sz);
+ if (ret < 0)
+ goto free_cf;
+ cf_argc = ret;
+ ret = lls(lls_parse(cf_argc, cf_argv, CMD_PTR, &cf_lpr, &errctx));
+ lls_free_argv(cf_argv);
+ if (ret < 0)
+ goto free_cf;
+ ret = lls(lls_merge(lpr, cf_lpr, CMD_PTR, &merged_lpr,
+ &errctx));
+ lls_free_parse_result(cf_lpr, CMD_PTR);
+ if (ret < 0)
+ goto free_cf;
+ lls_free_parse_result(lpr, CMD_PTR);
+ lpr = merged_lpr;
}
- free(config_file);
- if (conf.user_allow_given > 0) {
- uid_whitelist = para_malloc(conf.user_allow_given
- * sizeof(uid_t));
- for (i = 0; i < conf.user_allow_given; i++) {
+ daemon_set_loglevel(ENUM_STRING_VAL(LOGLEVEL));
+ if (OPT_GIVEN(USER_ALLOW)) {
+ uint32_t n = OPT_GIVEN(USER_ALLOW);
+ int i;
+
+ uid_whitelist = para_malloc(n * sizeof(uid_t));
+ for (i = 0; i < n; i++) {
+ const char *arg = lls_string_val(i,
+ OPT_RESULT(USER_ALLOW));
int32_t val;
struct passwd *pw;
- ret = para_atoi32(conf.user_allow_arg[i], &val);
+ ret = para_atoi32(arg, &val);
if (ret >= 0) {
uid_whitelist[i] = val;
continue;
}
errno = 0; /* see getpwnam(3) */
- pw = getpwnam(conf.user_allow_arg[i]);
+ pw = getpwnam(arg);
if (!pw) {
- PARA_EMERG_LOG("invalid username: %s\n",
- conf.user_allow_arg[i]);
- goto err;
+ PARA_EMERG_LOG("invalid username: %s\n", arg);
+ free(uid_whitelist);
+ goto free_cf;
}
uid_whitelist[i] = pw->pw_uid;
}
}
- return;
-err:
- exit(EXIT_FAILURE);
+ ret = 0;
+free_cf:
+ free(cf);
+ if (ret < 0) {
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", errctx);
+ free(errctx);
+ lls_free_parse_result(lpr, CMD_PTR);
+ PARA_EMERG_LOG("%s\n", para_strerror(-ret));
+ exit(EXIT_FAILURE);
+ }
}
static void setup_signal_handling(void)
const char *cmd;
struct audio_format_info *a;
- for (i = 0; i < conf.writer_given; i++) {
+ for (i = 0; i < OPT_GIVEN(WRITER); i++) {
int j, nw, af_mask;
- ret = parse_stream_command(conf.writer_arg[i], &cmd);
+ ret = parse_stream_command(lls_string_val(i,
+ OPT_RESULT(WRITER)), &cmd);
if (ret < 0)
return ret;
af_mask = ret;
FOR_EACH_AUDIO_FORMAT(i)
afi[i].receiver_num = -1;
- for (i = conf.receiver_given - 1; i >= 0; i--) {
+ for (i = OPT_GIVEN(RECEIVER) - 1; i >= 0; i--) {
int j, af_mask;
- ret = parse_stream_command(conf.receiver_arg[i], &arg);
+ ret = parse_stream_command(lls_string_val(i,
+ OPT_RESULT(RECEIVER)), &arg);
if (ret < 0)
goto out;
af_mask = ret;
{
int i, j, ret, af_mask, num_matches;
- for (i = 0; i < conf.filter_given; i++) {
+ for (i = 0; i < OPT_GIVEN(FILTER); i++) {
const char *arg;
- ret = parse_stream_command(conf.filter_arg[i], &arg);
+ ret = parse_stream_command(lls_string_val(i,
+ OPT_RESULT(FILTER)), &arg);
if (ret < 0)
goto out;
af_mask = ret;
}
if (num_matches == 0)
PARA_WARNING_LOG("ignoring filter spec: %s\n",
- conf.filter_arg[i]);
+ lls_string_val(i, OPT_RESULT(FILTER)));
}
ret = init_default_filters(); /* use default values for the rest */
out:
/* does not unlink socket on errors */
static void init_local_sockets(struct command_task *ct)
{
- if (conf.socket_given)
- socket_name = para_strdup(conf.socket_arg);
+ if (OPT_GIVEN(SOCKET))
+ socket_name = para_strdup(OPT_STRING_VAL(SOCKET));
else {
char *hn = para_hostname();
socket_name = make_message("/var/paraslash/audiod_socket.%s",
free(hn);
}
PARA_NOTICE_LOG("local socket: %s\n", socket_name);
- if (conf.force_given)
+ if (OPT_GIVEN(FORCE))
unlink(socket_name);
ct->fd[0] = create_local_socket(socket_name, 0);
ct->fd[1] = create_local_socket(socket_name,
unlink(socket_name);
close_stat_pipe();
close_unused_slots();
- audiod_cmdline_parser_free(&conf);
close_stat_clients();
free(uid_whitelist);
}
goto out;
}
close_stat_pipe();
- st->clock_diff_count = conf.clock_diff_count_arg;
+ st->clock_diff_count = OPT_UINT32_VAL(CLOCK_DIFF_COUNT);
goto out;
}
if (st->ct) {
{
memset(st, 0, sizeof(struct status_task));
st->sa_time_diff_sign = 1;
- st->clock_diff_count = conf.clock_diff_count_arg;
+ st->clock_diff_count = OPT_UINT32_VAL(CLOCK_DIFF_COUNT);
st->current_audio_format_num = -1;
st->btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stat"));
static void set_initial_status(void)
{
audiod_status = AUDIOD_ON;
- if (!conf.mode_given)
+ if (!OPT_GIVEN(MODE))
return;
- if (!strcmp(conf.mode_arg, "sb")) {
+ if (!strcmp(OPT_STRING_VAL(MODE), "sb")) {
audiod_status = AUDIOD_STANDBY;
return;
}
- if (!strcmp(conf.mode_arg, "off")) {
+ if (!strcmp(OPT_STRING_VAL(MODE), "off")) {
audiod_status = AUDIOD_OFF;
return;
}
- if (strcmp(conf.mode_arg, "on"))
+ if (strcmp(OPT_STRING_VAL(MODE), "on"))
PARA_WARNING_LOG("invalid mode\n");
}
-__noreturn static void print_help_and_die(void)
-{
- struct ggo_help h = DEFINE_GGO_HELP(audiod);
- bool d = conf.detailed_help_given;
- unsigned flags;
-
- flags = d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS;
- ggo_print_help(&h, flags);
-
- flags = d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS;
- print_receiver_helps(flags);
- print_filter_helps(flags);
- print_writer_helps(flags);
- exit(0);
-}
-
/**
* Lookup the given UID in the whitelist.
*
{
int i;
- if (!conf.user_allow_given)
+ if (!OPT_GIVEN(USER_ALLOW))
return true;
- for (i = 0; i < conf.user_allow_given; i++)
+ for (i = 0; i < OPT_GIVEN(USER_ALLOW); i++)
if (uid == uid_whitelist[i])
return true;
return false;
}
+static void handle_help_flags(void)
+{
+ char *help;
+ bool d = OPT_GIVEN(DETAILED_HELP);
+
+ if (d)
+ help = lls_long_help(CMD_PTR);
+ else if (OPT_GIVEN(HELP))
+ help = lls_short_help(CMD_PTR);
+ else
+ return;
+ printf("%s\n", help);
+ free(help);
+ print_receiver_helps(d);
+ print_filter_helps(d);
+ print_writer_helps(d);
+ exit(EXIT_SUCCESS);
+}
+
/**
* the main function of para_audiod
*
{
int ret, i;
struct command_task command_task_struct, *cmd_task = &command_task_struct;
- struct audiod_cmdline_parser_params params = {
- .override = 0,
- .initialize = 1,
- .check_required = 0,
- .check_ambiguity = 0,
- .print_errors = 1
- };
+ char *errctx;
valid_fd_012();
- audiod_cmdline_parser_ext(argc, argv, &conf, ¶ms);
- daemon_set_loglevel(conf.loglevel_arg);
- version_handle_flag("audiod", conf.version_given);
- /* init receivers/filters/writers early to make help work */
- recv_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);
+ ret = lls(lls_parse(argc, argv, CMD_PTR, &lpr, &errctx));
+ if (ret < 0)
+ goto out;
+ daemon_set_loglevel(ENUM_STRING_VAL(LOGLEVEL));
+ daemon_drop_privileges_or_die(OPT_STRING_VAL(USER),
+ OPT_STRING_VAL(GROUP));
+ version_handle_flag("audiod", OPT_GIVEN(VERSION));
+ handle_help_flags();
parse_config_or_die();
- if (daemon_init_colors_or_die(conf.color_arg, color_arg_auto, color_arg_no,
- conf.logfile_given)) {
- for (i = 0; i < conf.log_color_given; i++)
- daemon_set_log_color_or_die(conf.log_color_arg[i]);
- }
init_random_seed_or_die();
+ daemon_set_priority(OPT_UINT32_VAL(PRIORITY));
+ recv_init();
+ if (daemon_init_colors_or_die(OPT_UINT32_VAL(COLOR), COLOR_AUTO,
+ COLOR_NO, OPT_GIVEN(LOGFILE))) {
+ for (i = 0; i < OPT_GIVEN(LOG_COLOR); i++)
+ daemon_set_log_color_or_die(lls_string_val(i,
+ OPT_RESULT(LOG_COLOR)));
+ }
daemon_set_flag(DF_LOG_TIME);
daemon_set_flag(DF_LOG_HOSTNAME);
daemon_set_flag(DF_LOG_LL);
- if (conf.log_timing_given)
+ if (OPT_GIVEN(LOG_TIMING))
daemon_set_flag(DF_LOG_TIMING);
- if (conf.logfile_given) {
- daemon_set_logfile(conf.logfile_arg);
+ if (OPT_GIVEN(LOGFILE)) {
+ daemon_set_logfile(OPT_STRING_VAL(LOGFILE));
daemon_open_log_or_die();
}
ret = parse_stream_args();
init_status_task(stat_task);
init_command_task(cmd_task);
- if (conf.daemon_given)
+ if (OPT_GIVEN(DAEMON))
daemonize(false /* parent exits immediately */);
signal_task->task = task_register(&(struct task_info) {
sched_shutdown(&sched);
signal_shutdown(signal_task);
+out:
+ lls_free_parse_result(lpr, CMD_PTR);
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", errctx);
if (ret < 0)
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
/** array of audio format names supported by para_audiod */
extern const char *audio_formats[];
-/**
- * the possible modes of operation
- *
- * - off: disconnect from para_server
- * - on: receive status information from para_server and play the audio stream
- * - sb: only receive status information but not the audio stream
- */
-enum audiod_status_info {AUDIOD_OFF, AUDIOD_ON, AUDIOD_STANDBY};
-
extern int audiod_status;
/* defined in audiod.c */
#include <netdb.h>
#include <lopsub.h>
+#include "audiod.lsg.h"
#include "para.h"
#include "audiod_cmd.lsg.h"
-#include "audiod.cmdline.h"
#include "list.h"
#include "sched.h"
#include "buffer_tree.h"
build_audiod="yes"
executables="$executables audiod"
audiod_audio_formats="wma"
- audiod_cmdline_objs="$audiod_cmdline_objs
- audiod
- "
audiod_errlist_objs="$audiod_errlist_objs
audiod
signal
audiod_command
fecdec_filter
client_common
- ggo
udp_recv
color
fec
if test $HAVE_SAMPLERATE = yes; then
audiod_errlist_objs="$audiod_errlist_objs resample_filter check_wav"
fi
- audiod_objs="add_cmdline($audiod_cmdline_objs) $audiod_errlist_objs"
+ audiod_objs="$audiod_errlist_objs"
AC_SUBST(audiod_objs, add_dot_o($audiod_objs))
enum="$(for i in $audiod_audio_formats; do printf "AUDIO_FORMAT_${i}, " | tr '[a-z]' '[A-Z]'; done)"
+++ /dev/null
-args "--no-handle-help --no-handle-version --conf-parser"
-
-purpose "Connect to para_server, receive, decode and play audio streams"
-
-include(header.m4)
-define(CURRENT_PROGRAM,para_audiod)
-define(DEFAULT_CONFIG_FILE,~/.paraslash/audiod.conf)
-
-<qu>
-#########################
-section "General options"
-#########################
-</qu>
-
-include(loglevel.m4)
-include(color.m4)
-include(config_file.m4)
-include(logfile.m4)
-include(log_timing.m4)
-include(daemon.m4)
-include(user.m4)
-include(group.m4)
-include(priority.m4)
-
-<qu>
-########################
-section "Audiod options"
-########################
-
-option "force" F
-#~~~~~~~~~~~~~~~
-"force startup"
-flag off
-details="
- If this flag is not given, para_audiod refuses to start if the
- well-known socket file (see the --socket option) already exists
- because this usually means that para_audiod is already running
- and listening on that socket. After a crash or if para_audiod
- received a SIGKILL signal, a stale socket file might remain and
- you have to use --force once to force startup of para_audiod.
-"
-
-option "mode" m
-#~~~~~~~~~~~~~~
-"startup mode"
-string typestr="mode"
-default="on"
-optional
-details="
- Para_audiod supports three modes of operation: On, off and
- standby (sb). This option selects the mode that should be
- used on startup. If para_audiod operates in \"on\" mode, it
- will connect to para_server in order to receive its status
- information. If para_server announces the availability of an
- audio stream, para_audiod will automatically download, decode
- and play the audio stream according to the given stream I/O
- options, see below.
-
- In \"standby\" mode, para_audiod will only receive the
- status information from para_server but will not download
- the audio stream.
-
- In \"off\" mode, para_audiod does not connect para_server at
- all, but still listens on the local socket for connections.
-"
-
-option "socket" s
-#~~~~~~~~~~~~~~~~
-"well-known socket"
-string typestr="filename"
-optional
-details="
- Para_audiod uses a \"well-known\" socket to listen
- on for connections from para_audioc. This socket is a
- special file in the file system; its location defaults to
- /var/paraslash/audiod_sock.<host_name>.
-
- para_audioc, the client program used to connect to para_audiod,
- opens this socket in order to talk to para_audiod. If the
- default value for para_audiod is changed, para_audioc must be
- instructed to use also \"filename\" for connecting para_audiod.
-"
-
-option "user-allow" -
-#~~~~~~~~~~~~~~~~~~~~
-"allow this user to connect to audiod"
-string typestr = "username"
-optional
-multiple
-details = "
- Allow the user identified by username (either a string or
- a UID) to connect to para_audiod. This option may be given
- multiple times. If not specified at all, all users are allowed
- to connect.
-
- This feature is based on the ability to send unix
- credentials through local sockets using ancillary data
- (SCM_CREDENTIALS). Currently it only works on Linux. On
- other operating systems the option is silently ignored and
- all local users are allowed to connect.
-"
-
-option "clock-diff-count" -
-#~~~~~~~~~~~~~~~~~~~~~~~~~~
-"sync clock on startup"
-int typestr="count"
-default="0"
-optional
-details="
- Check the clock difference between the host running para_server
- and the local host running para_audiod that many times before
- starting any stream I/0. Set this to non-zero for non-local
- setups if the clocks of these two hosts are not synchronized
- by ntp or similar.
-"
-
-#############################
-section "Stream I/O options"
-#############################
-
-option "receiver" r
-#~~~~~~~~~~~~~~~~~~
-"select receiver"
-string typestr="receiver_spec"
-default="http"
-optional
-multiple
-details="
- This option may be given multiple times, for each audio format
- separately. If multiple definitions for an audio format are
- given, the first one is selected.
-
- The \"receiver_spec\" consists of an audio format specifier
- and one or more receiver arguments, separated by a colon.
-
- The audio format specifier is a regular expression which
- specifies the set of audio formats for which this option
- should apply.
-
- If any receiver options are present, the whole receiver
- argument must be quoted:
-
- -r 'mp3:http -i my.host.org -p 8009'
-
- Since a single dot '.' matches the name of any audio format,
- specifying '.' instead of 'mp3' above activates the http
- receiver for all audio formats.
-
-"
-
-option "filter" f
-#~~~~~~~~~~~~~~~~
-"Specify the filter configuration."
-string typestr = "filter_spec"
-optional
-multiple
-details = "
- This option may be given multiple times. The \"filter_spec\"
- consists of an audio format specifier (see above), the name
- of the filter, and any options for that filter. Note that
- order matters.
-
- The compiled-in defaults apply to all audio formats for which
- no --filter option was given. These defaults depend on the
- receiver being used.
-
- For HTTP streams, only the decoder for the current audio
- format is activated. UDP and DCCP streams, on the other
- hand, are sent FEC-encoded by para_server. In order to play
- such streams, the receiver output must be FEC-decoded first,
- i.e. fed to the fecdec filter. Therefore the default for UDP
- and DCCP streams is to activate the fecdec filter, followed
- by the decoding filter for the audio format.
-
- Examples:
-
- --filter 'mp3:mp3dec'
-
- --filter 'mp3|aac:compress --inertia 5 --damp 2'
-
- --filter '.:fecdec'
-
-"
-
-option "writer" w
-#~~~~~~~~~~~~~~~~
-"Specify stream writer."
-string typestr="writer_spec"
-optional
-multiple
-details="
- May be given multiple times, even multiple times for the same
- audio format. Default value is \"alsa\" for all supported
- audio formats. Example:
-
- --writer 'aac|wma:oss'
-
-"
-</qu>
--- /dev/null
+m4_define(PROGRAM, para_audiod)
+m4_define(DEFAULT_CONFIG_FILE, ~/.paraslash/audiod.conf)
+[suite audiod]
+version-string = GIT_VERSION()
+[supercommand para_audiod]
+ purpose = connect to para_server, receive, decode and play audio streams
+ [description]
+ para_audiod runs on a host with an audio device and connects
+ para_server to obtain status information and receive the current audio
+ stream. The stream is transformed through any number of filters and
+ then written to the configured output device.
+
+ Moreover, para_audiod listens on a local socket and sends status
+ information to local clients on request. Access to the local socket
+ can be restricted by means of Unix socket credentials, if available.
+ [/description]
+ m4_include(common-option-section.m4)
+ m4_include(help.m4)
+ m4_include(detailed-help.m4)
+ m4_include(version.m4)
+ m4_include(config-file.m4)
+ m4_include(loglevel.m4)
+ m4_include(logfile.m4)
+ m4_include(color.m4)
+ m4_include(log-timing.m4)
+ m4_include(daemon.m4)
+ m4_include(user.m4)
+ m4_include(group.m4)
+ m4_include(priority.m4)
+ m4_include(per-command-options-section.m4)
+ [option force]
+ summary = force startup
+ short_opt = F
+ [help]
+ If this flag is not given, para_audiod refuses to start if the
+ well-known socket file (see the --socket option) already exists
+ because this usually means that para_audiod is already running and
+ listening on that socket. After a crash or if para_audiod received
+ a SIGKILL signal, a stale socket file might remain and you have to
+ use --force once to force startup of para_audiod.
+ [/help]
+ [option mode]
+ summary = select startup mode
+ arg_info = required_arg
+ arg_type = string
+ typestr = mode
+ values = {AUDIOD_ON = "on", AUDIOD_OFF = "off", AUDIOD_STANDBY = "sb"}
+ default_val = on
+ [help]
+ para_audiod supports three modes of operation: On, off and standby
+ (sb). This option selects the mode that should be used at startup. If
+ mode is "on", para_audiiod connects para_server to receive status
+ information. If the server announces the availability of an audio
+ stream, para_audiod downloads, decodes and plays the audio stream
+ according to the given stream I/O options, see below.
+
+ In "standby" mode, para_audiod only receives the status information
+ from para_server but does not download the audio stream.
+
+ In "off" mode, para_audiod does not connect para_server at all,
+ but still listens on the local socket.
+ [/help]
+ [option socket]
+ short_opt = s
+ summary = path to the well-known socket
+ arg_info = required_arg
+ arg_type = string
+ typestr = path
+ [help]
+ para_audiod listens on a "well-known" socket for connections
+ from para_audioc. This socket is a special file in the file system;
+ its location defaults to /var/paraslash/audiod_sock.$hostname.
+
+ para_audioc, the client program used to connect to para_audiod,
+ opens this socket in order to talk to para_audiod. If the default
+ value for para_audiod is changed, para_audioc must be instructed to
+ use also <path> to connect para_audiod.
+ [/help]
+ [option user-allow]
+ summary = allow this user to connect to audiod
+ arg_info = required_arg
+ arg_type = string
+ typestr = username
+ [help]
+ Allow the user identified by username (either a string or a UID) to
+ connect to para_audiod. This option may be given multiple times. If
+ not specified at all, all users are allowed to connect.
+
+ This feature is based on the ability to send unix credentials through
+ local sockets using ancillary data (SCM_CREDENTIALS). Currently it
+ only works on Linux. On other operating systems the option is silently
+ ignored and all local users are allowed to connect.
+ [/help]
+ [option clock-diff-count]
+ summary = sync clock on startup
+ arg_info = required_arg
+ arg_type = uint32
+ typestr = count
+ [help]
+ Check the clock difference between the host running para_server and
+ the local host running para_audiod this many times before starting
+ any stream I/0. Set this to non-zero for non-local setups if the
+ clocks of these two hosts are not synchronized by ntp or similar.
+ [/help]
+ [option Stream-IO-options]
+ summary = Stream I/O options
+ flag ignored
+ [option receiver]
+ short_opt = r
+ summary = select receiver
+ arg_info = required_arg
+ arg_type = string
+ typestr = receiver_spec
+ default_val = http
+ flag multiple
+ [help]
+ This option may be given multiple times, for each audio format
+ separately. If multiple definitions for an audio format are given,
+ the first one is selected.
+
+ The <receiver_spec> consists of an audio format specifier and one or
+ more receiver arguments, separated by a colon.
+
+ The audio format specifier is a regular expression which specifies
+ the set of audio formats for which this option should apply.
+
+ If any receiver options are present, the whole receiver argument must
+ be quoted:
+
+ -r 'mp3:http -i my.host.org -p 8009'
+
+ Since a single dot '.' matches the name of any audio format, specifying
+ '.' instead of 'mp3' above activates the http receiver for all audio
+ formats.
+ [/help]
+ [option filter]
+ short_opt = f
+ summary = specify the filter configuration
+ arg_info = required_arg
+ arg_type = string
+ typestr = filter_spec
+ flag multiple
+ [help]
+ This option may be given multiple times. The <filter_spec< consists
+ of an audio format specifier (see above), the name of the filter,
+ and any options for that filter. Note that order matters.
+
+ The compiled-in defaults apply to all audio formats for which no
+ --filter option was given. These defaults depend on the receiver
+ being used.
+
+ For HTTP streams, only the decoder for the current audio format
+ is activated. UDP and DCCP streams, on the other hand, are sent
+ FEC-encoded by para_server. In order to play such streams, the
+ receiver output must be FEC-decoded first, i.e. fed to the fecdec
+ filter. Therefore the default for UDP and DCCP streams is to activate
+ the fecdec filter, followed by the decoding filter for the audio
+ format.
+
+ Examples:
+
+ --filter 'mp3:mp3dec'
+
+ --filter 'mp3|aac:compress --inertia 5 --damp 2'
+
+ --filter '.:fecdec'
+ [/help]
+ [option writer]
+ short_opt = w
+ summary = specify one or more stream writers
+ arg_info = required_arg
+ arg_type = string
+ typestr = writer_spec
+ flag multiple
+ [help]
+ May be given multiple times, even multiple times for the same audio
+ format. The default is to use the first supported writer. Example:
+
+ --writer 'aac|wma:oss'
+ [/help]
+ [option stream-delay]
+ summary = specify time interval for client sync
+ arg_info = required_arg
+ arg_type = uint32
+ typestr = count
+ [help]
+ Check the clock difference between the host running para_server and
+ the local host running para_audiod this many times before starting
+ any stream I/0. Set this to non-zero for non-local setups if the
+ clocks of these two hosts are not synchronized by ntp or similar.
+ [/help]
--- /dev/null
+[option color]
+ short_opt = C
+ summary = activate color output
+ typestr = when
+ arg_info = required_arg
+ arg_type = string
+ values = {COLOR_YES = "yes", COLOR_NO = "no", COLOR_AUTO = "auto"}
+ default_val = auto
+[option log-color]
+ summary = select a color for one type of log message
+ typestr = color_spec
+ arg_info = required_arg
+ arg_type = string
+ flag multiple
+ [help]
+ The format of <color_spec> is [<fg> [<bg>]] [<attr>].
+
+ Valid colors for <fg> and <bg> are "normal", "black", "red", "green",
+ "yellow", "blue", "magenta", "cyan", and "white".
+
+ The <attr> value must be one of "bold", "dim", "ul", "blink",
+ "reverse".
+
+ Examples:
+
+ --log-color "debug:green"
+ --log-color "info:yellow bold"
+ --log-color "notice:white red bold"
+ [/help]
--- /dev/null
+[option daemon]
+ short_opt = d
+ summary = run as background daemon
+ [help]
+ If this option is given and no logfile was specified, all messages
+ go to /dev/null.
+ [/help]
--- /dev/null
+[option group]
+ short_opt = g
+ summary = set group id
+ arg_info = required_arg
+ arg_type = string
+ typestr = groupname
+ [help]
+ This option sets the group id according to <group>. This option is
+ silently ignored if EUID != 0. Otherwise, real/effective GID and the
+ saved set-group ID are all set to the GID given by <group>. Must not
+ be given in the config file.
+ [/help]
--- /dev/null
+[option log-timing]
+ short_opt = T
+ summary = show milliseconds in log messages
+ [help]
+ Selecting this option causes milliseconds to be included in
+ the log message output. This allows to measure the interval
+ between log messages in milliseconds which is useful for
+ identifying timing problems.
+ [/help]
--- /dev/null
+[option logfile]
+short_opt = L
+arg_info = required_arg
+arg_type = string
+typestr = filename
+summary = where to write log output
+[help]
+ If this option is not given, PROGRAM() writes the log messages
+ to stderr.
+[/help]
--- /dev/null
+[option priority]
+ summary = adjust scheduling priority
+ arg_info = required_arg
+ arg_type = int32
+ typestr = prio
+ default_val = 0
+ [help]
+ 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.
+ [/help]
--- /dev/null
+[option user]
+ short_opt = u
+ summary = run as the given user
+ arg_info = required_arg
+ arg_type = string
+ typestr = username
+ [help]
+ PROGRAM() does not need any special privileges.
+
+ If started as root (EUID == 0) this option must be given at the
+ command line (not in the configuration file) so that PROGRAM()
+ can drop the root privileges right after parsing the command line
+ options, but before parsing the configuration file. In this case,
+ real/effective/saved UID are all set to the UID of <username>. As
+ the configuration file is read afterwards, those options that have
+ a default value depending on the UID (e.g. the directory for the
+ configuration file) are computed by using the uid of <username>. This
+ option has no effect if PROGRAM() is started as a non-root user (i.e.
+ EUID != 0).
+ [/help]
+