murphyif: Free the connect timer when unloading
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / constrain.c
1 /*
2  * module-murphy-ivi -- PulseAudio module for providing audio routing support
3  * Copyright (c) 2012, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU Lesser General Public License,
7  * version 2.1, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
17  * MA 02110-1301 USA.
18  *
19  */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24
25 #include <pulsecore/pulsecore-config.h>
26
27 #include <pulse/proplist.h>
28 #include <pulsecore/core-util.h>
29 #include <pulsecore/module.h>
30
31 #include "constrain.h"
32 #include "router.h"
33 #include "node.h"
34
35
36 static mir_constr_def *cstrdef_create(struct userdata *, const char *,
37                                       mir_constrain_func_t, const char *);
38 static void cstrdef_destroy(struct userdata *, mir_constr_def *);
39
40 static mir_constr_link *cstrlink_create(struct userdata *, mir_constr_def *,
41                                         mir_node *);
42 static void cstrlink_destroy(struct userdata *, mir_constr_link *);
43
44
45 static void pa_hashmap_constrdef_free(void *cd, void *u)
46 {
47     cstrdef_destroy(u, cd);
48 }
49
50
51 pa_constrain *pa_constrain_init(struct userdata *u)
52 {
53     pa_constrain *constrain = pa_xnew0(pa_constrain, 1);
54     
55     constrain->defs = pa_hashmap_new(pa_idxset_string_hash_func,
56                                      pa_idxset_string_compare_func);    
57     return constrain;
58 }
59
60 void pa_constrain_done(struct userdata *u)
61 {
62     pa_constrain   *constrain;
63     mir_constr_def *cd;
64     void *state;
65
66     if (u && (constrain = u->constrain)) {
67         PA_HASHMAP_FOREACH(cd, constrain->defs, state) {
68             cstrdef_destroy(u, cd);
69         }
70
71         pa_hashmap_free(constrain->defs);
72
73         pa_xfree(constrain);
74
75         u->constrain = NULL;
76     }
77 }
78
79
80 mir_constr_def *mir_constrain_create(struct userdata *u, const char *name,
81                                      mir_constrain_func_t func,
82                                      const char *key)
83 {
84     pa_constrain *constrain;
85     mir_constr_def *cd;
86
87     pa_assert(u);
88     pa_assert(name);
89     pa_assert(func);
90     pa_assert(key);
91     pa_assert_se((constrain = u->constrain));
92
93     if ((cd = mir_constrain_find(u, key))) {
94         if (pa_streq(name, cd->name) && func == cd->func)
95             return cd;
96         else {
97             pa_log_debug("attempt to redefine constrain %s/%s => %s/%s",
98                          cd->name,cd->key, name,key);
99             return NULL;
100         }
101     }
102
103     cd = cstrdef_create(u, name, func, key);
104
105     if (pa_hashmap_put(constrain->defs, cd->key, cd) < 0) {
106         pa_xfree(cd->key);
107         pa_xfree(cd->name);
108         pa_xfree(cd);
109         return NULL;
110     }
111
112     pa_log_debug("constrain %s/%s created", cd->name, cd->key);
113
114     return cd;
115 }
116
117 void mir_constrain_destroy(struct userdata *u, const char *key)
118 {
119     pa_constrain *constrain;
120     mir_constr_def *cd;
121
122     pa_assert(u);
123     pa_assert(key);
124     pa_assert_se((constrain = u->constrain));
125
126     if ((cd = pa_hashmap_remove(constrain->defs, key))) {
127         pa_log_debug("destroying constrain %s/%s", cd->name, cd->key);
128         cstrdef_destroy(u, cd);
129     }
130 }
131
132 mir_constr_def *mir_constrain_find(struct userdata *u, const char *key)
133 {
134     pa_constrain *constrain;
135     mir_constr_def *cd;
136
137     pa_assert(u);
138     pa_assert(key);
139     pa_assert_se((constrain = u->constrain));
140
141     cd = pa_hashmap_get(constrain->defs, key);
142
143     return cd;
144 }
145
146
147 void mir_constrain_add_node(struct userdata *u,
148                             mir_constr_def  *cd,
149                             mir_node        *node)
150 {
151     mir_constr_link *cl;
152
153     pa_assert(u);
154     pa_assert(node);
155
156     if (cd) {
157         cl = cstrlink_create(u, cd, node);
158
159         MIR_DLIST_APPEND(mir_constr_link, link, cl, &cd->nodes);
160         MIR_DLIST_APPEND(mir_constr_link, nodchain, cl, &node->constrains);
161         
162         pa_log_debug("node '%s' added to constrain %s/%s",
163                      node->amname, cd->name, cd->key);
164     }
165 }
166
167 void mir_constrain_remove_node(struct userdata *u, mir_node *node)
168 {
169     mir_constr_def  *cd;
170     mir_constr_link *cl, *n;
171
172     pa_assert(u);
173     pa_assert(node);
174
175     MIR_DLIST_FOR_EACH_SAFE(mir_constr_link,nodchain, cl,n, &node->constrains){
176         pa_assert_se((cd = cl->def));
177
178         pa_log_debug("node '%s' removed from constrain %s/%s",
179                      node->amname, cd->name, cd->key);
180
181         cstrlink_destroy(u, cl);
182     }
183 }
184
185
186 void mir_constrain_apply(struct userdata *u, mir_node *node, uint32_t stamp)
187 {
188     mir_constr_link *cl;
189     mir_constr_def  *cd;
190     mir_constr_link *c;
191     mir_node        *n;
192     mir_rtentry     *rte;
193     mir_rtgroup     *rtg;
194     bool        blocked;
195
196     pa_assert(u);
197     pa_assert(node);
198
199     MIR_DLIST_FOR_EACH(mir_constr_link, nodchain, cl, &node->constrains) {
200         pa_assert(node == cl->node);
201         pa_assert_se((cd = cl->def));
202
203         pa_log_debug("applying constrain %s/%s", cd->name, cd->key);
204
205         MIR_DLIST_FOR_EACH(mir_constr_link, link, c, &cd->nodes) {
206             n = c->node;
207             blocked = cd->func(u, cd, node, n);
208
209             MIR_DLIST_FOR_EACH(mir_rtentry, nodchain, rte, &n->rtentries) {
210                 pa_assert_se((rtg = rte->group));
211
212                 rte->blocked = blocked;
213                 rte->stamp   = stamp;
214
215                 pa_log_debug("   %sblocking '%s' in table '%s'",
216                              blocked ? "":"un", n->amname, rtg->name);
217             }
218         }
219     }
220
221
222 int mir_constrain_print(mir_node *node, char *buf, int len)
223 {
224     mir_constr_def  *cd;
225     mir_constr_link *cl;
226     char *p, *e, *s;
227
228     pa_assert(node);
229     pa_assert(buf);
230     pa_assert(len > 0);
231
232     buf[0] = '\0';
233
234     e = (p = buf) + len;
235     s = "";
236
237     MIR_DLIST_FOR_EACH(mir_constr_link, nodchain, cl, &node->constrains) {
238         if (p >= e)
239             break;
240
241         cd = cl->def;
242
243         p += snprintf(p, e-p, "%s'%s'", s, cd->name);
244         s  = " ";
245     }
246
247     return p - buf;
248 }
249
250 bool mir_constrain_port(struct userdata *u,
251                              mir_constr_def  *cd,
252                              mir_node        *active,
253                              mir_node        *node)
254 {
255     char *active_port;
256     char *node_port;
257     bool block;
258
259     pa_assert(u);
260     pa_assert(cd);
261     pa_assert(active);
262     pa_assert(node);
263
264     pa_assert_se((active_port = active->paport));
265     pa_assert_se((node_port = node->paport));
266
267     block = !pa_streq(active_port, node_port);
268
269     return block;
270 }
271
272 bool mir_constrain_profile(struct userdata *u,
273                                 mir_constr_def  *cd,
274                                 mir_node        *active,
275                                 mir_node        *node)
276 {
277     char *active_profile;
278     char *node_profile;
279     bool block;
280
281     pa_assert(u);
282     pa_assert(cd);
283     pa_assert(active);
284     pa_assert(node);
285
286     pa_assert_se((active_profile = active->pacard.profile));
287     pa_assert_se((node_profile = node->pacard.profile));
288
289     block = !pa_streq(active_profile, node_profile);
290
291     return block;
292 }
293
294 static mir_constr_def *cstrdef_create(struct userdata     *u,
295                                       const char          *name,
296                                       mir_constrain_func_t func,
297                                       const char          *key)
298 {
299     mir_constr_def *cd;
300
301     pa_assert(u);
302     pa_assert(name);
303     pa_assert(func);
304     pa_assert(key);
305
306     cd = pa_xnew0(mir_constr_def, 1);
307     cd->key  = pa_xstrdup(key);
308     cd->name = pa_xstrdup(name);
309     cd->func = func;
310     MIR_DLIST_INIT(cd->nodes);
311
312     return cd;
313 }
314
315 static void cstrdef_destroy(struct userdata *u, mir_constr_def *cd)
316 {
317     mir_constr_link *cl, *n;
318
319     pa_assert(u);
320     pa_assert(cd);
321
322     MIR_DLIST_FOR_EACH_SAFE(mir_constr_link, link, cl,n, &cd->nodes) {
323         cstrlink_destroy(u, cl);
324     }
325
326     pa_xfree(cd->name);
327     pa_xfree(cd);
328 }
329
330
331 static mir_constr_link *cstrlink_create(struct userdata *u,
332                                         mir_constr_def  *cd,
333                                         mir_node        *node)
334 {
335     mir_constr_link *cl;
336
337     pa_assert(u);
338     pa_assert(cd);
339     pa_assert(node);
340
341     cl = pa_xnew0(mir_constr_link, 1);
342     cl->def  = cd;
343     cl->node = node;
344     MIR_DLIST_INIT(cl->link);
345     MIR_DLIST_INIT(cl->nodchain);
346
347     return cl;
348 }
349
350 static void cstrlink_destroy(struct userdata *u, mir_constr_link *cl)
351 {
352     pa_assert(u);
353     pa_assert(cl);
354
355     MIR_DLIST_UNLINK(mir_constr_link, link, cl);
356     MIR_DLIST_UNLINK(mir_constr_link, nodchain, cl);
357
358     pa_xfree(cl);
359 }
360
361
362 /*
363  * Local Variables:
364  * c-basic-offset: 4
365  * indent-tabs-mode: nil
366  * End:
367  *
368  */