"Fossies" - the Fresh Open Source Software Archive

Member "pulseaudio-14.2/src/modules/alsa/alsa-mixer.h" (11 Jan 2021, 13489 Bytes) of package /linux/misc/pulseaudio-14.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "alsa-mixer.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.0_vs_14.2.

    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, see <http://www.gnu.org/licenses/>.
   22 ***/
   23 
   24 #include <alsa/asoundlib.h>
   25 
   26 #include <pulse/sample.h>
   27 #include <pulse/mainloop-api.h>
   28 #include <pulse/channelmap.h>
   29 #include <pulse/volume.h>
   30 
   31 #include <pulsecore/llist.h>
   32 #include <pulsecore/rtpoll.h>
   33 
   34 typedef struct pa_alsa_fdlist pa_alsa_fdlist;
   35 typedef struct pa_alsa_mixer pa_alsa_mixer;
   36 typedef struct pa_alsa_mixer_pdata pa_alsa_mixer_pdata;
   37 typedef struct pa_alsa_setting pa_alsa_setting;
   38 typedef struct pa_alsa_mixer_id pa_alsa_mixer_id;
   39 typedef struct pa_alsa_option pa_alsa_option;
   40 typedef struct pa_alsa_element pa_alsa_element;
   41 typedef struct pa_alsa_jack pa_alsa_jack;
   42 typedef struct pa_alsa_path pa_alsa_path;
   43 typedef struct pa_alsa_path_set pa_alsa_path_set;
   44 typedef struct pa_alsa_mapping pa_alsa_mapping;
   45 typedef struct pa_alsa_profile pa_alsa_profile;
   46 typedef struct pa_alsa_decibel_fix pa_alsa_decibel_fix;
   47 typedef struct pa_alsa_profile_set pa_alsa_profile_set;
   48 typedef struct pa_alsa_port_data pa_alsa_port_data;
   49 
   50 #include "alsa-util.h"
   51 #include "alsa-ucm.h"
   52 
   53 #define POSITION_MASK_CHANNELS 8
   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 entry for one ALSA mixer */
  105 struct pa_alsa_mixer {
  106     snd_mixer_t *mixer_handle;
  107     int card_index;
  108     pa_alsa_fdlist *fdl;
  109     bool used_for_probe_only:1;
  110 };
  111 
  112 /* ALSA mixer element identifier */
  113 struct pa_alsa_mixer_id {
  114     char *name;
  115     int index;
  116 };
  117 
  118 char *pa_alsa_mixer_id_to_string(char *dst, size_t dst_len, pa_alsa_mixer_id *id);
  119 
  120 /* An option belongs to an element and refers to one enumeration item
  121  * of the element is an enumeration item, or a switch status if the
  122  * element is a switch item. */
  123 struct pa_alsa_option {
  124     pa_alsa_element *element;
  125     PA_LLIST_FIELDS(pa_alsa_option);
  126 
  127     char *alsa_name;
  128     int alsa_idx;
  129 
  130     char *name;
  131     char *description;
  132     unsigned priority;
  133 
  134     pa_alsa_required_t required;
  135     pa_alsa_required_t required_any;
  136     pa_alsa_required_t required_absent;
  137 };
  138 
  139 /* An element wraps one specific ALSA element. A series of elements
  140  * make up a path (see below). If the element is an enumeration or switch
  141  * element it may include a list of options. */
  142 struct pa_alsa_element {
  143     pa_alsa_path *path;
  144     PA_LLIST_FIELDS(pa_alsa_element);
  145 
  146     struct pa_alsa_mixer_id alsa_id;
  147     pa_alsa_direction_t direction;
  148 
  149     pa_alsa_switch_use_t switch_use;
  150     pa_alsa_volume_use_t volume_use;
  151     pa_alsa_enumeration_use_t enumeration_use;
  152 
  153     pa_alsa_required_t required;
  154     pa_alsa_required_t required_any;
  155     pa_alsa_required_t required_absent;
  156 
  157     long constant_volume;
  158 
  159     unsigned int override_map;
  160     bool direction_try_other:1;
  161 
  162     bool has_dB:1;
  163     long min_volume, max_volume;
  164     long volume_limit; /* -1 for no configured limit */
  165     double min_dB, max_dB;
  166 
  167     pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][POSITION_MASK_CHANNELS];
  168     unsigned n_channels;
  169 
  170     pa_channel_position_mask_t merged_mask;
  171 
  172     PA_LLIST_HEAD(pa_alsa_option, options);
  173 
  174     pa_alsa_decibel_fix *db_fix;
  175 };
  176 
  177 struct pa_alsa_jack {
  178     pa_alsa_path *path;
  179     PA_LLIST_FIELDS(pa_alsa_jack);
  180 
  181     snd_mixer_t *mixer_handle;
  182     char *mixer_device_name;
  183 
  184     struct pa_alsa_mixer_id alsa_id;
  185     char *name; /* E g "Headphone" */
  186     bool has_control; /* is the jack itself present? */
  187     bool plugged_in; /* is this jack currently plugged in? */
  188     snd_mixer_elem_t *melem; /* Jack detection handle */
  189     pa_available_t state_unplugged, state_plugged;
  190 
  191     pa_alsa_required_t required;
  192     pa_alsa_required_t required_any;
  193     pa_alsa_required_t required_absent;
  194 
  195     pa_dynarray *ucm_devices; /* pa_alsa_ucm_device */
  196     pa_dynarray *ucm_hw_mute_devices; /* pa_alsa_ucm_device */
  197 
  198     bool append_pcm_to_name;
  199 };
  200 
  201 pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name, int index);
  202 void pa_alsa_jack_free(pa_alsa_jack *jack);
  203 void pa_alsa_jack_set_has_control(pa_alsa_jack *jack, bool has_control);
  204 void pa_alsa_jack_set_plugged_in(pa_alsa_jack *jack, bool plugged_in);
  205 void pa_alsa_jack_add_ucm_device(pa_alsa_jack *jack, pa_alsa_ucm_device *device);
  206 void pa_alsa_jack_add_ucm_hw_mute_device(pa_alsa_jack *jack, pa_alsa_ucm_device *device);
  207 
  208 /* A path wraps a series of elements into a single entity which can be
  209  * used to control it as if it had a single volume slider, a single
  210  * mute switch and a single list of selectable options. */
  211 struct pa_alsa_path {
  212     pa_alsa_direction_t direction;
  213     pa_device_port* port;
  214 
  215     char *name;
  216     char *description_key;
  217     char *description;
  218     char *availability_group;
  219     pa_device_port_type_t device_port_type;
  220     unsigned priority;
  221     bool autodetect_eld_device;
  222     pa_alsa_mixer *eld_mixer_handle;
  223     int eld_device;
  224     pa_proplist *proplist;
  225 
  226     bool probed:1;
  227     bool supported:1;
  228     bool has_mute:1;
  229     bool has_volume:1;
  230     bool has_dB:1;
  231     bool mute_during_activation:1;
  232     /* These two are used during probing only */
  233     bool has_req_any:1;
  234     bool req_any_present:1;
  235 
  236     long min_volume, max_volume;
  237     double min_dB, max_dB;
  238 
  239     /* This is used during parsing only, as a shortcut so that we
  240      * don't have to iterate the list all the time */
  241     pa_alsa_element *last_element;
  242     pa_alsa_option *last_option;
  243     pa_alsa_setting *last_setting;
  244     pa_alsa_jack *last_jack;
  245 
  246     PA_LLIST_HEAD(pa_alsa_element, elements);
  247     PA_LLIST_HEAD(pa_alsa_setting, settings);
  248     PA_LLIST_HEAD(pa_alsa_jack, jacks);
  249 };
  250 
  251 /* A path set is simply a set of paths that are applicable to a
  252  * device */
  253 struct pa_alsa_path_set {
  254     pa_hashmap *paths;
  255     pa_alsa_direction_t direction;
  256 };
  257 
  258 void pa_alsa_setting_dump(pa_alsa_setting *s);
  259 
  260 void pa_alsa_option_dump(pa_alsa_option *o);
  261 void pa_alsa_jack_dump(pa_alsa_jack *j);
  262 void pa_alsa_element_dump(pa_alsa_element *e);
  263 
  264 pa_alsa_path *pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction);
  265 pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction);
  266 pa_alsa_element *pa_alsa_element_get(pa_alsa_path *p, const char *section, bool prefixed);
  267 int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m, bool ignore_dB);
  268 void pa_alsa_path_dump(pa_alsa_path *p);
  269 int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
  270 int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, bool *muted);
  271 int pa_alsa_path_set_volume(pa_alsa_path *path, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v, bool deferred_volume, bool write_to_hw);
  272 int pa_alsa_path_set_mute(pa_alsa_path *path, snd_mixer_t *m, bool muted);
  273 int pa_alsa_path_select(pa_alsa_path *p, pa_alsa_setting *s, snd_mixer_t *m, bool device_is_muted);
  274 void pa_alsa_path_set_callback(pa_alsa_path *p, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
  275 void pa_alsa_path_free(pa_alsa_path *p);
  276 
  277 pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t direction, const char *paths_dir);
  278 void pa_alsa_path_set_dump(pa_alsa_path_set *s);
  279 void pa_alsa_path_set_set_callback(pa_alsa_path_set *ps, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
  280 void pa_alsa_path_set_free(pa_alsa_path_set *s);
  281 int pa_alsa_path_set_is_empty(pa_alsa_path_set *s);
  282 
  283 struct pa_alsa_mapping {
  284     pa_alsa_profile_set *profile_set;
  285 
  286     char *name;
  287     char *description;
  288     char *description_key;
  289     unsigned priority;
  290     pa_alsa_direction_t direction;
  291     /* These are copied over to the resultant sink/source */
  292     pa_proplist *proplist;
  293 
  294     pa_sample_spec sample_spec;
  295     pa_channel_map channel_map;
  296 
  297     char **device_strings;
  298 
  299     char **input_path_names;
  300     char **output_path_names;
  301     char **input_element; /* list of fallbacks */
  302     char **output_element;
  303     pa_alsa_path_set *input_path_set;
  304     pa_alsa_path_set *output_path_set;
  305 
  306     unsigned supported;
  307     bool exact_channels:1;
  308     bool fallback:1;
  309 
  310     /* The "y" in "hw:x,y". This is set to -1 before the device index has been
  311      * queried, or if the query failed. */
  312     int hw_device_index;
  313 
  314     /* Temporarily used during probing */
  315     snd_pcm_t *input_pcm;
  316     snd_pcm_t *output_pcm;
  317 
  318     pa_sink *sink;
  319     pa_source *source;
  320 
  321     /* ucm device context*/
  322     pa_alsa_ucm_mapping_context ucm_context;
  323 };
  324 
  325 struct pa_alsa_profile {
  326     pa_alsa_profile_set *profile_set;
  327 
  328     char *name;
  329     char *description;
  330     char *description_key;
  331     unsigned priority;
  332 
  333     char *input_name;
  334     char *output_name;
  335 
  336     bool supported:1;
  337     bool fallback_input:1;
  338     bool fallback_output:1;
  339 
  340     char **input_mapping_names;
  341     char **output_mapping_names;
  342 
  343     pa_idxset *input_mappings;
  344     pa_idxset *output_mappings;
  345 };
  346 
  347 struct pa_alsa_decibel_fix {
  348     char *key;
  349 
  350     pa_alsa_profile_set *profile_set;
  351 
  352     char *name; /* Alsa volume element name. */
  353     int index;  /* Alsa volume element index. */
  354     long min_step;
  355     long max_step;
  356 
  357     /* An array that maps alsa volume element steps to decibels. The steps can
  358      * be used as indices to this array, after subtracting min_step from the
  359      * real value.
  360      *
  361      * The values are actually stored as integers representing millibels,
  362      * because that's the format the alsa API uses. */
  363     long *db_values;
  364 };
  365 
  366 struct pa_alsa_profile_set {
  367     pa_hashmap *mappings;
  368     pa_hashmap *profiles;
  369     pa_hashmap *decibel_fixes;
  370     pa_hashmap *input_paths;
  371     pa_hashmap *output_paths;
  372 
  373     bool auto_profiles;
  374     bool ignore_dB:1;
  375     bool probed:1;
  376 };
  377 
  378 void pa_alsa_mapping_dump(pa_alsa_mapping *m);
  379 void pa_alsa_profile_dump(pa_alsa_profile *p);
  380 void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix);
  381 pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name);
  382 
  383 pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
  384 void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, pa_hashmap *mixers, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec);
  385 void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
  386 void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
  387 void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *s);
  388 
  389 pa_alsa_fdlist *pa_alsa_fdlist_new(void);
  390 void pa_alsa_fdlist_free(pa_alsa_fdlist *fdl);
  391 int pa_alsa_fdlist_set_handle(pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, snd_hctl_t *hctl_handle, pa_mainloop_api* m);
  392 
  393 /* Alternative for handling alsa mixer events in io-thread. */
  394 
  395 pa_alsa_mixer_pdata *pa_alsa_mixer_pdata_new(void);
  396 void pa_alsa_mixer_pdata_free(pa_alsa_mixer_pdata *pd);
  397 int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata *pd, snd_mixer_t *mixer, pa_rtpoll *rtp);
  398 
  399 /* Data structure for inclusion in pa_device_port for alsa
  400  * sinks/sources. This contains nothing that needs to be freed
  401  * individually */
  402 struct pa_alsa_port_data {
  403     pa_alsa_path *path;
  404     pa_alsa_setting *setting;
  405     bool suspend_when_unavailable;
  406 };
  407 
  408 void pa_alsa_add_ports(void *sink_or_source_new_data, pa_alsa_path_set *ps, pa_card *card);
  409 void pa_alsa_path_set_add_ports(pa_alsa_path_set *ps, pa_card_profile *cp, pa_hashmap *ports, pa_hashmap *extra, pa_core *core);
  410 
  411 #endif