mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-10-06 16:09:43 +00:00
alsa: sync with latest pulseaudio
Move some things around to make it easier to merge in changes.
This commit is contained in:
parent
6aa6b4eac7
commit
a67af43cad
|
@ -131,6 +131,16 @@ ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1252", ENV{PULSE_PROFILE_SET}="steel
|
|||
|
||||
ATTRS{idVendor}=="147a", ATTRS{idProduct}=="e055", ENV{PULSE_PROFILE_SET}="cmedia-high-speed-true-hdaudio.conf"
|
||||
|
||||
# HyperX Cloud Orbit S has three modes. Each mode has a separate product ID.
|
||||
# ID_SERIAL for this device is the device name + mode repeated three times.
|
||||
# ID_SERIAL is used for the ID_ID property, and the ID_ID property is used in
|
||||
# the card name in PulseAudio. The resulting card name is too long for the name
|
||||
# length limit, so we set a more sensible ID_ID here (the same as the default
|
||||
# ID_ID, but without repetition in the serial part).
|
||||
ATTRS{idVendor}=="0951", ATTRS{idProduct}=="16ff", ENV{ID_ID}="usb-HyperX_Cloud_Orbit_S_2Ch-$env{ID_USB_INTERFACE_NUM}"
|
||||
ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1702", ENV{ID_ID}="usb-HyperX_Cloud_Orbit_S_Hi-Res_2Ch-$env{ID_USB_INTERFACE_NUM}"
|
||||
ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1703", ENV{ID_ID}="usb-HyperX_Cloud_Orbit_S_3D_8Ch-$env{ID_USB_INTERFACE_NUM}"
|
||||
|
||||
GOTO="pulseaudio_end"
|
||||
|
||||
LABEL="pulseaudio_firewire_quirk"
|
||||
|
|
|
@ -51,7 +51,7 @@ static void init_device(pa_card *impl, pa_alsa_device *dev, pa_alsa_direction_t
|
|||
dev->device.name = m->name;
|
||||
dev->device.description = m->description;
|
||||
dev->device.priority = m->priority;
|
||||
dev->device.device_strings = m->device_strings;
|
||||
dev->device.device_strings = (const char **)m->device_strings;
|
||||
dev->device.format.format_mask = m->sample_spec.format;
|
||||
dev->device.format.rate_mask = m->sample_spec.rate;
|
||||
dev->device.format.channels = m->channel_map.channels;
|
||||
|
@ -114,15 +114,18 @@ static void add_profiles(pa_card *impl)
|
|||
pa_dynarray_init(&impl->out.devices, NULL);
|
||||
|
||||
ap = pa_xnew0(pa_alsa_profile, 1);
|
||||
ap->profile.name = pa_xstrdup("off");
|
||||
ap->profile.description = pa_xstrdup(_("Off"));
|
||||
ap->profile.name = ap->name = pa_xstrdup("off");
|
||||
ap->profile.description = ap->description = pa_xstrdup(_("Off"));
|
||||
ap->profile.available = ACP_AVAILABLE_YES;
|
||||
pa_hashmap_put(impl->profiles, ap->profile.name, ap);
|
||||
pa_hashmap_put(impl->profiles, ap->name, ap);
|
||||
|
||||
PA_HASHMAP_FOREACH(ap, impl->profile_set->profiles, state) {
|
||||
pa_alsa_mapping *m;
|
||||
|
||||
cp = &ap->profile;
|
||||
cp->name = ap->name;
|
||||
cp->description = ap->description;
|
||||
cp->priority = ap->priority ? ap->priority : 1;
|
||||
|
||||
pa_dynarray_init(&ap->out.devices, NULL);
|
||||
|
||||
|
@ -164,7 +167,7 @@ static void add_profiles(pa_card *impl)
|
|||
}
|
||||
cp->n_devices = pa_dynarray_size(&ap->out.devices);
|
||||
cp->devices = ap->out.devices.array.data;
|
||||
pa_hashmap_put(impl->profiles, cp->name, cp);
|
||||
pa_hashmap_put(impl->profiles, ap->name, cp);
|
||||
}
|
||||
|
||||
pa_dynarray_init(&impl->out.ports, NULL);
|
||||
|
@ -173,6 +176,7 @@ static void add_profiles(pa_card *impl)
|
|||
void *state2;
|
||||
dp->card = impl;
|
||||
dp->port.index = n_ports++;
|
||||
dp->port.priority = dp->priority;
|
||||
pa_dynarray_init(&dp->prof, NULL);
|
||||
pa_dynarray_init(&dp->devices, NULL);
|
||||
n_profiles = 0;
|
||||
|
@ -1320,7 +1324,7 @@ int acp_device_set_port(struct acp_device *dev, uint32_t port_index)
|
|||
if (p == old)
|
||||
return 0;
|
||||
|
||||
if (!pa_hashmap_get(d->ports, p->port.name))
|
||||
if (!pa_hashmap_get(d->ports, p->name))
|
||||
return -EINVAL;
|
||||
|
||||
if (old)
|
||||
|
|
|
@ -81,6 +81,9 @@ enum acp_available {
|
|||
ACP_AVAILABLE_YES = 2
|
||||
};
|
||||
|
||||
/** Port type. New types can be added in the future, so applications should
|
||||
* gracefully handle situations where a type identifier doesn't match any item
|
||||
* in this enumeration. */
|
||||
enum acp_port_type {
|
||||
ACP_PORT_TYPE_UNKNOWN = 0,
|
||||
ACP_PORT_TYPE_AUX = 1,
|
||||
|
@ -136,26 +139,47 @@ struct acp_card_events {
|
|||
};
|
||||
|
||||
struct acp_port {
|
||||
uint32_t index;
|
||||
uint32_t index; /**< unique index for this port */
|
||||
#define ACP_PORT_ACTIVE (1<<0)
|
||||
uint32_t flags;
|
||||
uint32_t flags; /**< extra port flags */
|
||||
|
||||
char *name;
|
||||
char *description;
|
||||
uint32_t priority;
|
||||
const char *name; /**< Name of this port */
|
||||
const char *description; /**< Description of this port */
|
||||
uint32_t priority; /**< The higher this value is, the more useful this port is as a default. */
|
||||
enum acp_direction direction;
|
||||
enum acp_available available;
|
||||
char *available_group; /* a string identifier which determine the group of devices
|
||||
* handling the available state simultaneously */
|
||||
enum acp_port_type type;
|
||||
enum acp_available available; /**< A flags (see #acp_port_available), indicating availability status of this port. */
|
||||
const char *availability_group; /**< An indentifier for the group of ports that share their availability status with
|
||||
* each other. This is meant especially for handling cases where one 3.5 mm connector
|
||||
* is used for headphones, headsets and microphones, and the hardware can only tell
|
||||
* that something was plugged in but not what exactly. In this situation the ports for
|
||||
* all those devices share their availability status, and PulseAudio can't tell which
|
||||
* one is actually plugged in, and some application may ask the user what was plugged
|
||||
* in. Such applications should get a list of all card ports and compare their
|
||||
* `available_group` fields. Ports that have the same group are those that need
|
||||
* input from the user to determine which device was plugged in. The application should
|
||||
* then activate the user-chosen port.
|
||||
*
|
||||
* May be NULL, in which case the port is not part of any availability group (which is
|
||||
* the same as having a group with only one member).
|
||||
*
|
||||
* The group identifier must be treated as an opaque identifier. The string may look
|
||||
* like an ALSA control name, but applications must not assume any such relationship.
|
||||
* The group naming scheme can change without a warning.
|
||||
*
|
||||
* Since one group can include both input and output ports, the grouping should be done
|
||||
* using pa_card_port_info instead of pa_sink_port_info, but this field is duplicated
|
||||
* also in pa_sink_port_info (and pa_source_port_info) in case someone finds that
|
||||
* convenient.
|
||||
*/
|
||||
enum acp_port_type type; /**< Port type, see #pa_device_port_type. */
|
||||
|
||||
struct acp_dict props;
|
||||
struct acp_dict props; /**< extra port properties */
|
||||
|
||||
uint32_t n_profiles;
|
||||
struct acp_card_profile **profiles;
|
||||
uint32_t n_profiles; /**< number of elements in profiles array */
|
||||
struct acp_card_profile **profiles; /**< array of profiles for this port */
|
||||
|
||||
uint32_t n_devices;
|
||||
struct acp_device **devices;
|
||||
uint32_t n_devices; /**< number of elements in devices array */
|
||||
struct acp_device **devices; /**< array of devices */
|
||||
};
|
||||
|
||||
struct acp_device {
|
||||
|
@ -165,13 +189,13 @@ struct acp_device {
|
|||
#define ACP_DEVICE_HW_MUTE (1<<2)
|
||||
uint32_t flags;
|
||||
|
||||
char *name;
|
||||
char *description;
|
||||
const char *name;
|
||||
const char *description;
|
||||
uint32_t priority;
|
||||
enum acp_direction direction;
|
||||
struct acp_dict props;
|
||||
|
||||
char **device_strings;
|
||||
const char **device_strings;
|
||||
struct acp_format format;
|
||||
|
||||
float base_volume;
|
||||
|
@ -186,9 +210,8 @@ struct acp_card_profile {
|
|||
#define ACP_PROFILE_ACTIVE (1<<0)
|
||||
uint32_t flags;
|
||||
|
||||
char *name;
|
||||
char *description;
|
||||
char *description_key;
|
||||
const char *name;
|
||||
const char *description;
|
||||
uint32_t priority;
|
||||
enum acp_available available;
|
||||
struct acp_dict props;
|
||||
|
|
|
@ -306,6 +306,327 @@ void pa_alsa_mixer_use_for_poll(pa_hashmap *mixers, snd_mixer_t *mixer_handle)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct pa_alsa_fdlist {
|
||||
unsigned num_fds;
|
||||
struct pollfd *fds;
|
||||
/* This is a temporary buffer used to avoid lots of mallocs */
|
||||
struct pollfd *work_fds;
|
||||
|
||||
snd_mixer_t *mixer;
|
||||
snd_hctl_t *hctl;
|
||||
|
||||
pa_mainloop_api *m;
|
||||
pa_defer_event *defer;
|
||||
pa_io_event **ios;
|
||||
|
||||
bool polled;
|
||||
|
||||
void (*cb)(void *userdata);
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
static void io_cb(pa_mainloop_api *a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
|
||||
struct pa_alsa_fdlist *fdl = userdata;
|
||||
int err;
|
||||
unsigned i;
|
||||
unsigned short revents;
|
||||
|
||||
pa_assert(a);
|
||||
pa_assert(fdl);
|
||||
pa_assert(fdl->mixer || fdl->hctl);
|
||||
pa_assert(fdl->fds);
|
||||
pa_assert(fdl->work_fds);
|
||||
|
||||
if (fdl->polled)
|
||||
return;
|
||||
|
||||
fdl->polled = true;
|
||||
|
||||
memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds);
|
||||
|
||||
for (i = 0; i < fdl->num_fds; i++) {
|
||||
if (e == fdl->ios[i]) {
|
||||
if (events & PA_IO_EVENT_INPUT)
|
||||
fdl->work_fds[i].revents |= POLLIN;
|
||||
if (events & PA_IO_EVENT_OUTPUT)
|
||||
fdl->work_fds[i].revents |= POLLOUT;
|
||||
if (events & PA_IO_EVENT_ERROR)
|
||||
fdl->work_fds[i].revents |= POLLERR;
|
||||
if (events & PA_IO_EVENT_HANGUP)
|
||||
fdl->work_fds[i].revents |= POLLHUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pa_assert(i != fdl->num_fds);
|
||||
|
||||
if (fdl->hctl)
|
||||
err = snd_hctl_poll_descriptors_revents(fdl->hctl, fdl->work_fds, fdl->num_fds, &revents);
|
||||
else
|
||||
err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents);
|
||||
|
||||
if (err < 0) {
|
||||
pa_log_error("Unable to get poll revent: %s", pa_alsa_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
a->defer_enable(fdl->defer, 1);
|
||||
|
||||
if (revents) {
|
||||
if (fdl->hctl)
|
||||
snd_hctl_handle_events(fdl->hctl);
|
||||
else
|
||||
snd_mixer_handle_events(fdl->mixer);
|
||||
}
|
||||
}
|
||||
|
||||
static void defer_cb(pa_mainloop_api *a, pa_defer_event *e, void *userdata) {
|
||||
struct pa_alsa_fdlist *fdl = userdata;
|
||||
unsigned num_fds, i;
|
||||
int err, n;
|
||||
struct pollfd *temp;
|
||||
|
||||
pa_assert(a);
|
||||
pa_assert(fdl);
|
||||
pa_assert(fdl->mixer || fdl->hctl);
|
||||
|
||||
a->defer_enable(fdl->defer, 0);
|
||||
|
||||
if (fdl->hctl)
|
||||
n = snd_hctl_poll_descriptors_count(fdl->hctl);
|
||||
else
|
||||
n = snd_mixer_poll_descriptors_count(fdl->mixer);
|
||||
|
||||
if (n < 0) {
|
||||
pa_log("snd_mixer_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
|
||||
return;
|
||||
}
|
||||
else if (n == 0) {
|
||||
pa_log_warn("Mixer has no poll descriptors. Please control mixer from PulseAudio only.");
|
||||
return;
|
||||
}
|
||||
num_fds = (unsigned) n;
|
||||
|
||||
if (num_fds != fdl->num_fds) {
|
||||
if (fdl->fds)
|
||||
pa_xfree(fdl->fds);
|
||||
if (fdl->work_fds)
|
||||
pa_xfree(fdl->work_fds);
|
||||
fdl->fds = pa_xnew0(struct pollfd, num_fds);
|
||||
fdl->work_fds = pa_xnew(struct pollfd, num_fds);
|
||||
}
|
||||
|
||||
memset(fdl->work_fds, 0, sizeof(struct pollfd) * num_fds);
|
||||
|
||||
if (fdl->hctl)
|
||||
err = snd_hctl_poll_descriptors(fdl->hctl, fdl->work_fds, num_fds);
|
||||
else
|
||||
err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds);
|
||||
|
||||
if (err < 0) {
|
||||
pa_log_error("Unable to get poll descriptors: %s", pa_alsa_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
fdl->polled = false;
|
||||
|
||||
if (memcmp(fdl->fds, fdl->work_fds, sizeof(struct pollfd) * num_fds) == 0)
|
||||
return;
|
||||
|
||||
if (fdl->ios) {
|
||||
for (i = 0; i < fdl->num_fds; i++)
|
||||
a->io_free(fdl->ios[i]);
|
||||
|
||||
if (num_fds != fdl->num_fds) {
|
||||
pa_xfree(fdl->ios);
|
||||
fdl->ios = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fdl->ios)
|
||||
fdl->ios = pa_xnew(pa_io_event*, num_fds);
|
||||
|
||||
/* Swap pointers */
|
||||
temp = fdl->work_fds;
|
||||
fdl->work_fds = fdl->fds;
|
||||
fdl->fds = temp;
|
||||
|
||||
fdl->num_fds = num_fds;
|
||||
|
||||
for (i = 0;i < num_fds;i++)
|
||||
fdl->ios[i] = a->io_new(a, fdl->fds[i].fd,
|
||||
((fdl->fds[i].events & POLLIN) ? PA_IO_EVENT_INPUT : 0) |
|
||||
((fdl->fds[i].events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0),
|
||||
io_cb, fdl);
|
||||
}
|
||||
|
||||
struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) {
|
||||
struct pa_alsa_fdlist *fdl;
|
||||
|
||||
fdl = pa_xnew0(struct pa_alsa_fdlist, 1);
|
||||
|
||||
return fdl;
|
||||
}
|
||||
|
||||
void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) {
|
||||
pa_assert(fdl);
|
||||
|
||||
if (fdl->defer) {
|
||||
pa_assert(fdl->m);
|
||||
fdl->m->defer_free(fdl->defer);
|
||||
}
|
||||
|
||||
if (fdl->ios) {
|
||||
unsigned i;
|
||||
pa_assert(fdl->m);
|
||||
for (i = 0; i < fdl->num_fds; i++)
|
||||
fdl->m->io_free(fdl->ios[i]);
|
||||
pa_xfree(fdl->ios);
|
||||
}
|
||||
|
||||
if (fdl->fds)
|
||||
pa_xfree(fdl->fds);
|
||||
if (fdl->work_fds)
|
||||
pa_xfree(fdl->work_fds);
|
||||
|
||||
pa_xfree(fdl);
|
||||
}
|
||||
|
||||
/* We can listen to either a snd_hctl_t or a snd_mixer_t, but not both */
|
||||
int pa_alsa_fdlist_set_handle(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, snd_hctl_t *hctl_handle, pa_mainloop_api *m) {
|
||||
pa_assert(fdl);
|
||||
pa_assert(hctl_handle || mixer_handle);
|
||||
pa_assert(!(hctl_handle && mixer_handle));
|
||||
pa_assert(m);
|
||||
pa_assert(!fdl->m);
|
||||
|
||||
fdl->hctl = hctl_handle;
|
||||
fdl->mixer = mixer_handle;
|
||||
fdl->m = m;
|
||||
fdl->defer = m->defer_new(m, defer_cb, fdl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pa_alsa_mixer_pdata {
|
||||
pa_rtpoll *rtpoll;
|
||||
pa_rtpoll_item *poll_item;
|
||||
snd_mixer_t *mixer;
|
||||
};
|
||||
|
||||
struct pa_alsa_mixer_pdata *pa_alsa_mixer_pdata_new(void) {
|
||||
struct pa_alsa_mixer_pdata *pd;
|
||||
|
||||
pd = pa_xnew0(struct pa_alsa_mixer_pdata, 1);
|
||||
|
||||
return pd;
|
||||
}
|
||||
|
||||
void pa_alsa_mixer_pdata_free(struct pa_alsa_mixer_pdata *pd) {
|
||||
pa_assert(pd);
|
||||
|
||||
if (pd->poll_item) {
|
||||
pa_rtpoll_item_free(pd->poll_item);
|
||||
}
|
||||
|
||||
pa_xfree(pd);
|
||||
}
|
||||
|
||||
static int rtpoll_work_cb(pa_rtpoll_item *i) {
|
||||
struct pa_alsa_mixer_pdata *pd;
|
||||
struct pollfd *p;
|
||||
unsigned n_fds;
|
||||
unsigned short revents = 0;
|
||||
int err, ret = 0;
|
||||
|
||||
pd = pa_rtpoll_item_get_work_userdata(i);
|
||||
pa_assert_fp(pd);
|
||||
pa_assert_fp(i == pd->poll_item);
|
||||
|
||||
p = pa_rtpoll_item_get_pollfd(i, &n_fds);
|
||||
|
||||
if ((err = snd_mixer_poll_descriptors_revents(pd->mixer, p, n_fds, &revents)) < 0) {
|
||||
pa_log_error("Unable to get poll revent: %s", pa_alsa_strerror(err));
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (revents) {
|
||||
if (revents & (POLLNVAL | POLLERR)) {
|
||||
pa_log_debug("Device disconnected, stopping poll on mixer");
|
||||
goto fail;
|
||||
} else if (revents & POLLERR) {
|
||||
/* This shouldn't happen. */
|
||||
pa_log_error("Got a POLLERR (revents = %04x), stopping poll on mixer", revents);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = snd_mixer_handle_events(pd->mixer);
|
||||
|
||||
if (PA_LIKELY(err >= 0)) {
|
||||
pa_rtpoll_item_free(i);
|
||||
pa_alsa_set_mixer_rtpoll(pd, pd->mixer, pd->rtpoll);
|
||||
} else {
|
||||
pa_log_error("Error handling mixer event: %s", pa_alsa_strerror(err));
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
pa_rtpoll_item_free(i);
|
||||
|
||||
pd->poll_item = NULL;
|
||||
pd->rtpoll = NULL;
|
||||
pd->mixer = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata *pd, snd_mixer_t *mixer, pa_rtpoll *rtp) {
|
||||
pa_rtpoll_item *i;
|
||||
struct pollfd *p;
|
||||
int err, n;
|
||||
|
||||
pa_assert(pd);
|
||||
pa_assert(mixer);
|
||||
pa_assert(rtp);
|
||||
|
||||
if ((n = snd_mixer_poll_descriptors_count(mixer)) < 0) {
|
||||
pa_log("snd_mixer_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
|
||||
return -1;
|
||||
}
|
||||
else if (n == 0) {
|
||||
pa_log_warn("Mixer has no poll descriptors. Please control mixer from PulseAudio only.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = pa_rtpoll_item_new(rtp, PA_RTPOLL_LATE, (unsigned) n);
|
||||
|
||||
p = pa_rtpoll_item_get_pollfd(i, NULL);
|
||||
|
||||
memset(p, 0, sizeof(struct pollfd) * n);
|
||||
|
||||
if ((err = snd_mixer_poll_descriptors(mixer, p, (unsigned) n)) < 0) {
|
||||
pa_log_error("Unable to get poll descriptors: %s", pa_alsa_strerror(err));
|
||||
pa_rtpoll_item_free(i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pd->rtpoll = rtp;
|
||||
pd->poll_item = i;
|
||||
pd->mixer = mixer;
|
||||
|
||||
pa_rtpoll_item_set_work_callback(i, rtpoll_work_cb, pd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_MAX] = {
|
||||
[PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */
|
||||
|
||||
|
@ -438,7 +759,7 @@ void pa_alsa_path_free(pa_alsa_path *p) {
|
|||
}
|
||||
|
||||
pa_proplist_free(p->proplist);
|
||||
pa_xfree(p->available_group);
|
||||
pa_xfree(p->availability_group);
|
||||
pa_xfree(p->name);
|
||||
pa_xfree(p->description);
|
||||
pa_xfree(p->description_key);
|
||||
|
@ -3424,9 +3745,9 @@ static void mapping_free(pa_alsa_mapping *m) {
|
|||
static void profile_free(pa_alsa_profile *p) {
|
||||
pa_assert(p);
|
||||
|
||||
pa_xfree(p->profile.name);
|
||||
pa_xfree(p->profile.description);
|
||||
pa_xfree(p->profile.description_key);
|
||||
pa_xfree(p->name);
|
||||
pa_xfree(p->description);
|
||||
pa_xfree(p->description_key);
|
||||
pa_xfree(p->input_name);
|
||||
pa_xfree(p->output_name);
|
||||
|
||||
|
@ -3503,9 +3824,9 @@ static pa_alsa_profile *profile_get(pa_alsa_profile_set *ps, const char *name) {
|
|||
|
||||
p = pa_xnew0(pa_alsa_profile, 1);
|
||||
p->profile_set = ps;
|
||||
p->profile.name = pa_xstrdup(name);
|
||||
p->name = pa_xstrdup(name);
|
||||
|
||||
pa_hashmap_put(ps->profiles, p->profile.name, p);
|
||||
pa_hashmap_put(ps->profiles, p->name, p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -3693,8 +4014,8 @@ static int mapping_parse_description(pa_config_parser_state *state) {
|
|||
pa_xfree(m->description);
|
||||
m->description = pa_xstrdup(state->rvalue);
|
||||
} else if ((p = profile_get(ps, state->section))) {
|
||||
pa_xfree(p->profile.description);
|
||||
p->profile.description = pa_xstrdup(state->rvalue);
|
||||
pa_xfree(p->description);
|
||||
p->description = pa_xstrdup(state->rvalue);
|
||||
} else {
|
||||
pa_log("[%s:%u] Section name %s invalid.", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
|
@ -3716,8 +4037,8 @@ static int mapping_parse_description_key(pa_config_parser_state *state) {
|
|||
pa_xfree(m->description_key);
|
||||
m->description_key = pa_xstrdup(state->rvalue);
|
||||
} else if ((p = profile_get(ps, state->section))) {
|
||||
pa_xfree(p->profile.description_key);
|
||||
p->profile.description_key = pa_xstrdup(state->rvalue);
|
||||
pa_xfree(p->description_key);
|
||||
p->description_key = pa_xstrdup(state->rvalue);
|
||||
} else {
|
||||
pa_log("[%s:%u] Section name %s invalid.", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
|
@ -3745,7 +4066,7 @@ static int mapping_parse_priority(pa_config_parser_state *state) {
|
|||
if ((m = pa_alsa_mapping_get(ps, state->section)))
|
||||
m->priority = prio;
|
||||
else if ((p = profile_get(ps, state->section)))
|
||||
p->profile.priority = prio;
|
||||
p->priority = prio;
|
||||
else {
|
||||
pa_log("[%s:%u] Section name %s invalid.", state->filename, state->lineno, state->section);
|
||||
return -1;
|
||||
|
@ -3963,7 +4284,7 @@ fail:
|
|||
}
|
||||
|
||||
/* the logic is simple: if we see the jack in multiple paths */
|
||||
/* assign all those jacks to one available_group */
|
||||
/* assign all those jacks to one availability_group */
|
||||
static void mapping_group_available(pa_hashmap *paths)
|
||||
{
|
||||
void *state, *state2;
|
||||
|
@ -3975,34 +4296,34 @@ static void mapping_group_available(pa_hashmap *paths)
|
|||
const char *found = NULL;
|
||||
bool has_control = false;
|
||||
PA_LLIST_FOREACH(j, p->jacks) {
|
||||
if (!j->has_control || j->state_plugged == PA_AVAILABLE_NO)
|
||||
continue;
|
||||
has_control = true;
|
||||
j->state_plugged = PA_AVAILABLE_UNKNOWN;
|
||||
PA_HASHMAP_FOREACH(p2, paths, state2) {
|
||||
if (p2 == p)
|
||||
if (!j->has_control || j->state_plugged == PA_AVAILABLE_NO)
|
||||
continue;
|
||||
has_control = true;
|
||||
PA_HASHMAP_FOREACH(p2, paths, state2) {
|
||||
if (p2 == p)
|
||||
break;
|
||||
PA_LLIST_FOREACH(j2, p->jacks) {
|
||||
if (!j2->has_control || j->state_plugged == PA_AVAILABLE_NO)
|
||||
continue;
|
||||
if (pa_streq(j->name, j2->name)) {
|
||||
j2->state_plugged = PA_AVAILABLE_UNKNOWN;
|
||||
found = p2->available_group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
if (!has_control)
|
||||
continue;
|
||||
if (!found) {
|
||||
p->available_group = pa_sprintf_malloc("Legacy %d", num);
|
||||
} else {
|
||||
p->available_group = pa_xstrdup(found);
|
||||
}
|
||||
if (!found)
|
||||
PA_LLIST_FOREACH(j2, p2->jacks) {
|
||||
if (!j2->has_control || j2->state_plugged == PA_AVAILABLE_NO)
|
||||
continue;
|
||||
if (pa_streq(j->name, j2->name)) {
|
||||
j->state_plugged = PA_AVAILABLE_UNKNOWN;
|
||||
j2->state_plugged = PA_AVAILABLE_UNKNOWN;
|
||||
found = p2->availability_group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
if (!has_control)
|
||||
continue;
|
||||
if (!found) {
|
||||
p->availability_group = pa_sprintf_malloc("Legacy %d", num);
|
||||
} else {
|
||||
p->availability_group = pa_xstrdup(found);
|
||||
}
|
||||
if (!found)
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
@ -4180,13 +4501,13 @@ static void profile_set_add_auto_pair(
|
|||
|
||||
p = pa_xnew0(pa_alsa_profile, 1);
|
||||
p->profile_set = ps;
|
||||
p->profile.name = name;
|
||||
p->name = name;
|
||||
|
||||
if (m) {
|
||||
p->output_name = pa_xstrdup(m->name);
|
||||
p->output_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
pa_idxset_put(p->output_mappings, m, NULL);
|
||||
p->profile.priority += m->priority * 100;
|
||||
p->priority += m->priority * 100;
|
||||
p->fallback_output = m->fallback;
|
||||
}
|
||||
|
||||
|
@ -4194,11 +4515,11 @@ static void profile_set_add_auto_pair(
|
|||
p->input_name = pa_xstrdup(n->name);
|
||||
p->input_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
pa_idxset_put(p->input_mappings, n, NULL);
|
||||
p->profile.priority += n->priority;
|
||||
p->priority += n->priority;
|
||||
p->fallback_input = n->fallback;
|
||||
}
|
||||
|
||||
pa_hashmap_put(ps->profiles, p->profile.name, p);
|
||||
pa_hashmap_put(ps->profiles, p->name, p);
|
||||
}
|
||||
|
||||
static void profile_set_add_auto(pa_alsa_profile_set *ps) {
|
||||
|
@ -4236,7 +4557,7 @@ static int profile_verify(pa_alsa_profile *p) {
|
|||
{ "output:unknown-stereo+input:unknown-stereo", N_("Stereo Duplex") },
|
||||
{ "off", N_("Off") }
|
||||
};
|
||||
const char *description_key = p->profile.description_key ? p->profile.description_key : p->profile.name;
|
||||
const char *description_key = p->description_key ? p->description_key : p->name;
|
||||
|
||||
pa_assert(p);
|
||||
|
||||
|
@ -4262,7 +4583,7 @@ static int profile_verify(pa_alsa_profile *p) {
|
|||
continue;
|
||||
|
||||
if (!(m = pa_hashmap_get(p->profile_set->mappings, *name)) || m->direction == PA_ALSA_DIRECTION_INPUT) {
|
||||
pa_log("Profile '%s' refers to nonexistent mapping '%s'.", p->profile.name, *name);
|
||||
pa_log("Profile '%s' refers to nonexistent mapping '%s'.", p->name, *name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -4298,7 +4619,7 @@ static int profile_verify(pa_alsa_profile *p) {
|
|||
continue;
|
||||
|
||||
if (!(m = pa_hashmap_get(p->profile_set->mappings, *name)) || m->direction == PA_ALSA_DIRECTION_OUTPUT) {
|
||||
pa_log("Profile '%s' refers to nonexistent mapping '%s'.", p->profile.name, *name);
|
||||
pa_log("Profile '%s' refers to nonexistent mapping '%s'.", p->name, *name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -4313,16 +4634,16 @@ static int profile_verify(pa_alsa_profile *p) {
|
|||
}
|
||||
|
||||
if (!p->input_mappings && !p->output_mappings) {
|
||||
pa_log("Profile '%s' lacks mappings.", p->profile.name);
|
||||
pa_log("Profile '%s' lacks mappings.", p->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!p->profile.description)
|
||||
p->profile.description = pa_xstrdup(lookup_description(description_key,
|
||||
if (!p->description)
|
||||
p->description = pa_xstrdup(lookup_description(description_key,
|
||||
well_known_descriptions,
|
||||
PA_ELEMENTSOF(well_known_descriptions)));
|
||||
|
||||
if (!p->profile.description) {
|
||||
if (!p->description) {
|
||||
uint32_t idx;
|
||||
pa_alsa_mapping *m;
|
||||
char *ptr;
|
||||
|
@ -4347,7 +4668,7 @@ static int profile_verify(pa_alsa_profile *p) {
|
|||
}
|
||||
|
||||
fclose(f);
|
||||
p->profile.description = ptr;
|
||||
p->description = ptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -4359,11 +4680,11 @@ void pa_alsa_profile_dump(pa_alsa_profile *p) {
|
|||
pa_assert(p);
|
||||
|
||||
pa_log_debug("Profile %s (%s), input=%s, output=%s priority=%u, supported=%s n_input_mappings=%u, n_output_mappings=%u",
|
||||
p->profile.name,
|
||||
pa_strnull(p->profile.description),
|
||||
p->name,
|
||||
pa_strnull(p->description),
|
||||
pa_strnull(p->input_name),
|
||||
pa_strnull(p->output_name),
|
||||
p->profile.priority,
|
||||
p->priority,
|
||||
pa_yes_no(p->supported),
|
||||
p->input_mappings ? pa_idxset_size(p->input_mappings) : 0,
|
||||
p->output_mappings ? pa_idxset_size(p->output_mappings) : 0);
|
||||
|
@ -4703,8 +5024,7 @@ void pa_alsa_profile_set_probe(
|
|||
if (p->output_mappings) {
|
||||
PA_IDXSET_FOREACH(m, p->output_mappings, idx) {
|
||||
if (pa_hashmap_get(broken_outputs, m) == m) {
|
||||
pa_log_debug("Skipping profile %s - will not be able to open output:%s",
|
||||
p->profile.name, m->name);
|
||||
pa_log_debug("Skipping profile %s - will not be able to open output:%s", p->name, m->name);
|
||||
p->supported = false;
|
||||
break;
|
||||
}
|
||||
|
@ -4714,8 +5034,7 @@ void pa_alsa_profile_set_probe(
|
|||
if (p->input_mappings && p->supported) {
|
||||
PA_IDXSET_FOREACH(m, p->input_mappings, idx) {
|
||||
if (pa_hashmap_get(broken_inputs, m) == m) {
|
||||
pa_log_debug("Skipping profile %s - will not be able to open input:%s",
|
||||
p->profile.name, m->name);
|
||||
pa_log_debug("Skipping profile %s - will not be able to open input:%s", p->name, m->name);
|
||||
p->supported = false;
|
||||
break;
|
||||
}
|
||||
|
@ -4723,7 +5042,7 @@ void pa_alsa_profile_set_probe(
|
|||
}
|
||||
|
||||
if (p->supported)
|
||||
pa_log_debug("Looking at profile %s", p->profile.name);
|
||||
pa_log_debug("Looking at profile %s", p->name);
|
||||
|
||||
/* Check if we can open all new ones */
|
||||
if (p->output_mappings && p->supported)
|
||||
|
@ -4780,7 +5099,7 @@ void pa_alsa_profile_set_probe(
|
|||
continue;
|
||||
}
|
||||
|
||||
pa_log_debug("Profile %s supported.", p->profile.name);
|
||||
pa_log_debug("Profile %s supported.", p->name);
|
||||
|
||||
if (p->output_mappings)
|
||||
PA_IDXSET_FOREACH(m, p->output_mappings, idx)
|
||||
|
@ -4848,7 +5167,7 @@ void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *ps) {
|
|||
|
||||
PA_HASHMAP_FOREACH(p, ps->profiles, state) {
|
||||
if (!p->supported)
|
||||
pa_hashmap_remove_and_free(ps->profiles, p->profile.name);
|
||||
pa_hashmap_remove_and_free(ps->profiles, p->name);
|
||||
}
|
||||
|
||||
PA_HASHMAP_FOREACH(m, ps->mappings, state) {
|
||||
|
@ -4862,7 +5181,7 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */
|
|||
const char* description,
|
||||
pa_alsa_path *path,
|
||||
pa_alsa_setting *setting,
|
||||
pa_alsa_profile *cp,
|
||||
pa_card_profile *cp,
|
||||
pa_hashmap *extra, /* sink/source ports */
|
||||
pa_core *core) {
|
||||
|
||||
|
@ -4881,12 +5200,12 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */
|
|||
pa_device_port_new_data_set_description(&port_data, description);
|
||||
pa_device_port_new_data_set_direction(&port_data, path->direction == PA_ALSA_DIRECTION_OUTPUT ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
|
||||
pa_device_port_new_data_set_type(&port_data, path->device_port_type);
|
||||
pa_device_port_new_data_set_available_group(&port_data, path->available_group);
|
||||
pa_device_port_new_data_set_availability_group(&port_data, path->availability_group);
|
||||
|
||||
p = pa_device_port_new(core, &port_data, sizeof(pa_alsa_port_data));
|
||||
pa_device_port_new_data_done(&port_data);
|
||||
pa_assert(p);
|
||||
pa_hashmap_put(ports, p->port.name, p);
|
||||
pa_hashmap_put(ports, p->name, p);
|
||||
pa_proplist_update(p->proplist, PA_UPDATE_REPLACE, path->proplist);
|
||||
|
||||
data = PA_DEVICE_PORT_DATA(p);
|
||||
|
@ -4897,10 +5216,10 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */
|
|||
}
|
||||
|
||||
if (cp)
|
||||
pa_hashmap_put(p->profiles, cp->profile.name, cp);
|
||||
pa_hashmap_put(p->profiles, cp->name, cp);
|
||||
|
||||
if (extra) {
|
||||
pa_hashmap_put(extra, p->port.name, p);
|
||||
pa_hashmap_put(extra, p->name, p);
|
||||
}
|
||||
|
||||
return p;
|
||||
|
@ -4908,7 +5227,7 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */
|
|||
|
||||
void pa_alsa_path_set_add_ports(
|
||||
pa_alsa_path_set *ps,
|
||||
pa_alsa_profile *cp,
|
||||
pa_card_profile *cp,
|
||||
pa_hashmap *ports, /* card ports */
|
||||
pa_hashmap *extra, /* sink/source ports */
|
||||
pa_core *core) {
|
||||
|
@ -4927,7 +5246,7 @@ void pa_alsa_path_set_add_ports(
|
|||
* single entry */
|
||||
pa_device_port *port = device_port_alsa_init(ports, path->name,
|
||||
path->description, path, path->settings, cp, extra, core);
|
||||
port->port.priority = path->priority * 100;
|
||||
port->priority = path->priority * 100;
|
||||
|
||||
} else {
|
||||
pa_alsa_setting *s;
|
||||
|
@ -4943,7 +5262,7 @@ void pa_alsa_path_set_add_ports(
|
|||
d = pa_xstrdup(path->description);
|
||||
|
||||
port = device_port_alsa_init(ports, n, d, path, s, cp, extra, core);
|
||||
port->port.priority = path->priority * 100 + s->priority;
|
||||
port->priority = path->priority * 100 + s->priority;
|
||||
|
||||
pa_xfree(n);
|
||||
pa_xfree(d);
|
||||
|
|
|
@ -37,6 +37,7 @@ typedef struct pa_alsa_decibel_fix pa_alsa_decibel_fix;
|
|||
typedef struct pa_alsa_profile_set pa_alsa_profile_set;
|
||||
typedef struct pa_alsa_port_data pa_alsa_port_data;
|
||||
typedef struct pa_alsa_profile pa_alsa_profile;
|
||||
typedef struct pa_alsa_profile pa_card_profile;
|
||||
typedef struct pa_alsa_device pa_alsa_device;
|
||||
|
||||
typedef enum pa_alsa_switch_use {
|
||||
|
@ -99,8 +100,8 @@ struct pa_alsa_setting {
|
|||
struct pa_alsa_mixer {
|
||||
snd_mixer_t *mixer_handle;
|
||||
int card_index;
|
||||
bool used_for_probe_only:1;
|
||||
bool used_for_poll:1;
|
||||
bool used_for_probe_only:1;
|
||||
};
|
||||
|
||||
/* ALSA mixer element identifier */
|
||||
|
@ -207,7 +208,7 @@ struct pa_alsa_path {
|
|||
char *name;
|
||||
char *description_key;
|
||||
char *description;
|
||||
char *available_group;
|
||||
char *availability_group;
|
||||
pa_device_port_type_t device_port_type;
|
||||
unsigned priority;
|
||||
bool autodetect_eld_device;
|
||||
|
@ -357,6 +358,11 @@ struct pa_alsa_profile {
|
|||
|
||||
pa_alsa_profile_set *profile_set;
|
||||
|
||||
char *name;
|
||||
char *description;
|
||||
char *description_key;
|
||||
unsigned priority;
|
||||
|
||||
char *input_name;
|
||||
char *output_name;
|
||||
|
||||
|
@ -419,6 +425,18 @@ void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *s);
|
|||
|
||||
void pa_alsa_mixer_use_for_poll(pa_hashmap *mixers, snd_mixer_t *mixer_handle);
|
||||
|
||||
#if 0
|
||||
pa_alsa_fdlist *pa_alsa_fdlist_new(void);
|
||||
void pa_alsa_fdlist_free(pa_alsa_fdlist *fdl);
|
||||
int pa_alsa_fdlist_set_handle(pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, snd_hctl_t *hctl_handle, pa_mainloop_api* m);
|
||||
|
||||
/* Alternative for handling alsa mixer events in io-thread. */
|
||||
|
||||
pa_alsa_mixer_pdata *pa_alsa_mixer_pdata_new(void);
|
||||
void pa_alsa_mixer_pdata_free(pa_alsa_mixer_pdata *pd);
|
||||
int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata *pd, snd_mixer_t *mixer, pa_rtpoll *rtp);
|
||||
#endif
|
||||
|
||||
/* Data structure for inclusion in pa_device_port for alsa
|
||||
* sinks/sources. This contains nothing that needs to be freed
|
||||
* individually */
|
||||
|
|
|
@ -941,7 +941,7 @@ static void probe_volumes(pa_hashmap *hash, bool is_sink, snd_pcm_t *pcm_handle,
|
|||
pa_log_warn("Path %s is not a volume control", data->path->name);
|
||||
pa_hashmap_remove(data->paths, profile);
|
||||
} else
|
||||
pa_log_debug("Set up h/w volume using '%s' for %s:%s", path->name, profile, port->port.name);
|
||||
pa_log_debug("Set up h/w volume using '%s' for %s:%s", path->name, profile, port->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -962,7 +962,7 @@ static void ucm_add_port_combination(
|
|||
pa_alsa_ucm_device **pdevices,
|
||||
int num,
|
||||
pa_hashmap *ports,
|
||||
pa_alsa_profile *cp,
|
||||
pa_card_profile *cp,
|
||||
pa_core *core) {
|
||||
|
||||
pa_device_port *port;
|
||||
|
@ -1050,7 +1050,7 @@ static void ucm_add_port_combination(
|
|||
pa_device_port_new_data_set_type(&port_data, type);
|
||||
pa_device_port_new_data_set_direction(&port_data, is_sink ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
|
||||
if (jack)
|
||||
pa_device_port_new_data_set_available_group(&port_data, jack->name);
|
||||
pa_device_port_new_data_set_availability_group(&port_data, jack->name);
|
||||
|
||||
port = pa_device_port_new(core, &port_data, sizeof(pa_alsa_ucm_port_data));
|
||||
pa_device_port_new_data_done(&port_data);
|
||||
|
@ -1059,8 +1059,8 @@ static void ucm_add_port_combination(
|
|||
ucm_port_data_init(data, context->ucm, port, pdevices, num);
|
||||
port->impl_free = ucm_port_data_free;
|
||||
|
||||
pa_hashmap_put(ports, port->port.name, port);
|
||||
pa_log_debug("Add port %s: %s", port->port.name, port->port.description);
|
||||
pa_hashmap_put(ports, port->name, port);
|
||||
pa_log_debug("Add port %s: %s", port->name, port->description);
|
||||
|
||||
if (num == 1) {
|
||||
/* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination
|
||||
|
@ -1093,21 +1093,21 @@ static void ucm_add_port_combination(
|
|||
}
|
||||
}
|
||||
|
||||
port->port.priority = priority;
|
||||
port->priority = priority;
|
||||
|
||||
pa_xfree(name);
|
||||
pa_xfree(desc);
|
||||
|
||||
direction = is_sink ? "output" : "input";
|
||||
pa_log_debug("Port %s direction %s, priority %d", port->port.name, direction, priority);
|
||||
pa_log_debug("Port %s direction %s, priority %d", port->name, direction, priority);
|
||||
|
||||
if (cp) {
|
||||
pa_log_debug("Adding profile %s to port %s.", cp->profile.name, port->port.name);
|
||||
pa_hashmap_put(port->profiles, cp->profile.name, cp);
|
||||
pa_log_debug("Adding profile %s to port %s.", cp->name, port->name);
|
||||
pa_hashmap_put(port->profiles, cp->name, cp);
|
||||
}
|
||||
|
||||
if (hash) {
|
||||
pa_hashmap_put(hash, port->port.name, port);
|
||||
pa_hashmap_put(hash, port->name, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1195,7 +1195,7 @@ static void ucm_add_ports_combination(
|
|||
int dev_num,
|
||||
uint32_t map_index,
|
||||
pa_hashmap *ports,
|
||||
pa_alsa_profile *cp,
|
||||
pa_card_profile *cp,
|
||||
pa_core *core) {
|
||||
|
||||
pa_alsa_ucm_device *dev;
|
||||
|
@ -1252,7 +1252,7 @@ void pa_alsa_ucm_add_ports_combination(
|
|||
pa_alsa_ucm_mapping_context *context,
|
||||
bool is_sink,
|
||||
pa_hashmap *ports,
|
||||
pa_alsa_profile *cp,
|
||||
pa_card_profile *cp,
|
||||
pa_core *core) {
|
||||
|
||||
pa_alsa_ucm_device **pdevices;
|
||||
|
@ -1382,7 +1382,7 @@ int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *p
|
|||
PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) {
|
||||
const char *dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_NAME);
|
||||
|
||||
if (ucm_port_contains(port->port.name, dev_name, is_sink))
|
||||
if (ucm_port_contains(port->name, dev_name, is_sink))
|
||||
enable_devs[enable_num++] = dev_name;
|
||||
else {
|
||||
pa_log_debug("Disable ucm device %s", dev_name);
|
||||
|
@ -1723,14 +1723,14 @@ static int ucm_create_profile(
|
|||
|
||||
p = pa_xnew0(pa_alsa_profile, 1);
|
||||
p->profile_set = ps;
|
||||
p->profile.name = pa_xstrdup(verb_name);
|
||||
p->profile.description = pa_xstrdup(verb_desc);
|
||||
p->name = pa_xstrdup(verb_name);
|
||||
p->description = pa_xstrdup(verb_desc);
|
||||
|
||||
p->output_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
p->input_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
|
||||
p->supported = true;
|
||||
pa_hashmap_put(ps->profiles, p->profile.name, p);
|
||||
pa_hashmap_put(ps->profiles, p->name, p);
|
||||
|
||||
/* TODO: get profile priority from policy management */
|
||||
priority = verb->priority;
|
||||
|
@ -1751,7 +1751,7 @@ static int ucm_create_profile(
|
|||
pa_xfree(verb_cmp);
|
||||
}
|
||||
|
||||
p->profile.priority = priority;
|
||||
p->priority = priority;
|
||||
|
||||
PA_LLIST_FOREACH(dev, verb->devices) {
|
||||
pa_alsa_jack *jack;
|
||||
|
@ -1939,10 +1939,10 @@ static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set *
|
|||
|
||||
PA_HASHMAP_FOREACH(p, ps->profiles, state) {
|
||||
/* change verb */
|
||||
pa_log_info("Set ucm verb to %s", p->profile.name);
|
||||
pa_log_info("Set ucm verb to %s", p->name);
|
||||
|
||||
if ((snd_use_case_set(ucm->ucm_mgr, "_verb", p->profile.name)) < 0) {
|
||||
pa_log("Failed to set verb %s", p->profile.name);
|
||||
if ((snd_use_case_set(ucm->ucm_mgr, "_verb", p->name)) < 0) {
|
||||
pa_log("Failed to set verb %s", p->name);
|
||||
p->supported = false;
|
||||
continue;
|
||||
}
|
||||
|
@ -1982,7 +1982,7 @@ static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set *
|
|||
continue;
|
||||
}
|
||||
|
||||
pa_log_debug("Profile %s supported.", p->profile.name);
|
||||
pa_log_debug("Profile %s supported.", p->name);
|
||||
|
||||
PA_IDXSET_FOREACH(m, p->output_mappings, idx)
|
||||
if (!PA_UCM_IS_MODIFIER_MAPPING(m))
|
||||
|
@ -2345,7 +2345,7 @@ void pa_alsa_ucm_add_ports_combination(
|
|||
pa_alsa_ucm_mapping_context *context,
|
||||
bool is_sink,
|
||||
pa_hashmap *ports,
|
||||
pa_alsa_card_profile *cp,
|
||||
pa_card_profile *cp,
|
||||
pa_core *core) {
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ void pa_alsa_ucm_add_ports_combination(
|
|||
pa_alsa_ucm_mapping_context *context,
|
||||
bool is_sink,
|
||||
pa_hashmap *ports,
|
||||
pa_alsa_profile *cp,
|
||||
pa_card_profile *cp,
|
||||
pa_core *core);
|
||||
int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *port, bool is_sink);
|
||||
|
||||
|
|
|
@ -532,7 +532,7 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
if (!pa_channel_map_superset(&m->channel_map, map))
|
||||
continue;
|
||||
|
||||
pa_log_debug("Checking for superset %s (%s)", m->device.name, m->device.device_strings[0]);
|
||||
pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
|
||||
|
||||
pcm_handle = pa_alsa_open_by_device_id_mapping(
|
||||
dev_id,
|
||||
|
|
|
@ -51,11 +51,11 @@ void pa_device_port_new_data_set_available(pa_device_port_new_data *data, pa_ava
|
|||
data->available = available;
|
||||
}
|
||||
|
||||
void pa_device_port_new_data_set_available_group(pa_device_port_new_data *data, const char *group)
|
||||
void pa_device_port_new_data_set_availability_group(pa_device_port_new_data *data, const char *group)
|
||||
{
|
||||
pa_assert(data);
|
||||
pa_xfree(data->available_group);
|
||||
data->available_group = pa_xstrdup(group);
|
||||
pa_xfree(data->availability_group);
|
||||
data->availability_group = pa_xstrdup(group);
|
||||
}
|
||||
|
||||
void pa_device_port_new_data_set_direction(pa_device_port_new_data *data, pa_direction_t direction)
|
||||
|
@ -75,7 +75,7 @@ void pa_device_port_new_data_done(pa_device_port_new_data *data)
|
|||
pa_assert(data);
|
||||
pa_xfree(data->name);
|
||||
pa_xfree(data->description);
|
||||
pa_xfree(data->available_group);
|
||||
pa_xfree(data->availability_group);
|
||||
}
|
||||
|
||||
pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, size_t extra)
|
||||
|
@ -89,17 +89,20 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si
|
|||
|
||||
p = calloc(1, sizeof(pa_device_port) + extra);
|
||||
|
||||
p->port.name = data->name;
|
||||
p->port.name = p->name = data->name;
|
||||
data->name = NULL;
|
||||
p->port.description = data->description;
|
||||
p->port.description = p->description = data->description;
|
||||
data->description = NULL;
|
||||
p->port.priority = 0;
|
||||
p->priority = p->port.priority = 0;
|
||||
p->available = data->available;
|
||||
p->port.available = (enum acp_available) data->available;
|
||||
p->port.available_group = data->available_group;
|
||||
data->available_group = NULL;
|
||||
p->port.availability_group = p->availability_group = data->availability_group;
|
||||
data->availability_group = NULL;
|
||||
p->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
|
||||
p->direction = data->direction;
|
||||
p->port.direction = data->direction == PA_DIRECTION_OUTPUT ?
|
||||
ACP_DIRECTION_PLAYBACK : ACP_DIRECTION_CAPTURE;
|
||||
p->type = data->type;
|
||||
p->port.type = (enum acp_port_type) data->type;
|
||||
|
||||
p->proplist = pa_proplist_new();
|
||||
|
@ -110,15 +113,16 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si
|
|||
|
||||
void pa_device_port_set_available(pa_device_port *p, pa_available_t status)
|
||||
{
|
||||
enum acp_available old = p->port.available;
|
||||
pa_available_t old = p->available;
|
||||
|
||||
if (old == (enum acp_available) status)
|
||||
if (old == status)
|
||||
return;
|
||||
p->available = status;
|
||||
p->port.available = (enum acp_available) status;
|
||||
|
||||
if (p->card && p->card->events && p->card->events->port_available)
|
||||
p->card->events->port_available(p->card->user_data, p->port.index,
|
||||
old, (enum acp_available) status);
|
||||
(enum acp_available)old, p->port.available);
|
||||
}
|
||||
|
||||
bool pa_alsa_device_init_description(pa_proplist *p, pa_card *card) {
|
||||
|
|
|
@ -65,6 +65,18 @@ struct pa_device_port {
|
|||
|
||||
pa_card *card;
|
||||
|
||||
char *name;
|
||||
char *description;
|
||||
char *preferred_profile;
|
||||
pa_device_port_type_t type;
|
||||
|
||||
unsigned priority;
|
||||
pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
|
||||
char *availability_group; /* a string indentifier which determine the group of devices handling the available state simulteneously */
|
||||
|
||||
pa_direction_t direction;
|
||||
int64_t latency_offset;
|
||||
|
||||
pa_proplist *proplist;
|
||||
pa_hashmap *profiles;
|
||||
pa_dynarray prof;
|
||||
|
@ -81,7 +93,7 @@ typedef struct pa_device_port_new_data {
|
|||
char *name;
|
||||
char *description;
|
||||
pa_available_t available;
|
||||
char *available_group;
|
||||
char *availability_group;
|
||||
pa_direction_t direction;
|
||||
pa_device_port_type_t type;
|
||||
} pa_device_port_new_data;
|
||||
|
@ -90,7 +102,7 @@ pa_device_port_new_data *pa_device_port_new_data_init(pa_device_port_new_data *d
|
|||
void pa_device_port_new_data_set_name(pa_device_port_new_data *data, const char *name);
|
||||
void pa_device_port_new_data_set_description(pa_device_port_new_data *data, const char *description);
|
||||
void pa_device_port_new_data_set_available(pa_device_port_new_data *data, pa_available_t available);
|
||||
void pa_device_port_new_data_set_available_group(pa_device_port_new_data *data, const char *group);
|
||||
void pa_device_port_new_data_set_availability_group(pa_device_port_new_data *data, const char *group);
|
||||
void pa_device_port_new_data_set_direction(pa_device_port_new_data *data, pa_direction_t direction);
|
||||
void pa_device_port_new_data_set_type(pa_device_port_new_data *data, pa_device_port_type_t type);
|
||||
void pa_device_port_new_data_done(pa_device_port_new_data *data);
|
||||
|
|
|
@ -28,6 +28,9 @@ required-any = any
|
|||
state.plugged = unknown
|
||||
state.unplugged = unknown
|
||||
|
||||
[Jack Line - Input]
|
||||
required-any = any
|
||||
|
||||
[Element Capture]
|
||||
switch = mute
|
||||
volume = merge
|
||||
|
|
|
@ -29,6 +29,9 @@ required-any = any
|
|||
state.plugged = unknown
|
||||
state.unplugged = unknown
|
||||
|
||||
[Jack Mic - Input]
|
||||
required-any = any
|
||||
|
||||
[Element Capture]
|
||||
switch = mute
|
||||
volume = merge
|
||||
|
|
|
@ -52,6 +52,9 @@ state.unplugged = unknown
|
|||
[Jack Headphone Mic]
|
||||
required-any = any
|
||||
|
||||
[Jack Headphone - Output]
|
||||
required-any = any
|
||||
|
||||
[Element Hardware Master]
|
||||
switch = mute
|
||||
volume = merge
|
||||
|
|
|
@ -69,6 +69,9 @@ required-any = any
|
|||
state.plugged = unknown
|
||||
state.unplugged = unknown
|
||||
|
||||
[Jack Speaker - Output]
|
||||
required-any = any
|
||||
|
||||
[Element Hardware Master]
|
||||
switch = mute
|
||||
volume = merge
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
|
||||
|
||||
; [General]
|
||||
; type = ... # The device type. It's highly recommended to set a type for every path.
|
||||
; # See parse_type() in alsa-mixer.c for supported values.
|
||||
; priority = ... # Priority for this path
|
||||
; description-key = ... # The path description is looked up from a table in path_verify() in
|
||||
; # src/modules/alsa/alsa-mixer.c. By default the path name (i.e. the file name
|
||||
|
|
Loading…
Reference in a new issue