para_play: introduce struct private_alsa_data
[paraslash.git] / filter_chain.c
1 /*
2  * Copyright (C) 2005-2006 Andre Noll <maan@systemlinux.org>
3  *
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  *
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  *
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17  */
18
19 /** \file filter_chain.c common helper functions for filter input/output */
20
21 #include "para.h"
22 #include "list.h"
23 #include "filter.h"
24 #include "error.h"
25 #include "string.h"
26
27 DEFINE_FILTER_ARRAY(filters);
28
29 /**
30  * call the init function of each supported filter
31  *
32  * \param all_filters the array of all supported filters
33  * \sa filter::init
34  */
35 void filter_init(struct filter *all_filters)
36 {
37         struct filter *f;
38
39         for (f = all_filters; f->name; f++)
40                 f->init(f);
41 }
42
43 /**
44  * close and destroy a filter callback
45  *
46  * \param fcb the filter callback to close
47  *
48  * This removes \a fcb from the list of filter callbacks and calls
49  * the close callback associated with \a fcb.
50  */
51 static void close_filter_callback(struct filter_callback *fcb)
52 {
53         PARA_NOTICE_LOG("closing filter_callback %p, data: %p\n", fcb, fcb->data);
54         list_del(&fcb->node);
55         fcb->close(fcb);
56 }
57
58 /**
59  * close all callbacks of a filter node
60  *
61  * \param fn the filter node which contains the filter callbacks to be closed
62  *
63  * Call close_filter_callback() for each entry in the filter callback list
64  * of \a fn.
65  */
66 static void close_callbacks(struct filter_node *fn)
67 {
68         struct filter_callback *fcb, *tmp;
69
70         list_for_each_entry_safe(fcb, tmp, &fn->callbacks, node)
71                 close_filter_callback(fcb);
72 }
73
74 static void call_callbacks(struct filter_node *fn, char *inbuf, size_t inlen,
75         char *outbuf, size_t outlen)
76 {
77         struct filter_callback *fcb, *tmp;
78         list_for_each_entry_safe(fcb, tmp, &fn->callbacks, node) {
79                 int ret;
80                 if (inlen && fcb->input_cb) {
81                         ret = fcb->input_cb(inbuf, inlen, fcb);
82                         if (ret < 0) {
83                                 close_filter_callback(fcb);
84                                 continue;
85                         }
86                 }
87                 if (!outlen || !fcb->output_cb)
88                         continue;
89                 ret = fcb->output_cb(outbuf, outlen, fcb);
90                 if (ret < 0)
91                         close_filter_callback(fcb);
92         }
93 }
94
95 /**
96  * call the convert function of each filter
97  *
98  * \param fci the filter chain containing the list of filter nodes.
99  *
100  * This is the core function of the filter subsystem. It loops over the list of
101  * filter nodes determined by \a fci and calls the filter's convert function if
102  * there is input available for the filter node in question. If the convert
103  * function consumed some or all of its input data, all registered input
104  * callbacks are called.  Similarly, if a convert function produced output, all
105  * registerd output callbacks get called.
106  *
107  * \return The sum of output bytes produced by the convert functions on success,
108  * negative return value on errors.
109  *
110  * \sa filter_node, filter#convert, filter_callback
111  */
112 int filter_io(struct filter_chain_info *fci)
113 {
114         struct filter_node *fn;
115         char *ib;
116         size_t *loaded;
117         int conv, conv_total = 0;
118 again:
119         ib = fci->inbuf;
120         loaded = fci->in_loaded;
121         conv = 0;
122         list_for_each_entry(fn, &fci->filters, node) {
123                 int ret;
124                 if (*loaded && fn->loaded < fn->bufsize) {
125                         size_t old_fn_loaded = fn->loaded;
126                         PARA_DEBUG_LOG("fc %p loaded: %zd, calling %s convert\n", fci, *loaded, fn->filter->name);
127                         ret = fn->filter->convert(ib, *loaded, fn);
128                         if (ret < 0) {
129                                 if (!fci->error)
130                                         fci->error = -ret;
131                                 return ret;
132                         }
133                         call_callbacks(fn, ib, ret, fn->buf + old_fn_loaded, fn->loaded - old_fn_loaded);
134                         *loaded -= ret;
135                         conv += ret;
136                         if (*loaded && ret) {
137                                 PARA_DEBUG_LOG("moving %zd bytes in input buffer for %s filter\n",
138                                         *loaded,  fn->filter->name);
139                                 memmove(ib, ib + ret, *loaded);
140                         }
141                 }
142                 ib = fn->buf;
143                 loaded = &fn->loaded;
144         }
145 //      PARA_DEBUG_LOG("loaded: %d\n", *loaded);
146         conv_total += conv;
147         if (conv)
148                 goto again;
149         return conv_total;
150 }
151
152 /**
153  * close all filter nodes and its callbacks
154  *
155  * \param fci the filter chain to close
156  *
157  * For each filter node determined by \a fci, call the close function of each
158  * registered filter callback as well as the close function of the
159  * corresponding filter.  Free all resources and destroy all callback lists and
160  * the filter node list.
161  *
162  * \sa filter::close, filter_callback::close
163  */
164 void close_filters(struct filter_chain_info *fci)
165 {
166         struct filter_node *fn, *tmp;
167
168         if (!fci)
169                 return;
170         PARA_DEBUG_LOG("closing filter chain %p\n", fci);
171         list_for_each_entry_safe(fn, tmp, &fci->filters, node) {
172                 PARA_NOTICE_LOG("closing %s filter callbacks (fci %p, fn %p)\n", fn->filter->name, fci, fn);
173                 close_callbacks(fn);
174                 PARA_NOTICE_LOG("closing %s filter (fci %p, fn %p)\n", fn->filter->name, fci, fn);
175                 fn->filter->close(fn);
176                 list_del(&fn->node);
177                 free(fn);
178         }
179 }
180
181 /*
182  * If the filter has a command line parser and options is not NULL, run it.
183  * Returns filter_num on success, negative on errors
184  */
185 static int parse_filter_args(int filter_num, char *options, void **conf)
186 {
187         struct filter *f = &filters[filter_num];
188         int i, argc = 2;
189         char **argv;
190
191 //      PARA_DEBUG_LOG("%s, options: %s, parser: %p\n", f->name,
192 //              options? options : "(none)", f->parse_config);
193         if (!f->parse_config)
194                 return strlen(options)? -E_BAD_FILTER_OPTIONS : filter_num;
195 //      PARA_DEBUG_LOG("options: %s\n", options);
196         argc = split_args(options, &argv, " \t");
197 //              PARA_DEBUG_LOG("argc = %d, argv[0]: %s\n", argc, argv[0]);
198         for (i = argc - 1; i >= 0; i--)
199                 argv[i + 1] = argv[i];
200         argv[0] = para_strdup(f->name);
201         argc += 1;
202         *conf = f->parse_config(argc, argv);
203         return *conf? filter_num : -E_BAD_FILTER_OPTIONS;
204 }
205
206 /**
207  * check the filter command line options
208  *
209  * \param fa the command line options
210  * \param conf points to the filter configuration upon successful return
211  *
212  * Check if \a fa starts with a the name of a supported filter, followed by
213  * a colon. If yes, call the command line parser of that filter.
214  *
215  * \return On success, the number of the filter is returned and \a conf
216  * is initialized to point to the filter configuration determined by \a fa.
217  * On errors, a negative value is returned.
218  *
219  * Note: If \a fa specifies a filter that has no command line parser success is
220  * returned, and \a conf is initialized to \p NULL.
221  *
222  * \sa filter::parse_config
223  */
224 int check_filter_arg(char *fa, void **conf)
225 {
226         int j;
227
228         *conf = NULL;
229 //      PARA_DEBUG_LOG("arg: %s\n", fa);
230         for (j = 0; filters[j].name; j++) {
231                 const char *name = filters[j].name;
232                 size_t len = strlen(name);
233                 char c;
234                 if (strlen(fa) < len)
235                         continue;
236                 if (strncmp(name, fa, len))
237                         continue;
238                 c = fa[len];
239                 if (c && c != ' ')
240                         continue;
241                 if (c && !filters[j].parse_config)
242                         return -E_BAD_FILTER_OPTIONS;
243                 return parse_filter_args(j, c? fa + len + 1 :
244                         fa + strlen(fa), conf);
245         }
246         return -E_UNSUPPORTED_FILTER;
247 }
248