X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=write_common.c;h=14cc98a4189a5f74907f8bfcf416f62bcc2515c5;hp=faf20749ba33062ed66845cafa38a283bcaa3c02;hb=57a338b4f7a8346708636de18780eaec52750e96;hpb=ae8073c5441aeee5d3b63840e84d8c33e2c583ee diff --git a/write_common.c b/write_common.c index faf20749..14cc98a4 100644 --- a/write_common.c +++ b/write_common.c @@ -1,157 +1,176 @@ -/* - * Copyright (C) 2006-2011 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2006 Andre Noll , see file COPYING. */ /** \file write_common.c common functions of para_audiod and para_write */ #include -#include +#include +#include "write_cmd.lsg.h" #include "para.h" #include "string.h" #include "list.h" #include "sched.h" -#include "ggo.h" #include "buffer_tree.h" #include "write.h" #include "error.h" -/** the array containing the names of all supported writers */ -const char *writer_names[] ={WRITER_NAMES}; +/** Loop over all writers. */ +#define FOR_EACH_WRITER(i) for (i = 1; lls_cmd(i, write_cmd_suite); i++) -/** the array of supported writers */ -struct writer writers[NUM_SUPPORTED_WRITERS] = {WRITER_ARRAY}; -/** - * Call the init function of each supported paraslash writer. - */ -void writer_init(void) +static inline bool writer_supported(int wid) +{ + return lls_user_data(WRITE_CMD(wid)); +} + +/* simply return the first available writer */ +static int default_writer_id(void) { int i; FOR_EACH_WRITER(i) - writers[i].init(&writers[i]); + if (writer_supported(i)) + return i; + assert(0); /* the file writer should always be available */ } + /** - * Check if given string is a valid command line for any writer. - * - * \param \wa String of the form writer_name:options. - * \param writer_num Contains the number of the writer upon success. + * Return the writer structure from a writer ID. * - * This function checks whether \a wa starts with the name of a supported - * paraslash writer, optionally followed by a colon and any options for that - * writer. If a valid writer name was found and further are present, the - * remaining part of \a wa is passed to that writer's config parser. + * \param wid If non-positive, a pointer to the default writer is returned. * - * \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. + * \return Pointer to a (constant) struct writer. */ -void *check_writer_arg(const char *wa, int *writer_num) +const struct writer *writer_get(int wid) { - int i; - - *writer_num = -E_WRITE_COMMON_SYNTAX; - PARA_INFO_LOG("checking %s\n", wa); - FOR_EACH_WRITER(i) { - const char *name = writer_names[i]; - size_t len = strlen(name); - char c; - if (strlen(wa) < len) - continue; - if (strncmp(name, wa, len)) - continue; - c = wa[len]; - if (c && c != ' ') - continue; - *writer_num = i; - return writers[i].parse_config_or_die(c? wa + len + 1 : ""); - } - PARA_ERROR_LOG("writer not found\n"); - return NULL; + if (wid < 0) + wid = default_writer_id(); + return lls_user_data(WRITE_CMD(wid)); } /** - * Open a writer node and register the corresponding task. + * Return name of the writer identified by a writer ID. * - * \param wn The writer node to open. - * \param parent The parent btr node (the source for the writer node). + * \param wid If non-positive, the name of the default writer is returned. * - * The configuration of the writer node stored in \p wn->conf must be - * initialized before this function may be called. + * \return The returned buffer must not be freed by the caller. */ -void register_writer_node(struct writer_node *wn, struct btr_node *parent) +const char *writer_name(int wid) { - struct writer *w = writers + wn->writer_num; - char *name = make_message("%s writer", writer_names[wn->writer_num]); - - wn->btrn = btr_new_node(&(struct btr_node_description) - EMBRACE(.name = name, .parent = parent, - .handler = w->execute, .context = wn)); - strcpy(wn->task.status, name); - free(name); - wn->task.post_select = w->post_select; - wn->task.pre_select = w->pre_select; - register_task(&wn->task); + if (wid <= 0) + wid = default_writer_id(); + return lls_command_name(WRITE_CMD(wid)); } /** - * Parse config and register a task for a writer node. + * Check if the given string is a valid command line for any writer. * - * \param arg Command line arguments. - * \param parent The new node will be a child of \a parent. - * \param wn The writer node. + * \param wa String of the form writer_name options. + * \param lprp Contains the parsed command line on success. * - * 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. + * If wa is \p NULL, the (configuration-dependent) default writer is assumed. + * Otherwise, the function checks whether \a wa starts with the name of a + * supported writer. If a valid writer name was found, the rest of the command + * line is passed to the config parser of this writer. * - * 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. + * \return On success, the positive writer ID is returned. Otherwise the + * function prints an error message and calls exit(). */ -int setup_writer_node(const char *arg, struct btr_node *parent, - struct writer_node *wn) +int check_writer_arg_or_die(const char *wa, struct lls_parse_result **lprp) { - 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(""); + int ret, writer_num, argc; + char **argv = NULL, *errctx = NULL; + const struct lls_command *cmd; + + if (!wa || !*wa) { + writer_num = default_writer_id(); + cmd = WRITE_CMD(writer_num); + argv = para_malloc(2 * sizeof(char *)); + argc = 1; + argv[0] = para_strdup(lls_command_name(cmd)); + argv[1] = NULL; + goto parse; + } + ret = create_argv(wa, " \t\n", &argv); + if (ret < 0) + goto fail; + argc = ret; + ret = lls(lls_lookup_subcmd(argv[0], write_cmd_suite, &errctx)); + if (ret < 0) + goto free_argv; + writer_num = ret; + cmd = WRITE_CMD(writer_num); + if (!writer_supported(writer_num)) { + ret = -ERRNO_TO_PARA_ERROR(EINVAL); + errctx = make_message("%s writer is not supported", + lls_command_name(cmd)); + goto free_argv; } - if (!wn->conf) - return -E_WRITE_COMMON_SYNTAX; - register_writer_node(wn, parent); - return 1; +parse: + ret = lls(lls_parse(argc, argv, cmd, lprp, &errctx)); + if (ret >= 0) + ret = writer_num; +free_argv: + free_argv(argv); + if (ret >= 0) + return ret; +fail: + if (errctx) + PARA_ERROR_LOG("%s\n", errctx); + free(errctx); + PARA_EMERG_LOG("%s\n", para_strerror(-ret)); + exit(EXIT_FAILURE); +} + +/** + * Open a writer node and register the corresponding task. + * + * \param wn The writer node to open. + * \param parent The parent btr node (the source for the writer node). + * \param s The scheduler instance to register the task to. + */ +void register_writer_node(struct writer_node *wn, struct btr_node *parent, + struct sched *s) +{ + const struct writer *w = writer_get(wn->wid); + + wn->btrn = btr_new_node(&(struct btr_node_description) + EMBRACE(.name = writer_name(wn->wid), .parent = parent, + .handler = w->execute, .context = wn)); + wn->task = task_register(&(struct task_info) { + .name = writer_name(wn->wid), + .pre_select = w->pre_select, + .post_select = w->post_select, + .context = wn, + }, s); } /** * Print the help text of all writers to stdout. * - * \param detailed Whether to print the detailed help text. + * \param detailed Whether to print the short or the detailed help. */ -void print_writer_helps(int detailed) +void print_writer_helps(bool detailed) { int i; - printf_or_die("\nAvailable writers: \n\t"); - FOR_EACH_WRITER(i) - printf_or_die("%s%s", i? " " : "", writer_names[i]); - printf_or_die("\n\n"); + printf("\nAvailable writers: "); FOR_EACH_WRITER(i) { - struct writer *w = writers + i; - - if (!w->help.short_help) + if (!writer_supported(i)) + continue; + printf("%s%s", i? " " : "", writer_name(i)); + } + printf("\n"); + FOR_EACH_WRITER(i) { + const struct lls_command *cmd = WRITE_CMD(i); + char *help; + if (!writer_supported(i)) + continue; + help = detailed? lls_long_help(cmd) : lls_short_help(cmd); + if (!help) continue; - printf_or_die("Options for %s:\n", writer_names[i]); - ggo_print_help(&w->help, detailed); + printf("%s\n", help); + free(help); } }