]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-mixer.h
sink, source: Always create a hashmap for ports.
[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
52 typedef enum pa_alsa_switch_use {
53 PA_ALSA_SWITCH_IGNORE,
54 PA_ALSA_SWITCH_MUTE, /* make this switch follow mute status */
55 PA_ALSA_SWITCH_OFF, /* set this switch to 'off' unconditionally */
56 PA_ALSA_SWITCH_ON, /* set this switch to 'on' unconditionally */
57 PA_ALSA_SWITCH_SELECT /* allow the user to select switch status through a setting */
58 } pa_alsa_switch_use_t;
59
60 typedef enum pa_alsa_volume_use {
61 PA_ALSA_VOLUME_IGNORE,
62 PA_ALSA_VOLUME_MERGE, /* merge this volume slider into the global volume slider */
63 PA_ALSA_VOLUME_OFF, /* set this volume to minimal unconditionally */
64 PA_ALSA_VOLUME_ZERO, /* set this volume to 0dB unconditionally */
65 PA_ALSA_VOLUME_CONSTANT /* set this volume to a constant value unconditionally */
66 } pa_alsa_volume_use_t;
67
68 typedef enum pa_alsa_enumeration_use {
69 PA_ALSA_ENUMERATION_IGNORE,
70 PA_ALSA_ENUMERATION_SELECT
71 } pa_alsa_enumeration_use_t;
72
73 typedef enum pa_alsa_required {
74 PA_ALSA_REQUIRED_IGNORE,
75 PA_ALSA_REQUIRED_SWITCH,
76 PA_ALSA_REQUIRED_VOLUME,
77 PA_ALSA_REQUIRED_ENUMERATION,
78 PA_ALSA_REQUIRED_ANY
79 } pa_alsa_required_t;
80
81 typedef enum pa_alsa_direction {
82 PA_ALSA_DIRECTION_ANY,
83 PA_ALSA_DIRECTION_OUTPUT,
84 PA_ALSA_DIRECTION_INPUT
85 } pa_alsa_direction_t;
86
87 /* A setting combines a couple of options into a single entity that
88 * may be selected. Only one setting can be active at the same
89 * time. */
90 struct pa_alsa_setting {
91 pa_alsa_path *path;
92 PA_LLIST_FIELDS(pa_alsa_setting);
93
94 pa_idxset *options;
95
96 char *name;
97 char *description;
98 unsigned priority;
99 };
100
101 /* An option belongs to an element and refers to one enumeration item
102 * of the element is an enumeration item, or a switch status if the
103 * element is a switch item. */
104 struct pa_alsa_option {
105 pa_alsa_element *element;
106 PA_LLIST_FIELDS(pa_alsa_option);
107
108 char *alsa_name;
109 int alsa_idx;
110
111 char *name;
112 char *description;
113 unsigned priority;
114
115 pa_alsa_required_t required;
116 pa_alsa_required_t required_any;
117 pa_alsa_required_t required_absent;
118 };
119
120 /* An element wraps one specific ALSA element. A series of elements
121 * make up a path (see below). If the element is an enumeration or switch
122 * element it may include a list of options. */
123 struct pa_alsa_element {
124 pa_alsa_path *path;
125 PA_LLIST_FIELDS(pa_alsa_element);
126
127 char *alsa_name;
128 pa_alsa_direction_t direction;
129
130 pa_alsa_switch_use_t switch_use;
131 pa_alsa_volume_use_t volume_use;
132 pa_alsa_enumeration_use_t enumeration_use;
133
134 pa_alsa_required_t required;
135 pa_alsa_required_t required_any;
136 pa_alsa_required_t required_absent;
137
138 long constant_volume;
139
140 pa_bool_t override_map:1;
141 pa_bool_t direction_try_other:1;
142
143 pa_bool_t has_dB:1;
144 long min_volume, max_volume;
145 long volume_limit; /* -1 for no configured limit */
146 double min_dB, max_dB;
147
148 pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][2];
149 unsigned n_channels;
150
151 pa_channel_position_mask_t merged_mask;
152
153 PA_LLIST_HEAD(pa_alsa_option, options);
154
155 pa_alsa_decibel_fix *db_fix;
156 };
157
158 struct pa_alsa_jack {
159 pa_alsa_path *path;
160 PA_LLIST_FIELDS(pa_alsa_jack);
161
162 char *name; /* E g "Headphone" */
163 char *alsa_name; /* E g "Headphone Jack" */
164 pa_bool_t has_control; /* is the jack itself present? */
165 pa_bool_t plugged_in; /* is this jack currently plugged in? */
166 snd_hctl_elem_t *hctl_elem; /* Jack detection handle */
167 pa_port_available_t state_unplugged, state_plugged;
168
169 pa_alsa_required_t required;
170 pa_alsa_required_t required_any;
171 pa_alsa_required_t required_absent;
172 };
173
174 /* A path wraps a series of elements into a single entity which can be
175 * used to control it as if it had a single volume slider, a single
176 * mute switch and a single list of selectable options. */
177 struct pa_alsa_path {
178 pa_alsa_direction_t direction;
179 pa_device_port* port;
180
181 char *name;
182 char *description;
183 unsigned priority;
184 pa_proplist *proplist;
185
186 pa_bool_t probed:1;
187 pa_bool_t supported:1;
188 pa_bool_t has_mute:1;
189 pa_bool_t has_volume:1;
190 pa_bool_t has_dB:1;
191 /* These two are used during probing only */
192 pa_bool_t has_req_any:1;
193 pa_bool_t req_any_present:1;
194
195 long min_volume, max_volume;
196 double min_dB, max_dB;
197
198 /* This is used during parsing only, as a shortcut so that we
199 * don't have to iterate the list all the time */
200 pa_alsa_element *last_element;
201 pa_alsa_option *last_option;
202 pa_alsa_setting *last_setting;
203 pa_alsa_jack *last_jack;
204
205 PA_LLIST_HEAD(pa_alsa_element, elements);
206 PA_LLIST_HEAD(pa_alsa_setting, settings);
207 PA_LLIST_HEAD(pa_alsa_jack, jacks);
208 };
209
210 /* A path set is simply a set of paths that are applicable to a
211 * device */
212 struct pa_alsa_path_set {
213 pa_hashmap *paths;
214 pa_alsa_direction_t direction;
215 };
216
217 int pa_alsa_setting_select(pa_alsa_setting *s, snd_mixer_t *m);
218 void pa_alsa_setting_dump(pa_alsa_setting *s);
219
220 void pa_alsa_option_dump(pa_alsa_option *o);
221 void pa_alsa_jack_dump(pa_alsa_jack *j);
222 void pa_alsa_element_dump(pa_alsa_element *e);
223
224 pa_alsa_path *pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction);
225 pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction);
226 int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, snd_hctl_t *hctl, pa_bool_t ignore_dB);
227 void pa_alsa_path_dump(pa_alsa_path *p);
228 int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
229 int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t *muted);
230 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);
231 int pa_alsa_path_set_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t muted);
232 int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m);
233 void pa_alsa_path_set_callback(pa_alsa_path *p, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
234 void pa_alsa_path_free(pa_alsa_path *p);
235
236 pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t direction, const char *paths_dir);
237 void pa_alsa_path_set_dump(pa_alsa_path_set *s);
238 void pa_alsa_path_set_set_callback(pa_alsa_path_set *ps, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
239 void pa_alsa_path_set_free(pa_alsa_path_set *s);
240
241 struct pa_alsa_mapping {
242 pa_alsa_profile_set *profile_set;
243
244 char *name;
245 char *description;
246 unsigned priority;
247 pa_alsa_direction_t direction;
248
249 pa_channel_map channel_map;
250
251 char **device_strings;
252
253 char **input_path_names;
254 char **output_path_names;
255 char **input_element; /* list of fallbacks */
256 char **output_element;
257 pa_alsa_path_set *input_path_set;
258 pa_alsa_path_set *output_path_set;
259
260 unsigned supported;
261
262 /* Temporarily used during probing */
263 snd_pcm_t *input_pcm;
264 snd_pcm_t *output_pcm;
265
266 pa_sink *sink;
267 pa_source *source;
268 };
269
270 struct pa_alsa_profile {
271 pa_alsa_profile_set *profile_set;
272
273 char *name;
274 char *description;
275 unsigned priority;
276
277 pa_bool_t supported:1;
278
279 char **input_mapping_names;
280 char **output_mapping_names;
281
282 pa_idxset *input_mappings;
283 pa_idxset *output_mappings;
284 };
285
286 struct pa_alsa_decibel_fix {
287 pa_alsa_profile_set *profile_set;
288
289 char *name; /* Alsa volume element name. */
290 long min_step;
291 long max_step;
292
293 /* An array that maps alsa volume element steps to decibels. The steps can
294 * be used as indices to this array, after subtracting min_step from the
295 * real value.
296 *
297 * The values are actually stored as integers representing millibels,
298 * because that's the format the alsa API uses. */
299 long *db_values;
300 };
301
302 struct pa_alsa_profile_set {
303 pa_hashmap *mappings;
304 pa_hashmap *profiles;
305 pa_hashmap *decibel_fixes;
306 pa_hashmap *input_paths;
307 pa_hashmap *output_paths;
308
309 pa_bool_t auto_profiles;
310 pa_bool_t ignore_dB:1;
311 pa_bool_t probed:1;
312 };
313
314 void pa_alsa_mapping_dump(pa_alsa_mapping *m);
315 void pa_alsa_profile_dump(pa_alsa_profile *p);
316 void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix);
317
318 pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
319 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);
320 void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
321 void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
322
323 snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl);
324
325 pa_alsa_fdlist *pa_alsa_fdlist_new(void);
326 void pa_alsa_fdlist_free(pa_alsa_fdlist *fdl);
327 int pa_alsa_fdlist_set_handle(pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, snd_hctl_t *hctl_handle, pa_mainloop_api* m);
328
329 /* Alternative for handling alsa mixer events in io-thread. */
330
331 pa_alsa_mixer_pdata *pa_alsa_mixer_pdata_new(void);
332 void pa_alsa_mixer_pdata_free(pa_alsa_mixer_pdata *pd);
333 int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata *pd, snd_mixer_t *mixer, pa_rtpoll *rtp);
334
335 /* Data structure for inclusion in pa_device_port for alsa
336 * sinks/sources. This contains nothing that needs to be freed
337 * individually */
338 struct pa_alsa_port_data {
339 pa_alsa_path *path;
340 pa_alsa_setting *setting;
341 };
342
343 void pa_alsa_add_ports(void *sink_or_source_new_data, pa_alsa_path_set *ps, pa_card *card);
344 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);
345
346 #endif