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, "hfgw"))
115 node->type = mir_bluetooth_carkit;
116 else if (!strcmp(prof->name, "a2dp_source"))
117 node->type = mir_bluetooth_source;
118 else if (!strcmp(prof->name, "a2dp_sink"))
119 node->type = mir_bluetooth_sink;
123 if (!node->amname[0]) {
124 if (node->type != mir_node_type_unknown)
125 node->amname = (char *)mir_node_type_str(node->type);
126 else if (port && port->description)
127 node->amname = port->description;
128 else if (port && port->name)
129 node->amname = port->name;
131 node->amname = node->paname;
135 if (node->direction == mir_input)
136 node->privacy = mir_privacy_unknown;
138 switch (node->type) {
142 case mir_front_speakers:
143 case mir_rear_speakers:
144 node->privacy = mir_public;
149 case mir_wired_headset:
150 case mir_wired_headphone:
151 case mir_usb_headset:
152 case mir_usb_headphone:
153 case mir_bluetooth_sco:
154 case mir_bluetooth_a2dp:
155 node->privacy = mir_private;
163 case mir_bluetooth_sink:
164 node->privacy = mir_privacy_unknown;
171 /* data->direction must be set */
172 void pa_classify_guess_device_node_type_and_name(mir_node *node,
180 if (node->direction == mir_output && strcasestr(name, "headphone")) {
181 node->type = mir_wired_headphone;
182 node->amname = (char *)desc;
184 else if (strcasestr(name, "headset")) {
185 node->type = mir_wired_headset;
186 node->amname = (char *)desc;
188 else if (strcasestr(name, "line")) {
189 node->type = mir_jack;
190 node->amname = (char *)desc;
192 else if (strcasestr(name, "spdif")) {
193 node->type = mir_spdif;
194 node->amname = (char *)desc;
196 else if (strcasestr(name, "hdmi")) {
197 node->type = mir_hdmi;
198 node->amname = (char *)desc;
200 else if (node->direction == mir_input && strcasestr(name, "microphone")) {
201 node->type = mir_microphone;
202 node->amname = (char *)desc;
204 else if (node->direction == mir_output && strcasestr(name,"analog-output"))
205 node->type = mir_speakers;
206 else if (node->direction == mir_input && strcasestr(name, "analog-input"))
207 node->type = mir_jack;
209 node->type = mir_node_type_unknown;
214 mir_node_type pa_classify_guess_stream_node_type(pa_proplist *pl)
221 static map_t role_map[] = {
222 {"video" , mir_player },
223 {"music" , mir_player },
224 {"game" , mir_game },
225 {"event" , mir_event },
226 {"navigator", mir_navigator },
227 {"phone" , mir_phone },
228 {"carkit" , mir_phone },
229 {"animation", mir_browser },
230 {"test" , mir_player },
231 {NULL, mir_node_type_unknown}
234 static map_t bin_map[] = {
235 {"rhytmbox" , mir_player },
236 {"firefox" , mir_browser},
237 {"chrome" , mir_browser},
238 {"sound-juicer", mir_player },
239 {NULL, mir_node_type_unknown}
243 mir_node_type rtype, btype;
250 rtype = btype = mir_node_type_unknown;
252 role = pa_proplist_gets(pl, PA_PROP_MEDIA_ROLE);
253 bin = pa_proplist_gets(pl, PA_PROP_APPLICATION_PROCESS_BINARY);
256 for (m = role_map; m->id; m++) {
257 if (pa_streq(role, m->id))
263 if (rtype != mir_node_type_unknown && rtype != mir_player)
267 for (m = bin_map; m->id; m++) {
268 if (pa_streq(bin, m->id))
274 if (btype == mir_node_type_unknown)
280 mir_node_type pa_classify_guess_application_class(mir_node *node)
286 if (node->implement == mir_stream)
289 if (node->direction == mir_output)
290 class = mir_node_type_unknown;
292 switch (node->type) {
293 default: class = mir_node_type_unknown; break;
294 case mir_bluetooth_carkit: class = mir_phone; break;
295 case mir_bluetooth_source: class = mir_player; break;
304 pa_bool_t pa_classify_multiplex_stream(mir_node *node)
306 static pa_bool_t multiplex[mir_application_class_end] = {
307 [ mir_player ] = TRUE,
309 [ mir_browser ] = TRUE,
316 if (node->implement == mir_stream && node->direction == mir_input) {
319 if (class > mir_application_class_begin &&
320 class < mir_application_class_end)
322 return multiplex[class];
329 const char *pa_classify_loopback_stream(mir_node *node)
331 const char *role[mir_device_class_end - mir_device_class_begin] = {
333 [ mir_bluetooth_sco - mir_device_class_begin ] = "phone" ,
334 [ mir_bluetooth_carkit - mir_device_class_begin ] = "carkit",
336 [ mir_bluetooth_source - mir_device_class_begin ] = "music" ,
343 if (node->implement == mir_device && node->direction == mir_input) {
346 if (class >= mir_device_class_begin && class < mir_device_class_end) {
347 return role[class - mir_device_class_begin];