]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-mixer.h
alsa-mixer: Add possibility to configure ELD device
[pulseaudio] / src / modules / alsa / alsa-mixer.h
1 #ifndef fooalsamixerhfoo
2 #define fooalsamixerhfoo
3
4 /***
5 This file is part of PulseAudio.
6
7 Copyright 2004-2006 Lennart Poettering
8 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
9
10 PulseAudio is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published
12 by the Free Software Foundation; either version 2.1 of the License,
13 or (at your option) any later version.
14
15 PulseAudio is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public License
21 along with PulseAudio; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 USA.
24 ***/
25
26 #include <asoundlib.h>
27
28 #include <pulse/sample.h>
29 #include <pulse/mainloop-api.h>
30 #include <pulse/channelmap.h>
31 #include <pulse/volume.h>
32
33 #include <pulsecore/llist.h>
34 #include <pulsecore/rtpoll.h>
35
36 typedef struct pa_alsa_fdlist pa_alsa_fdlist;
37 typedef struct pa_alsa_mixer_pdata pa_alsa_mixer_pdata;
38 typedef struct pa_alsa_setting pa_alsa_setting;
39 typedef struct pa_alsa_option pa_alsa_option;
40 typedef struct pa_alsa_element pa_alsa_element;
41 typedef struct pa_alsa_jack pa_alsa_jack;
42 typedef struct pa_alsa_path pa_alsa_path;
43 typedef struct pa_alsa_path_set pa_alsa_path_set;
44 typedef struct pa_alsa_mapping pa_alsa_mapping;
45 typedef struct pa_alsa_profile pa_alsa_profile;
46 typedef struct pa_alsa_decibel_fix pa_alsa_decibel_fix;
47 typedef struct pa_alsa_profile_set pa_alsa_profile_set;
48 typedef struct pa_alsa_port_data pa_alsa_port_data;
49
50 #include "alsa-util.h"
51 #include "alsa-ucm.h"
52
53 typedef enum pa_alsa_switch_use {
54 PA_ALSA_SWITCH_IGNORE,
55 PA_ALSA_SWITCH_MUTE, /* make this switch follow mute status */
56 PA_ALSA_SWITCH_OFF, /* set this switch to 'off' unconditionally */
57 PA_ALSA_SWITCH_ON, /* set this switch to 'on' unconditionally */
58 PA_ALSA_SWITCH_SELECT /* allow the user to select switch status through a setting */
59 } pa_alsa_switch_use_t;
60
61 typedef enum pa_alsa_volume_use {
62 PA_ALSA_VOLUME_IGNORE,
63 PA_ALSA_VOLUME_MERGE, /* merge this volume slider into the global volume slider */
64 PA_ALSA_VOLUME_OFF, /* set this volume to minimal unconditionally */
65 PA_ALSA_VOLUME_ZERO, /* set this volume to 0dB unconditionally */
66 PA_ALSA_VOLUME_CONSTANT /* set this volume to a constant value unconditionally */
67 } pa_alsa_volume_use_t;
68
69 typedef enum pa_alsa_enumeration_use {
70 PA_ALSA_ENUMERATION_IGNORE,
71 PA_ALSA_ENUMERATION_SELECT
72 } pa_alsa_enumeration_use_t;
73
74 typedef enum pa_alsa_required {
75 PA_ALSA_REQUIRED_IGNORE,
76 PA_ALSA_REQUIRED_SWITCH,
77 PA_ALSA_REQUIRED_VOLUME,
78 PA_ALSA_REQUIRED_ENUMERATION,
79 PA_ALSA_REQUIRED_ANY
80 } pa_alsa_required_t;
81
82 typedef enum pa_alsa_direction {
83 PA_ALSA_DIRECTION_ANY,
84 PA_ALSA_DIRECTION_OUTPUT,
85 PA_ALSA_DIRECTION_INPUT
86 } pa_alsa_direction_t;
87
88 /* A setting combines a couple of options into a single entity that
89 * may be selected. Only one setting can be active at the same
90 * time. */
91 struct pa_alsa_setting {
92 pa_alsa_path *path;
93 PA_LLIST_FIELDS(pa_alsa_setting);
94
95 pa_idxset *options;
96
97 char *name;
98 char *description;
99 unsigned priority;
100 };
101
102 /* An option belongs to an element and refers to one enumeration item
103 * of the element is an enumeration item, or a switch status if the
104 * element is a switch item. */
105 struct pa_alsa_option {
106 pa_alsa_element *element;
107 PA_LLIST_FIELDS(pa_alsa_option);
108
109 char *alsa_name;
110 int alsa_idx;
111
112 char *name;
113 char *description;
114 unsigned priority;
115
116 pa_alsa_required_t required;
117 pa_alsa_required_t required_any;
118 pa_alsa_required_t required_absent;
119 };
120
121 /* An element wraps one specific ALSA element. A series of elements
122 * make up a path (see below). If the element is an enumeration or switch
123 * element it may include a list of options. */
124 struct pa_alsa_element {
125 pa_alsa_path *path;
126 PA_LLIST_FIELDS(pa_alsa_element);
127
128 char *alsa_name;
129 pa_alsa_direction_t direction;
130
131 pa_alsa_switch_use_t switch_use;
132 pa_alsa_volume_use_t volume_use;
133 pa_alsa_enumeration_use_t enumeration_use;
134
135 pa_alsa_required_t required;
136 pa_alsa_required_t required_any;
137 pa_alsa_required_t required_absent;
138
139 long constant_volume;
140
141 pa_bool_t override_map:1;
142 pa_bool_t direction_try_other:1;
143
144 pa_bool_t has_dB:1;
145 long min_volume, max_volume;
146 long volume_limit; /* -1 for no configured limit */
147 double min_dB, max_dB;
148
149 pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][2];
150 unsigned n_channels;
151
152 pa_channel_position_mask_t merged_mask;
153
154 PA_LLIST_HEAD(pa_alsa_option, options);
155
156 pa_alsa_decibel_fix *db_fix;
157 };
158
159 struct pa_alsa_jack {
160 pa_alsa_path *path;
161 PA_LLIST_FIELDS(pa_alsa_jack);
162
163 char *name; /* E g "Headphone" */
164 char *alsa_name; /* E g "Headphone Jack" */
165 pa_bool_t has_control; /* is the jack itself present? */
166 pa_bool_t plugged_in; /* is this jack currently plugged in? */
167 snd_hctl_elem_t *hctl_elem; /* Jack detection handle */
168 pa_available_t state_unplugged, state_plugged;
169
170 pa_alsa_required_t required;
171 pa_alsa_required_t required_any;
172 pa_alsa_required_t required_absent;
173 };
174
175 /* A path wraps a series of elements into a single entity which can be
176 * used to control it as if it had a single volume slider, a single
177 * mute switch and a single list of selectable options. */
178 struct pa_alsa_path {
179 pa_alsa_direction_t direction;
180 pa_device_port* port;
181
182 char *name;
183 char *description;
184 unsigned priority;
185 int eld_device;
186 pa_proplist *proplist;
187
188 pa_bool_t probed:1;
189 pa_bool_t supported:1;
190 pa_bool_t has_mute:1;
191 pa_bool_t has_volume:1;
192 pa_bool_t has_dB:1;
193 bool mute_during_activation:1;
194 /* These two are used during probing only */
195 pa_bool_t has_req_any:1;
196 pa_bool_t req_any_present:1;
197
198 long min_volume, max_volume;
199 double min_dB, max_dB;
200
201 /* This is used during parsing only, as a shortcut so that we
202 * don't have to iterate the list all the time */
203 pa_alsa_element *last_element;
204 pa_alsa_option *last_option;
205 pa_alsa_setting *last_setting;
206 pa_alsa_jack *last_jack;
207
208 PA_LLIST_HEAD(pa_alsa_element, elements);
209 PA_LLIST_HEAD(pa_alsa_setting, settings);
210 PA_LLIST_HEAD(pa_alsa_jack, jacks);
211 };
212
213 /* A path set is simply a set of paths that are applicable to a
214 * device */
215 struct pa_alsa_path_set {
216 pa_hashmap *paths;
217 pa_alsa_direction_t direction;
218 };
219
220 void pa_alsa_setting_dump(pa_alsa_setting *s);
221
222 void pa_alsa_option_dump(pa_alsa_option *o);
223 void pa_alsa_jack_dump(pa_alsa_jack *j);
224 void pa_alsa_element_dump(pa_alsa_element *e);
225
226 pa_alsa_path *pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction);
227 pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction);
228 int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, snd_hctl_t *hctl, pa_bool_t ignore_dB);
229 void pa_alsa_path_dump(pa_alsa_path *p);
230 int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
231 int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t *muted);
232 int pa_alsa_path_set_volume(pa_alsa_path *path, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v, pa_bool_t deferred_volume, pa_bool_t write_to_hw);
233 int pa_alsa_path_set_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t muted);
234 int pa_alsa_path_select(pa_alsa_path *p, pa_alsa_setting *s, snd_mixer_t *m, bool device_is_muted);
235 void pa_alsa_path_set_callback(pa_alsa_path *p, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
236 void pa_alsa_path_free(pa_alsa_path *p);
237
238 pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t direction, const char *paths_dir);
239 void pa_alsa_path_set_dump(pa_alsa_path_set *s);
240 void pa_alsa_path_set_set_callback(pa_alsa_path_set *ps, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
241 void pa_alsa_path_set_free(pa_alsa_path_set *s);
242
243 struct pa_alsa_mapping {
244 pa_alsa_profile_set *profile_set;
245
246 char *name;
247 char *description;
248 unsigned priority;
249 pa_alsa_direction_t direction;
250 /* These are copied over to the resultant sink/source */
251 pa_proplist *proplist;
252
253 pa_channel_map channel_map;
254
255 char **device_strings;
256
257 char **input_path_names;
258 char **output_path_names;
259 char **input_element; /* list of fallbacks */
260 char **output_element;
261 pa_alsa_path_set *input_path_set;
262 pa_alsa_path_set *output_path_set;
263
264 unsigned supported;
265
266 /* Temporarily used during probing */
267 snd_pcm_t *input_pcm;
268 snd_pcm_t *output_pcm;
269
270 pa_sink *sink;
271 pa_source *source;
272
273 /* ucm device context*/
274 pa_alsa_ucm_mapping_context ucm_context;
275 };
276
277 struct pa_alsa_profile {
278 pa_alsa_profile_set *profile_set;
279
280 char *name;
281 char *description;
282 unsigned priority;
283
284 pa_bool_t supported:1;
285
286 char **input_mapping_names;
287 char **output_mapping_names;
288
289 pa_idxset *input_mappings;
290 pa_idxset *output_mappings;
291 };
292
293 struct pa_alsa_decibel_fix {
294 pa_alsa_profile_set *profile_set;
295
296 char *name; /* Alsa volume element name. */
297 long min_step;
298 long max_step;
299
300 /* An array that maps alsa volume element steps to decibels. The steps can
301 * be used as indices to this array, after subtracting min_step from the
302 * real value.
303 *
304 * The values are actually stored as integers representing millibels,
305 * because that's the format the alsa API uses. */
306 long *db_values;
307 };
308
309 struct pa_alsa_profile_set {
310 pa_hashmap *mappings;
311 pa_hashmap *profiles;
312 pa_hashmap *decibel_fixes;
313 pa_hashmap *input_paths;
314 pa_hashmap *output_paths;
315
316 pa_bool_t auto_profiles;
317 pa_bool_t ignore_dB:1;
318 pa_bool_t probed:1;
319 };
320
321 void pa_alsa_mapping_dump(pa_alsa_mapping *m);
322 void pa_alsa_profile_dump(pa_alsa_profile *p);
323 void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix);
324 pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name);
325
326 pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
327 void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec);
328 void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
329 void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
330 void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *s);
331
332 snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl);
333
334 pa_alsa_fdlist *pa_alsa_fdlist_new(void);
335 void pa_alsa_fdlist_free(pa_alsa_fdlist *fdl);
336 int pa_alsa_fdlist_set_handle(pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, snd_hctl_t *hctl_handle, pa_mainloop_api* m);
337
338 /* Alternative for handling alsa mixer events in io-thread. */
339
340 pa_alsa_mixer_pdata *pa_alsa_mixer_pdata_new(void);
341 void pa_alsa_mixer_pdata_free(pa_alsa_mixer_pdata *pd);
342 int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata *pd, snd_mixer_t *mixer, pa_rtpoll *rtp);
343
344 /* Data structure for inclusion in pa_device_port for alsa
345 * sinks/sources. This contains nothing that needs to be freed
346 * individually */
347 struct pa_alsa_port_data {
348 pa_alsa_path *path;
349 pa_alsa_setting *setting;
350 };
351
352 void pa_alsa_add_ports(void *sink_or_source_new_data, pa_alsa_path_set *ps, pa_card *card);
353 void pa_alsa_path_set_add_ports(pa_alsa_path_set *ps, pa_card_profile *cp, pa_hashmap *ports, pa_hashmap *extra, pa_core *core);
354
355 #endif