acp: sync with latests

This commit is contained in:
Wim Taymans 2020-09-30 12:56:05 +02:00
parent bc35221210
commit 41db0f35b3
6 changed files with 468 additions and 11 deletions

View file

@ -19,6 +19,7 @@ SUBSYSTEM!="sound", GOTO="pulseaudio_end"
ACTION!="change", GOTO="pulseaudio_end"
KERNEL!="card*", GOTO="pulseaudio_end"
SUBSYSTEMS=="usb", GOTO="pulseaudio_check_usb"
SUBSYSTEMS=="pci", GOTO="pulseaudio_check_pci"
SUBSYSTEMS=="firewire", GOTO="pulseaudio_firewire_quirk"
SUBSYSTEMS=="platform", DRIVERS=="thinkpad_acpi", ENV{PULSE_IGNORE}="1"
@ -121,6 +122,9 @@ ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="usb-g
ATTRS{idVendor}=="2f12", ATTRS{idProduct}=="0109", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# ID 9886:002c is for the Astro A50 Gen4
ATTRS{idVendor}=="9886", ATTRS{idProduct}=="002c", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# ID 1532:0520 is for the Razer Kraken Tournament Edition
ATTRS{idVendor}=="1532", ATTRS{idProduct}=="0520", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# ID 1038:1250 is for the Arctis 5
# ID 1037:12aa is for the Arctis 5 2019
@ -143,6 +147,16 @@ ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1703", ENV{ID_ID}="usb-HyperX_Cloud_
GOTO="pulseaudio_end"
LABEL="pulseaudio_check_pci"
# Creative SoundBlaster Audigy-based cards
# EMU10k2/CA0100/CA0102/CA10200
ATTRS{vendor}=="0x1102", ATTRS{device}=="0x0004", ENV{PULSE_PROFILE_SET}="audigy.conf"
# CA0108/CA10300
ATTRS{vendor}=="0x1102", ATTRS{device}=="0x0008", ENV{PULSE_PROFILE_SET}="audigy.conf"
GOTO="pulseaudio_end"
LABEL="pulseaudio_firewire_quirk"
# Focusrite Saffire Pro 10/26 i/o has a quirk to disappear from IEEE 1394 bus when losing connections.

View file

