From 3021e8663b01ab847f04ac96ea942b3ccc2acc34 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Thu, 1 Nov 2018 14:33:09 +0200 Subject: steam fixes --- src/libasound.c | 24 +++++++++++ src/pcm.c | 124 +++++++++++++++++++++++++++++++++++++++++++------------- src/stubs.h | 10 ----- 3 files changed, 119 insertions(+), 39 deletions(-) diff --git a/src/libasound.c b/src/libasound.c index d7027e9..d1add52 100644 --- a/src/libasound.c +++ b/src/libasound.c @@ -307,12 +307,36 @@ snd_ctl_card_info_get_name(const snd_ctl_card_info_t *obj) return CARD_NAMES[obj->id]; } +const char* +snd_ctl_card_info_get_id(const snd_ctl_card_info_t *obj) +{ + return snd_ctl_card_info_get_name(obj); +} + +const char* +snd_ctl_card_info_get_driver(const snd_ctl_card_info_t *obj) +{ + return snd_ctl_card_info_get_name(obj); +} + +const char* +snd_ctl_card_info_get_longname(const snd_ctl_card_info_t *obj) +{ + return snd_ctl_card_info_get_name(obj); +} + const char* snd_ctl_card_info_get_mixername(const snd_ctl_card_info_t *obj) { return snd_ctl_card_info_get_name(obj); } +const char* +snd_ctl_card_info_get_components(const snd_ctl_card_info_t *obj) +{ + return snd_ctl_card_info_get_name(obj); +} + int snd_seq_query_next_port(snd_seq_t *handle, snd_seq_port_info_t *info) { diff --git a/src/pcm.c b/src/pcm.c index 9c2f763..c078a92 100644 --- a/src/pcm.c +++ b/src/pcm.c @@ -95,13 +95,16 @@ struct _snd_pcm_hw_params { snd_pcm_format_t supported[ARRAY_SIZE(SUPPORTED_FORMATS)]; unsigned int pchan[2], rchan[2], rate[2]; } limits; + int period_time; snd_pcm_format_t format; snd_pcm_access_t access; snd_pcm_stream_t stream; bool needs_conversion; // for unsupported formats }; -struct _snd_pcm_sw_params { char noop; }; +struct _snd_pcm_sw_params { + snd_pcm_uframes_t avail_min; +}; struct _snd_pcm { struct _snd_pcm_hw_params hw; @@ -239,6 +242,7 @@ snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mod dump_cap(name, &(*pcm)->hw.cap, &(*pcm)->hw.limits); (*pcm)->hw.format = SND_PCM_FORMAT_UNKNOWN; + (*pcm)->hw.period_time = -1; return 0; fail: @@ -310,12 +314,6 @@ snd_pcm_state(snd_pcm_t *pcm) return SND_PCM_STATE_OPEN; } -int -snd_pcm_wait(snd_pcm_t *pcm, int timeout) -{ - return 1; // we are always ready for io -} - snd_pcm_sframes_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes) { @@ -438,34 +436,61 @@ snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) return ret; } -snd_pcm_sframes_t -snd_pcm_avail_update(snd_pcm_t *pcm) +static uint64_t +get_time_ns(void) { - struct pollfd pfd[16]; - int nfds = sio_nfds(pcm->hdl); - assert((unsigned int)nfds < ARRAY_SIZE(pfd)); + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint64_t)ts.tv_sec * (uint64_t)1e9 + (uint64_t)ts.tv_nsec; +} + +int +snd_pcm_wait(snd_pcm_t *pcm, int timeout) +{ + while (1) { + const uint64_t start = get_time_ns(); + + struct pollfd pfd[16]; + int nfds = sio_nfds(pcm->hdl); + assert((unsigned int)nfds < ARRAY_SIZE(pfd)); + + const int want = (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN); + nfds = sio_pollfd(pcm->hdl, pfd, want); + + errno = 0; + while ((nfds = poll(pfd, nfds, timeout)) < 0) { + if (errno == EINVAL) { + WARNX1("poll EINVAL"); + goto nodata; + } else if (errno == EINTR) { + WARNX1("poll EINTR"); + goto nodata; + } else if (errno != EAGAIN) + goto nodata; // timeout + } - nfds = sio_pollfd(pcm->hdl, pfd, (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN)); + if (timeout > 0) { + const uint64_t delta = ((get_time_ns() - start) / 1e6); + if ((uint64_t)timeout <= delta) + goto nodata; // timeout; - // XXX: timeout should be period time/buffer time(?) - errno = 0; - while ((nfds = poll(pfd, nfds, -1)) < 0) { - if (errno == EINVAL) { - WARNX1("poll EINVAL"); - goto nodata; + timeout -= delta; } + + if (sio_revents(pcm->hdl, pfd) & want) + break; } + return 1; - const int revents = sio_revents(pcm->hdl, pfd); - if (!(revents & POLLOUT) && !(revents & POLLIN)) - goto nodata; +nodata: + return 0; +} +snd_pcm_sframes_t +snd_pcm_avail_update(snd_pcm_t *pcm) +{ + while (snd_pcm_wait(pcm, pcm->hw.period_time) && pcm->avail < pcm->sw.avail_min); return (pcm->avail > pcm->hw.par.appbufsz ? pcm->hw.par.appbufsz : pcm->avail); - -nodata: - // NOTE: returning 1, as some programs don't check the return value :/ (namely qwebengine) - // thus they SIGFPE by dividing by 0 or -1 - return 1; } snd_pcm_sframes_t @@ -477,7 +502,7 @@ snd_pcm_avail(snd_pcm_t *pcm) int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { - if (delayp) *delayp = pcm->written - pcm->position; + if (delayp) *delayp = (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? pcm->written - pcm->position : pcm->position - pcm->written); return 0; } @@ -844,6 +869,18 @@ snd_pcm_hw_params_set_buffer_size_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *para return 0; } +int +snd_pcm_hw_params_set_buffer_size_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val) +{ + return snd_pcm_hw_params_set_buffer_size_near(pcm, params, val); +} + +int +snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val) +{ + return snd_pcm_hw_params_set_buffer_size_near(pcm, params, &val); +} + int snd_pcm_hw_params_get_buffer_size_min(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val) { @@ -928,7 +965,22 @@ int snd_pcm_hw_params_get_periods_max(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { if (dir) *dir = 0; - if (val) *val = 32; + if (val) *val = params->par.appbufsz / params->par.round; + return 0; +} + +int +snd_pcm_hw_params_set_period_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir) +{ + params->period_time = val / (uint64_t)1e3; + return 0; +} + +int +snd_pcm_hw_params_set_period_time_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) +{ + if (dir) *dir = 0; + if (val) snd_pcm_hw_params_set_period_time(pcm, params, *val, 0); return 0; } @@ -950,6 +1002,13 @@ snd_pcm_sw_params_free(snd_pcm_sw_params_t *ptr) free(ptr); } +int +snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) +{ + pcm->sw = *params; + return 0; +} + int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) { @@ -957,6 +1016,13 @@ snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) return 0; } +int +snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val) +{ + params->avail_min = val; + return 0; +} + int snd_pcm_set_params(snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency) { diff --git a/src/stubs.h b/src/stubs.h index 4b49cbd..0b66678 100644 --- a/src/stubs.h +++ b/src/stubs.h @@ -118,10 +118,6 @@ void snd_ctl_elem_id_set_index(snd_ctl_elem_id_t *obj, unsigned int val) { WARNX void snd_ctl_card_info_clear(snd_ctl_card_info_t *obj) { WARNX1("stub"); } void snd_ctl_card_info_copy(snd_ctl_card_info_t *dst, const snd_ctl_card_info_t *src) { WARNX1("stub"); } int snd_ctl_card_info_get_card(const snd_ctl_card_info_t *obj) { WARNX1("stub"); return 0; } -const char *snd_ctl_card_info_get_id(const snd_ctl_card_info_t *obj) { WARNX1("stub"); return NULL; } -const char *snd_ctl_card_info_get_driver(const snd_ctl_card_info_t *obj) { WARNX1("stub"); return NULL; } -const char *snd_ctl_card_info_get_longname(const snd_ctl_card_info_t *obj) { WARNX1("stub"); return NULL; } -const char *snd_ctl_card_info_get_components(const snd_ctl_card_info_t *obj) { WARNX1("stub"); return NULL; } size_t snd_ctl_event_sizeof(void) { WARNX1("stub"); return 0; } int snd_ctl_event_malloc(snd_ctl_event_t **ptr) { WARNX1("stub"); return -1; } void snd_ctl_event_free(snd_ctl_event_t *obj) { WARNX1("stub"); } @@ -457,7 +453,6 @@ int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm, snd snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler) { WARNX1("stub"); return NULL; } int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info) { WARNX1("stub"); return 0; } int snd_pcm_hw_free(snd_pcm_t *pcm) { WARNX1("stub"); return 0; } -int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) { WARNX1("stub"); return 0; } int snd_pcm_hwsync(snd_pcm_t *pcm) { WARNX1("stub"); return 0; } int snd_pcm_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail, snd_htimestamp_t *tstamp) { WARNX1("stub"); return 0; } int snd_pcm_avail_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *availp, snd_pcm_sframes_t *delayp) { WARNX1("stub"); return 0; } @@ -542,11 +537,9 @@ int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, unsigne int snd_pcm_hw_params_get_period_time_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_get_period_time_max(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_test_period_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir) { WARNX1("stub"); return 0; } -int snd_pcm_hw_params_set_period_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_period_time_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_period_time_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_period_time_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *min, int *mindir, unsigned int *max, int *maxdir) { WARNX1("stub"); return 0; } -int snd_pcm_hw_params_set_period_time_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_period_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_period_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_test_period_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int dir) { WARNX1("stub"); return 0; } @@ -577,8 +570,6 @@ int snd_pcm_hw_params_set_buffer_time_near(snd_pcm_t *pcm, snd_pcm_hw_params_t * int snd_pcm_hw_params_set_buffer_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_buffer_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_test_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val) { WARNX1("stub"); return 0; } -int snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val) { WARNX1("stub"); return 0; } -int snd_pcm_hw_params_set_buffer_size_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_buffer_size_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_buffer_size_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *min, snd_pcm_uframes_t *max) { WARNX1("stub"); return 0; } int snd_pcm_hw_params_set_buffer_size_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val) { WARNX1("stub"); return 0; } @@ -590,7 +581,6 @@ int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *param int snd_pcm_sw_params_get_tstamp_mode(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_t *val) { WARNX1("stub"); return 0; } int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t val) { WARNX1("stub"); return 0; } int snd_pcm_sw_params_get_tstamp_type(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t *val) { WARNX1("stub"); return 0; } -int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val) { WARNX1("stub"); return 0; } int snd_pcm_sw_params_get_avail_min(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val) { WARNX1("stub"); return 0; } int snd_pcm_sw_params_set_period_event(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, int val) { WARNX1("stub"); return 0; } int snd_pcm_sw_params_get_period_event(const snd_pcm_sw_params_t *params, int *val) { WARNX1("stub"); return 0; } -- cgit v1.2.3