2 * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file filter.c The stand-alone filter program. */
12 #include "filter.lsg.h"
13 #include "filter_cmd.lsg.h"
17 #include "buffer_tree.h"
26 /** Array of error strings. */
28 static struct lls_parse_result *lpr; /* command line options */
30 #define CMD_PTR (lls_cmd(0, filter_suite))
31 #define OPT_RESULT(_name) \
32 (lls_opt_result(LSG_FILTER_PARA_FILTER_OPT_ ## _name, lpr))
33 #define OPT_GIVEN(_name) (lls_opt_given(OPT_RESULT(_name)))
34 #define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name)))
36 /** The list of all status items used by para_{server,audiod,gui}. */
37 const char *status_item_list[] = {STATUS_ITEMS};
40 * Dummy version which only contains NULL pointers.
42 * This is used by the amp filter which first tries to obtain the amplification
43 * value from an element in this array.
45 char *stat_item_values[NUM_STAT_ITEMS] = {NULL};
47 /** The task that reads from stdin. */
48 static struct stdin_task stdin_task_struct;
49 /** pointer to the stdin task. */
50 static struct stdin_task *sit = &stdin_task_struct;
52 /** The task that writes converted data to stdout. */
53 static struct stdout_task stdout_task_struct;
54 /** Pointer to the stdout task. */
55 static struct stdout_task *sot = &stdout_task_struct;
58 INIT_STDERR_LOGGING(loglevel);
60 static void handle_help_flag(void)
64 if (OPT_GIVEN(DETAILED_HELP))
65 help = lls_long_help(CMD_PTR);
66 else if (OPT_GIVEN(HELP))
67 help = lls_short_help(CMD_PTR);
72 print_filter_helps(OPT_GIVEN(DETAILED_HELP));
76 static int parse_config(void)
78 char *home, *cf; /* config file */
82 version_handle_flag("filter", OPT_GIVEN(VERSION));
84 home = para_homedir();
85 cf = make_message("%s/.paraslash/filter.conf", home);
87 if (!stat(cf, &statbuf)) {
91 char **cf_argv, *errctx;
92 struct lls_parse_result *cf_lpr, *merged_lpr;
94 ret = mmap_full_file(cf, O_RDONLY, &map, &sz, NULL);
95 if (ret != -E_EMPTY) {
98 ret = lls(lls_convert_config(map, sz, NULL, &cf_argv,
100 para_munmap(map, sz);
102 PARA_ERROR_LOG("syntax error in %s\n", cf);
106 ret = lls(lls_parse(cf_argc, cf_argv, CMD_PTR, &cf_lpr,
108 lls_free_argv(cf_argv);
110 PARA_ERROR_LOG("parse error in %s\n", cf);
113 ret = lls(lls_merge(lpr, cf_lpr, CMD_PTR, &merged_lpr, &errctx));
114 lls_free_parse_result(cf_lpr, CMD_PTR);
117 lls_free_parse_result(lpr, CMD_PTR);
119 loglevel = OPT_UINT32_VAL(LOGLEVEL);
122 if (!OPT_GIVEN(FILTER)) {
130 * The main function of para_filter.
132 * Para_filter reads data from stdin, converts it by using a chain
133 * of filters (specified on the command line) and writes the resulting
136 * \param argc Number of command line options.
137 * \param argv Vector of arguments.
139 * \return \a EXIT_SUCCESS on success, EXIT_FAILURE on errors.
141 int main(int argc, char *argv[])
143 static struct sched s;
145 const struct filter *f;
146 struct btr_node *parent;
147 struct filter_node **fns;
148 struct lls_parse_result *filter_lpr; /* per-filter options */
151 ret = lls(lls_parse(argc, argv, CMD_PTR, &lpr, &errctx));
154 loglevel = OPT_UINT32_VAL(LOGLEVEL);
155 ret = parse_config();
158 sit->btrn = btr_new_node(&(struct btr_node_description)
159 EMBRACE(.name = "stdin"));
160 stdin_task_register(sit, &s);
162 fns = para_malloc(OPT_GIVEN(FILTER) * sizeof(*fns));
163 for (i = 0, parent = sit->btrn; i < OPT_GIVEN(FILTER); i++) {
164 const char *fa = lls_string_val(i, OPT_RESULT(FILTER));
166 struct filter_node *fn;
169 fn = fns[i] = para_calloc(sizeof(*fn));
170 fn->filter_num = filter_setup(fa, &fn->conf, &filter_lpr);
171 name = filter_name(fn->filter_num);
172 fn->lpr = filter_lpr;
173 PARA_DEBUG_LOG("filter #%d: %s\n", i, name);
174 f = filter_get(fn->filter_num);
175 fn->btrn = btr_new_node(&(struct btr_node_description)
176 EMBRACE(.name = name, .parent = parent,
177 .handler = f->execute, .context = fn));
179 ti.pre_select = f->pre_select;
180 ti.post_select = f->post_select;
184 fn->task = task_register(&ti, &s);
187 sot->btrn = btr_new_node(&(struct btr_node_description)
188 EMBRACE(.name = "stdout", .parent = parent));
189 stdout_task_register(sot, &s);
191 s.default_timeout.tv_sec = 1;
192 s.default_timeout.tv_usec = 0;
193 btr_log_tree(sit->btrn, LL_INFO);
196 for (i--; i >= 0; i--) {
197 struct filter_node *fn = fns[i];
199 f = filter_get(fn->filter_num);
202 btr_remove_node(&fn->btrn);
204 f->teardown(fn->lpr, fn->conf);
208 btr_remove_node(&sit->btrn);
209 btr_remove_node(&sot->btrn);
211 lls_free_parse_result(lpr, CMD_PTR);
215 PARA_ERROR_LOG("%s\n", errctx);
217 PARA_ERROR_LOG("%s\n", para_strerror(-ret));
219 exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS);