Merge branch 'refs/heads/t/sqrt'
[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; FILTER_CMD(j); 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, or
32  * NULL if the filter number is out of range.
33  *
34  * \sa filter_name().
35  */
36 const struct filter *filter_get(int filter_num)
37 {
38         if (filter_num < 1 || filter_num > LSG_NUM_FILTER_CMD_SUBCOMMANDS)
39                 return NULL;
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 /**
49  * Return the name of a filter, given its number.
50  *
51  * \param filter_num See \ref filter_get().
52  *
53  * \return A pointer to a string literal, or NULL if filter_num is out of
54  * range. The caller must not attempt to call free(3) on the returned pointer.
55  */
56 const char *filter_name(int filter_num)
57 {
58         if (filter_num < 1 || filter_num > LSG_NUM_FILTER_CMD_SUBCOMMANDS)
59                 return NULL;
60         return lls_command_name(FILTER_CMD(filter_num));
61 }
62
63 /**
64  * Parse a filter command line and call the corresponding ->setup method.
65  *
66  * \param fa The filter argument.
67  * \param conf Points to filter-specific setup upon successful return.
68  * \param lprp Parsed command line options are returned here.
69  *
70  * Check if the given filter argument starts with the name of a supported
71  * filter, optionally followed by options for this filter. If yes, call the
72  * command line parser of that filter and its ->setup method.
73  *
74  * \return This function either succeeds or does not return. On success, the
75  * number of the filter is returned and conf is initialized to point to the
76  * filter configuration as returned by the filter's ->setup() method, if any.
77  * Moreover, *lprp is initialized to contain the parsed command line options.
78  * On errors, the function calls exit(EXIT_FAILURE).
79  */
80 int filter_setup(const char *fa, void **conf, struct lls_parse_result **lprp)
81 {
82         int ret, filter_num, argc;
83         char *errctx = NULL, **argv;
84         const struct lls_command *cmd;
85         const struct filter *f;
86
87         ret = create_argv(fa, " \t\n", &argv);
88         if (ret < 0)
89                 goto fail;
90         argc = ret;
91         ret = lls(lls_lookup_subcmd(argv[0], filter_cmd_suite, &errctx));
92         if (ret < 0)
93                 goto free_argv;
94         filter_num = ret;
95         cmd = FILTER_CMD(filter_num);
96         if (!filter_supported(filter_num)) {
97                 ret = -E_UNSUPPORTED_FILTER;
98                 errctx = make_message("bad filter name: %s",
99                         lls_command_name(cmd));
100                 goto free_argv;
101         }
102         ret = lls(lls_parse(argc, argv, cmd, lprp, &errctx));
103         if (ret < 0)
104                 goto free_argv;
105         f = filter_get(filter_num);
106         *conf = f->setup? f->setup(*lprp) : NULL;
107         ret = filter_num;
108 free_argv:
109         free_argv(argv);
110         if (ret >= 0)
111                 return ret;
112 fail:
113         if (errctx)
114                 PARA_ERROR_LOG("%s\n", errctx);
115         free(errctx);
116         PARA_EMERG_LOG("%s\n", para_strerror(-ret));
117         exit(EXIT_FAILURE);
118 }
119
120 /**
121  * Print help text of each filter to stdout.
122  *
123  * \param detailed Whether to print short or long help.
124  */
125 void print_filter_helps(bool detailed)
126 {
127         int i, num = 0;
128
129         printf("\nAvailable filters: ");
130         FOR_EACH_FILTER(i) {
131                 if (!filter_supported(i))
132                         continue;
133                 if (num > 50) {
134                         printf("\n                  ");
135                         num = 0;
136                 }
137                 num += printf("%s%s", i? " " : "", filter_name(i));
138         }
139         printf("\n");
140
141         FOR_EACH_FILTER(i) {
142                 const struct lls_command *cmd = FILTER_CMD(i);
143                 char *help;
144
145                 if (!filter_supported(i))
146                         continue;
147                 help = detailed? lls_long_help(cmd) : lls_short_help(cmd);
148                 if (!help)
149                         continue;
150                 printf("%s\n", help);
151                 free(help);
152         }
153 }
154
155 /**
156  * Print a short summary of all available filters to stdout.
157  *
158  * For each supported filter, the filter name and the purpose text is printed
159  * in a single line. Since no options are shown, the filter list is more
160  * concise than the text obtained from print_filter_helps().
161  */
162 void print_filter_list(void)
163 {
164         int i;
165
166         printf("Available filters:\n");
167         FOR_EACH_FILTER(i) {
168                 const struct lls_command *cmd = FILTER_CMD(i);
169                 if (!filter_supported(i))
170                         continue;
171                 printf("%-9s %s\n", filter_name(i), lls_purpose(cmd));
172         }
173 }
174
175 /**
176  * Set select timeout of the scheduler.
177  *
178  * \param s The scheduler.
179  * \param context Pointer to the filter node (task context).
180  *
181  * This looks at the status of the btr node of the filter. If data is available
182  * in the input queue of the filter, or if an error occurred, a minimal timeout
183  * for the next select call is requested from the scheduler. Otherwise the
184  * scheduler timeout is left unchanged.
185  */
186 void generic_filter_pre_select(struct sched *s, void *context)
187 {
188         struct filter_node *fn = context;
189
190         if (btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL) != 0)
191                 sched_min_delay(s);
192 }
193
194 #ifdef WORDS_BIGENDIAN
195 #define DECODER_SAMPLE_FORMAT SF_S16_BE
196 #else
197 #define DECODER_SAMPLE_FORMAT SF_S16_LE
198 #endif
199
200 /**
201  * Execute a btr command for a decoder.
202  *
203  * The buffer tree nodes of the writers ask the parent nodes about sample_rate,
204  * channels count and sample format. This function is called by all decoders to
205  * answer these queries.
206  *
207  * \param cmd The command to be executed by the child node.
208  * \param sample_rate Known to the decoder.
209  * \param channels Known to the decoder.
210  * \param result Ascii representation on the answer is stored here.
211  *
212  * \return Standard.
213  */
214 int decoder_execute(const char *cmd, unsigned sample_rate, unsigned channels,
215                 char **result)
216 {
217         if (!strcmp(cmd, "sample_rate")) {
218                 if (sample_rate == 0)
219                         return -E_BTR_NAVAIL;
220                 *result = make_message("%u", sample_rate);
221                 return 1;
222         }
223         if (!strcmp(cmd, "channels")) {
224                 if (channels == 0)
225                         return -E_BTR_NAVAIL;
226                 *result = make_message("%u", channels);
227                 return 1;
228         }
229         if (!strcmp(cmd, "sample_format")) {
230                 *result = make_message("%d", DECODER_SAMPLE_FORMAT);
231                 return 1;
232         }
233         return -ERRNO_TO_PARA_ERROR(ENOTSUP);
234 }