routing: add loopback support to nodes
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / node.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
22 #include <pulsecore/pulsecore-config.h>
23
24 #include <pulsecore/hashmap.h>
25 #include <pulsecore/idxset.h>
26 #include <pulsecore/strbuf.h>
27
28
29 #include "node.h"
30 #include "discover.h"
31 #include "router.h"
32 #include "constrain.h"
33
34 struct pa_nodeset {
35     pa_idxset *nodes;
36 };
37
38
39 pa_nodeset *pa_nodeset_init(struct userdata *u)
40 {
41     pa_nodeset *ns;
42
43     pa_assert(u);
44
45     ns = pa_xnew0(pa_nodeset, 1);
46     ns->nodes = pa_idxset_new(pa_idxset_trivial_hash_func,
47                               pa_idxset_trivial_compare_func);
48     return ns;
49 }
50
51 void pa_nodeset_done(struct userdata *u)
52 {
53     pa_nodeset *ns;
54
55     if (u && (ns = u->nodeset)) {
56         pa_idxset_free(ns->nodes, NULL, NULL);
57         free(ns);
58     }    
59 }
60
61
62 mir_node *mir_node_create(struct userdata *u, mir_node *data)
63 {
64     pa_nodeset *ns;
65     mir_node *node;
66
67     pa_assert(u);
68     pa_assert(data);
69     pa_assert_se((ns = u->nodeset));
70     pa_assert(data->key);
71     pa_assert(data->paname);
72     
73     node = pa_xnew0(mir_node, 1);
74
75     node->key       = pa_xstrdup(data->key);
76     node->direction = data->direction;
77     node->implement = data->implement;
78     node->channels  = data->channels;
79     node->location  = data->location;
80     node->privacy   = data->privacy;
81     node->type      = data->type;
82     node->visible   = data->visible;
83     node->available = data->available;
84     node->amname    = pa_xstrdup(data->amname ? data->amname : data->paname);
85     node->amdescr   = pa_xstrdup(data->amdescr ? data->amdescr : "");
86     node->amid      = data->amid;
87     node->paname    = pa_xstrdup(data->paname);
88     node->paidx     = data->paidx;
89     node->mux       = data->mux;
90     node->loop      = data->loop;
91     node->stamp     = data->stamp;
92     MIR_DLIST_INIT(node->rtentries);
93     MIR_DLIST_INIT(node->constrains);
94     
95     if (node->implement == mir_device) {
96         node->pacard.index   = data->pacard.index;
97         if (data->pacard.profile)
98             node->pacard.profile = pa_xstrdup(data->pacard.profile);
99         if (data->paport)
100             node->paport = pa_xstrdup(data->paport);
101     }
102
103     pa_idxset_put(ns->nodes, node, &node->index);
104
105     mir_router_register_node(u, node);
106     
107     return node;
108 }
109
110 void mir_node_destroy(struct userdata *u, mir_node *node)
111 {
112     pa_nodeset *ns;
113
114     pa_assert(u);
115     pa_assert_se((ns = u->nodeset));
116
117     if (node) {
118         mir_router_unregister_node(u, node);
119
120         pa_idxset_remove_by_index(ns->nodes, node->index);
121
122         pa_xfree(node->key);
123         pa_xfree(node->amname);
124         pa_xfree(node->amdescr);
125         pa_xfree(node->paname);
126         pa_xfree(node->pacard.profile);
127         pa_xfree(node->paport);
128
129         pa_xfree(node);
130     }
131 }
132
133 mir_node *mir_node_find_by_index(struct userdata *u, uint32_t nodidx)
134 {
135     pa_nodeset *ns;
136     mir_node *node;
137
138     pa_assert(u);
139     pa_assert_se((ns = u->nodeset));
140
141     node = pa_idxset_get_by_index(ns->nodes, nodidx);
142
143     return node;
144 }
145
146 int mir_node_print(mir_node *node, char *buf, int len)
147 {
148     char *p, *e;
149     char mux[256];
150     char loop[256];
151     char constr[512];
152
153     pa_assert(node);
154     pa_assert(buf);
155     pa_assert(len > 0);
156
157     pa_multiplex_print(node->mux, mux, sizeof(mux));
158     pa_loopback_print(node->loop, loop, sizeof(loop));
159     mir_constrain_print(node, constr, sizeof(constr));
160
161     e = (p = buf) + len;
162
163 #define PRINT(f,v) if (p < e) p += snprintf(p, e-p, f "\n", v)
164
165     PRINT("   index         : %u"  ,  node->index);
166     PRINT("   key           : '%s'",  node->key ? node->key : "");
167     PRINT("   direction     : %s"  ,  mir_direction_str(node->direction));
168     PRINT("   implement     : %s"  ,  mir_implement_str(node->implement));
169     PRINT("   channels      : %u"  ,  node->channels);
170     PRINT("   location      : %s"  ,  mir_location_str(node->location));
171     PRINT("   privacy       : %s"  ,  mir_privacy_str(node->privacy));
172     PRINT("   type          : %s"  ,  mir_node_type_str(node->type));
173     PRINT("   visible       : %s"  ,  node->visible ? "yes" : "no");
174     PRINT("   available     : %s"  ,  node->available ? "yes" : "no");
175     PRINT("   amname        : '%s'",  node->amname ? node->amname : "");
176     PRINT("   amdescr       : '%s'",  node->amdescr ? node->amdescr : "");
177     PRINT("   amid          : %u"  ,  node->amid);
178     PRINT("   paname        : '%s'",  node->paname ? node->paname : "");
179     PRINT("   paidx         : %u"  ,  node->paidx);
180     PRINT("   pacard.index  : %u"  ,  node->pacard.index);
181     PRINT("   pacard.profile: '%s'",  node->pacard.profile ?
182                                       node->pacard.profile : "");
183     PRINT("   paport        : '%s'",  node->paport ? node->paport : "");
184     PRINT("   mux           : %s"  ,  mux);
185     PRINT("   loop          : %s"  ,  loop);
186     PRINT("   constrain     : %s"  ,  constr);
187     PRINT("   stamp         : %u"  ,  node->stamp);
188
189 #undef PRINT
190
191     return p - buf;
192 }
193
194 const char *mir_direction_str(mir_direction direction)
195 {
196     switch (direction) {
197     case mir_direction_unknown:  return "unknown";
198     case mir_input:              return "input";
199     case mir_output:             return "output";
200     default:                     return "< ??? >";
201     }
202 }
203
204 const char *mir_implement_str(mir_implement implement)
205 {
206     switch (implement) {
207     case mir_implementation_unknown:  return "unknown";
208     case mir_device:                  return "device";
209     case mir_stream:                  return "stream";
210     default:                          return "< ??? >";
211     }
212 }
213
214 const char *mir_location_str(mir_location location)
215 {
216     switch (location) {
217     case mir_location_unknown:  return "unknown";
218     case mir_internal:          return "internal";
219     case mir_external:          return "external";
220     default:                    return "< ??? >";
221     }
222
223
224
225 const char *mir_node_type_str(mir_node_type type)
226 {
227     switch (type) {
228     case mir_node_type_unknown:   return "Unknown";
229     case mir_radio:               return "Radio";
230     case mir_player:              return "Player";
231     case mir_navigator:           return "Navigator";
232     case mir_game:                return "Game";
233     case mir_browser:             return "Browser";
234     case mir_phone:               return "Phone";
235     case mir_event:               return "Event";
236     case mir_speakers:            return "Speakers";
237     case mir_microphone:          return "Microphone";
238     case mir_jack:                return "Line";
239     case mir_spdif:               return "SPDIF";
240     case mir_hdmi:                return "HDMI";
241     case mir_wired_headset:       return "Wired Headset";
242     case mir_wired_headphone:     return "Wired Headphone";
243     case mir_usb_headset:         return "USB Headset";
244     case mir_bluetooth_sco:       return "Bluetooth Handsfree";
245     case mir_bluetooth_a2dp:      return "Bluetooth Stereo";
246     default:                      return "<user defined>";
247     }
248 }
249
250
251 const char *mir_privacy_str(mir_privacy privacy)
252 {
253     switch (privacy) {
254     case mir_privacy_unknown:  return "<unknown>";
255     case mir_public:           return "public";
256     case mir_private:          return "private";
257     default:                   return "< ??? >";
258     }
259 }
260
261                                   
262 /*
263  * Local Variables:
264  * c-basic-offset: 4
265  * indent-tabs-mode: nil
266  * End:
267  *
268  */