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,
22 #include <pulsecore/pulsecore-config.h>
24 #include <pulsecore/card.h>
25 #include <pulsecore/device-port.h>
26 #include <pulsecore/core-util.h>
32 void pa_classify_node_by_card(mir_node *node,
34 pa_card_profile *prof,
46 bus = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_BUS);
47 form = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_FORM_FACTOR);
49 desc = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_DESCRIPTION);
52 node->type = mir_node_type_unknown;
55 if (!strcasecmp(form, "internal")) {
56 node->location = mir_external;
57 if (port && !strcasecmp(bus, "pci")) {
58 pa_classify_guess_device_node_type_and_name(node, port->name,
62 else if (!strcasecmp(form, "speaker") || !strcasecmp(form, "car")) {
63 if (node->direction == mir_output) {
64 node->location = mir_internal;
65 node->type = mir_speakers;
68 else if (!strcasecmp(form, "handset")) {
69 node->location = mir_external;
70 node->type = mir_phone;
71 node->privacy = mir_private;
73 else if (!strcasecmp(form, "headset")) {
74 node->location = mir_external;
76 if (!strcasecmp(bus,"usb")) {
77 node->type = mir_usb_headset;
79 else if (!strcasecmp(bus,"bluetooth")) {
80 if (prof && !strcmp(prof->name, "a2dp"))
81 node->type = mir_bluetooth_a2dp;
83 node->type = mir_bluetooth_sco;
86 node->type = mir_wired_headset;
90 else if (!strcasecmp(form, "headphone")) {
91 if (node->direction == mir_output) {
92 node->location = mir_external;
94 if (!strcasecmp(bus,"usb"))
95 node->type = mir_usb_headphone;
96 else if (strcasecmp(bus,"bluetooth"))
97 node->type = mir_wired_headphone;
101 else if (!strcasecmp(form, "microphone")) {
102 if (node->direction == mir_input) {
103 node->location = mir_external;
104 node->type = mir_microphone;
109 if (port && !strcasecmp(bus, "pci")) {
110 pa_classify_guess_device_node_type_and_name(node, port->name,
113 else if (prof && !strcasecmp(bus, "bluetooth")) {
114 if (!strcmp(prof->name, "a2dp"))
115 node->type = mir_bluetooth_a2dp;
116 else if (!strcmp(prof->name, "hsp"))
117 node->type = mir_bluetooth_sco;
118 else if (!strcmp(prof->name, "hfgw"))
119 node->type = mir_bluetooth_carkit;
120 else if (!strcmp(prof->name, "a2dp_source"))
121 node->type = mir_bluetooth_source;
122 else if (!strcmp(prof->name, "a2dp_sink"))
123 node->type = mir_bluetooth_sink;
127 if (!node->amname[0]) {
128 if (node->type != mir_node_type_unknown)
129 node->amname = (char *)mir_node_type_str(node->type);
130 else if (port && port->description)
131 node->amname = port->description;
132 else if (port && port->name)
133 node->amname = port->name;
135 node->amname = node->paname;
139 if (node->direction == mir_input)
140 node->privacy = mir_privacy_unknown;
142 switch (node->type) {
146 case mir_front_speakers:
147 case mir_rear_speakers:
148 node->privacy = mir_public;
153 case mir_wired_headset:
154 case mir_wired_headphone:
155 case mir_usb_headset:
156 case mir_usb_headphone:
157 case mir_bluetooth_sco:
158 case mir_bluetooth_a2dp:
159 node->privacy = mir_private;
167 case mir_bluetooth_sink:
168 node->privacy = mir_privacy_unknown;
175 /* data->direction must be set */
176 void pa_classify_guess_device_node_type_and_name(mir_node *node,
184 if (node->direction == mir_output && strcasestr(name, "headphone")) {
185 node->type = mir_wired_headphone;
186 node->amname = (char *)desc;
188 else if (strcasestr(name, "headset")) {
189 node->type = mir_wired_headset;
190 node->amname = (char *)desc;
192 else if (strcasestr(name, "line")) {
193 node->type = mir_jack;
194 node->amname = (char *)desc;
196 else if (strcasestr(name, "spdif")) {
197 node->type = mir_spdif;
198 node->amname = (char *)desc;
200 else if (strcasestr(name, "hdmi")) {
201 node->type = mir_hdmi;
202 node->amname = (char *)desc;
204 else if (node->direction == mir_input && strcasestr(name, "microphone")) {
205 node->type = mir_microphone;
206 node->amname = (char *)desc;
208 else if (node->direction == mir_output && strcasestr(name,"analog-output"))
209 node->type = mir_speakers;
210 else if (node->direction == mir_input && strcasestr(name, "analog-input"))
211 node->type = mir_jack;
213 node->type = mir_node_type_unknown;
218 mir_node_type pa_classify_guess_stream_node_type(pa_proplist *pl)
225 static map_t role_map[] = {
226 {"video" , mir_player },
227 {"music" , mir_player },
228 {"game" , mir_game },
229 {"event" , mir_event },
230 {"navigator", mir_navigator },
231 {"phone" , mir_phone },
232 {"carkit" , mir_phone },
233 {"animation", mir_browser },
234 {"test" , mir_player },
235 {NULL, mir_node_type_unknown}
238 static map_t bin_map[] = {
239 {"rhytmbox" , mir_player },
240 {"firefox" , mir_browser},
241 {"chrome" , mir_browser},
242 {"sound-juicer", mir_player },
243 {NULL, mir_node_type_unknown}
247 mir_node_type rtype, btype;
254 rtype = btype = mir_node_type_unknown;
256 role = pa_proplist_gets(pl, PA_PROP_MEDIA_ROLE);
257 bin = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY);
260 for (m = role_map; m->id; m++) {
261 if (pa_streq(role, m->id))
267 if (rtype != mir_node_type_unknown && rtype != mir_player)
271 for (m = bin_map; m->id; m++) {
272 if (pa_streq(bin, m->id))
278 if (btype == mir_node_type_unknown)
284 mir_node_type pa_classify_guess_application_class(mir_node *node)
290 if (node->implement == mir_stream)
293 if (node->direction == mir_output)
294 class = mir_node_type_unknown;
296 switch (node->type) {
297 default: class = mir_node_type_unknown; break;
298 case mir_bluetooth_carkit: class = mir_phone; break;
299 case mir_bluetooth_source: class = mir_player; break;
308 pa_bool_t pa_classify_multiplex_stream(mir_node *node)
310 static pa_bool_t multiplex[mir_application_class_end] = {
311 [ mir_player ] = TRUE,
313 [ mir_browser ] = TRUE,
320 if (node->implement == mir_stream && node->direction == mir_input) {
323 if (class > mir_application_class_begin &&
324 class < mir_application_class_end)
326 return multiplex[class];
333 const char *pa_classify_loopback_stream(mir_node *node)
335 const char *role[mir_device_class_end - mir_device_class_begin] = {
336 [ mir_bluetooth_carkit - mir_device_class_begin ] = "phone",
337 [ mir_bluetooth_source - mir_device_class_begin ] = "music" ,
344 if (node->implement == mir_device) {
347 if (class >= mir_device_class_begin && class < mir_device_class_end) {
348 return role[class - mir_device_class_begin];