Convert filters to lopsub.
[paraslash.git] / filter_common.c
1 /*
2 * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
3 *
4 * Licensed under the GPL v2. For licencing details see COPYING.
5 */
6
7 /** \file filter_common.c Common helper functions for filter input/output. */
8
9 #include <regex.h>
10 #include <sys/types.h>
11 #include <lopsub.h>
12
13 #include "filter_cmd.lsg.h"
14 #include "para.h"
15 #include "list.h"
16 #include "sched.h"
17 #include "fd.h"
18 #include "buffer_tree.h"
19 #include "filter.h"
20 #include "error.h"
21 #include "string.h"
22
23 /** Iterate over all filters. */
24 #define FOR_EACH_FILTER(j) for (j = 1; lls_cmd(j, filter_cmd_suite); j++)
25
26 /**
27 * Obtain a reference to a filter structure.
28 *
29 * \param filter_num Between zero and NUM_SUPPORTED_FILTERS, inclusively.
30 *
31 * \return Pointer to the filter identified by the given filter number.
32 *
33 * It is a fatal error if the given number is out of range. In this case
34 * the function aborts.
35 */
36 const struct filter *filter_get(int filter_num)
37 {
38 assert(filter_num >= 1);
39 assert(filter_num <= LSG_NUM_FILTER_CMD_SUBCOMMANDS);
40 return lls_user_data(FILTER_CMD(filter_num));
41 }
42
43 static inline bool filter_supported(int filter_num)
44 {
45 return lls_user_data(FILTER_CMD(filter_num));
46 }
47
48 const char *filter_name(int filter_num)
49 {
50 return lls_command_name(FILTER_CMD(filter_num));
51 }
52
53 /**
54 * Parse a filter command line and call the corresponding ->setup method.
55 *
56 * \param fa The filter argument.
57 * \param conf Points to filter-specific setup upon successful return.
58 * \param lprp Parsed command line options are returned here.
59 *
60 * Check if the given filter argument starts with the name of a supported
61 * filter, optionally followed by options for this filter. If yes, call the
62 * command line parser of that filter and its ->setup method.
63 *
64 * \return This function either succeeds or does not return. On success, the
65 * number of the filter is returned and conf is initialized to point to the
66 * filter configuration as returned by the filter's ->setup() method, if any.
67 * Moreover, *lprp is initialized to contain the parsed command line options.
68 * On errors, the function calls exit(EXIT_FAILURE).
69 */
70 int filter_setup(const char *fa, void **conf, struct lls_parse_result **lprp)
71 {
72 int ret, filter_num, argc;
73 char *errctx = NULL, **argv;
74 const struct lls_command *cmd;
75 const struct filter *f;
76
77 ret = create_argv(fa, " \t\n", &argv);
78 if (ret < 0)
79 goto fail;
80 argc = ret;
81 ret = lls(lls_lookup_subcmd(argv[0], filter_cmd_suite, &errctx));
82 if (ret < 0)
83 goto free_argv;
84 filter_num = ret;
85 cmd = FILTER_CMD(filter_num);
86 if (!filter_supported(filter_num)) {
87 ret = -E_UNSUPPORTED_FILTER;
88 errctx = make_message("bad filter name: %s",
89 lls_command_name(cmd));
90 goto free_argv;
91 }
92 ret = lls(lls_parse(argc, argv, cmd, lprp, &errctx));
93 if (ret < 0)
94 goto free_argv;
95 f = filter_get(filter_num);
96 *conf = f->setup? f->setup(*lprp) : NULL;
97 ret = filter_num;
98 free_argv:
99 free_argv(argv);
100 if (ret >= 0)
101 return ret;
102 fail:
103 if (errctx)
104 PARA_ERROR_LOG("%s\n", errctx);
105 free(errctx);
106 PARA_EMERG_LOG("%s\n", para_strerror(-ret));
107 exit(EXIT_FAILURE);
108 }
109
110 /**
111 * Print help text of each filter to stdout.
112 *
113 * \param detailed Whether to print short or long help.
114 */
115 void print_filter_helps(bool detailed)
116 {
117 int i, num = 0;
118
119 printf("\nAvailable filters: ");
120 FOR_EACH_FILTER(i) {
121 if (!filter_supported(i))
122 continue;
123 if (num > 50) {
124 printf("\n ");
125 num = 0;
126 }
127 num += printf("%s%s", i? " " : "", filter_name(i));
128 }
129 printf("\n");
130
131 FOR_EACH_FILTER(i) {
132 const struct lls_command *cmd = FILTER_CMD(i);
133 char *help;
134
135 if (!filter_supported(i))
136 continue;
137 help = detailed? lls_long_help(cmd) : lls_short_help(cmd);
138 if (!help)
139 continue;
140 printf("%s\n", help);
141 free(help);
142 }
143 }
144
145 /**
146 * Set select timeout of the scheduler.
147 *
148 * \param s The scheduler.
149 * \param context Pointer to the filter node (task context).
150 *
151 * This looks at the status of the btr node of the filter. If data is available
152 * in the input queue of the filter, or if an error occurred, a minimal timeout
153 * for the next select call is requested from the scheduler. Otherwise the
154 * scheduler timeout is left unchanged.
155 */
156 void generic_filter_pre_select(struct sched *s, void *context)
157 {
158 struct filter_node *fn = context;
159
160 if (btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL) != 0)
161 sched_min_delay(s);
162 }
163
164 #ifdef WORDS_BIGENDIAN
165 #define DECODER_SAMPLE_FORMAT SF_S16_BE
166 #else
167 #define DECODER_SAMPLE_FORMAT SF_S16_LE
168 #endif
169
170 /**
171 * Execute a btr command for a decoder.
172 *
173 * The buffer tree nodes of the writers ask the parent nodes about sample_rate,
174 * channels count and sample format. This function is called by all decoders to
175 * answer these queries.
176 *
177 * \param cmd The command to be executed by the child node.
178 * \param sample_rate Known to the decoder.
179 * \param channels Known to the decoder.
180 * \param result Ascii representation on the answer is stored here.
181 *
182 * \return Standard.
183 */
184 int decoder_execute(const char *cmd, unsigned sample_rate, unsigned channels,
185 char **result)
186 {
187 if (!strcmp(cmd, "sample_rate")) {
188 if (sample_rate == 0)
189 return -E_BTR_NAVAIL;
190 *result = make_message("%u", sample_rate);
191 return 1;
192 }
193 if (!strcmp(cmd, "channels")) {
194 if (channels == 0)
195 return -E_BTR_NAVAIL;
196 *result = make_message("%u", channels);
197 return 1;
198 }
199 if (!strcmp(cmd, "sample_format")) {
200 *result = make_message("%d", DECODER_SAMPLE_FORMAT);
201 return 1;
202 }
203 return -ERRNO_TO_PARA_ERROR(ENOTSUP);
204 }