/** \file audiod.c the paraslash's audio daemon */
#include <regex.h>
#include <sys/types.h>
-#include <dirent.h>
#include <signal.h>
-#include <openssl/rc4.h>
#include <stdbool.h>
#include "para.h"
#include "write.h"
#include "write_common.h"
#include "signal.h"
+#include "version.h"
/** define the array of error lists needed by para_audiod */
INIT_AUDIOD_ERRLISTS;
* \return The audio format number on success, -E_UNSUPPORTED_AUDIO_FORMAT if
* \a name is not a supported audio format.
*/
-int get_audio_format_num(const char *name)
+static int get_audio_format_num(const char *name)
{
int i;
return -E_UNSUPPORTED_AUDIO_FORMAT;
}
+static int get_matching_audio_format_nums(const char *re)
+{
+ int i, ret;
+ regex_t preg;
+
+ ret = para_regcomp(&preg, re, REG_EXTENDED | REG_NOSUB);
+ if (ret < 0)
+ return ret;
+ ret = 0;
+ FOR_EACH_AUDIO_FORMAT(i)
+ if (regexec(&preg, audio_formats[i], 0, NULL, 0) != REG_NOMATCH)
+ ret |= (1 << i);
+ regfree(&preg);
+ return ret;
+}
+
/**
* Compute the play time based on information of the given slot.
*
static void kill_all_decoders(int error)
{
- int i, j;
+ int i;
FOR_EACH_SLOT(i) {
- struct slot_info *s = &slot[i];
- struct audio_format_info *a;
+ struct slot_info *s = slot + i;
if (s->format < 0)
continue;
- a = afi + s->format;
- if (s->wns)
- for (j = 0; j < a->num_writers; j++)
- kill_btrn(s->wns[j].btrn, &s->wns[j].task, error);
- if (s->fns)
- for (j = 0; j < a->num_writers; j++)
- kill_btrn(s->fns[j].btrn, &s->wns[j].task, error);
- if (s->receiver_node)
- kill_btrn(s->receiver_node->btrn, &s->receiver_node->task,
+ if (!s->receiver_node)
+ continue;
+ kill_btrn(s->receiver_node->btrn, &s->receiver_node->task,
error);
}
}
return -E_NO_MORE_SLOTS;
}
-/**
- * get the number of filters
- *
- * \param audio_format_num the number identifying the audio format
- *
- * \return the number of filters for the given audio format
- *
- * \sa struct filter;
- */
-int num_filters(int audio_format_num)
-{
- return afi[audio_format_num].num_filters;
-}
-
static void open_filters(struct slot_info *s)
{
struct audio_format_info *a = afi + s->format;
for (i = conf.receiver_given - 1; i >= 0; i--) {
char *arg = conf.receiver_arg[i];
char *recv_arg = strchr(arg, ':');
+ int af_mask, j;
+
ret = -E_MISSING_COLON;
if (!recv_arg)
goto out;
*recv_arg = '\0';
recv_arg++;
- ret = get_audio_format_num(arg);
+ ret = get_matching_audio_format_nums(arg);
if (ret < 0)
goto out;
- /*
- * If multiple receivers are given for this audio format, the
- * last one wins and we have to free the previous receiver
- * config here. Since we are iterating backwards, the winning
- * receiver arg is in fact the first one given.
- */
- if (afi[ret].receiver_conf)
- afi[ret].receiver->free_config(afi[ret].receiver_conf);
- afi[ret].receiver_conf = check_receiver_arg(recv_arg, &receiver_num);
- if (!afi[ret].receiver_conf) {
+ af_mask = ret;
+ FOR_EACH_AUDIO_FORMAT(j) {
+ a = afi + j;
+ if ((af_mask & (1 << j)) == 0) /* no match */
+ continue;
+ /*
+ * If multiple receivers are given for this audio format, the
+ * last one wins and we have to free the previous receiver
+ * config here. Since we are iterating backwards, the winning
+ * receiver arg is in fact the first one given.
+ */
+ if (a->receiver_conf)
+ a->receiver->free_config(a->receiver_conf);
+ a->receiver_conf = check_receiver_arg(recv_arg, &receiver_num);
ret = -E_RECV_SYNTAX;
- goto out;
+ if (!a->receiver_conf)
+ goto out;
+ a->receiver = receivers + receiver_num;
}
- afi[ret].receiver = &receivers[receiver_num];
}
/*
* Use the first available receiver with no arguments for those audio
return -E_RECV_SYNTAX;
a->receiver = &receivers[receiver_num];
}
+ FOR_EACH_AUDIO_FORMAT(i) {
+ a = afi + i;
+ PARA_INFO_LOG("receiving %s streams via %s receiver\n",
+ audio_formats[i], a->receiver->name);
+ }
ret = 1;
out:
free(cmd);
if (s->format < 0)
return;
- if (s->receiver_node && s->receiver_node->task.error != -E_TASK_UNREGISTERED)
+ if (s->receiver_node && s->receiver_node->task.error >= 0)
return;
for (i = 0; i < a->num_filters; i++)
- if (s->fns && s->fns[i].task.error != -E_TASK_UNREGISTERED)
+ if (s->fns && s->fns[i].task.error >= 0)
return;
if (a->num_writers > 0) {
for (i = 0; i < a->num_writers; i++)
- if (s->wns && s->wns[i].task.error != -E_TASK_UNREGISTERED)
+ if (s->wns && s->wns[i].task.error >= 0)
return;
} else {
- if (s->wns && s->wns[0].task.error != -E_TASK_UNREGISTERED)
+ if (s->wns && s->wns[0].task.error >= 0)
return;
}
PARA_INFO_LOG("closing slot %d\n", slot_num);
kill_btrn(st->ct->btrn, &st->ct->task, -E_AUDIOD_OFF);
goto out;
}
- if (st->ct->task.error != -E_TASK_UNREGISTERED)
+ if (st->ct->task.error >= 0)
goto out;
close_stat_pipe();
st->clock_diff_count = conf.clock_diff_count_arg;
size_t sz;
int ret;
if (st->ct->task.error < 0) {
- if (st->ct->task.error != -E_TASK_UNREGISTERED)
+ if (st->ct->task.error >= 0)
goto out;
close_stat_pipe();
goto out;