+/*
+ * 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)
+ EMBRACE(.name = "stdin"));
+ stdin_set_defaults(&sit);
+ register_task(&sit.task);
+
+ cwt->state = CWS_NEED_HEADER;
+ cwt->min_iqs = WAV_HEADER_LEN;
+ cwt->btrn = btr_new_node(&(struct btr_node_description)
+ EMBRACE(.name = "check_wav", .parent = sit.btrn,
+ .handler = check_wav_exec, .context = cwt));
+ sprintf(cwt->task.status, "check_wav");
+ cwt->task.pre_select = check_wav_pre_select;
+ cwt->task.post_select = check_wav_post_select;
+ cwt->task.error = 0;
+ register_task(&cwt->task);
+
+ if (!conf.writer_given) {
+ wns = para_calloc(sizeof(*wns));
+ 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++)
+ 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);
+ if (ret >= 0) {
+ int j;
+ for (j = 0; j < i; j++) {
+ struct task *t = &wns[j].task;
+ assert(t->error < 0);
+ if (t->error != -E_WRITE_COMMON_EOF
+ && t->error != -E_BTR_EOF) {
+ PARA_ERROR_LOG("%s: %s\n", t->status,
+ para_strerror(-t->error));
+ if (ret >= 0)
+ ret = t->error;
+ }
+ }
+ }
+ for (i--; i >= 0; i--) {
+ struct writer_node *wn = wns + i;
+ struct writer *w = writers + wn->writer_num;
+
+ w->close(wn);
+ btr_free_node(wn->btrn);
+ w->free_config(wn->conf);
+ free(wn->conf);
+ }
+ free(wns);
+ btr_free_node(cwt->btrn);
+ return ret;
+}
+