2 * module-murphy-ivi -- PulseAudio module for providing audio routing support
3 * Copyright (c) 2012, Intel Corporation.
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.
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.
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,
25 #include <pulsecore/pulsecore-config.h>
27 #include <pulsecore/card.h>
28 #include <pulsecore/device-port.h>
29 #include <pulsecore/core-util.h>
35 void pa_classify_node_by_card(mir_node *node,
37 pa_card_profile *prof,
49 bus = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_BUS);
50 form = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_FORM_FACTOR);
52 desc = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_DESCRIPTION);
55 node->type = mir_node_type_unknown;
58 if (!strcasecmp(form, "internal")) {
59 node->location = mir_external;
60 if (port && !strcasecmp(bus, "pci")) {
61 pa_classify_guess_device_node_type_and_name(node, port->name,
65 else if (!strcasecmp(form, "speaker") || !strcasecmp(form, "car")) {
66 if (node->direction == mir_output) {
67 node->location = mir_internal;
68 node->type = mir_speakers;
71 else if (!strcasecmp(form, "handset")) {
72 node->location = mir_external;
73 node->type = mir_phone;
74 node->privacy = mir_private;
76 else if (!strcasecmp(form, "headset")) {
77 node->location = mir_external;
79 if (!strcasecmp(bus,"usb")) {
80 node->type = mir_usb_headset;
82 else if (!strcasecmp(bus,"bluetooth")) {
83 if (prof && !strcmp(prof->name, "a2dp"))
84 node->type = mir_bluetooth_a2dp;
86 node->type = mir_bluetooth_sco;
89 node->type = mir_wired_headset;
93 else if (!strcasecmp(form, "headphone")) {
94 if (node->direction == mir_output) {
95 node->location = mir_external;
97 if (!strcasecmp(bus,"usb"))
98 node->type = mir_usb_headphone;
99 else if (strcasecmp(bus,"bluetooth"))
100 node->type = mir_wired_headphone;
104 else if (!strcasecmp(form, "microphone")) {
105 if (node->direction == mir_input) {
106 node->location = mir_external;
107 node->type = mir_microphone;
112 if (port && !strcasecmp(bus, "pci")) {
113 pa_classify_guess_device_node_type_and_name(node, port->name,
116 else if (prof && !strcasecmp(bus, "bluetooth")) {
117 if (!strcmp(prof->name, "a2dp"))
118 node->type = mir_bluetooth_a2dp;
119 else if (!strcmp(prof->name, "hsp"))
120 node->type = mir_bluetooth_sco;
121 else if (!strcmp(prof->name, "hfgw"))
122 node->type = mir_bluetooth_carkit;
123 else if (!strcmp(prof->name, "a2dp_source"))
124 node->type = mir_bluetooth_source;
125 else if (!strcmp(prof->name, "a2dp_sink"))
126 node->type = mir_bluetooth_sink;
130 if (!node->amname[0]) {
131 if (node->type != mir_node_type_unknown)
132 node->amname = (char *)mir_node_type_str(node->type);
133 else if (port && port->description)
134 node->amname = port->description;
135 else if (port && port->name)
136 node->amname = port->name;
138 node->amname = node->paname;
142 if (node->direction == mir_input)
143 node->privacy = mir_privacy_unknown;
145 switch (node->type) {
149 case mir_front_speakers:
150 case mir_rear_speakers:
151 node->privacy = mir_public;
156 case mir_wired_headset:
157 case mir_wired_headphone:
158 case mir_usb_headset:
159 case mir_usb_headphone:
160 case mir_bluetooth_sco:
161 case mir_bluetooth_a2dp:
162 node->privacy = mir_private;
170 case mir_bluetooth_sink:
171 node->privacy = mir_privacy_unknown;
178 /* data->direction must be set */
179 void pa_classify_guess_device_node_type_and_name(mir_node *node,
187 if (node->direction == mir_output && strcasestr(name, "headphone")) {
188 node->type = mir_wired_headphone;
189 node->amname = (char *)desc;
191 else if (strcasestr(name, "headset")) {
192 node->type = mir_wired_headset;
193 node->amname = (char *)desc;
195 else if (strcasestr(name, "line")) {
196 node->type = mir_jack;
197 node->amname = (char *)desc;
199 else if (strcasestr(name, "spdif")) {
200 node->type = mir_spdif;
201 node->amname = (char *)desc;
203 else if (strcasestr(name, "hdmi")) {
204 node->type = mir_hdmi;
205 node->amname = (char *)desc;
207 else if (node->direction == mir_input && strcasestr(name, "microphone")) {
208 node->type = mir_microphone;
209 node->amname = (char *)desc;
211 else if (node->direction == mir_output && strcasestr(name,"analog-output"))
212 node->type = mir_speakers;
213 else if (node->direction == mir_input && strcasestr(name, "analog-input"))
214 node->type = mir_jack;
216 node->type = mir_node_type_unknown;
221 mir_node_type pa_classify_guess_stream_node_type(pa_proplist *pl)
228 static map_t role_map[] = {
229 {"video" , mir_player },
230 {"music" , mir_player },
231 {"game" , mir_game },
232 {"event" , mir_event },
233 {"navigator", mir_navigator },
234 {"phone" , mir_phone },
235 {"carkit" , mir_phone },
236 {"animation", mir_browser },
237 {"test" , mir_player },
238 {"ringtone" , mir_alert },
239 {"camera" , mir_camera },
240 {"system" , mir_system },
241 {NULL, mir_node_type_unknown}
244 static map_t bin_map[] = {
245 {"rhytmbox" , mir_player },
246 {"firefox" , mir_browser},
247 {"chrome" , mir_browser},
248 {"sound-juicer", mir_player },
249 {NULL, mir_node_type_unknown}
253 mir_node_type rtype, btype;
260 rtype = btype = mir_node_type_unknown;
262 role = pa_proplist_gets(pl, PA_PROP_MEDIA_ROLE);
263 bin = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY);
266 for (m = role_map; m->id; m++) {
267 if (pa_streq(role, m->id))
273 if (rtype != mir_node_type_unknown && rtype != mir_player)
277 for (m = bin_map; m->id; m++) {
278 if (pa_streq(bin, m->id))
284 if (btype == mir_node_type_unknown)
290 mir_node_type pa_classify_guess_application_class(mir_node *node)
296 if (node->implement == mir_stream)
299 if (node->direction == mir_output)
300 class = mir_node_type_unknown;
302 switch (node->type) {
303 default: class = mir_node_type_unknown; break;
304 case mir_bluetooth_carkit: class = mir_phone; break;
305 case mir_bluetooth_source: class = mir_player; break;
314 pa_bool_t pa_classify_multiplex_stream(mir_node *node)
316 static pa_bool_t multiplex[mir_application_class_end] = {
317 [ mir_player ] = TRUE,
319 [ mir_browser ] = TRUE,
326 if (node->implement == mir_stream && node->direction == mir_input) {
329 if (class > mir_application_class_begin &&
330 class < mir_application_class_end)
332 return multiplex[class];
339 const char *pa_classify_loopback_stream(mir_node *node)
341 const char *role[mir_device_class_end - mir_device_class_begin] = {
342 [ mir_bluetooth_carkit - mir_device_class_begin ] = "phone",
343 [ mir_bluetooth_source - mir_device_class_begin ] = "music" ,
350 if (node->implement == mir_device) {
353 if (class >= mir_device_class_begin && class < mir_device_class_end) {
354 return role[class - mir_device_class_begin];