Merge branch 't/writer_setup_cleanup'
authorAndre Noll <maan@systemlinux.org>
Thu, 18 Aug 2011 13:26:34 +0000 (15:26 +0200)
committerAndre Noll <maan@systemlinux.org>
Thu, 18 Aug 2011 13:29:31 +0000 (15:29 +0200)
NEWS
audiod.c
error.h
write.c
write_common.c
write_common.h

diff --git a/NEWS b/NEWS
index 05c866b4a4a745d7acbbc5abdc0ad663cfc7d5f2..946524b2c033a89475f4dbcfd10949b3cad81f2c 100644 (file)
--- 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.
 
index c7998cdb7d02259b4e4da84353a2fdade8ec5584..c78df5b83bab6e0685eda33274c68a2f8f3f454f 100644 (file)
--- 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 da0efc47f6ea317d8f026482a76d0c18dead58d6..a56faf544534557cf96e9e434acfa696a2bf7c3e 100644 (file)
--- 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 6b574414b6b13c227c98b008addd28f4b2302b33..3b5f2d193f31ddc1d8c130703637810f807f255f 100644 (file)
--- 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);
index faf20749ba33062ed66845cafa38a283bcaa3c02..b85699367acd45d88eb4044da6450d2717f48437 100644 (file)
@@ -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.
  *
index 5f55120b25f85aca0f05b58000dc1889425193d5..00ded8f37bb29f4219340286edee7f66a82fa0bf 100644 (file)
@@ -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);