1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2009 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include "compat.h"
22 #include "device-port.h"
23 #include "alsa-mixer.h"
24
25 static const char *port_types[] = {
26 [PA_DEVICE_PORT_TYPE_UNKNOWN] = "unknown",
27 [PA_DEVICE_PORT_TYPE_AUX] = "aux",
28 [PA_DEVICE_PORT_TYPE_SPEAKER] = "speaker",
29 [PA_DEVICE_PORT_TYPE_HEADPHONES] = "headphones",
30 [PA_DEVICE_PORT_TYPE_LINE] = "line",
31 [PA_DEVICE_PORT_TYPE_MIC] = "mic",
32 [PA_DEVICE_PORT_TYPE_HEADSET] = "headset",
33 [PA_DEVICE_PORT_TYPE_HANDSET] = "handset",
34 [PA_DEVICE_PORT_TYPE_EARPIECE] = "earpiece",
35 [PA_DEVICE_PORT_TYPE_SPDIF] = "spdif",
36 [PA_DEVICE_PORT_TYPE_HDMI] = "hdmi",
37 [PA_DEVICE_PORT_TYPE_TV] = "tv",
38 [PA_DEVICE_PORT_TYPE_RADIO] = "radio",
39 [PA_DEVICE_PORT_TYPE_VIDEO] = "video",
40 [PA_DEVICE_PORT_TYPE_USB] = "usb",
41 [PA_DEVICE_PORT_TYPE_BLUETOOTH] = "bluetooth",
42 [PA_DEVICE_PORT_TYPE_PORTABLE] = "portable",
43 [PA_DEVICE_PORT_TYPE_HANDSFREE] = "handsfree",
44 [PA_DEVICE_PORT_TYPE_CAR] = "car",
45 [PA_DEVICE_PORT_TYPE_HIFI] = "hifi",
46 [PA_DEVICE_PORT_TYPE_PHONE] = "phone",
47 [PA_DEVICE_PORT_TYPE_NETWORK] = "network",
48 [PA_DEVICE_PORT_TYPE_ANALOG] = "analog",
49 };
50
str_port_type(pa_device_port_type_t type)51 static const char *str_port_type(pa_device_port_type_t type)
52 {
53 int idx = (type < PA_ELEMENTSOF(port_types)) ? type : 0;
54 return port_types[idx];
55 }
56
pa_device_port_new_data_init(pa_device_port_new_data * data)57 pa_device_port_new_data *pa_device_port_new_data_init(pa_device_port_new_data *data)
58 {
59 pa_assert(data);
60 pa_zero(*data);
61 data->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
62 data->available = PA_AVAILABLE_UNKNOWN;
63 return data;
64 }
65
pa_device_port_new_data_set_name(pa_device_port_new_data * data,const char * name)66 void pa_device_port_new_data_set_name(pa_device_port_new_data *data, const char *name)
67 {
68 pa_assert(data);
69 pa_xfree(data->name);
70 data->name = pa_xstrdup(name);
71 }
72
pa_device_port_new_data_set_description(pa_device_port_new_data * data,const char * description)73 void pa_device_port_new_data_set_description(pa_device_port_new_data *data, const char *description)
74 {
75 pa_assert(data);
76 pa_xfree(data->description);
77 data->description = pa_xstrdup(description);
78 }
79
pa_device_port_new_data_set_available(pa_device_port_new_data * data,pa_available_t available)80 void pa_device_port_new_data_set_available(pa_device_port_new_data *data, pa_available_t available)
81 {
82 pa_assert(data);
83 data->available = available;
84 }
85
pa_device_port_new_data_set_availability_group(pa_device_port_new_data * data,const char * group)86 void pa_device_port_new_data_set_availability_group(pa_device_port_new_data *data, const char *group)
87 {
88 pa_assert(data);
89 pa_xfree(data->availability_group);
90 data->availability_group = pa_xstrdup(group);
91 }
92
pa_device_port_new_data_set_direction(pa_device_port_new_data * data,pa_direction_t direction)93 void pa_device_port_new_data_set_direction(pa_device_port_new_data *data, pa_direction_t direction)
94 {
95 pa_assert(data);
96 data->direction = direction;
97 }
98
pa_device_port_new_data_set_type(pa_device_port_new_data * data,pa_device_port_type_t type)99 void pa_device_port_new_data_set_type(pa_device_port_new_data *data, pa_device_port_type_t type)
100 {
101 pa_assert(data);
102 data->type = type;
103 }
104
pa_device_port_new_data_done(pa_device_port_new_data * data)105 void pa_device_port_new_data_done(pa_device_port_new_data *data)
106 {
107 pa_assert(data);
108 pa_xfree(data->name);
109 pa_xfree(data->description);
110 pa_xfree(data->availability_group);
111 }
112
pa_device_port_new(pa_core * c,pa_device_port_new_data * data,size_t extra)113 pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, size_t extra)
114 {
115 pa_device_port *p;
116
117 pa_assert(data);
118 pa_assert(data->name);
119 pa_assert(data->description);
120 pa_assert(data->direction == PA_DIRECTION_OUTPUT || data->direction == PA_DIRECTION_INPUT);
121
122 p = calloc(1, sizeof(pa_device_port) + extra);
123
124 p->port.name = p->name = data->name;
125 data->name = NULL;
126 p->port.description = p->description = data->description;
127 data->description = NULL;
128 p->priority = p->port.priority = 0;
129 p->available = data->available;
130 p->port.available = (enum acp_available) data->available;
131 p->availability_group = data->availability_group;
132 data->availability_group = NULL;
133 p->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
134 p->direction = data->direction;
135 p->port.direction = data->direction == PA_DIRECTION_OUTPUT ?
136 ACP_DIRECTION_PLAYBACK : ACP_DIRECTION_CAPTURE;
137 p->type = data->type;
138
139 p->proplist = pa_proplist_new();
140 pa_proplist_sets(p->proplist, ACP_KEY_PORT_TYPE, str_port_type(data->type));
141 if (p->availability_group)
142 pa_proplist_sets(p->proplist, ACP_KEY_PORT_AVAILABILITY_GROUP, p->availability_group);
143
144 p->user_data = (void*)((uint8_t*)p + sizeof(pa_device_port));
145
146 return p;
147 }
148
pa_device_port_free(pa_device_port * port)149 void pa_device_port_free(pa_device_port *port)
150 {
151 pa_xfree(port->name);
152 pa_xfree(port->description);
153 pa_xfree(port->availability_group);
154 pa_hashmap_free(port->profiles);
155 pa_proplist_free(port->proplist);
156 if (port->impl_free)
157 port->impl_free (port);
158 free(port);
159 }
160
pa_device_port_set_available(pa_device_port * p,pa_available_t status)161 void pa_device_port_set_available(pa_device_port *p, pa_available_t status)
162 {
163 pa_available_t old = p->available;
164
165 if (old == status)
166 return;
167 p->available = status;
168 p->port.available = (enum acp_available) status;
169
170 if (p->card && p->card->events && p->card->events->port_available)
171 p->card->events->port_available(p->card->user_data, p->port.index,
172 (enum acp_available)old, p->port.available);
173 }
174
pa_alsa_device_init_description(pa_proplist * p,pa_card * card)175 bool pa_alsa_device_init_description(pa_proplist *p, pa_card *card) {
176 const char *s, *d = NULL, *k;
177 pa_assert(p);
178
179 if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
180 return true;
181
182 if (card)
183 if ((s = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_DESCRIPTION)))
184 d = s;
185
186 if (!d)
187 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
188 if (pa_streq(s, "internal"))
189 d = _("Built-in Audio");
190
191 if (!d)
192 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
193 if (pa_streq(s, "modem"))
194 d = _("Modem");
195
196 if (!d)
197 d = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME);
198
199 if (!d)
200 return false;
201
202 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
203
204 if (d && k)
205 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
206 else if (d)
207 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
208
209 return true;
210 }
211