@ -1106,6 +1106,7 @@ struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props)
char device_id[16];
bool ignore_dB = false;
uint32_t profile_index;
int res;
impl = calloc(1, sizeof(*impl));
if (impl == NULL)
@ -1154,15 +1155,22 @@ struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props)
snd_config_update_free_global();
if (impl->use_ucm && !pa_alsa_ucm_query_profiles(&impl->ucm, card->index)) {
res = impl->use_ucm ? pa_alsa_ucm_query_profiles(&impl->ucm, card->index) : -1;
if (res == -PA_ALSA_ERR_UCM_LINKED) {
res = -ENOENT;
goto error;
}
if (res == 0) {
pa_log_info("Found UCM profiles");
impl->profile_set = pa_alsa_ucm_add_profile_set(&impl->ucm, &impl->ucm.default_channel_map);
} else {
impl->use_ucm = false;
impl->profile_set = pa_alsa_profile_set_new(profile_set, &impl->ucm.default_channel_map);
}
if (impl->profile_set == NULL)
return NULL;
if (impl->profile_set == NULL) {
res = -ENOTSUP;
goto error;
}
impl->profile_set->ignore_dB = ignore_dB;
@ -1197,6 +1205,11 @@ struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props)
init_eld_ctls(impl);
return &impl->card;
error:
pa_alsa_refcnt_dec();
free(impl);
errno = -res;
return NULL;
}
void acp_card_add_listener(struct acp_card *card,
@ -1209,7 +1222,9 @@ void acp_card_add_listener(struct acp_card *card,
void acp_card_destroy(struct acp_card *card)
{
pa_card *impl = (pa_card *)card;
pa_alsa_refcnt_dec();
free(impl);
}
int acp_card_poll_descriptors_count(struct acp_card *card)

View file

@ -742,13 +742,13 @@ static void append_lost_relationship(pa_alsa_ucm_device *dev) {
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) {
char *card_name;
const char **verb_list;
const char **verb_list, *value;
int num_verbs, i, err = 0;
/* support multiple card instances, address card directly by index */
card_name = pa_sprintf_malloc("hw:%i", card_index);
if (card_name == NULL)
return -ENOMEM;
return -PA_ALSA_ERR_UNSPECIFIED;
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
if (err < 0) {
/* fallback longname: is UCM available for this card ? */
@ -756,22 +756,36 @@ int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) {
err = snd_card_get_name(card_index, &card_name);
if (err < 0) {
pa_log("Card can't get card_name from card_index %d", card_index);
err = -PA_ALSA_ERR_UNSPECIFIED;
goto name_fail;
}
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
if (err < 0) {
pa_log_info("UCM not available for card %s", card_name);
err = -PA_ALSA_ERR_UCM_OPEN;
goto ucm_mgr_fail;
}
}
err = snd_use_case_get(ucm->ucm_mgr, "=Linked", &value);
if (err >= 0) {
if (strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
free((void *)value);
pa_log_info("Empty (linked) UCM for card %s", card_name);
err = -PA_ALSA_ERR_UCM_LINKED;
goto ucm_verb_fail;
}
free((void *)value);
}
pa_log_info("UCM available for card %s", card_name);
/* get a list of all UCM verbs (profiles) for this card */
num_verbs = snd_use_case_verb_list(ucm->ucm_mgr, &verb_list);
if (num_verbs < 0) {
pa_log("UCM verb list not found for %s", card_name);
err = -PA_ALSA_ERR_UNSPECIFIED;
goto ucm_verb_fail;
}
@ -791,7 +805,7 @@ int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) {
if (!ucm->verbs) {
pa_log("No UCM verb is valid for %s", card_name);
err = -1;
err = -PA_ALSA_ERR_UCM_NO_VERB;
}
snd_use_case_free_list(verb_list, num_verbs);

View file

@ -1055,6 +1055,293 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
snd_ctl_close(ctl);
}
int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
snd_pcm_state_t state;
snd_pcm_hw_params_t *hwparams;
int err;
pa_assert(pcm);
if (revents & POLLERR)
pa_log_debug("Got POLLERR from ALSA");
if (revents & POLLNVAL)
pa_log_warn("Got POLLNVAL from ALSA");
if (revents & POLLHUP)
pa_log_warn("Got POLLHUP from ALSA");
if (revents & POLLPRI)
pa_log_warn("Got POLLPRI from ALSA");
if (revents & POLLIN)
pa_log_debug("Got POLLIN from ALSA");
if (revents & POLLOUT)
pa_log_debug("Got POLLOUT from ALSA");
state = snd_pcm_state(pcm);
pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
/* Try to recover from this error */
switch (state) {
case SND_PCM_STATE_DISCONNECTED:
/* Do not try to recover */
pa_log_info("Device disconnected.");
return -1;
case SND_PCM_STATE_XRUN:
if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
return -1;
}
break;
case SND_PCM_STATE_SUSPENDED:
snd_pcm_hw_params_alloca(&hwparams);
if ((err = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(err));
return -1;
}
if (snd_pcm_hw_params_can_resume(hwparams)) {
/* Retry resume 3 times before giving up, then fallback to restarting the stream. */
for (int i = 0; i < 3; i++) {
if ((err = snd_pcm_resume(pcm)) == 0)
return 0;
if (err != -EAGAIN)
break;
pa_msleep(25);
}
pa_log_warn("Could not recover alsa device from SUSPENDED state, trying to restart PCM");
}
/* Fall through */
default:
snd_pcm_drop(pcm);
return 1;
}
return 0;
}
pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
int n, err;
struct pollfd *pollfd;
pa_rtpoll_item *item;
pa_assert(pcm);
if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
return NULL;
}
item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
pa_rtpoll_item_free(item);
return NULL;
}
return item;
}
snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
snd_pcm_sframes_t n;
size_t k;
pa_assert(pcm);
pa_assert(hwbuf_size > 0);
pa_assert(ss);
/* Some ALSA driver expose weird bugs, let's inform the user about
* what is going on */
n = snd_pcm_avail(pcm);
if (n <= 0)
return n;
k = (size_t) n * pa_frame_size(ss);
if (PA_UNLIKELY(k >= hwbuf_size * 5 ||
k >= pa_bytes_per_second(ss)*10)) {
PA_ONCE_BEGIN {
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
pa_log(ngettext("snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
(unsigned long) k),
(unsigned long) k,
(unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
pa_strnull(dn));
pa_xfree(dn);
pa_alsa_dump(PA_LOG_ERROR, pcm);
} PA_ONCE_END;
/* Mhmm, let's try not to fail completely */
n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
}
return n;
}
int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_status_t *status, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss,
bool capture) {
ssize_t k;
size_t abs_k;
int err;
snd_pcm_sframes_t avail = 0;
#if (SND_LIB_VERSION >= ((1<<16)|(1<<8)|0)) /* API additions in 1.1.0 */
snd_pcm_audio_tstamp_config_t tstamp_config;
#endif
pa_assert(pcm);
pa_assert(delay);
pa_assert(hwbuf_size > 0);
pa_assert(ss);
/* Some ALSA driver expose weird bugs, let's inform the user about
* what is going on. We're going to get both the avail and delay values so
* that we can compare and check them for capture.
* This is done with snd_pcm_status() which provides
* avail, delay and timestamp values in a single kernel call to improve
* timer-based scheduling */
#if (SND_LIB_VERSION >= ((1<<16)|(1<<8)|0)) /* API additions in 1.1.0 */
/* The time stamp configuration needs to be set so that the
* ALSA code will use the internal delay reported by the driver.
* The time stamp configuration was introduced in alsa version 1.1.0. */
tstamp_config.type_requested = 1; /* ALSA default time stamp type */
tstamp_config.report_delay = 1;
snd_pcm_status_set_audio_htstamp_config(status, &tstamp_config);
#endif
if ((err = snd_pcm_status(pcm, status)) < 0)
return err;
avail = snd_pcm_status_get_avail(status);
*delay = snd_pcm_status_get_delay(status);
k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
abs_k = k >= 0 ? (size_t) k : (size_t) -k;
if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
abs_k >= pa_bytes_per_second(ss)*10)) {
PA_ONCE_BEGIN {
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
pa_log(ngettext("snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
(signed long) k),
(signed long) k,
k < 0 ? "-" : "",
(unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
pa_strnull(dn));
pa_xfree(dn);
pa_alsa_dump(PA_LOG_ERROR, pcm);
} PA_ONCE_END;
/* Mhmm, let's try not to fail completely */
if (k < 0)
*delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
else
*delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
}
if (capture) {
abs_k = (size_t) avail * pa_frame_size(ss);
if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
abs_k >= pa_bytes_per_second(ss)*10)) {
PA_ONCE_BEGIN {
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
pa_log(ngettext("snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
(unsigned long) k),
(unsigned long) k,
(unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
pa_strnull(dn));
pa_xfree(dn);
pa_alsa_dump(PA_LOG_ERROR, pcm);
} PA_ONCE_END;
/* Mhmm, let's try not to fail completely */
avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
}
if (PA_UNLIKELY(*delay < avail)) {
PA_ONCE_BEGIN {
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
(unsigned long) *delay,
(unsigned long) avail,
pa_strnull(dn));
pa_xfree(dn);
pa_alsa_dump(PA_LOG_ERROR, pcm);
} PA_ONCE_END;
/* try to fixup */
*delay = avail;
}
}
return 0;
}
int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss) {
int r;
snd_pcm_uframes_t before;
size_t k;
pa_assert(pcm);
pa_assert(areas);
pa_assert(offset);
pa_assert(frames);
pa_assert(hwbuf_size > 0);
pa_assert(ss);
before = *frames;
r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
if (r < 0)
return r;
k = (size_t) *frames * pa_frame_size(ss);
if (PA_UNLIKELY(*frames > before ||
k >= hwbuf_size * 3 ||
k >= pa_bytes_per_second(ss)*10))
PA_ONCE_BEGIN {
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
pa_log(ngettext("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
(unsigned long) k),
(unsigned long) k,
(unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
pa_strnull(dn));
pa_xfree(dn);
pa_alsa_dump(PA_LOG_ERROR, pcm);
} PA_ONCE_END;
return r;
}
#endif
char *pa_alsa_get_driver_name(int card) {
@ -1112,9 +1399,7 @@ char *pa_alsa_get_reserve_name(const char *device) {
return pa_sprintf_malloc("Audio%i", i);
}
#endif
#if 0
unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
static unsigned int all_rates[] = { 8000, 11025, 12000,
16000, 22050, 24000,
@ -1165,9 +1450,7 @@ unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_
return rates;
}
#endif
#if 0
pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_format_t fallback_format) {
static const snd_pcm_format_t format_trans_to_pa[] = {
[SND_PCM_FORMAT_U8] = PA_SAMPLE_U8,
@ -1507,6 +1790,24 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool
return NULL;
}
#if 0
void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer_handle, pa_mainloop_api *ml)
{
pa_alsa_mixer *pm;
void *state;
PA_HASHMAP_FOREACH(pm, mixers, state)
if (pm->mixer_handle == mixer_handle) {
pm->used_for_probe_only = false;
if (!pm->fdl) {
pm->fdl = pa_alsa_fdlist_new();
if (pm->fdl)
pa_alsa_fdlist_set_handle(pm->fdl, pm->mixer_handle, NULL, ml);
}
}
}
#endif
void pa_alsa_mixer_free(pa_alsa_mixer *mixer)
{
if (mixer->mixer_handle)

View file

@ -29,6 +29,13 @@
#include "alsa-mixer.h"
enum {
PA_ALSA_ERR_UNSPECIFIED = 1,
PA_ALSA_ERR_UCM_OPEN = 1000,
PA_ALSA_ERR_UCM_NO_VERB = 1001,
PA_ALSA_ERR_UCM_LINKED = 1002
};
int pa_alsa_set_hw_params(
snd_pcm_t *pcm_handle,
pa_sample_spec *ss, /* modified at return */
@ -120,6 +127,16 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name);
#endif
bool pa_alsa_init_description(pa_proplist *p, pa_card *card);
#if 0
int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);
pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll);
snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss);
int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_status_t *status, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss, bool capture);
int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss);
#endif
char *pa_alsa_get_driver_name(int card);
char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm);
@ -143,7 +160,9 @@ snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, u
snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe);
snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe);
snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool probe);
#if 0
void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer, pa_mainloop_api *ml);
#endif
void pa_alsa_mixer_free(pa_alsa_mixer *mixer);
typedef struct pa_hdmi_eld pa_hdmi_eld;

View file

@ -0,0 +1,94 @@
# This file is part of PulseAudio.
#
# 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/>.
; Creative Sound Blaster Audigy product line
;
; These are just copies of the mappings we find in default.conf, with the
; small change of making analog-stereo and analog-mono non-fallback mappings.
; This is needed because these cards only support duplex profiles with mono
; inputs, and in the default configuration, with stereo being a fallback
; mapping, the mono mapping is never tried.
;
; See default.conf for an explanation on the directives used here.
[General]
auto-profiles = yes
# Based on stereo-fallback
[Mapping analog-stereo]
device-strings = hw:%f
channel-map = front-left,front-right
paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2
paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headphone-mic analog-input-headset-mic
priority = 1
# Based on mono-fallback
[Mapping analog-mono]
device-strings = hw:%f
channel-map = mono
paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2 analog-output-mono
paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headset-mic
priority = 1
# The rest of these are identical to what's in default.conf
[Mapping analog-surround-21]
device-strings = surround21:%f
channel-map = front-left,front-right,lfe
paths-output = analog-output analog-output-lineout analog-output-speaker
priority = 13
direction = output
[Mapping analog-surround-40]
device-strings = surround40:%f
channel-map = front-left,front-right,rear-left,rear-right
paths-output = analog-output analog-output-lineout analog-output-speaker
priority = 12
direction = output
[Mapping analog-surround-41]
device-strings = surround41:%f
channel-map = front-left,front-right,rear-left,rear-right,lfe
paths-output = analog-output analog-output-lineout analog-output-speaker
priority = 13
direction = output
[Mapping analog-surround-50]
device-strings = surround50:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center
paths-output = analog-output analog-output-lineout analog-output-speaker
priority = 12
direction = output
[Mapping analog-surround-51]
device-strings = surround51:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
paths-output = analog-output analog-output-lineout analog-output-speaker
priority = 13
direction = output
[Mapping analog-surround-71]
device-strings = surround71:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
description = Analog Surround 7.1
paths-output = analog-output analog-output-lineout analog-output-speaker
priority = 12
direction = output
[Mapping iec958-stereo]
device-strings = iec958:%f
channel-map = left,right
paths-input = iec958-stereo-input
paths-output = iec958-stereo-output
priority = 5