1 /* ALSA Card Profile 2 * 3 * Copyright © 2020 Wim Taymans 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 25 #ifndef ACP_H 26 #define ACP_H 27 28 #ifdef __cplusplus 29 extern "C" { 30 #else 31 #include <stdbool.h> 32 #endif 33 34 #include <stdio.h> 35 #include <stdarg.h> 36 #include <stdint.h> 37 #include <poll.h> 38 39 #ifdef __GNUC__ 40 #define ACP_PRINTF_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1))) 41 #else 42 #define ACP_PRINTF_FUNC(fmt, arg1) 43 #endif 44 45 #define ACP_INVALID_INDEX ((uint32_t)-1) 46 #define ACP_MAX_CHANNELS 64 47 48 struct acp_dict_item { 49 const char *key; 50 const char *value; 51 }; 52 #define ACP_DICT_ITEM_INIT(key,value) (struct acp_dict_item) { key, value } 53 54 struct acp_dict { 55 uint32_t flags; 56 uint32_t n_items; 57 const struct acp_dict_item *items; 58 }; 59 60 enum acp_channel { 61 ACP_CHANNEL_UNKNOWN, /**< unspecified */ 62 ACP_CHANNEL_NA, /**< N/A, silent */ 63 64 ACP_CHANNEL_MONO, /**< mono stream */ 65 66 ACP_CHANNEL_FL, /**< front left */ 67 ACP_CHANNEL_FR, /**< front right */ 68 ACP_CHANNEL_FC, /**< front center */ 69 ACP_CHANNEL_LFE, /**< LFE */ 70 ACP_CHANNEL_SL, /**< side left */ 71 ACP_CHANNEL_SR, /**< side right */ 72 ACP_CHANNEL_FLC, /**< front left center */ 73 ACP_CHANNEL_FRC, /**< front right center */ 74 ACP_CHANNEL_RC, /**< rear center */ 75 ACP_CHANNEL_RL, /**< rear left */ 76 ACP_CHANNEL_RR, /**< rear right */ 77 ACP_CHANNEL_TC, /**< top center */ 78 ACP_CHANNEL_TFL, /**< top front left */ 79 ACP_CHANNEL_TFC, /**< top front center */ 80 ACP_CHANNEL_TFR, /**< top front right */ 81 ACP_CHANNEL_TRL, /**< top rear left */ 82 ACP_CHANNEL_TRC, /**< top rear center */ 83 ACP_CHANNEL_TRR, /**< top rear right */ 84 ACP_CHANNEL_RLC, /**< rear left center */ 85 ACP_CHANNEL_RRC, /**< rear right center */ 86 ACP_CHANNEL_FLW, /**< front left wide */ 87 ACP_CHANNEL_FRW, /**< front right wide */ 88 ACP_CHANNEL_LFE2, /**< LFE 2 */ 89 ACP_CHANNEL_FLH, /**< front left high */ 90 ACP_CHANNEL_FCH, /**< front center high */ 91 ACP_CHANNEL_FRH, /**< front right high */ 92 ACP_CHANNEL_TFLC, /**< top front left center */ 93 ACP_CHANNEL_TFRC, /**< top front right center */ 94 ACP_CHANNEL_TSL, /**< top side left */ 95 ACP_CHANNEL_TSR, /**< top side right */ 96 ACP_CHANNEL_LLFE, /**< left LFE */ 97 ACP_CHANNEL_RLFE, /**< right LFE */ 98 ACP_CHANNEL_BC, /**< bottom center */ 99 ACP_CHANNEL_BLC, /**< bottom left center */ 100 ACP_CHANNEL_BRC, /**< bottom right center */ 101 102 ACP_CHANNEL_START_Aux = 0x1000, 103 ACP_CHANNEL_LAST_Aux = 0x1fff, 104 105 ACP_CHANNEL_START_Custom = 0x10000, 106 }; 107 108 char *acp_channel_str(char *buf, size_t len, enum acp_channel ch); 109 110 struct acp_format { 111 uint32_t flags; 112 uint32_t format_mask; 113 uint32_t rate_mask; 114 uint32_t channels; 115 uint32_t map[ACP_MAX_CHANNELS]; 116 }; 117 118 #define ACP_DICT_INIT(items,n_items) (struct acp_dict) { 0, n_items, items } 119 #define ACP_DICT_INIT_ARRAY(items) (struct acp_dict) { 0, sizeof(items)/sizeof((items)[0]), items } 120 121 #define acp_dict_for_each(item, dict) \ 122 for ((item) = (dict)->items; \ 123 (item) < &(dict)->items[(dict)->n_items]; \ 124 (item)++) 125 126 enum acp_direction { 127 ACP_DIRECTION_PLAYBACK = 1, 128 ACP_DIRECTION_CAPTURE = 2 129 }; 130 131 const char *acp_direction_str(enum acp_direction direction); 132 133 enum acp_available { 134 ACP_AVAILABLE_UNKNOWN = 0, 135 ACP_AVAILABLE_NO = 1, 136 ACP_AVAILABLE_YES = 2 137 }; 138 139 const char *acp_available_str(enum acp_available status); 140 141 #define ACP_KEY_PORT_TYPE "port.type" /**< a Port type, like "aux", "speaker", ... */ 142 #define ACP_KEY_PORT_AVAILABILITY_GROUP "port.availability-group" 143 /**< An identifier for the group of ports that share their availability status with 144 * each other. This is meant especially for handling cases where one 3.5 mm connector 145 * is used for headphones, headsets and microphones, and the hardware can only tell 146 * that something was plugged in but not what exactly. In this situation the ports for 147 * all those devices share their availability status, and ACP can't tell which 148 * one is actually plugged in, and some application may ask the user what was plugged 149 * in. Such applications should get a list of all card ports and compare their 150 * `available_group` fields. Ports that have the same group are those that need 151 * input from the user to determine which device was plugged in. The application should 152 * then activate the user-chosen port. 153 * 154 * May be NULL, in which case the port is not part of any availability group (which is 155 * the same as having a group with only one member). 156 * 157 * The group identifier must be treated as an opaque identifier. The string may look 158 * like an ALSA control name, but applications must not assume any such relationship. 159 * The group naming scheme can change without a warning. 160 */ 161 162 struct acp_device; 163 164 struct acp_card_events { 165 #define ACP_VERSION_CARD_EVENTS 0 166 uint32_t version; 167 168 void (*destroy) (void *data); 169 170 void (*props_changed) (void *data); 171 172 void (*profile_changed) (void *data, uint32_t old_index, uint32_t new_index); 173 174 void (*profile_available) (void *data, uint32_t index, 175 enum acp_available old, enum acp_available available); 176 177 void (*port_changed) (void *data, uint32_t old_index, uint32_t new_index); 178 179 void (*port_available) (void *data, uint32_t index, 180 enum acp_available old, enum acp_available available); 181 182 void (*volume_changed) (void *data, struct acp_device *dev); 183 void (*mute_changed) (void *data, struct acp_device *dev); 184 }; 185 186 struct acp_port { 187 uint32_t index; /**< unique index for this port */ 188 #define ACP_PORT_ACTIVE (1<<0) 189 #define ACP_PORT_SAVE (1<<1) /* if the port needs saving */ 190 uint32_t flags; /**< extra port flags */ 191 192 const char *name; /**< Name of this port */ 193 const char *description; /**< Description of this port */ 194 uint32_t priority; /**< The higher this value is, the more useful this port is as a default. */ 195 enum acp_direction direction; 196 enum acp_available available; /**< A flags (see #acp_port_available), indicating availability status of this port. */ 197 struct acp_dict props; /**< extra port properties */ 198 199 uint32_t n_profiles; /**< number of elements in profiles array */ 200 struct acp_card_profile **profiles; /**< array of profiles for this port */ 201 202 uint32_t n_devices; /**< number of elements in devices array */ 203 struct acp_device **devices; /**< array of devices */ 204 }; 205 206 struct acp_device { 207 uint32_t index; 208 #define ACP_DEVICE_ACTIVE (1<<0) 209 #define ACP_DEVICE_HW_VOLUME (1<<1) 210 #define ACP_DEVICE_HW_MUTE (1<<2) 211 #define ACP_DEVICE_UCM_DEVICE (1<<3) 212 #define ACP_DEVICE_IEC958 (1<<4) 213 uint32_t flags; 214 215 const char *name; 216 const char *description; 217 uint32_t priority; 218 enum acp_direction direction; 219 struct acp_dict props; 220 221 const char **device_strings; 222 struct acp_format format; 223 224 float base_volume; 225 float volume_step; 226 227 uint32_t n_ports; 228 struct acp_port **ports; 229 230 int64_t latency_ns; 231 uint32_t codecs[32]; 232 uint32_t n_codecs; 233 }; 234 235 struct acp_card_profile { 236 uint32_t index; 237 #define ACP_PROFILE_ACTIVE (1<<0) 238 #define ACP_PROFILE_OFF (1<<1) /* the Off profile */ 239 #define ACP_PROFILE_SAVE (1<<2) /* if the profile needs saving */ 240 uint32_t flags; 241 242 const char *name; 243 const char *description; 244 uint32_t priority; 245 enum acp_available available; 246 struct acp_dict props; 247 248 uint32_t n_devices; 249 struct acp_device **devices; 250 }; 251 252 struct acp_card { 253 uint32_t index; 254 uint32_t flags; 255 256 struct acp_dict props; 257 258 uint32_t n_profiles; 259 uint32_t active_profile_index; 260 struct acp_card_profile **profiles; 261 262 uint32_t n_devices; 263 struct acp_device **devices; 264 265 uint32_t n_ports; 266 struct acp_port **ports; 267 uint32_t preferred_input_port_index; 268 uint32_t preferred_output_port_index; 269 }; 270 271 struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props); 272 273 void acp_card_add_listener(struct acp_card *card, 274 const struct acp_card_events *events, void *user_data); 275 276 void acp_card_destroy(struct acp_card *card); 277 278 int acp_card_poll_descriptors_count(struct acp_card *card); 279 int acp_card_poll_descriptors(struct acp_card *card, struct pollfd *pfds, unsigned int space); 280 int acp_card_poll_descriptors_revents(struct acp_card *card, struct pollfd *pfds, 281 unsigned int nfds, unsigned short *revents); 282 int acp_card_handle_events(struct acp_card *card); 283 284 uint32_t acp_card_find_best_profile_index(struct acp_card *card, const char *name); 285 int acp_card_set_profile(struct acp_card *card, uint32_t profile_index, uint32_t flags); 286 287 uint32_t acp_device_find_best_port_index(struct acp_device *dev, const char *name); 288 int acp_device_set_port(struct acp_device *dev, uint32_t port_index, uint32_t flags); 289 290 int acp_device_set_volume(struct acp_device *dev, const float *volume, uint32_t n_volume); 291 int acp_device_get_soft_volume(struct acp_device *dev, float *volume, uint32_t n_volume); 292 int acp_device_get_volume(struct acp_device *dev, float *volume, uint32_t n_volume); 293 int acp_device_set_mute(struct acp_device *dev, bool mute); 294 int acp_device_get_mute(struct acp_device *dev, bool *mute); 295 296 typedef void (*acp_log_func) (void *data, 297 int level, const char *file, int line, const char *func, 298 const char *fmt, va_list arg) ACP_PRINTF_FUNC(6,0); 299 300 void acp_set_log_func(acp_log_func, void *data); 301 void acp_set_log_level(int level); 302 303 #ifdef __cplusplus 304 } 305 #endif 306 307 #endif /* ACP_H */ 308