utils: index is unsigned type
[staging/agl-audio-plugin.git] / node.c
1 /*
2  * module-agl-audio -- PulseAudio module for providing audio routing support
3  * (forked from "module-murphy-ivi" - https://github.com/otcshare )
4  * Copyright (c) 2012, Intel Corporation.
5  * Copyright (c) 2016, IoT.bzh
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU Lesser General Public License,
9  * version 2.1, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
19  * MA 02110-1301 USA.
20  *
21  */
22 #include "node.h"
23 #include "router.h"
24
25 #include <pulsecore/idxset.h>
26 #include <pulsecore/core-util.h>
27 #include <pulsecore/pulsecore-config.h>
28
29 agl_nodeset *agl_nodeset_init (struct userdata *u)
30 {
31         agl_nodeset *ns;
32
33         pa_assert (u);
34
35         ns = pa_xnew0 (agl_nodeset, 1);
36         ns->nodes = pa_idxset_new (pa_idxset_trivial_hash_func,
37                                    pa_idxset_trivial_compare_func);
38         ns->roles = pa_hashmap_new (pa_idxset_string_hash_func,
39                                     pa_idxset_string_compare_func);
40         ns->binaries = pa_hashmap_new (pa_idxset_string_hash_func,
41                                        pa_idxset_string_compare_func);
42         return ns;
43 }
44
45 void agl_nodeset_done(struct userdata *u)
46 {
47         agl_nodeset *ns;
48         agl_nodeset_map *role, *binary;
49         void *state;
50         int i;
51
52         if (u && (ns = u->nodeset)) {
53                 pa_idxset_free (ns->nodes, NULL);
54
55                 PA_HASHMAP_FOREACH(role, ns->roles, state) {
56                         pa_xfree ((void *)role->name);
57                         pa_xfree ((void *)role->resdef);
58                 }
59                 pa_hashmap_free (ns->roles);
60
61                 PA_HASHMAP_FOREACH(binary, ns->binaries, state) {
62                         pa_xfree ((void *)binary->name);
63                         pa_xfree ((void *)binary->resdef);
64                 }
65                 pa_hashmap_free (ns->binaries);
66
67                 for (i = 0;  i < APCLASS_DIM;  i++)
68                         pa_xfree((void *)ns->class_name[i]);
69
70                 free(ns);
71         }
72 }
73
74 int agl_nodeset_add_role (struct userdata *u, const char *role, agl_node_type type, agl_nodeset_resdef *resdef)
75 {
76         agl_nodeset *ns;
77         agl_nodeset_map *map;
78
79         pa_assert (u);
80         pa_assert_se (ns = u->nodeset);
81
82         map = pa_xnew0 (agl_nodeset_map, 1);
83         map->name = pa_xstrdup (role);
84         map->type = type;
85         map->role = pa_xstrdup (role);
86
87         if (resdef) {
88                 map->resdef = pa_xnew (agl_nodeset_resdef, 1);
89                 memcpy (map->resdef, resdef, sizeof(agl_nodeset_resdef));
90         }
91
92         return pa_hashmap_put (ns->roles, (void *)map->name, map);
93 }
94
95 agl_node *agl_node_create (struct userdata *u, agl_node *data)
96 {
97         agl_nodeset *ns;
98         agl_node *node;
99
100         pa_assert (u);
101         pa_assert_se (ns = u->nodeset);
102
103         node = pa_xnew0 (agl_node, 1);
104
105         pa_idxset_put (ns->nodes, node, &node->index);
106
107         if (data) {
108                 node->key = pa_xstrdup (data->key);
109                 node->direction = data->direction;
110                 node->implement = data->implement;
111                 node->channels = data->channels;
112                 node->location = data->location;
113                 node->privacy = data->privacy;
114                 node->type = data->type;
115                 node->zone = pa_xstrdup (data->zone);
116                 node->visible = data->visible;
117                 node->available = data->available;
118                 node->amname = pa_xstrdup (data->amname ? data->amname : data->paname);
119                 node->amdescr = pa_xstrdup(data->amdescr ? data->amdescr : "");
120                 node->amid = data->amid;
121                 node->paname = pa_xstrdup (data->paname);
122                 node->stamp = data->stamp;
123                 node->rset.id = data->rset.id ? pa_xstrdup(data->rset.id) : NULL;
124                 node->rset.grant = data->rset.grant;
125
126                 if (node->implement == agl_device) {
127                         node->pacard.index = data->pacard.index;
128                         if (data->pacard.profile)
129                                 node->pacard.profile = pa_xstrdup (data->pacard.profile);
130                         if (data->paport)
131                                 node->paport = data->paport;
132                 }
133         }
134
135         return node;
136 }
137
138 void agl_node_destroy (struct userdata *u, agl_node *node)
139 {
140         agl_nodeset *ns;
141
142         pa_assert (u);
143         pa_assert (node);
144         pa_assert_se (ns = u->nodeset);
145
146         pa_idxset_remove_by_index (ns->nodes, node->index);
147
148         pa_xfree (node);
149 }
150
151
152 agl_node_type agl_node_type_from_str (const char *str)
153 {
154         agl_node_type type;
155
156         pa_assert (str);
157
158         if (pa_streq (str, "agl_radio"))
159                 type = agl_radio;
160         else if (pa_streq (str, "agl_music"))
161                 type = agl_player;
162         else if (pa_streq (str, "agl_navigator"))
163                 type = agl_navigator;
164         else if (pa_streq (str, "agl_game"))
165                 type = agl_game;
166         else if (pa_streq (str, "agl_browser"))
167                 type = agl_browser;
168         else if (pa_streq (str, "agl_camera"))
169                 type = agl_camera;
170         else if (pa_streq (str, "agl_phone"))
171                 type = agl_phone;
172         else if (pa_streq (str, "agl_alert"))
173                 type = agl_alert;
174         else if (pa_streq (str, "agl_event"))
175                 type = agl_event;
176         else if (pa_streq (str, "agl_system"))
177                 type = agl_system;
178         else
179                 type = agl_node_type_unknown;
180
181         return type;
182 }
183
184 const char *agl_node_type_str (agl_node_type type)
185 {
186         switch (type) {
187                 case agl_node_type_unknown: return "Unknown";
188                 case agl_radio:             return "Radio";
189                 case agl_player:            return "Player";
190                 case agl_navigator:         return "Navigator";
191                 case agl_game:              return "Game";
192                 case agl_browser:           return "Browser";
193                 case agl_camera:            return "Camera";
194                 case agl_phone:             return "Phone";
195                 case agl_alert:             return "Alert";
196                 case agl_event:             return "Event";
197                 case agl_system:            return "System";
198                 default:                    return "default";
199         }
200 }
201
202 const char *agl_node_direction_str (agl_direction direction)
203 {
204         switch (direction) {
205                 case agl_direction_unknown: return "unknown";
206                 case agl_input:             return "input";
207                 case agl_output:            return "output";
208                 default:                    return "< ??? >";
209         }
210 }
211
212 agl_node *agl_node_get_from_data (struct userdata *u, agl_direction type, void *data)
213 {
214         pa_sink_input_new_data *sinp_data;
215         pa_source_output_new_data *sout_data;
216         agl_nodeset *nodeset;
217         agl_node *node;
218         uint32_t index;
219
220         pa_assert (u);
221         pa_assert (data);
222         pa_assert (nodeset = u->nodeset);
223
224         pa_assert (type == agl_input || type == agl_output);
225
226         /* input (= sink_input) */
227         if (type == agl_input) {
228                 sinp_data = (pa_sink_input_new_data *) data;
229                 PA_IDXSET_FOREACH(node, nodeset->nodes, index) {
230                         if (node->client == sinp_data->client)
231                                 return node;
232                 }
233         /* output (= source_output) TODO */
234         /*} else {*/
235         }
236
237         return NULL;
238 }
239
240 agl_node *agl_node_get_from_client (struct userdata *u, pa_client *client)
241 {
242         agl_nodeset *nodeset;
243         agl_node *node;
244         uint32_t index;
245
246         pa_assert (u);
247         pa_assert (client);
248         pa_assert (nodeset = u->nodeset);
249
250         PA_IDXSET_FOREACH(node, nodeset->nodes, index) {
251                 if (node->client == client)
252                         return node;
253         }
254
255         return NULL;
256 }
257
258 bool agl_node_has_highest_priority (struct userdata *u, agl_node *node)
259 {
260         agl_nodeset *nodeset;
261         agl_node *n;
262         int priority;
263         uint32_t index;
264
265         pa_assert (u);
266         pa_assert (node);
267         pa_assert (nodeset = u->nodeset);
268
269         priority = agl_router_get_node_priority (u, node);
270
271         PA_IDXSET_FOREACH(n, nodeset->nodes, index) {
272                 if ((n != node) && (agl_router_get_node_priority (u, n) >= priority))
273                         return false;
274         }
275
276         return true;
277 }