mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05:00
acp: sync with latests
This commit is contained in:
parent
bc35221210
commit
41db0f35b3
6 changed files with 468 additions and 11 deletions
|
|
@ -19,6 +19,7 @@ SUBSYSTEM!="sound", GOTO="pulseaudio_end"
|
||||||
ACTION!="change", GOTO="pulseaudio_end"
|
ACTION!="change", GOTO="pulseaudio_end"
|
||||||
KERNEL!="card*", GOTO="pulseaudio_end"
|
KERNEL!="card*", GOTO="pulseaudio_end"
|
||||||
SUBSYSTEMS=="usb", GOTO="pulseaudio_check_usb"
|
SUBSYSTEMS=="usb", GOTO="pulseaudio_check_usb"
|
||||||
|
SUBSYSTEMS=="pci", GOTO="pulseaudio_check_pci"
|
||||||
SUBSYSTEMS=="firewire", GOTO="pulseaudio_firewire_quirk"
|
SUBSYSTEMS=="firewire", GOTO="pulseaudio_firewire_quirk"
|
||||||
|
|
||||||
SUBSYSTEMS=="platform", DRIVERS=="thinkpad_acpi", ENV{PULSE_IGNORE}="1"
|
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"
|
ATTRS{idVendor}=="2f12", ATTRS{idProduct}=="0109", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
||||||
# ID 9886:002c is for the Astro A50 Gen4
|
# ID 9886:002c is for the Astro A50 Gen4
|
||||||
ATTRS{idVendor}=="9886", ATTRS{idProduct}=="002c", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
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 1038:1250 is for the Arctis 5
|
||||||
# ID 1037:12aa is for the Arctis 5 2019
|
# 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"
|
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"
|
LABEL="pulseaudio_firewire_quirk"
|
||||||
|
|
||||||
# Focusrite Saffire Pro 10/26 i/o has a quirk to disappear from IEEE 1394 bus when losing connections.
|
# Focusrite Saffire Pro 10/26 i/o has a quirk to disappear from IEEE 1394 bus when losing connections.
|
||||||
|
|
|
||||||
|
|
@ -1106,6 +1106,7 @@ struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props)
|
||||||
char device_id[16];
|
char device_id[16];
|
||||||
bool ignore_dB = false;
|
bool ignore_dB = false;
|
||||||
uint32_t profile_index;
|
uint32_t profile_index;
|
||||||
|
int res;
|
||||||
|
|
||||||
impl = calloc(1, sizeof(*impl));
|
impl = calloc(1, sizeof(*impl));
|
||||||
if (impl == NULL)
|
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();
|
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");
|
pa_log_info("Found UCM profiles");
|
||||||
impl->profile_set = pa_alsa_ucm_add_profile_set(&impl->ucm, &impl->ucm.default_channel_map);
|
impl->profile_set = pa_alsa_ucm_add_profile_set(&impl->ucm, &impl->ucm.default_channel_map);
|
||||||
} else {
|
} else {
|
||||||
impl->use_ucm = false;
|
impl->use_ucm = false;
|
||||||
impl->profile_set = pa_alsa_profile_set_new(profile_set, &impl->ucm.default_channel_map);
|
impl->profile_set = pa_alsa_profile_set_new(profile_set, &impl->ucm.default_channel_map);
|
||||||
}
|
}
|
||||||
if (impl->profile_set == NULL)
|
if (impl->profile_set == NULL) {
|
||||||
return NULL;
|
res = -ENOTSUP;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
impl->profile_set->ignore_dB = ignore_dB;
|
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);
|
init_eld_ctls(impl);
|
||||||
|
|
||||||
return &impl->card;
|
return &impl->card;
|
||||||
|
error:
|
||||||
|
pa_alsa_refcnt_dec();
|
||||||
|
free(impl);
|
||||||
|
errno = -res;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void acp_card_add_listener(struct acp_card *card,
|
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)
|
void acp_card_destroy(struct acp_card *card)
|
||||||
{
|
{
|
||||||
|
pa_card *impl = (pa_card *)card;
|
||||||
pa_alsa_refcnt_dec();
|
pa_alsa_refcnt_dec();
|
||||||
|
free(impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int acp_card_poll_descriptors_count(struct acp_card *card)
|
int acp_card_poll_descriptors_count(struct acp_card *card)
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) {
|
||||||
char *card_name;
|
char *card_name;
|
||||||
const char **verb_list;
|
const char **verb_list, *value;
|
||||||
int num_verbs, i, err = 0;
|
int num_verbs, i, err = 0;
|
||||||
|
|
||||||
/* support multiple card instances, address card directly by index */
|
/* support multiple card instances, address card directly by index */
|
||||||
card_name = pa_sprintf_malloc("hw:%i", card_index);
|
card_name = pa_sprintf_malloc("hw:%i", card_index);
|
||||||
if (card_name == NULL)
|
if (card_name == NULL)
|
||||||
return -ENOMEM;
|
return -PA_ALSA_ERR_UNSPECIFIED;
|
||||||
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
|
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* fallback longname: is UCM available for this card ? */
|
/* 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);
|
err = snd_card_get_name(card_index, &card_name);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pa_log("Card can't get card_name from card_index %d", card_index);
|
pa_log("Card can't get card_name from card_index %d", card_index);
|
||||||
|
err = -PA_ALSA_ERR_UNSPECIFIED;
|
||||||
goto name_fail;
|
goto name_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
|
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pa_log_info("UCM not available for card %s", card_name);
|
pa_log_info("UCM not available for card %s", card_name);
|
||||||
|
err = -PA_ALSA_ERR_UCM_OPEN;
|
||||||
goto ucm_mgr_fail;
|
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);
|
pa_log_info("UCM available for card %s", card_name);
|
||||||
|
|
||||||
/* get a list of all UCM verbs (profiles) for this card */
|
/* get a list of all UCM verbs (profiles) for this card */
|
||||||
num_verbs = snd_use_case_verb_list(ucm->ucm_mgr, &verb_list);
|
num_verbs = snd_use_case_verb_list(ucm->ucm_mgr, &verb_list);
|
||||||
if (num_verbs < 0) {
|
if (num_verbs < 0) {
|
||||||
pa_log("UCM verb list not found for %s", card_name);
|
pa_log("UCM verb list not found for %s", card_name);
|
||||||
|
err = -PA_ALSA_ERR_UNSPECIFIED;
|
||||||
goto ucm_verb_fail;
|
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) {
|
if (!ucm->verbs) {
|
||||||
pa_log("No UCM verb is valid for %s", card_name);
|
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);
|
snd_use_case_free_list(verb_list, num_verbs);
|
||||||
|
|
|
||||||
|
|
@ -1055,6 +1055,293 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
|
||||||
|
|
||||||
snd_ctl_close(ctl);
|
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
|
#endif
|
||||||
|
|
||||||
char *pa_alsa_get_driver_name(int card) {
|
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);
|
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) {
|
unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
|
||||||
static unsigned int all_rates[] = { 8000, 11025, 12000,
|
static unsigned int all_rates[] = { 8000, 11025, 12000,
|
||||||
16000, 22050, 24000,
|
16000, 22050, 24000,
|
||||||
|
|
@ -1165,9 +1450,7 @@ unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_
|
||||||
|
|
||||||
return rates;
|
return rates;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_format_t fallback_format) {
|
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[] = {
|
static const snd_pcm_format_t format_trans_to_pa[] = {
|
||||||
[SND_PCM_FORMAT_U8] = PA_SAMPLE_U8,
|
[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;
|
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)
|
void pa_alsa_mixer_free(pa_alsa_mixer *mixer)
|
||||||
{
|
{
|
||||||
if (mixer->mixer_handle)
|
if (mixer->mixer_handle)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,13 @@
|
||||||
|
|
||||||
#include "alsa-mixer.h"
|
#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(
|
int pa_alsa_set_hw_params(
|
||||||
snd_pcm_t *pcm_handle,
|
snd_pcm_t *pcm_handle,
|
||||||
pa_sample_spec *ss, /* modified at return */
|
pa_sample_spec *ss, /* modified at return */
|
||||||
|
|
@ -120,6 +127,16 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name);
|
||||||
#endif
|
#endif
|
||||||
bool pa_alsa_init_description(pa_proplist *p, pa_card *card);
|
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(int card);
|
||||||
char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm);
|
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(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_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);
|
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);
|
void pa_alsa_mixer_free(pa_alsa_mixer *mixer);
|
||||||
|
|
||||||
typedef struct pa_hdmi_eld pa_hdmi_eld;
|
typedef struct pa_hdmi_eld pa_hdmi_eld;
|
||||||
|
|
|
||||||
94
spa/plugins/alsa/mixer/profile-sets/audigy.conf
Normal file
94
spa/plugins/alsa/mixer/profile-sets/audigy.conf
Normal 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue