318 lines
11 KiB
C
318 lines
11 KiB
C
#ifndef fooalsaucmhfoo
|
|
#define fooalsaucmhfoo
|
|
|
|
/***
|
|
This file is part of PulseAudio.
|
|
|
|
Copyright 2011 Wolfson Microelectronics PLC
|
|
Author Margarita Olaya <magi@slimlogic.co.uk>
|
|
Copyright 2012 Feng Wei <wei.feng@freescale.com>, Freescale Ltd.
|
|
|
|
PulseAudio is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published
|
|
by the Free Software Foundation; either version 2.1 of the License,
|
|
or (at your option) any later version.
|
|
|
|
PulseAudio is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
|
***/
|
|
|
|
#ifdef HAVE_ALSA_UCM
|
|
#include <alsa/use-case.h>
|
|
#else
|
|
typedef void snd_use_case_mgr_t;
|
|
#endif
|
|
|
|
#include "compat.h"
|
|
|
|
#include "alsa-mixer.h"
|
|
|
|
/** For devices: List of verbs, devices or modifiers available */
|
|
#define PA_ALSA_PROP_UCM_NAME "alsa.ucm.name"
|
|
|
|
/** For devices: List of supported devices per verb*/
|
|
#define PA_ALSA_PROP_UCM_DESCRIPTION "alsa.ucm.description"
|
|
|
|
/** For devices: Playback device name e.g PlaybackPCM */
|
|
#define PA_ALSA_PROP_UCM_SINK "alsa.ucm.sink"
|
|
|
|
/** For devices: Capture device name e.g CapturePCM*/
|
|
#define PA_ALSA_PROP_UCM_SOURCE "alsa.ucm.source"
|
|
|
|
/** For devices: Playback roles */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_ROLES "alsa.ucm.playback.roles"
|
|
|
|
/** For devices: Playback control device name */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE "alsa.ucm.playback.ctldev"
|
|
|
|
/** For devices: Playback control volume ID string. e.g PlaybackVolume */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_VOLUME "alsa.ucm.playback.volume"
|
|
|
|
/** For devices: Playback switch e.g PlaybackSwitch */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_SWITCH "alsa.ucm.playback.switch"
|
|
|
|
/** For devices: Playback mixer device name */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE "alsa.ucm.playback.mixer.device"
|
|
|
|
/** For devices: Playback mixer identifier */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM "alsa.ucm.playback.mixer.element"
|
|
|
|
/** For devices: Playback mixer master identifier */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM "alsa.ucm.playback.master.element"
|
|
|
|
/** For devices: Playback mixer master type */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type"
|
|
|
|
/** For devices: Playback mixer master identifier */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ID "alsa.ucm.playback.master.id"
|
|
|
|
/** For devices: Playback mixer master type */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type"
|
|
|
|
/** For devices: Playback priority */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY "alsa.ucm.playback.priority"
|
|
|
|
/** For devices: Playback rate */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_RATE "alsa.ucm.playback.rate"
|
|
|
|
/** For devices: Playback channels */
|
|
#define PA_ALSA_PROP_UCM_PLAYBACK_CHANNELS "alsa.ucm.playback.channels"
|
|
|
|
/** For devices: Capture roles */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_ROLES "alsa.ucm.capture.roles"
|
|
|
|
/** For devices: Capture control device name */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE "alsa.ucm.capture.ctldev"
|
|
|
|
/** For devices: Capture controls volume ID string. e.g CaptureVolume */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_VOLUME "alsa.ucm.capture.volume"
|
|
|
|
/** For devices: Capture switch e.g CaptureSwitch */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_SWITCH "alsa.ucm.capture.switch"
|
|
|
|
/** For devices: Capture mixer device name */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE "alsa.ucm.capture.mixer.device"
|
|
|
|
/** For devices: Capture mixer identifier */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM "alsa.ucm.capture.mixer.element"
|
|
|
|
/** For devices: Capture mixer identifier */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM "alsa.ucm.capture.master.element"
|
|
|
|
/** For devices: Capture mixer identifier */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type"
|
|
|
|
/** For devices: Capture mixer identifier */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ID "alsa.ucm.capture.master.id"
|
|
|
|
/** For devices: Capture mixer identifier */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type"
|
|
|
|
/** For devices: Capture priority */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_PRIORITY "alsa.ucm.capture.priority"
|
|
|
|
/** For devices: Capture rate */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_RATE "alsa.ucm.capture.rate"
|
|
|
|
/** For devices: Capture channels */
|
|
#define PA_ALSA_PROP_UCM_CAPTURE_CHANNELS "alsa.ucm.capture.channels"
|
|
|
|
/** For devices: Quality of Service */
|
|
#define PA_ALSA_PROP_UCM_QOS "alsa.ucm.qos"
|
|
|
|
/** For devices: The modifier (if any) that this device corresponds to */
|
|
#define PA_ALSA_PROP_UCM_MODIFIER "alsa.ucm.modifier"
|
|
|
|
/* Corresponds to the "JackCTL" UCM value. */
|
|
#define PA_ALSA_PROP_UCM_JACK_DEVICE "alsa.ucm.jack_device"
|
|
|
|
/* Corresponds to the "JackControl" UCM value. */
|
|
#define PA_ALSA_PROP_UCM_JACK_CONTROL "alsa.ucm.jack_control"
|
|
|
|
/* Corresponds to the "JackHWMute" UCM value. */
|
|
#define PA_ALSA_PROP_UCM_JACK_HW_MUTE "alsa.ucm.jack_hw_mute"
|
|
|
|
typedef struct pa_alsa_ucm_verb pa_alsa_ucm_verb;
|
|
typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier;
|
|
typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
|
|
typedef struct pa_alsa_ucm_config pa_alsa_ucm_config;
|
|
typedef struct pa_alsa_ucm_mapping_context pa_alsa_ucm_mapping_context;
|
|
typedef struct pa_alsa_ucm_profile_context pa_alsa_ucm_profile_context;
|
|
typedef struct pa_alsa_ucm_port_data pa_alsa_ucm_port_data;
|
|
typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume;
|
|
typedef struct pa_alsa_ucm_split pa_alsa_ucm_split;
|
|
|
|
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index);
|
|
pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_channel_map *default_channel_map);
|
|
int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, pa_alsa_profile *new_profile, pa_alsa_profile *old_profile);
|
|
|
|
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);
|
|
|
|
void pa_alsa_ucm_add_ports(
|
|
pa_hashmap **hash,
|
|
pa_proplist *proplist,
|
|
pa_alsa_ucm_mapping_context *context,
|
|
bool is_sink,
|
|
pa_card *card,
|
|
snd_pcm_t *pcm_handle,
|
|
bool ignore_dB);
|
|
void pa_alsa_ucm_add_port(
|
|
pa_hashmap *hash,
|
|
pa_alsa_ucm_mapping_context *context,
|
|
bool is_sink,
|
|
pa_hashmap *ports,
|
|
pa_card_profile *cp,
|
|
pa_core *core);
|
|
int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *port);
|
|
|
|
void pa_alsa_ucm_free(pa_alsa_ucm_config *ucm);
|
|
void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context);
|
|
|
|
void pa_alsa_ucm_roled_stream_begin(pa_alsa_ucm_config *ucm, const char *role, pa_direction_t dir);
|
|
void pa_alsa_ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, pa_direction_t dir);
|
|
|
|
/* UCM - Use Case Manager is available on some audio cards */
|
|
|
|
struct pa_alsa_ucm_split {
|
|
/* UCM SplitPCM channel remapping */
|
|
bool leader;
|
|
int hw_channels;
|
|
int channels;
|
|
int idx[PA_CHANNELS_MAX];
|
|
enum snd_pcm_chmap_position pos[PA_CHANNELS_MAX];
|
|
bool broken;
|
|
};
|
|
|
|
struct pa_alsa_ucm_device {
|
|
PA_LLIST_FIELDS(pa_alsa_ucm_device);
|
|
|
|
pa_proplist *proplist;
|
|
|
|
pa_device_port_type_t type;
|
|
|
|
unsigned playback_priority;
|
|
unsigned capture_priority;
|
|
|
|
unsigned playback_rate;
|
|
unsigned capture_rate;
|
|
|
|
unsigned playback_channels;
|
|
unsigned capture_channels;
|
|
|
|
/* These may be different per verb, so we store this as a hashmap of verb -> volume_control. We might eventually want to
|
|
* make this a hashmap of verb -> per-verb-device-properties-struct. */
|
|
pa_hashmap *playback_volumes;
|
|
pa_hashmap *capture_volumes;
|
|
|
|
pa_alsa_mapping *playback_mapping;
|
|
pa_alsa_mapping *capture_mapping;
|
|
|
|
pa_idxset *conflicting_devices;
|
|
pa_idxset *supported_devices;
|
|
|
|
/* One device may be part of multiple ports, since each device has
|
|
* a dedicated port, and in addition to that we sometimes generate ports
|
|
* that represent combinations of devices. */
|
|
pa_dynarray *ucm_ports; /* struct ucm_port */
|
|
|
|
pa_alsa_jack *jack;
|
|
pa_dynarray *hw_mute_jacks; /* pa_alsa_jack */
|
|
pa_available_t available;
|
|
|
|
char *eld_mixer_device_name;
|
|
int eld_device;
|
|
|
|
pa_alsa_ucm_split *playback_split;
|
|
pa_alsa_ucm_split *capture_split;
|
|
};
|
|
|
|
void pa_alsa_ucm_device_update_available(pa_alsa_ucm_device *device);
|
|
|
|
struct pa_alsa_ucm_modifier {
|
|
PA_LLIST_FIELDS(pa_alsa_ucm_modifier);
|
|
|
|
pa_proplist *proplist;
|
|
|
|
pa_idxset *conflicting_devices;
|
|
pa_idxset *supported_devices;
|
|
|
|
pa_direction_t action_direction;
|
|
|
|
char *media_role;
|
|
|
|
/* Non-NULL if the modifier has its own PlaybackPCM/CapturePCM */
|
|
pa_alsa_mapping *playback_mapping;
|
|
pa_alsa_mapping *capture_mapping;
|
|
|
|
/* Count how many role matched streams are running */
|
|
int enabled_counter;
|
|
};
|
|
|
|
struct pa_alsa_ucm_verb {
|
|
PA_LLIST_FIELDS(pa_alsa_ucm_verb);
|
|
|
|
pa_proplist *proplist;
|
|
unsigned priority;
|
|
|
|
PA_LLIST_HEAD(pa_alsa_ucm_device, devices);
|
|
PA_LLIST_HEAD(pa_alsa_ucm_modifier, modifiers);
|
|
};
|
|
|
|
struct pa_alsa_ucm_config {
|
|
pa_sample_spec default_sample_spec;
|
|
pa_channel_map default_channel_map;
|
|
unsigned default_fragment_size_msec;
|
|
unsigned default_n_fragments;
|
|
bool split_enable;
|
|
|
|
snd_use_case_mgr_t *ucm_mgr;
|
|
pa_alsa_ucm_verb *active_verb;
|
|
char *alib_prefix;
|
|
|
|
pa_hashmap *mixers;
|
|
PA_LLIST_HEAD(pa_alsa_ucm_verb, verbs);
|
|
PA_LLIST_HEAD(pa_alsa_jack, jacks);
|
|
};
|
|
|
|
struct pa_alsa_ucm_mapping_context {
|
|
pa_alsa_ucm_config *ucm;
|
|
pa_direction_t direction;
|
|
|
|
pa_alsa_ucm_device *ucm_device;
|
|
pa_alsa_ucm_modifier *ucm_modifier;
|
|
};
|
|
|
|
struct pa_alsa_ucm_profile_context {
|
|
pa_alsa_ucm_verb *verb;
|
|
};
|
|
|
|
struct pa_alsa_ucm_port_data {
|
|
pa_alsa_ucm_config *ucm;
|
|
pa_device_port *core_port;
|
|
|
|
pa_alsa_ucm_device *device;
|
|
|
|
/* verb name -> pa_alsa_path for volume control */
|
|
pa_hashmap *paths;
|
|
/* Current path, set when activating verb */
|
|
pa_alsa_path *path;
|
|
|
|
/* ELD info */
|
|
char *eld_mixer_device_name;
|
|
int eld_device; /* PCM device number */
|
|
};
|
|
|
|
long pa_alsa_ucm_port_device_status(pa_alsa_ucm_port_data *data);
|
|
|
|
struct pa_alsa_ucm_volume {
|
|
char *mixer_elem; /* mixer element identifier */
|
|
char *master_elem; /* master mixer element identifier */
|
|
char *master_type;
|
|
};
|
|
|
|
#endif
|