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