router: fix for bluetooth disappearing causing assert in combine
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / classify.c
1 #include <stdio.h>
2
3 #include <pulsecore/pulsecore-config.h>
4
5 #include <pulsecore/card.h>
6 #include <pulsecore/device-port.h>
7 #include <pulsecore/core-util.h>
8
9 #include "classify.h"
10 #include "node.h"
11
12
13 void pa_classify_node_by_card(mir_node        *node,
14                               pa_card         *card,
15                               pa_card_profile *prof,
16                               pa_device_port  *port)
17 {
18     const char *bus;
19     const char *form;
20     
21     pa_assert(node);
22     pa_assert(card);
23
24     bus  = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_BUS);
25     form = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_FORM_FACTOR);
26
27     if (form) {
28         if (!strcasecmp(form, "internal")) {
29             node->location = mir_external;
30             if (port && !strcasecmp(bus, "pci")) {
31                 pa_classify_guess_device_node_type_and_name(node, port->name,
32                                                             port->description);
33             }
34         }
35         else if (!strcasecmp(form, "speaker") || !strcasecmp(form, "car")) {
36             if (node->direction == mir_output) {
37                 node->location = mir_internal;
38                 node->type = mir_speakers;
39             }
40         }
41         else if (!strcasecmp(form, "handset")) {
42             node->location = mir_external;
43             node->type = mir_phone;
44             node->privacy = mir_private;
45         }
46         else if (!strcasecmp(form, "headset")) {
47             node->location = mir_external;
48             if (bus) {
49                 if (!strcasecmp(bus,"usb")) {
50                     node->type = mir_usb_headset;
51                 }
52                 else if (!strcasecmp(bus,"bluetooth")) {
53                     if (prof && !strcmp(prof->name, "a2dp"))
54                         node->type = mir_bluetooth_a2dp;
55                     else 
56                         node->type = mir_bluetooth_sco;
57                 }
58                 else {
59                     node->type = mir_wired_headset;
60                 }
61             }
62         }
63         else if (!strcasecmp(form, "headphone")) {
64             if (node->direction == mir_output) {
65                 node->location = mir_external;
66                 if (bus) {
67                     if (!strcasecmp(bus,"usb"))
68                         node->type = mir_usb_headphone;
69                     else if (strcasecmp(bus,"bluetooth"))
70                         node->type = mir_wired_headphone;
71                 }
72             }
73         }
74         else if (!strcasecmp(form, "microphone")) {
75             if (node->direction == mir_input) {
76                 node->location = mir_external;
77                 node->type = mir_microphone;
78             }
79         }
80     }
81     else {
82         if (port && !strcasecmp(bus, "pci")) {
83             pa_classify_guess_device_node_type_and_name(node, port->name,
84                                                         port->description);
85         }
86     }
87
88     if (!node->amname[0]) {
89         if (node->type != mir_node_type_unknown)
90             node->amname = (char *)mir_node_type_str(node->type);
91         else if (port && port->description)
92             node->amname = port->description;
93         else if (port && port->name)
94             node->amname = port->name;
95         else
96             node->amname = node->paname;
97     }
98
99
100     if (node->direction == mir_input)
101         node->privacy = mir_privacy_unknown;
102     else {
103         switch (node->type) {
104             /* public */
105         default:
106         case mir_speakers:
107         case mir_front_speakers:
108         case mir_rear_speakers:
109             node->privacy = mir_public;
110             break;
111             
112             /* private */
113         case mir_phone:
114         case mir_wired_headset:
115         case mir_wired_headphone:
116         case mir_usb_headset:
117         case mir_usb_headphone:
118         case mir_bluetooth_sco:
119         case mir_bluetooth_a2dp:
120             node->privacy = mir_private;
121             break;
122             
123             /* unknown */
124         case mir_null:
125         case mir_jack:
126         case mir_spdif:
127         case mir_hdmi:
128             node->privacy = mir_privacy_unknown;
129             break;
130         } /* switch */
131     }
132 }
133
134
135 /* data->direction must be set */
136 void pa_classify_guess_device_node_type_and_name(mir_node   *node,
137                                                  const char *name,
138                                                  const char *desc)
139 {
140     pa_assert(node);
141     pa_assert(name);
142     pa_assert(desc);
143
144     if (node->direction == mir_output && strcasestr(name, "headphone")) {
145         node->type = mir_wired_headphone;
146         node->amname = (char *)desc;
147     }
148     else if (strcasestr(name, "headset")) {
149         node->type = mir_wired_headset;
150         node->amname = (char *)desc;
151     }
152     else if (strcasestr(name, "line")) {
153         node->type = mir_jack;
154         node->amname = (char *)desc;
155     }
156     else if (strcasestr(name, "spdif")) {
157         node->type = mir_spdif;
158         node->amname = (char *)desc;
159     }
160     else if (strcasestr(name, "hdmi")) {
161         node->type = mir_hdmi;
162         node->amname = (char *)desc;
163     }
164     else if (node->direction == mir_input && strcasestr(name, "microphone")) {
165         node->type = mir_microphone;
166         node->amname = (char *)desc;
167     }
168     else if (node->direction == mir_output && strcasestr(name,"analog-output"))
169         node->type = mir_speakers;
170     else if (node->direction == mir_input && strcasestr(name, "analog-input"))
171         node->type = mir_jack;
172     else {
173         node->type = mir_node_type_unknown;
174     }
175 }
176
177
178 mir_node_type pa_classify_guess_stream_node_type(pa_proplist *pl)
179 {
180     typedef struct {
181         char *id;
182         mir_node_type type;
183     } map_t;
184
185     static map_t role_map[] = {
186         {"video"    , mir_player },
187         {"music"    , mir_player },
188         {"game"     , mir_game   },
189         {"event"    , mir_event  },
190         {"phone"    , mir_player },
191         {"animation", mir_browser},
192         {"test"     , mir_player },
193         {NULL, mir_node_type_unknown}
194     };
195
196     static map_t bin_map[] = {
197         {"rhytmbox"    , mir_player },
198         {"firefox"     , mir_browser},
199         {"chrome"      , mir_browser},
200         {"sound-juicer", mir_player },
201         {NULL, mir_node_type_unknown}
202     };
203
204
205     mir_node_type  rtype, btype;
206     const char    *role;
207     const char    *bin;
208     map_t         *m;
209
210     pa_assert(pl);
211
212     rtype = btype = mir_node_type_unknown;
213
214     role = pa_proplist_gets(pl, PA_PROP_MEDIA_ROLE);
215     bin  = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY);
216
217     if (role) {
218         for (m = role_map;  m->id;  m++) {
219             if (pa_streq(role, m->id))
220                 break;
221         }
222         rtype = m->type;
223     }
224
225     if (rtype != mir_node_type_unknown && rtype != mir_player)
226         return rtype;
227
228     if (bin) {
229         for (m = bin_map;  m->id;  m++) {
230             if (pa_streq(bin, m->id))
231                 break;
232         }
233         btype = m->type;
234     }
235
236     if (btype == mir_node_type_unknown)
237         return rtype;
238
239     return btype;
240 }
241
242
243 pa_bool_t pa_classify_multiplex_stream(mir_node *node)
244 {
245     static pa_bool_t multiplex[mir_application_class_end] = {
246         [ mir_player  ] = TRUE,
247         [ mir_game    ] = TRUE,
248         [ mir_browser ] = TRUE,
249     };
250
251     mir_node_type class;
252
253     pa_assert(node);
254
255     //return FALSE;
256
257     if (node->implement == mir_stream && node->direction == mir_input) {
258         class = node->type;
259
260         if (class > mir_application_class_begin &&
261             class < mir_application_class_end)
262         {
263             return multiplex[class];
264         }
265     }
266
267     return FALSE;
268 }