1 #ifndef fooalsamixerhfoo
2 #define fooalsamixerhfoo
5 This file is part of PulseAudio.
7 Copyright 2004-2006 Lennart Poettering
8 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
26 #include <asoundlib.h>
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>
35 #include <pulsecore/llist.h>
36 #include <pulsecore/rtpoll.h>
37 #include <pulsecore/core.h>
38 #include <pulsecore/log.h>
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
;
53 #include "alsa-util.h"
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
;
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
;
70 typedef enum pa_alsa_enumeration_use
{
71 PA_ALSA_ENUMERATION_IGNORE
,
72 PA_ALSA_ENUMERATION_SELECT
73 } pa_alsa_enumeration_use_t
;
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
,
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
;
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
92 struct pa_alsa_setting
{
94 PA_LLIST_FIELDS(pa_alsa_setting
);
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
);
117 pa_alsa_required_t required
;
118 pa_alsa_required_t required_any
;
119 pa_alsa_required_t required_absent
;
122 /* And 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 includes a list of options. */
125 struct pa_alsa_element
{
127 PA_LLIST_FIELDS(pa_alsa_element
);
130 pa_alsa_direction_t direction
;
132 pa_alsa_switch_use_t switch_use
;
133 pa_alsa_volume_use_t volume_use
;
134 pa_alsa_enumeration_use_t enumeration_use
;
136 pa_alsa_required_t required
;
137 pa_alsa_required_t required_any
;
138 pa_alsa_required_t required_absent
;
140 pa_bool_t override_map
:1;
141 pa_bool_t direction_try_other
:1;
144 long min_volume
, max_volume
;
145 double min_dB
, max_dB
;
147 pa_channel_position_mask_t masks
[SND_MIXER_SCHN_LAST
][2];
150 pa_channel_position_mask_t merged_mask
;
152 PA_LLIST_HEAD(pa_alsa_option
, options
);
155 /* A path wraps a series of elements into a single entity which can be
156 * used to control it as if it had a single volume slider, a single
157 * mute switch and a single list of selectable options. */
158 struct pa_alsa_path
{
159 pa_alsa_path_set
*path_set
;
160 PA_LLIST_FIELDS(pa_alsa_path
);
162 pa_alsa_direction_t direction
;
169 pa_bool_t supported
:1;
170 pa_bool_t has_mute
:1;
171 pa_bool_t has_volume
:1;
173 /* These two are used during probing only */
174 pa_bool_t has_req_any
:1;
175 pa_bool_t req_any_present
:1;
177 long min_volume
, max_volume
;
178 double min_dB
, max_dB
;
180 /* This is used during parsing only, as a shortcut so that we
181 * don't have to iterate the list all the time */
182 pa_alsa_element
*last_element
;
183 pa_alsa_option
*last_option
;
184 pa_alsa_setting
*last_setting
;
186 PA_LLIST_HEAD(pa_alsa_element
, elements
);
187 PA_LLIST_HEAD(pa_alsa_setting
, settings
);
190 /* A path set is simply a set of paths that are applicable to a
192 struct pa_alsa_path_set
{
193 PA_LLIST_HEAD(pa_alsa_path
, paths
);
194 pa_alsa_direction_t direction
;
197 /* This is used during parsing only, as a shortcut so that we
198 * don't have to iterate the list all the time */
199 pa_alsa_path
*last_path
;
202 int pa_alsa_setting_select(pa_alsa_setting
*s
, snd_mixer_t
*m
);
203 void pa_alsa_setting_dump(pa_alsa_setting
*s
);
205 void pa_alsa_option_dump(pa_alsa_option
*o
);
207 void pa_alsa_element_dump(pa_alsa_element
*e
);
209 pa_alsa_path
*pa_alsa_path_new(const char *fname
, pa_alsa_direction_t direction
);
210 pa_alsa_path
*pa_alsa_path_synthesize(const char *element
, pa_alsa_direction_t direction
);
211 int pa_alsa_path_probe(pa_alsa_path
*p
, snd_mixer_t
*m
, pa_bool_t ignore_dB
);
212 void pa_alsa_path_dump(pa_alsa_path
*p
);
213 int pa_alsa_path_get_volume(pa_alsa_path
*p
, snd_mixer_t
*m
, const pa_channel_map
*cm
, pa_cvolume
*v
);
214 int pa_alsa_path_get_mute(pa_alsa_path
*path
, snd_mixer_t
*m
, pa_bool_t
*muted
);
215 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
);
216 int pa_alsa_path_set_mute(pa_alsa_path
*path
, snd_mixer_t
*m
, pa_bool_t muted
);
217 int pa_alsa_path_select(pa_alsa_path
*p
, snd_mixer_t
*m
);
218 void pa_alsa_path_set_callback(pa_alsa_path
*p
, snd_mixer_t
*m
, snd_mixer_elem_callback_t cb
, void *userdata
);
219 void pa_alsa_path_free(pa_alsa_path
*p
);
221 pa_alsa_path_set
*pa_alsa_path_set_new(pa_alsa_mapping
*m
, pa_alsa_direction_t direction
);
222 void pa_alsa_path_set_probe(pa_alsa_path_set
*s
, snd_mixer_t
*m
, pa_bool_t ignore_dB
);
223 void pa_alsa_path_set_dump(pa_alsa_path_set
*s
);
224 void pa_alsa_path_set_set_callback(pa_alsa_path_set
*ps
, snd_mixer_t
*m
, snd_mixer_elem_callback_t cb
, void *userdata
);
225 void pa_alsa_path_set_free(pa_alsa_path_set
*s
);
227 struct pa_alsa_mapping
{
228 pa_alsa_profile_set
*profile_set
;
233 pa_alsa_direction_t direction
;
235 pa_channel_map channel_map
;
237 char **device_strings
;
239 char **input_path_names
;
240 char **output_path_names
;
241 char **input_element
; /* list of fallbacks */
242 char **output_element
;
246 /* Temporarily used during probing */
247 snd_pcm_t
*input_pcm
;
248 snd_pcm_t
*output_pcm
;
254 struct pa_alsa_profile
{
255 pa_alsa_profile_set
*profile_set
;
261 pa_bool_t supported
:1;
263 char **input_mapping_names
;
264 char **output_mapping_names
;
266 pa_idxset
*input_mappings
;
267 pa_idxset
*output_mappings
;
270 struct pa_alsa_decibel_fix
{
271 pa_alsa_profile_set
*profile_set
;
273 char *name
; /* Alsa volume element name. */
277 /* An array that maps alsa volume element steps to decibels. The steps can
278 * be used as indices to this array, after substracting min_step from the
281 * The values are actually stored as integers representing millibels,
282 * because that's the format the alsa API uses. */
286 struct pa_alsa_profile_set
{
287 pa_hashmap
*mappings
;
288 pa_hashmap
*profiles
;
289 pa_hashmap
*decibel_fixes
;
291 pa_bool_t auto_profiles
;
295 void pa_alsa_mapping_dump(pa_alsa_mapping
*m
);
296 void pa_alsa_profile_dump(pa_alsa_profile
*p
);
297 void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix
*db_fix
);
299 pa_alsa_profile_set
* pa_alsa_profile_set_new(const char *fname
, const pa_channel_map
*bonus
);
300 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
);
301 void pa_alsa_profile_set_free(pa_alsa_profile_set
*s
);
302 void pa_alsa_profile_set_dump(pa_alsa_profile_set
*s
);
304 snd_mixer_t
*pa_alsa_open_mixer_for_pcm(snd_pcm_t
*pcm
, char **ctl_device
);
306 pa_alsa_fdlist
*pa_alsa_fdlist_new(void);
307 void pa_alsa_fdlist_free(pa_alsa_fdlist
*fdl
);
308 int pa_alsa_fdlist_set_mixer(pa_alsa_fdlist
*fdl
, snd_mixer_t
*mixer_handle
, pa_mainloop_api
* m
);
310 /* Alternative for handling alsa mixer events in io-thread. */
312 pa_alsa_mixer_pdata
*pa_alsa_mixer_pdata_new(void);
313 void pa_alsa_mixer_pdata_free(pa_alsa_mixer_pdata
*pd
);
314 int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata
*pd
, snd_mixer_t
*mixer
, pa_rtpoll
*rtp
);
316 /* Data structure for inclusion in pa_device_port for alsa
317 * sinks/sources. This contains nothing that needs to be freed
319 struct pa_alsa_port_data
{
321 pa_alsa_setting
*setting
;
324 void pa_alsa_add_ports(pa_hashmap
**p
, pa_alsa_path_set
*ps
);