1 #ifndef fooalsaucmhfoo
2 #define fooalsaucmhfoo
3 
4 /***
5   This file is part of PulseAudio.
6 
7   Copyright 2011 Wolfson Microelectronics PLC
8   Author Margarita Olaya <magi@slimlogic.co.uk>
9   Copyright 2012 Feng Wei <wei.feng@freescale.com>, Freescale Ltd.
10 
11   PulseAudio is free software; you can redistribute it and/or modify
12   it under the terms of the GNU Lesser General Public License as published
13   by the Free Software Foundation; either version 2.1 of the License,
14   or (at your option) any later version.
15 
16   PulseAudio is distributed in the hope that it will be useful, but
17   WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19   General Public License for more details.
20 
21   You should have received a copy of the GNU Lesser General Public License
22   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
23 ***/
24 
25 #ifdef HAVE_ALSA_UCM
26 #include <alsa/use-case.h>
27 #else
28 typedef void snd_use_case_mgr_t;
29 #endif
30 
31 #include "compat.h"
32 
33 #include "alsa-mixer.h"
34 
35 /** For devices: List of verbs, devices or modifiers available */
36 #define PA_ALSA_PROP_UCM_NAME                       "alsa.ucm.name"
37 
38 /** For devices: List of supported devices per verb*/
39 #define PA_ALSA_PROP_UCM_DESCRIPTION                "alsa.ucm.description"
40 
41 /** For devices: Playback device name e.g PlaybackPCM */
42 #define PA_ALSA_PROP_UCM_SINK                       "alsa.ucm.sink"
43 
44 /** For devices: Capture device name e.g CapturePCM*/
45 #define PA_ALSA_PROP_UCM_SOURCE                     "alsa.ucm.source"
46 
47 /** For devices: Playback roles */
48 #define PA_ALSA_PROP_UCM_PLAYBACK_ROLES             "alsa.ucm.playback.roles"
49 
50 /** For devices: Playback control device name  */
51 #define PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE        "alsa.ucm.playback.ctldev"
52 
53 /** For devices: Playback control volume ID string. e.g PlaybackVolume */
54 #define PA_ALSA_PROP_UCM_PLAYBACK_VOLUME            "alsa.ucm.playback.volume"
55 
56 /** For devices: Playback switch e.g PlaybackSwitch */
57 #define PA_ALSA_PROP_UCM_PLAYBACK_SWITCH            "alsa.ucm.playback.switch"
58 
59 /** For devices: Playback mixer device name  */
60 #define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE      "alsa.ucm.playback.mixer.device"
61 
62 /** For devices: Playback mixer identifier */
63 #define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM        "alsa.ucm.playback.mixer.element"
64 
65 /** For devices: Playback mixer master identifier */
66 #define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM       "alsa.ucm.playback.master.element"
67 
68 /** For devices: Playback mixer master type */
69 #define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE       "alsa.ucm.playback.master.type"
70 
71 /** For devices: Playback mixer master identifier */
72 #define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ID         "alsa.ucm.playback.master.id"
73 
74 /** For devices: Playback mixer master type */
75 #define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE       "alsa.ucm.playback.master.type"
76 
77 /** For devices: Playback priority */
78 #define PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY          "alsa.ucm.playback.priority"
79 
80 /** For devices: Playback rate */
81 #define PA_ALSA_PROP_UCM_PLAYBACK_RATE              "alsa.ucm.playback.rate"
82 
83 /** For devices: Playback channels */
84 #define PA_ALSA_PROP_UCM_PLAYBACK_CHANNELS          "alsa.ucm.playback.channels"
85 
86 /** For devices: Capture roles */
87 #define PA_ALSA_PROP_UCM_CAPTURE_ROLES              "alsa.ucm.capture.roles"
88 
89 /** For devices: Capture control device name  */
90 #define PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE         "alsa.ucm.capture.ctldev"
91 
92 /** For devices: Capture controls volume ID string. e.g CaptureVolume */
93 #define PA_ALSA_PROP_UCM_CAPTURE_VOLUME             "alsa.ucm.capture.volume"
94 
95 /** For devices: Capture switch e.g CaptureSwitch */
96 #define PA_ALSA_PROP_UCM_CAPTURE_SWITCH             "alsa.ucm.capture.switch"
97 
98 /** For devices: Capture mixer device name  */
99 #define PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE       "alsa.ucm.capture.mixer.device"
100 
101 /** For devices: Capture mixer identifier */
102 #define PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM         "alsa.ucm.capture.mixer.element"
103 
104 /** For devices: Capture mixer identifier */
105 #define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM        "alsa.ucm.capture.master.element"
106 
107 /** For devices: Capture mixer identifier */
108 #define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE        "alsa.ucm.capture.master.type"
109 
110 /** For devices: Capture mixer identifier */
111 #define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ID          "alsa.ucm.capture.master.id"
112 
113 /** For devices: Capture mixer identifier */
114 #define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE        "alsa.ucm.capture.master.type"
115 
116 /** For devices: Capture priority */
117 #define PA_ALSA_PROP_UCM_CAPTURE_PRIORITY           "alsa.ucm.capture.priority"
118 
119 /** For devices: Capture rate */
120 #define PA_ALSA_PROP_UCM_CAPTURE_RATE               "alsa.ucm.capture.rate"
121 
122 /** For devices: Capture channels */
123 #define PA_ALSA_PROP_UCM_CAPTURE_CHANNELS           "alsa.ucm.capture.channels"
124 
125 /** For devices: Quality of Service */
126 #define PA_ALSA_PROP_UCM_QOS                        "alsa.ucm.qos"
127 
128 /** For devices: The modifier (if any) that this device corresponds to */
129 #define PA_ALSA_PROP_UCM_MODIFIER "alsa.ucm.modifier"
130 
131 /* Corresponds to the "JackCTL" UCM value. */
132 #define PA_ALSA_PROP_UCM_JACK_DEVICE		    "alsa.ucm.jack_device"
133 
134 /* Corresponds to the "JackControl" UCM value. */
135 #define PA_ALSA_PROP_UCM_JACK_CONTROL               "alsa.ucm.jack_control"
136 
137 /* Corresponds to the "JackHWMute" UCM value. */
138 #define PA_ALSA_PROP_UCM_JACK_HW_MUTE               "alsa.ucm.jack_hw_mute"
139 
140 typedef struct pa_alsa_ucm_verb pa_alsa_ucm_verb;
141 typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier;
142 typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
143 typedef struct pa_alsa_ucm_config pa_alsa_ucm_config;
144 typedef struct pa_alsa_ucm_mapping_context pa_alsa_ucm_mapping_context;
145 typedef struct pa_alsa_ucm_port_data pa_alsa_ucm_port_data;
146 typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume;
147 
148 int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index);
149 pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_channel_map *default_channel_map);
150 int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile);
151 
152 int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, const char *verb_desc, pa_alsa_ucm_verb **p_verb);
153 
154 void pa_alsa_ucm_add_ports(
155         pa_hashmap **hash,
156         pa_proplist *proplist,
157         pa_alsa_ucm_mapping_context *context,
158         bool is_sink,
159         pa_card *card,
160         snd_pcm_t *pcm_handle,
161         bool ignore_dB);
162 void pa_alsa_ucm_add_ports_combination(
163         pa_hashmap *hash,
164         pa_alsa_ucm_mapping_context *context,
165         bool is_sink,
166         pa_hashmap *ports,
167         pa_card_profile *cp,
168         pa_core *core);
169 int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *port, bool is_sink);
170 
171 void pa_alsa_ucm_free(pa_alsa_ucm_config *ucm);
172 void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context);
173 
174 void pa_alsa_ucm_roled_stream_begin(pa_alsa_ucm_config *ucm, const char *role, pa_direction_t dir);
175 void pa_alsa_ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, pa_direction_t dir);
176 
177 /* UCM - Use Case Manager is available on some audio cards */
178 
179 struct pa_alsa_ucm_device {
180     PA_LLIST_FIELDS(pa_alsa_ucm_device);
181 
182     pa_proplist *proplist;
183 
184     pa_device_port_type_t type;
185 
186     unsigned playback_priority;
187     unsigned capture_priority;
188 
189     unsigned playback_rate;
190     unsigned capture_rate;
191 
192     unsigned playback_channels;
193     unsigned capture_channels;
194 
195     /* These may be different per verb, so we store this as a hashmap of verb -> volume_control. We might eventually want to
196      * make this a hashmap of verb -> per-verb-device-properties-struct. */
197     pa_hashmap *playback_volumes;
198     pa_hashmap *capture_volumes;
199 
200     pa_alsa_mapping *playback_mapping;
201     pa_alsa_mapping *capture_mapping;
202 
203     pa_idxset *conflicting_devices;
204     pa_idxset *supported_devices;
205 
206     /* One device may be part of multiple ports, since each device has
207      * a dedicated port, and in addition to that we sometimes generate ports
208      * that represent combinations of devices. */
209     pa_dynarray *ucm_ports; /* struct ucm_port */
210 
211     pa_alsa_jack *jack;
212     pa_dynarray *hw_mute_jacks; /* pa_alsa_jack */
213     pa_available_t available;
214 
215     char *eld_mixer_device_name;
216     int eld_device;
217 };
218 
219 void pa_alsa_ucm_device_update_available(pa_alsa_ucm_device *device);
220 
221 struct pa_alsa_ucm_modifier {
222     PA_LLIST_FIELDS(pa_alsa_ucm_modifier);
223 
224     pa_proplist *proplist;
225 
226     int n_confdev;
227     int n_suppdev;
228 
229     const char **conflicting_devices;
230     const char **supported_devices;
231 
232     pa_direction_t action_direction;
233 
234     char *media_role;
235 
236     /* Non-NULL if the modifier has its own PlaybackPCM/CapturePCM */
237     pa_alsa_mapping *playback_mapping;
238     pa_alsa_mapping *capture_mapping;
239 
240     /* Count how many role matched streams are running */
241     int enabled_counter;
242 };
243 
244 struct pa_alsa_ucm_verb {
245     PA_LLIST_FIELDS(pa_alsa_ucm_verb);
246 
247     pa_proplist *proplist;
248     unsigned priority;
249 
250     PA_LLIST_HEAD(pa_alsa_ucm_device, devices);
251     PA_LLIST_HEAD(pa_alsa_ucm_modifier, modifiers);
252 };
253 
254 struct pa_alsa_ucm_config {
255     pa_sample_spec default_sample_spec;
256     pa_channel_map default_channel_map;
257     unsigned default_fragment_size_msec;
258     unsigned default_n_fragments;
259 
260     snd_use_case_mgr_t *ucm_mgr;
261     pa_alsa_ucm_verb *active_verb;
262     char *alib_prefix;
263 
264     pa_hashmap *mixers;
265     PA_LLIST_HEAD(pa_alsa_ucm_verb, verbs);
266     PA_LLIST_HEAD(pa_alsa_jack, jacks);
267 };
268 
269 struct pa_alsa_ucm_mapping_context {
270     pa_alsa_ucm_config *ucm;
271     pa_direction_t direction;
272 
273     pa_idxset *ucm_devices;
274     pa_idxset *ucm_modifiers;
275 };
276 
277 struct pa_alsa_ucm_port_data {
278     pa_alsa_ucm_config *ucm;
279     pa_device_port *core_port;
280 
281     /* A single port will be associated with multiple devices if it represents
282      * a combination of devices. */
283     pa_dynarray *devices; /* pa_alsa_ucm_device */
284 
285     /* profile name -> pa_alsa_path for volume control */
286     pa_hashmap *paths;
287     /* Current path, set when activating profile */
288     pa_alsa_path *path;
289 
290     /* ELD info */
291     char *eld_mixer_device_name;
292     int eld_device; /* PCM device number */
293 };
294 
295 struct pa_alsa_ucm_volume {
296     char *mixer_elem;	/* mixer element identifier */
297     char *master_elem;	/* master mixer element identifier */
298     char *master_type;
299 };
300 
301 #endif
302