From: Andre Noll Date: Thu, 18 Aug 2011 13:26:34 +0000 (+0200) Subject: Merge branch 't/writer_setup_cleanup' X-Git-Tag: v0.4.8~4 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=4a4d8f266a79275d7b2c902dc69b5ec8d46406b2;hp=9fe520149ef6bbc6bed4ee538bd2310af9d6a2cd Merge branch 't/writer_setup_cleanup' --- diff --git a/NEWS b/NEWS index 05c866b4..946524b2 100644 --- a/NEWS +++ b/NEWS @@ -20,8 +20,9 @@ are the highlights of this release. tarballs. This reduces the size of the tarballs but requires gengetopt to build the tarball. - Compiles cleanly also with llvm/clang. - - The alsa writer used poll fds instead of computing timeouts. - Corrupt mp3 files are handled more gracefully. + - The alsa writer uses poll fds instead of computing timeouts. + - Cleanup of the generic writer API. - sched: Optimized zero timeouts. - vss timeout cleanups. diff --git a/audiod.c b/audiod.c index c7998cdb..c78df5b8 100644 --- a/audiod.c +++ b/audiod.c @@ -522,16 +522,12 @@ static void open_writers(struct slot_info *s) assert(s->wns == NULL); s->wns = para_calloc(PARA_MAX(1U, a->num_writers) * sizeof(struct writer_node)); - if (a->num_writers == 0) - setup_writer_node(NULL, parent, s->wns); - else { - PARA_INFO_LOG("opening %s writers\n", audio_formats[s->format]); - for (i = 0; i < a->num_writers; i++) { - wn = s->wns + i; - wn->conf = a->writer_conf[i]; - wn->writer_num = a->writer_nums[i]; - register_writer_node(wn, parent); - } + PARA_INFO_LOG("opening %s writers\n", audio_formats[s->format]); + for (i = 0; i < a->num_writers; i++) { + wn = s->wns + i; + wn->conf = a->writer_conf[i]; + wn->writer_num = a->writer_nums[i]; + register_writer_node(wn, parent); } } @@ -780,29 +776,38 @@ static int parse_writer_args(void) ret = parse_stream_command(conf.writer_arg[i], &cmd); if (ret < 0) - goto out; + return ret; af_mask = ret; FOR_EACH_AUDIO_FORMAT(j) { a = afi + j; if ((af_mask & (1 << j)) == 0) /* no match */ continue; - ret = -E_WRITE_COMMON_SYNTAX; - wconf = check_writer_arg(cmd, &writer_num); - if (!wconf) - goto out; + wconf = check_writer_arg_or_die(cmd, &writer_num); nw = a->num_writers; a->writer_nums = para_realloc(a->writer_nums, (nw + 1) * sizeof(int)); a->writer_conf = para_realloc(a->writer_conf, (nw + 1) * sizeof(void *)); a->writer_nums[nw] = writer_num; a->writer_conf[nw] = wconf; - PARA_INFO_LOG("%s writer #%d: %s\n", audio_formats[writer_num], + PARA_INFO_LOG("%s writer #%d: %s\n", audio_formats[j], nw, writer_names[writer_num]); a->num_writers++; } } - ret = 1; -out: - return ret; + /* Use default writer for audio formats which are not yet set up. */ + FOR_EACH_AUDIO_FORMAT(i) { + struct writer *w = writers + DEFAULT_WRITER; + a = afi + i; + if (a->num_writers > 0) + continue; /* already set up */ + PARA_INFO_LOG("%s writer: %s (default)\n", audio_formats[i], + writer_names[DEFAULT_WRITER]); + a->writer_nums = para_malloc(sizeof(int)); + a->writer_nums[0] = DEFAULT_WRITER; + a->writer_conf = para_malloc(sizeof(void *)); + a->writer_conf[0] = w->parse_config_or_die(""); + a->num_writers = 1; + } + return 1; } static int parse_receiver_args(void) diff --git a/error.h b/error.h index da0efc47..a56faf54 100644 --- a/error.h +++ b/error.h @@ -34,6 +34,7 @@ DEFINE_ERRLIST_OBJECT_ENUM; #define STDOUT_ERRORS #define FILE_WRITE_ERRORS #define STDIN_ERRORS +#define WRITE_ERRORS extern const char **para_errlist[]; @@ -422,10 +423,6 @@ extern const char **para_errlist[]; PARA_ERROR(READ_PATTERN, "did not read expected pattern"), \ -#define WRITE_ERRORS \ - PARA_ERROR(WRITE_SYNTAX, "para_write syntax error"), \ - - #define ALSA_WRITE_ERRORS \ PARA_ERROR(BROKEN_CONF, "Broken alsa configuration"), \ PARA_ERROR(ACCESS_TYPE, "alsa access type not available"), \ @@ -445,7 +442,6 @@ extern const char **para_errlist[]; #define WRITE_COMMON_ERRORS \ - PARA_ERROR(WRITE_COMMON_SYNTAX, "syntax error in write option"), \ PARA_ERROR(WRITE_COMMON_EOF, "end of file"), \ diff --git a/write.c b/write.c index 6b574414..3b5f2d19 100644 --- a/write.c +++ b/write.c @@ -165,11 +165,44 @@ __noreturn static void print_help_and_die(void) exit(0); } -static int main_btr(struct sched *s) +/* + * Parse config and register a task for a writer node. + * + * \param arg Command line arguments. + * \param parent The new node will be a child of \a parent. + * \param wn The writer node. + * + * If arg is \p NULL, the OS-dependent default writer is used with no + * arguments. The default writers are alsa for Linux, osx for OS X, oss for + * *BSD, and the file writer if the default writer is not supported. + * + * Once the writer configuration has been retrieved from the ->parse_config + * callback a writer node is created, its buffer tree node is added to the + * buffer tree as a child of the given parent. + * + * Finally, the new writer node's task structure is initialized and registered + * to the paraslash scheduler. + * + * \return Standard. + */ +static void setup_writer_node(const char *arg, struct btr_node *parent, + struct writer_node *wn) +{ + if (arg) + wn->conf = check_writer_arg_or_die(arg, &wn->writer_num); + else { + wn->writer_num = DEFAULT_WRITER; + wn->conf = writers[DEFAULT_WRITER].parse_config_or_die(""); + } + register_writer_node(wn, parent); +} + +static int setup_and_schedule(void) { int i, ret; struct check_wav_task _cwt, *cwt = &_cwt; struct writer_node *wns; + static struct sched s; loglevel = get_loglevel_by_name(conf.loglevel_arg); sit.btrn = btr_new_node(&(struct btr_node_description) @@ -188,27 +221,20 @@ static int main_btr(struct sched *s) cwt->task.error = 0; register_task(&cwt->task); - ret = -E_WRITE_SYNTAX; if (!conf.writer_given) { - i = 0; wns = para_calloc(sizeof(*wns)); - ret = setup_writer_node(NULL, cwt->btrn, wns); - if (ret < 0) - goto out; + setup_writer_node(NULL, cwt->btrn, wns); i = 1; } else { wns = para_calloc(conf.writer_given * sizeof(*wns)); - for (i = 0; i < conf.writer_given; i++) { - ret = setup_writer_node(conf.writer_arg[i], - cwt->btrn, wns + i); - if (ret < 0) - goto out; - } + for (i = 0; i < conf.writer_given; i++) + setup_writer_node(conf.writer_arg[i], cwt->btrn, + wns + i); } - s->default_timeout.tv_sec = 10; - s->default_timeout.tv_usec = 50000; - ret = schedule(s); + s.default_timeout.tv_sec = 10; + s.default_timeout.tv_usec = 50000; + ret = schedule(&s); if (ret >= 0) { int j; for (j = 0; j < i; j++) { @@ -223,7 +249,6 @@ static int main_btr(struct sched *s) } } } -out: for (i--; i >= 0; i--) { struct writer_node *wn = wns + i; struct writer *w = writers + wn->writer_num; @@ -251,8 +276,7 @@ out: */ int main(int argc, char *argv[]) { - int ret = -E_WRITE_SYNTAX; - static struct sched s; + int ret; writer_init(); write_cmdline_parser(argc, argv, &conf); @@ -260,7 +284,7 @@ int main(int argc, char *argv[]) if (conf.help_given || conf.detailed_help_given) print_help_and_die(); - ret = main_btr(&s); + ret = setup_and_schedule(); if (ret < 0) { PARA_ERROR_LOG("%s\n", para_strerror(-ret)); exit(EXIT_FAILURE); diff --git a/write_common.c b/write_common.c index faf20749..b8569936 100644 --- a/write_common.c +++ b/write_common.c @@ -47,14 +47,13 @@ void writer_init(void) * * \return On success, a pointer to the gengetopt args info struct is returned * and \a writer_num contains the number of the writer. Otherwise this function - * returns \p NULL. + * prints an error message and calls exit(). */ -void *check_writer_arg(const char *wa, int *writer_num) +void *check_writer_arg_or_die(const char *wa, int *writer_num) { int i; - *writer_num = -E_WRITE_COMMON_SYNTAX; - PARA_INFO_LOG("checking %s\n", wa); + PARA_INFO_LOG("checking %s\n", wa); FOR_EACH_WRITER(i) { const char *name = writer_names[i]; size_t len = strlen(name); @@ -69,8 +68,8 @@ void *check_writer_arg(const char *wa, int *writer_num) *writer_num = i; return writers[i].parse_config_or_die(c? wa + len + 1 : ""); } - PARA_ERROR_LOG("writer not found\n"); - return NULL; + PARA_EMERG_LOG("invalid writer %s\n", wa); + exit(EXIT_FAILURE); } /** @@ -97,41 +96,6 @@ void register_writer_node(struct writer_node *wn, struct btr_node *parent) register_task(&wn->task); } -/** - * Parse config and register a task for a writer node. - * - * \param arg Command line arguments. - * \param parent The new node will be a child of \a parent. - * \param wn The writer node. - * - * If arg is \p NULL, the OS-dependent default writer is used with no - * arguments. The default writers are alsa for Linux, osx for OS X, oss for - * *BSD, and the file writer if the default writer is not supported. - * - * Once the writer configuration has been retrieved from the ->parse_config - * callback a writer node is created, its buffer tree node is added to the - * buffer tree as a child of the given parent. - * - * Finally, the new writer node's task structure is initialized and registered - * to the paraslash scheduler. - * - * \return Standard. - */ -int setup_writer_node(const char *arg, struct btr_node *parent, - struct writer_node *wn) -{ - if (arg) - wn->conf = check_writer_arg(arg, &wn->writer_num); - else { - wn->writer_num = DEFAULT_WRITER; - wn->conf = writers[DEFAULT_WRITER].parse_config_or_die(""); - } - if (!wn->conf) - return -E_WRITE_COMMON_SYNTAX; - register_writer_node(wn, parent); - return 1; -} - /** * Print the help text of all writers to stdout. * diff --git a/write_common.h b/write_common.h index 5f55120b..00ded8f3 100644 --- a/write_common.h +++ b/write_common.h @@ -7,11 +7,9 @@ /** \file write_common.h Exported symbols from write_common.c. */ void writer_init(void); -void *check_writer_arg(const char *wa, int *writer_num); +void *check_writer_arg_or_die(const char *wa, int *writer_num); void print_writer_helps(int detailed); void register_writer_node(struct writer_node *wn, struct btr_node *parent); -int setup_writer_node(const char *arg, struct btr_node *parent, - struct writer_node *wn); void get_btr_sample_rate(struct btr_node *btrn, int32_t *result); void get_btr_channels(struct btr_node *btrn, int32_t *result); void get_btr_sample_format(struct btr_node *btrn, int32_t *result);