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