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