From: Abramo Bagnara Date: Fri, 29 Dec 2000 15:00:53 +0000 (+0000) Subject: PCM API cleaning. silencing implementation. xfer_min removal X-Git-Tag: v1.0.3~1038 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=8f1b27dfb8b649367fb62101ff7ad27b863396d0;p=alsa-lib.git PCM API cleaning. silencing implementation. xfer_min removal --- diff --git a/aserver/aserver.c b/aserver/aserver.c index d9c8abbf..d6dd0c3f 100644 --- a/aserver/aserver.c +++ b/aserver/aserver.c @@ -460,9 +460,6 @@ int pcm_shm_cmd(client_t *client) ctrl->result = snd_pcm_mmap_forward(pcm, ctrl->u.mmap_forward.frames); ctrl->appl_ptr = *pcm->appl_ptr; break; - case SND_PCM_IOCTL_SET_AVAIL_MIN: - ctrl->result = snd_pcm_set_avail_min(pcm, ctrl->u.set_avail_min.frames); - break; case SND_PCM_IOCTL_POLL_DESCRIPTOR: ctrl->result = 0; return shm_ack_fd(client, snd_pcm_poll_descriptor(pcm)); diff --git a/include/aserver.h b/include/aserver.h index 079dbb40..29b22678 100644 --- a/include/aserver.h +++ b/include/aserver.h @@ -30,7 +30,6 @@ #define SND_PCM_IOCTL_ASYNC _IO ('A', 0xf6) #define SND_PCM_IOCTL_CLOSE _IO ('A', 0xf7) #define SND_PCM_IOCTL_POLL_DESCRIPTOR _IO ('A', 0xf8) -#define SND_PCM_IOCTL_SET_AVAIL_MIN _IO ('A', 0xf9) typedef struct { long result; @@ -46,6 +45,7 @@ typedef struct { snd_pcm_hw_params_t hw_refine; snd_pcm_hw_params_t hw_params; snd_pcm_sw_params_t sw_params; + snd_pcm_sw_params_t sw_refine; snd_pcm_status_t status; struct { ssize_t frames; @@ -63,9 +63,6 @@ typedef struct { struct { ssize_t frames; } mmap_forward; - struct { - ssize_t frames; - } set_avail_min; } u; char data[0]; } snd_pcm_shm_ctrl_t; diff --git a/include/pcm.h b/include/pcm.h index 03ee123c..42ace3a8 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -59,6 +59,7 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock); int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid); int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info); int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); +int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); int snd_pcm_status(snd_pcm_t *pcm, snd_pcm_status_t *status); int snd_pcm_prepare(snd_pcm_t *pcm); @@ -78,11 +79,8 @@ ssize_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, size_t size); int snd_pcm_dump_hw_setup(snd_pcm_t *pcm, FILE *fp); int snd_pcm_dump_sw_setup(snd_pcm_t *pcm, FILE *fp); int snd_pcm_dump_setup(snd_pcm_t *pcm, FILE *fp); -int snd_pcm_dump_hw_params(snd_pcm_hw_params_t *params, FILE *fp); -int snd_pcm_dump_hw_params_fail(snd_pcm_hw_params_t *params, FILE *fp); -int snd_pcm_dump_sw_params_fail(snd_pcm_sw_params_t *params, FILE *fp); int snd_pcm_dump(snd_pcm_t *pcm, FILE *fp); -int snd_pcm_dump_status(snd_pcm_status_t *status, FILE *fp); +int snd_pcm_status_dump(snd_pcm_status_t *status, FILE *fp); int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2); int snd_pcm_unlink(snd_pcm_t *pcm); @@ -105,22 +103,40 @@ int mask_eq(const mask_t *a, const mask_t *b); int mask_single(const mask_t *mask); int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); -int snd_pcm_hw_params_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, + unsigned int var); +int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val); -int snd_pcm_hw_params_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val); -int snd_pcm_hw_params_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val); -int snd_pcm_hw_params_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int min, unsigned int max); -int snd_pcm_hw_params_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int par); -int snd_pcm_hw_params_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int par); -int snd_pcm_hw_params_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val); -int snd_pcm_hw_params_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, const mask_t *mask); +int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, + unsigned int var); +const mask_t *snd_pcm_hw_param_value_mask(const snd_pcm_hw_params_t *params, + unsigned int var); +const interval_t *snd_pcm_hw_param_value_interval(const snd_pcm_hw_params_t *params, + unsigned int var); +unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params, + unsigned int var); +unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params, + unsigned int var); +int snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm, + snd_pcm_hw_params_t *fail, + snd_pcm_hw_params_t *success, + unsigned int depth, + FILE *fp); + int snd_pcm_hw_params_info_rate(const snd_pcm_hw_params_t *params, unsigned int *rate_num, unsigned int *rate_den); @@ -128,48 +144,50 @@ int snd_pcm_hw_params_info_msbits(const snd_pcm_hw_params_t *params); int snd_pcm_hw_params_info_flags(const snd_pcm_hw_params_t *params); int snd_pcm_hw_params_info_fifo_size(const snd_pcm_hw_params_t *params); int snd_pcm_hw_params_info_dig_groups(const snd_pcm_hw_params_t *params); -int snd_pcm_hw_params_value(const snd_pcm_hw_params_t *params, - unsigned int var); -const mask_t *snd_pcm_hw_params_value_mask(const snd_pcm_hw_params_t *params, - unsigned int var); -const interval_t *snd_pcm_hw_params_value_interval(const snd_pcm_hw_params_t *params, - unsigned int var); -unsigned int snd_pcm_hw_params_value_min(const snd_pcm_hw_params_t *params, - unsigned int var); -unsigned int snd_pcm_hw_params_value_max(const snd_pcm_hw_params_t *params, - unsigned int var); -int snd_pcm_hw_params_test(const snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val); -int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); +int snd_pcm_hw_params_dump(snd_pcm_hw_params_t *params, FILE *fp); -typedef struct _snd_pcm_strategy snd_pcm_strategy_t; +typedef struct _snd_pcm_hw_strategy snd_pcm_hw_strategy_t; /* choices need to be sorted on ascending badness */ -typedef struct _snd_pcm_strategy_simple_choices_list { +typedef struct _snd_pcm_hw_strategy_simple_choices_list { unsigned int value; unsigned int badness; -} snd_pcm_strategy_simple_choices_list_t; - -int snd_pcm_hw_info_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *info, - const snd_pcm_strategy_t *strategy); - -int snd_pcm_strategy_free(snd_pcm_strategy_t *strategy); -int snd_pcm_strategy_simple(snd_pcm_strategy_t **strategyp, - unsigned int badness_min, - unsigned int badness_max); -int snd_pcm_strategy_simple_near(snd_pcm_strategy_t *strategy, int order, - unsigned int param, - unsigned int best, - unsigned int mul); -int snd_pcm_strategy_simple_choices(snd_pcm_strategy_t *strategy, int order, +} snd_pcm_hw_strategy_simple_choices_list_t; + +int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, + const snd_pcm_hw_strategy_t *strategy, + unsigned int badness_min, + unsigned int badness_max); + +int snd_pcm_hw_strategy_free(snd_pcm_hw_strategy_t *strategy); +int snd_pcm_hw_strategy_simple(snd_pcm_hw_strategy_t **strategyp, + unsigned int badness_min, + unsigned int badness_max); +int snd_pcm_hw_strategy_simple_near(snd_pcm_hw_strategy_t *strategy, int order, unsigned int param, - unsigned int count, - snd_pcm_strategy_simple_choices_list_t *choices); -int snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm, - snd_pcm_hw_params_t *fail, - snd_pcm_hw_params_t *success, - unsigned int depth, - FILE *fp); + unsigned int best, + unsigned int mul); +int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy, int order, + unsigned int param, + unsigned int count, + snd_pcm_hw_strategy_simple_choices_list_t *choices); + +#define SND_PCM_SW_PARAM_START_MODE 0 +#define SND_PCM_SW_PARAM_READY_MODE 1 +#define SND_PCM_SW_PARAM_XRUN_MODE 2 +#define SND_PCM_SW_PARAM_SILENCE_MODE 3 +#define SND_PCM_SW_PARAM_TSTAMP_MODE 4 +#define SND_PCM_SW_PARAM_AVAIL_MIN 5 +#define SND_PCM_SW_PARAM_XFER_ALIGN 6 +#define SND_PCM_SW_PARAM_SILENCE_THRESHOLD 7 +#define SND_PCM_SW_PARAM_SILENCE_SIZE 8 +#define SND_PCM_SW_PARAM_LAST 8 + +int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); +int snd_pcm_sw_param_set(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, unsigned int var, unsigned int val); +int snd_pcm_sw_param_near(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, unsigned int var, unsigned int val); +int snd_pcm_sw_param_value(snd_pcm_sw_params_t *params, unsigned int var); +int snd_pcm_sw_params_dump(snd_pcm_sw_params_t *params, FILE *fp); /* mmap */ const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm); @@ -183,14 +201,20 @@ ssize_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, size_t size); ssize_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, size_t size); ssize_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, size_t size); +const char *snd_pcm_stream_name(unsigned int stream); +const char *snd_pcm_hw_param_name(unsigned int params); +const char *snd_pcm_sw_param_name(unsigned int params); const char *snd_pcm_access_name(unsigned int access); const char *snd_pcm_format_name(unsigned int format); const char *snd_pcm_subformat_name(unsigned int subformat); -const char *snd_pcm_hw_param_name(unsigned int params); -const char *snd_pcm_sw_param_name(unsigned int params); - const char *snd_pcm_format_description(unsigned int format); int snd_pcm_format_value(const char* name); +const char *snd_pcm_start_mode_name(unsigned int mode); +const char *snd_pcm_ready_mode_name(unsigned int mode); +const char *snd_pcm_xrun_mode_name(unsigned int mode); +const char *snd_pcm_silence_mode_name(unsigned int mode); +const char *snd_pcm_tstamp_mode_name(unsigned int mode); +const char *snd_pcm_state_name(unsigned int state); int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, size_t dst_offset, size_t samples, int format); diff --git a/src/pcm/Makefile.am b/src/pcm/Makefile.am index 38e3892f..8e9d4075 100644 --- a/src/pcm/Makefile.am +++ b/src/pcm/Makefile.am @@ -5,7 +5,8 @@ libpcm_la_SOURCES = mask.c interval.c \ pcm.c pcm_hw.c pcm_plugin.c pcm_copy.c pcm_linear.c \ pcm_route.c pcm_mulaw.c pcm_alaw.c pcm_adpcm.c \ pcm_rate.c pcm_plug.c pcm_misc.c pcm_mmap.c pcm_multi.c \ - pcm_shm.c pcm_file.c pcm_share.c pcm_null.c pcm_params.c + pcm_shm.c pcm_file.c pcm_share.c pcm_null.c \ + pcm_params.c noinst_HEADERS = pcm_local.h pcm_plugin.h mask.h mask_inline.h \ interval.h interval_inline.h diff --git a/src/pcm/interval.c b/src/pcm/interval.c index 7e77fc18..081702ef 100644 --- a/src/pcm/interval.c +++ b/src/pcm/interval.c @@ -20,6 +20,7 @@ */ #define INTERVAL_C +#define INTERVAL_INLINE #include #include @@ -215,6 +216,30 @@ int interval_refine_set(interval_t *i, unsigned int val) return interval_refine(i, &t); } +/* a <- b + c */ +int interval_add(interval_t *a, const interval_t *b, const interval_t *c) +{ + interval_t t; + assert(!a->empty && !b->empty && !c->empty); + t.min = add(b->min, c->min); + t.openmin = (b->openmin || c->openmin); + t.max = add(b->max, c->max); + t.openmax = (b->openmax || c->openmax); + return interval_refine(a, &t); +} + +/* a <- b - c */ +int interval_sub(interval_t *a, const interval_t *b, const interval_t *c) +{ + interval_t t; + assert(!a->empty && !b->empty && !c->empty); + t.min = sub(b->min, c->max); + t.openmin = (b->openmin || c->openmax); + t.max = add(b->max, c->min); + t.openmax = (b->openmax || c->openmin); + return interval_refine(a, &t); +} + /* a <- b * c */ int interval_mul(interval_t *a, const interval_t *b, const interval_t *c) { diff --git a/src/pcm/interval.h b/src/pcm/interval.h index 6fd91f77..8c6e0d8d 100644 --- a/src/pcm/interval.h +++ b/src/pcm/interval.h @@ -21,10 +21,9 @@ #include -#ifdef INTERVAL_C +#ifdef INTERVAL_INLINE #include "interval_inline.h" -#endif - +#else void interval_all(interval_t *i); void interval_setreal(interval_t *i); int interval_empty(const interval_t *i); @@ -33,18 +32,22 @@ int interval_value(const interval_t *i); int interval_min(const interval_t *i); int interval_max(const interval_t *i); int interval_test(const interval_t *i, unsigned int val); -int interval_refine_min(interval_t *i, unsigned int min); -int interval_refine_max(interval_t *i, unsigned int max); -int interval_refine(interval_t *i, const interval_t *v); -int interval_refine_first(interval_t *i); -int interval_refine_last(interval_t *i); -int interval_refine_set(interval_t *i, unsigned int val); +void interval_copy(interval_t *dst, const interval_t *src); +int interval_eq(const interval_t *i1, const interval_t *i2); +#endif + +int interval_add(interval_t *a, const interval_t *b, const interval_t *c); +int interval_sub(interval_t *a, const interval_t *b, const interval_t *c); int interval_mul(interval_t *a, const interval_t *b, const interval_t *c); int interval_div(interval_t *a, const interval_t *b, const interval_t *c); int interval_muldivk(interval_t *a, unsigned int k, const interval_t *b, const interval_t *c); int interval_mulkdiv(interval_t *a, unsigned int k, const interval_t *b, const interval_t *c); -void interval_copy(interval_t *dst, const interval_t *src); void interval_print(const interval_t *i, FILE *fp); -int interval_eq(const interval_t *i1, const interval_t *i2); +int interval_refine_min(interval_t *i, unsigned int min); +int interval_refine_max(interval_t *i, unsigned int max); +int interval_refine(interval_t *i, const interval_t *v); +int interval_refine_first(interval_t *i); +int interval_refine_last(interval_t *i); +int interval_refine_set(interval_t *i, unsigned int val); diff --git a/src/pcm/interval_inline.h b/src/pcm/interval_inline.h index ceb11206..ae78bcf6 100644 --- a/src/pcm/interval_inline.h +++ b/src/pcm/interval_inline.h @@ -22,7 +22,7 @@ #ifdef INTERVAL_C #define INLINE inline #else -#define INLINE static inline +#define INLINE extern inline #endif INLINE void interval_all(interval_t *i) diff --git a/src/pcm/mask.c b/src/pcm/mask.c index 124ea7e9..68c2fa4c 100644 --- a/src/pcm/mask.c +++ b/src/pcm/mask.c @@ -20,6 +20,7 @@ */ #define MASK_C +#define MASK_INLINE #include #include diff --git a/src/pcm/mask.h b/src/pcm/mask.h index 8324bbdd..541c58b0 100644 --- a/src/pcm/mask.h +++ b/src/pcm/mask.h @@ -27,14 +27,14 @@ #define MASK_MAX 32 -#ifdef MASK_C +#ifdef MASK_INLINE #include "mask_inline.h" -#endif - +#else void mask_none(mask_t *mask); void mask_all(mask_t *mask); void mask_load(mask_t *mask, unsigned int msk); int mask_empty(const mask_t *mask); +int mask_full(const mask_t *mask); void mask_set(mask_t *mask, unsigned int val); void mask_reset(mask_t *mask, unsigned int val); void mask_copy(mask_t *mask, const mask_t *v); @@ -55,3 +55,4 @@ int mask_refine_min(mask_t *mask, unsigned int val); int mask_refine_max(mask_t *mask, unsigned int val); int mask_refine_set(mask_t *mask, unsigned int val); int mask_value(const mask_t *mask); +#endif diff --git a/src/pcm/mask_inline.h b/src/pcm/mask_inline.h index abfbfa46..7915f4ee 100644 --- a/src/pcm/mask_inline.h +++ b/src/pcm/mask_inline.h @@ -19,10 +19,17 @@ * */ +#include +#include + #ifdef MASK_C #define INLINE inline #else -#define INLINE static inline +#define INLINE extern inline +#endif + +#ifndef MASK_MASK +#define MASK_MAX 32 #endif struct _mask { @@ -90,6 +97,11 @@ INLINE int mask_empty(const mask_t *mask) return mask_bits(mask) == 0; } +INLINE int mask_full(const mask_t *mask) +{ + return mask_bits(mask) == ~0U; +} + INLINE unsigned int mask_count(const mask_t *mask) { return hweight32(mask_bits(mask)); diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 3f84ec82..b94d3208 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -94,24 +94,6 @@ int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info) return pcm->ops->info(pcm->op_arg, info); } -int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) -{ - int err; - assert(pcm && params); - assert(pcm->setup); - if ((err = pcm->ops->sw_params(pcm->op_arg, params)) < 0) - return err; - pcm->start_mode = params->start_mode; - pcm->ready_mode = params->ready_mode; - pcm->xrun_mode = params->xrun_mode; - pcm->avail_min = params->avail_min; - pcm->xfer_min = params->xfer_min; - pcm->xfer_align = params->xfer_align; - pcm->time = params->time; - pcm->boundary = params->boundary; - return 0; -} - int snd_pcm_status(snd_pcm_t *pcm, snd_pcm_status_t *status) { assert(pcm && status); @@ -182,19 +164,6 @@ ssize_t snd_pcm_rewind(snd_pcm_t *pcm, size_t frames) return pcm->fast_ops->rewind(pcm->fast_op_arg, frames); } -int snd_pcm_set_avail_min(snd_pcm_t *pcm, size_t frames) -{ - int err; - assert(pcm); - assert(pcm->setup); - assert(frames > 0); - err = pcm->fast_ops->set_avail_min(pcm->fast_op_arg, frames); - if (err < 0) - return err; - pcm->avail_min = frames; - return 0; -} - ssize_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, size_t size) { assert(pcm); @@ -311,6 +280,8 @@ int snd_pcm_poll_descriptor(snd_pcm_t *pcm) #define STREAM(v) [SND_PCM_STREAM_##v] = #v #define READY(v) [SND_PCM_READY_##v] = #v #define XRUN(v) [SND_PCM_XRUN_##v] = #v +#define SILENCE(v) [SND_PCM_SILENCE_##v] = #v +#define TSTAMP(v) [SND_PCM_TSTAMP_##v] = #v #define ACCESS(v) [SND_PCM_ACCESS_##v] = #v #define START(v) [SND_PCM_START_##v] = #v #define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v @@ -355,11 +326,13 @@ char *snd_pcm_hw_param_names[] = { char *snd_pcm_sw_param_names[] = { SW_PARAM(START_MODE), SW_PARAM(READY_MODE), + SW_PARAM(XRUN_MODE), + SW_PARAM(SILENCE_MODE), + SW_PARAM(TSTAMP_MODE), SW_PARAM(AVAIL_MIN), - SW_PARAM(XFER_MIN), SW_PARAM(XFER_ALIGN), - SW_PARAM(XRUN_MODE), - SW_PARAM(TIME), + SW_PARAM(SILENCE_THRESHOLD), + SW_PARAM(SILENCE_SIZE), }; char *snd_pcm_access_names[] = { @@ -447,32 +420,118 @@ char *snd_pcm_ready_mode_names[] = { }; char *snd_pcm_xrun_mode_names[] = { - XRUN(ASAP), XRUN(FRAGMENT), + XRUN(ASAP), XRUN(NONE), }; -static char *onoff[] = { - [0] = "OFF", - [1] = "ON", +char *snd_pcm_silence_mode_names[] = { + SILENCE(FRAGMENT), + SILENCE(ASAP), +}; + +char *snd_pcm_tstamp_mode_names[] = { + TSTAMP(NONE), + TSTAMP(MMAP), }; -#define assoc(value, names) ({ \ - unsigned int __v = value; \ - assert(__v < sizeof(names) / sizeof(names[0])); \ - names[__v]; \ -}) +const char *snd_pcm_stream_name(unsigned int stream) +{ + assert(stream <= SND_PCM_STREAM_LAST); + return snd_pcm_stream_names[stream]; +} + +const char *snd_pcm_access_name(unsigned int access) +{ + assert(access <= SND_PCM_ACCESS_LAST); + return snd_pcm_access_names[access]; +} + +const char *snd_pcm_format_name(unsigned int format) +{ + assert(format <= SND_PCM_FORMAT_LAST); + return snd_pcm_format_names[format]; +} + +const char *snd_pcm_format_description(unsigned int format) +{ + assert(format <= SND_PCM_FORMAT_LAST); + return snd_pcm_format_descriptions[format]; +} + +int snd_pcm_format_value(const char* name) +{ + unsigned int format; + for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) + if (snd_pcm_format_names[format] && + strcasecmp(name, snd_pcm_format_names[format]) == 0) + return format; + return -1; +} + +const char *snd_pcm_subformat_name(unsigned int subformat) +{ + assert(subformat <= SND_PCM_SUBFORMAT_LAST); + return snd_pcm_subformat_names[subformat]; +} + +const char *snd_pcm_hw_param_name(unsigned int param) +{ + assert(param <= SND_PCM_HW_PARAM_LAST); + return snd_pcm_hw_param_names[param]; +} +const char *snd_pcm_sw_param_name(unsigned int param) +{ + assert(param <= SND_PCM_SW_PARAM_LAST); + return snd_pcm_sw_param_names[param]; +} + +const char *snd_pcm_start_mode_name(unsigned int mode) +{ + assert(mode <= SND_PCM_START_LAST); + return snd_pcm_start_mode_names[mode]; +} + +const char *snd_pcm_ready_mode_name(unsigned int mode) +{ + assert(mode <= SND_PCM_READY_LAST); + return snd_pcm_ready_mode_names[mode]; +} + +const char *snd_pcm_xrun_mode_name(unsigned int mode) +{ + assert(mode <= SND_PCM_XRUN_LAST); + return snd_pcm_xrun_mode_names[mode]; +} + +const char *snd_pcm_silence_mode_name(unsigned int mode) +{ + assert(mode <= SND_PCM_SILENCE_LAST); + return snd_pcm_silence_mode_names[mode]; +} + +const char *snd_pcm_tstamp_mode_name(unsigned int mode) +{ + assert(mode <= SND_PCM_TSTAMP_LAST); + return snd_pcm_tstamp_mode_names[mode]; +} + +const char *snd_pcm_state_name(unsigned int state) +{ + assert(state <= SND_PCM_STATE_LAST); + return snd_pcm_state_names[state]; +} int snd_pcm_dump_hw_setup(snd_pcm_t *pcm, FILE *fp) { assert(pcm); assert(fp); assert(pcm->setup); - fprintf(fp, "stream : %s\n", assoc(pcm->stream, snd_pcm_stream_names)); - fprintf(fp, "access : %s\n", assoc(pcm->access, snd_pcm_access_names)); - fprintf(fp, "format : %s\n", assoc(pcm->format, snd_pcm_format_names)); - fprintf(fp, "subformat : %s\n", assoc(pcm->subformat, snd_pcm_subformat_names)); + fprintf(fp, "stream : %s\n", snd_pcm_stream_name(pcm->stream)); + fprintf(fp, "access : %s\n", snd_pcm_access_name(pcm->access)); + fprintf(fp, "format : %s\n", snd_pcm_format_name(pcm->format)); + fprintf(fp, "subformat : %s\n", snd_pcm_subformat_name(pcm->subformat)); fprintf(fp, "channels : %u\n", pcm->channels); fprintf(fp, "rate : %u\n", pcm->rate); fprintf(fp, "exact rate : %g (%u/%u)\n", (double) pcm->rate_num / pcm->rate_den, pcm->rate_num, pcm->rate_den); @@ -487,13 +546,15 @@ int snd_pcm_dump_sw_setup(snd_pcm_t *pcm, FILE *fp) assert(pcm); assert(fp); assert(pcm->setup); - fprintf(fp, "start_mode : %s\n", assoc(pcm->start_mode, snd_pcm_start_mode_names)); - fprintf(fp, "ready_mode : %s\n", assoc(pcm->ready_mode, snd_pcm_ready_mode_names)); - fprintf(fp, "xrun_mode : %s\n", assoc(pcm->xrun_mode, snd_pcm_xrun_mode_names)); + fprintf(fp, "start_mode : %s\n", snd_pcm_start_mode_name(pcm->start_mode)); + fprintf(fp, "xrun_mode : %s\n", snd_pcm_xrun_mode_name(pcm->xrun_mode)); + fprintf(fp, "ready_mode : %s\n", snd_pcm_ready_mode_name(pcm->ready_mode)); + fprintf(fp, "silence_mode : %s\n", snd_pcm_silence_mode_name(pcm->silence_mode)); + fprintf(fp, "tstamp_mode : %s\n", snd_pcm_tstamp_mode_name(pcm->tstamp_mode)); fprintf(fp, "avail_min : %ld\n", (long)pcm->avail_min); - fprintf(fp, "xfer_min : %ld\n", (long)pcm->xfer_min); fprintf(fp, "xfer_align : %ld\n", (long)pcm->xfer_align); - fprintf(fp, "time : %s\n", assoc(pcm->time, onoff)); + fprintf(fp, "silence_threshold: %ld\n", (long)pcm->silence_threshold); + fprintf(fp, "silence_size : %ld\n", (long)pcm->silence_size); fprintf(fp, "boundary : %ld\n", (long)pcm->boundary); return 0; } @@ -505,51 +566,10 @@ int snd_pcm_dump_setup(snd_pcm_t *pcm, FILE *fp) return 0; } -int snd_pcm_dump_sw_params_fail(snd_pcm_sw_params_t *params, FILE *fp) -{ - int k; - if (params->fail_mask == 0) { - fprintf(fp, "unknown sw_params failure reason\n"); - return 0; - } - fprintf(fp, "sw_params failed on the following field value(s):\n"); - for (k = 0; k <= SND_PCM_SW_PARAM_LAST; ++k) { - if (!(params->fail_mask & (1U << k))) - continue; - switch (k) { - case SND_PCM_SW_PARAM_START_MODE: - fprintf(fp, "start_mode: %s\n", assoc(params->start_mode, snd_pcm_start_mode_names)); - break; - case SND_PCM_SW_PARAM_READY_MODE: - fprintf(fp, "ready_mode: %s\n", assoc(params->ready_mode, snd_pcm_ready_mode_names)); - break; - case SND_PCM_SW_PARAM_XRUN_MODE: - fprintf(fp, "xrun_mode: %s\n", assoc(params->xrun_mode, snd_pcm_xrun_mode_names)); - break; - case SND_PCM_SW_PARAM_AVAIL_MIN: - fprintf(fp, "avail_min: %ld\n", (long)params->avail_min); - break; - case SND_PCM_SW_PARAM_XFER_MIN: - fprintf(fp, "xfer_min: %ld\n", (long)params->xfer_min); - break; - case SND_PCM_SW_PARAM_XFER_ALIGN: - fprintf(fp, "xfer_align: %ld\n", (long)params->xfer_align); - break; - case SND_PCM_SW_PARAM_TIME: - fprintf(fp, "time: %d\n", params->time); - break; - default: - assert(0); - break; - } - } - return 0; -} - -int snd_pcm_dump_status(snd_pcm_status_t *status, FILE *fp) +int snd_pcm_status_dump(snd_pcm_status_t *status, FILE *fp) { assert(status); - fprintf(fp, "state : %s\n", assoc(status->state, snd_pcm_state_names)); + fprintf(fp, "state : %s\n", snd_pcm_state_name(status->state)); fprintf(fp, "trigger_time: %ld.%06ld\n", status->trigger_time.tv_sec, status->trigger_time.tv_usec); fprintf(fp, "tstamp : %ld.%06ld\n", @@ -568,46 +588,6 @@ int snd_pcm_dump(snd_pcm_t *pcm, FILE *fp) return 0; } -const char *snd_pcm_access_name(unsigned int access) -{ - assert(access <= SND_PCM_ACCESS_LAST); - return snd_pcm_access_names[access]; -} - -const char *snd_pcm_format_name(unsigned int format) -{ - assert(format <= SND_PCM_FORMAT_LAST); - return snd_pcm_format_names[format]; -} - -const char *snd_pcm_format_description(unsigned int format) -{ - assert(format <= SND_PCM_FORMAT_LAST); - return snd_pcm_format_descriptions[format]; -} - -int snd_pcm_format_value(const char* name) -{ - unsigned int format; - for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) - if (snd_pcm_format_names[format] && - strcasecmp(name, snd_pcm_format_names[format]) == 0) - return format; - return -1; -} - -const char *snd_pcm_subformat_name(unsigned int subformat) -{ - assert(subformat <= SND_PCM_SUBFORMAT_LAST); - return snd_pcm_subformat_names[subformat]; -} - -const char *snd_pcm_hw_param_name(unsigned int param) -{ - assert(param <= SND_PCM_HW_PARAM_LAST); - return snd_pcm_hw_param_names[param]; -} - ssize_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes) { assert(pcm); diff --git a/src/pcm/pcm_adpcm.c b/src/pcm/pcm_adpcm.c index 4c184abb..41acc108 100644 --- a/src/pcm/pcm_adpcm.c +++ b/src/pcm/pcm_adpcm.c @@ -339,36 +339,36 @@ static int snd_pcm_adpcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) { mask_t *format_mask = alloca(mask_sizeof()); mask_load(format_mask, SND_PCM_FMTBIT_LINEAR); - err = _snd_pcm_hw_params_mask(params, 1, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; } else { - err = _snd_pcm_hw_params_set(params, 1, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FORMAT, SND_PCM_FORMAT_IMA_ADPCM); if (err < 0) return err; } - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); if (err < 0) return err; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, adpcm->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); err = snd_pcm_hw_refine2(params, &sparams, snd_pcm_hw_refine, slave, @@ -395,11 +395,11 @@ static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, adpcm->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); err = snd_pcm_hw_params2(params, &sparams, snd_pcm_hw_params, slave, @@ -415,7 +415,7 @@ static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) { - adpcm->getput_idx = get_index(snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT), SND_PCM_FORMAT_S16); + adpcm->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT), SND_PCM_FORMAT_S16); adpcm->func = adpcm_encode; } else { adpcm->getput_idx = put_index(SND_PCM_FORMAT_S16, adpcm->sformat); @@ -423,7 +423,7 @@ static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) } } else { if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) { - adpcm->getput_idx = put_index(SND_PCM_FORMAT_S16, snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT)); + adpcm->getput_idx = put_index(SND_PCM_FORMAT_S16, snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT)); adpcm->func = adpcm_decode; } else { adpcm->getput_idx = get_index(adpcm->sformat, SND_PCM_FORMAT_S16); @@ -432,7 +432,7 @@ static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) } if (adpcm->states) free(adpcm->states); - adpcm->states = malloc(snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_CHANNELS) * sizeof(*adpcm->states)); + adpcm->states = malloc(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS) * sizeof(*adpcm->states)); return 0; } diff --git a/src/pcm/pcm_alaw.c b/src/pcm/pcm_alaw.c index 8fd84589..feb60008 100644 --- a/src/pcm/pcm_alaw.c +++ b/src/pcm/pcm_alaw.c @@ -221,36 +221,36 @@ static int snd_pcm_alaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; if (alaw->sformat == SND_PCM_FORMAT_A_LAW) { mask_t *format_mask = alloca(mask_sizeof()); mask_load(format_mask, SND_PCM_FMTBIT_LINEAR); - err = _snd_pcm_hw_params_mask(params, 1, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; } else { - err = _snd_pcm_hw_params_set(params, 1, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FORMAT, SND_PCM_FORMAT_A_LAW); if (err < 0) return err; } - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); if (err < 0) return err; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, alaw->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); err = snd_pcm_hw_refine2(params, &sparams, snd_pcm_hw_refine, slave, @@ -277,11 +277,11 @@ static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, alaw->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); err = snd_pcm_hw_params2(params, &sparams, snd_pcm_hw_params, slave, @@ -297,7 +297,7 @@ static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { if (alaw->sformat == SND_PCM_FORMAT_A_LAW) { - alaw->getput_idx = get_index(snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT), SND_PCM_FORMAT_S16); + alaw->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT), SND_PCM_FORMAT_S16); alaw->func = alaw_encode; } else { alaw->getput_idx = put_index(SND_PCM_FORMAT_S16, alaw->sformat); @@ -305,7 +305,7 @@ static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) } } else { if (alaw->sformat == SND_PCM_FORMAT_A_LAW) { - alaw->getput_idx = put_index(SND_PCM_FORMAT_S16, snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT)); + alaw->getput_idx = put_index(SND_PCM_FORMAT_S16, snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT)); alaw->func = alaw_decode; } else { alaw->getput_idx = get_index(alaw->sformat, SND_PCM_FORMAT_S16); diff --git a/src/pcm/pcm_copy.c b/src/pcm/pcm_copy.c index 594ead57..cdba7cce 100644 --- a/src/pcm/pcm_copy.c +++ b/src/pcm/pcm_copy.c @@ -38,12 +38,12 @@ static int snd_pcm_copy_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); err = snd_pcm_hw_refine2(params, &sparams, snd_pcm_hw_refine, slave, @@ -64,7 +64,7 @@ static int snd_pcm_copy_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); err = snd_pcm_hw_params2(params, &sparams, snd_pcm_hw_params, slave, diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index 4a801405..98a39fea 100644 --- a/src/pcm/pcm_file.c +++ b/src/pcm/pcm_file.c @@ -254,12 +254,6 @@ static ssize_t snd_pcm_file_avail_update(snd_pcm_t *pcm) return snd_pcm_avail_update(file->slave); } -static int snd_pcm_file_set_avail_min(snd_pcm_t *pcm, size_t frames) -{ - snd_pcm_file_t *file = pcm->private; - return snd_pcm_set_avail_min(file->slave, frames); -} - static int snd_pcm_file_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) { snd_pcm_file_t *file = pcm->private; @@ -337,7 +331,6 @@ snd_pcm_fast_ops_t snd_pcm_file_fast_ops = { readn: snd_pcm_file_readn, avail_update: snd_pcm_file_avail_update, mmap_forward: snd_pcm_file_mmap_forward, - set_avail_min: snd_pcm_file_set_avail_min, }; int snd_pcm_file_open(snd_pcm_t **pcmp, char *name, char *fname, int fd, char *fmt, snd_pcm_t *slave, int close_slave) diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 77bf9d94..ebe34b5e 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -152,6 +152,17 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) { snd_pcm_hw_t *hw = pcm->private; int fd = hw->fd; + if (params->start_mode == pcm->start_mode && + params->ready_mode == pcm->ready_mode && + params->xrun_mode == pcm->xrun_mode && + params->silence_mode == pcm->silence_mode && + params->tstamp_mode == pcm->tstamp_mode && + params->xfer_align == pcm->xfer_align && + params->silence_threshold == pcm->silence_threshold && + params->silence_size == pcm->silence_size) { + hw->mmap_control->avail_min = params->avail_min; + return 0; + } if (ioctl(fd, SND_PCM_IOCTL_SW_PARAMS, params) < 0) { SYSERR("SND_PCM_IOCTL_SW_PARAMS failed"); return -errno; @@ -482,13 +493,6 @@ static ssize_t snd_pcm_hw_avail_update(snd_pcm_t *pcm) return avail; } -static int snd_pcm_hw_set_avail_min(snd_pcm_t *pcm, size_t frames) -{ - snd_pcm_hw_t *hw = pcm->private; - hw->mmap_control->avail_min = frames; - return 0; -} - static void snd_pcm_hw_dump(snd_pcm_t *pcm, FILE *fp) { snd_pcm_hw_t *hw = pcm->private; @@ -535,7 +539,6 @@ snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = { readn: snd_pcm_hw_readn, avail_update: snd_pcm_hw_avail_update, mmap_forward: snd_pcm_hw_mmap_forward, - set_avail_min: snd_pcm_hw_set_avail_min, }; int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdevice, int stream, int mode) diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c index 6fb66128..560c24ed 100644 --- a/src/pcm/pcm_linear.c +++ b/src/pcm/pcm_linear.c @@ -84,25 +84,25 @@ static int snd_pcm_linear_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN); mask_load(format_mask, SND_PCM_FMTBIT_LINEAR); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); if (err < 0) return err; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, linear->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); err = snd_pcm_hw_refine2(params, &sparams, snd_pcm_hw_refine, slave, @@ -129,11 +129,11 @@ static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, linear->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); err = snd_pcm_hw_params2(params, &sparams, snd_pcm_hw_params, slave, @@ -148,11 +148,11 @@ static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) - linear->conv_idx = conv_index(snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT), + linear->conv_idx = conv_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT), linear->sformat); else linear->conv_idx = conv_index(linear->sformat, - snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT)); + snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT)); return 0; } diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 5c354ab4..616554bf 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -86,7 +86,6 @@ typedef struct { ssize_t (*readn)(snd_pcm_t *pcm, void **bufs, size_t size); ssize_t (*avail_update)(snd_pcm_t *pcm); ssize_t (*mmap_forward)(snd_pcm_t *pcm, size_t size); - int (*set_avail_min)(snd_pcm_t *pcm, size_t frames); } snd_pcm_fast_ops_t; struct _snd_pcm { @@ -104,12 +103,15 @@ struct _snd_pcm { size_t fragment_size; /* fragment size */ unsigned int fragments; /* fragments */ unsigned int start_mode; /* start mode */ - unsigned int ready_mode; /* ready detection mode */ unsigned int xrun_mode; /* xrun detection mode */ + unsigned int ready_mode; /* ready detection mode */ + unsigned int tstamp_mode; /* timestamp mode */ size_t avail_min; /* min avail frames for wakeup */ - size_t xfer_min; /* xfer min size */ + unsigned int silence_mode; /* Silence filling mode */ + size_t silence_threshold; /* Silence filling happens when + noise is nearest than this */ + size_t silence_size; /* Silence filling size */ size_t xfer_align; /* xfer size need to be a multiple */ - unsigned int time: 1; /* timestamp switch */ size_t boundary; /* pointers wrap point */ unsigned int info; /* Info for returned setup */ unsigned int msbits; /* used most significant bits */ @@ -120,6 +122,7 @@ struct _snd_pcm { size_t bits_per_sample; size_t bits_per_frame; size_t *appl_ptr; + size_t min_align; volatile size_t *hw_ptr; int mmap_rw; snd_pcm_channel_info_t *mmap_channels; @@ -168,7 +171,6 @@ ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, snd_pcm_xfer_areas_func_t func); ssize_t snd_pcm_read_mmap(snd_pcm_t *pcm, size_t size); ssize_t snd_pcm_write_mmap(snd_pcm_t *pcm, size_t size); -int snd_pcm_hw_info_complete(snd_pcm_hw_params_t *info); int snd_pcm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info); int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info, int shmid); @@ -313,17 +315,17 @@ static inline int muldiv_near(int a, int b, int c) int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params); void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params); -int _snd_pcm_hw_params_mask(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params, int hw, unsigned int var, const mask_t *mask); -int _snd_pcm_hw_params_first(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, int hw, unsigned int var); -int _snd_pcm_hw_params_last(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, int hw, unsigned int var); -int _snd_pcm_hw_params_set(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params, int hw, unsigned int var, unsigned int val); -int _snd_pcm_hw_params_min(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params, int hw, unsigned int var, unsigned int val); -int _snd_pcm_hw_params_max(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, int hw, unsigned int var, unsigned int val); int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params, snd_pcm_hw_params_t *sparams, diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c index 010245e3..5f663464 100644 --- a/src/pcm/pcm_mulaw.c +++ b/src/pcm/pcm_mulaw.c @@ -238,37 +238,37 @@ static int snd_pcm_mulaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, - access_mask); + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + access_mask); if (err < 0) return err; if (mulaw->sformat == SND_PCM_FORMAT_MU_LAW) { mask_t *format_mask = alloca(mask_sizeof()); mask_load(format_mask, SND_PCM_FMTBIT_LINEAR); - err = _snd_pcm_hw_params_mask(params, 1, - SND_PCM_HW_PARAM_FORMAT, - format_mask); + err = _snd_pcm_hw_param_mask(params, 1, + SND_PCM_HW_PARAM_FORMAT, + format_mask); if (err < 0) return err; } else { - err = _snd_pcm_hw_params_set(params, 1, - SND_PCM_HW_PARAM_FORMAT, - SND_PCM_FORMAT_MU_LAW); + err = _snd_pcm_hw_param_set(params, 1, + SND_PCM_HW_PARAM_FORMAT, + SND_PCM_FORMAT_MU_LAW); if (err < 0) return err; } - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD); if (err < 0) return err; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, - saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - mulaw->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + saccess_mask); + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + mulaw->sformat); + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD); err = snd_pcm_hw_refine2(params, &sparams, snd_pcm_hw_refine, slave, SND_PCM_HW_PARBIT_CHANNELS | @@ -294,12 +294,12 @@ static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, - saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - mulaw->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + saccess_mask); + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + mulaw->sformat); + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD); err = snd_pcm_hw_params2(params, &sparams, snd_pcm_hw_params, slave, SND_PCM_HW_PARBIT_CHANNELS | @@ -314,7 +314,7 @@ static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { if (mulaw->sformat == SND_PCM_FORMAT_MU_LAW) { - mulaw->getput_idx = get_index(snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT), SND_PCM_FORMAT_S16); + mulaw->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT), SND_PCM_FORMAT_S16); mulaw->func = mulaw_encode; } else { mulaw->getput_idx = put_index(SND_PCM_FORMAT_S16, mulaw->sformat); @@ -322,7 +322,7 @@ static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) } } else { if (mulaw->sformat == SND_PCM_FORMAT_MU_LAW) { - mulaw->getput_idx = put_index(SND_PCM_FORMAT_S16, snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT)); + mulaw->getput_idx = put_index(SND_PCM_FORMAT_S16, snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT)); mulaw->func = mulaw_decode; } else { mulaw->getput_idx = get_index(mulaw->sformat, SND_PCM_FORMAT_S16); diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index c4e5f425..4cb55f8d 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -103,7 +103,7 @@ static int snd_pcm_multi_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_hw_params_t sparams; int changed = 0; int err; - const mask_t *access_mask = snd_pcm_hw_params_value_mask(params, SND_PCM_HW_PARAM_ACCESS); + const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS); mask_t *saccess_mask = alloca(mask_sizeof()); if (mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) || mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) @@ -122,7 +122,7 @@ static int snd_pcm_multi_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) } } - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_CHANNELS, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_CHANNELS, multi->channels_count); if (err < 0) return err; @@ -131,10 +131,10 @@ static int snd_pcm_multi_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) for (k = 0; k < multi->slaves_count; ++k) { snd_pcm_t *slave = multi->slaves[k].pcm; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, multi->slaves[k].channels_count); err = snd_pcm_hw_refine2(params, &sparams, @@ -161,7 +161,7 @@ static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_multi_t *multi = pcm->private; unsigned int k; int err; - const mask_t *access_mask = snd_pcm_hw_params_value_mask(params, SND_PCM_HW_PARAM_ACCESS); + const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS); mask_t *saccess_mask = alloca(mask_sizeof()); if (mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) || mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) @@ -183,9 +183,9 @@ static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_t *slave = multi->slaves[k].pcm; snd_pcm_hw_params_t sparams; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, multi->slaves[k].channels_count); err = snd_pcm_hw_params2(params, &sparams, snd_pcm_hw_params, slave, @@ -347,12 +347,6 @@ static ssize_t snd_pcm_multi_mmap_forward(snd_pcm_t *pcm, size_t size) return size; } -static int snd_pcm_multi_set_avail_min(snd_pcm_t *pcm, size_t frames) -{ - snd_pcm_multi_t *multi = pcm->private; - return snd_pcm_set_avail_min(multi->slaves[0].pcm, frames); -} - static int snd_pcm_multi_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) { return 0; @@ -425,7 +419,6 @@ snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = { rewind: snd_pcm_multi_rewind, avail_update: snd_pcm_multi_avail_update, mmap_forward: snd_pcm_multi_mmap_forward, - set_avail_min: snd_pcm_multi_set_avail_min, }; int snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c index 0e3ad1aa..3390e49c 100644 --- a/src/pcm/pcm_null.c +++ b/src/pcm/pcm_null.c @@ -229,17 +229,11 @@ static ssize_t snd_pcm_null_avail_update(snd_pcm_t *pcm) return pcm->buffer_size; } -static int snd_pcm_null_set_avail_min(snd_pcm_t *pcm, size_t frames) -{ - pcm->avail_min = frames; - return 0; -} - static int snd_pcm_null_hw_refine(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params) { - _snd_pcm_hw_refine(params); + int err = _snd_pcm_hw_refine(params); params->fifo_size = 0; - return 0; + return err; } static int snd_pcm_null_hw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t * params ATTRIBUTE_UNUSED) @@ -247,20 +241,8 @@ static int snd_pcm_null_hw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_pa return 0; } -static int snd_pcm_null_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params) +static int snd_pcm_null_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED) { - if (params->start_mode > SND_PCM_START_LAST) { - params->fail_mask = 1 << SND_PCM_SW_PARAM_START_MODE; - return -EINVAL; - } - if (params->ready_mode > SND_PCM_READY_LAST) { - params->fail_mask = 1 << SND_PCM_SW_PARAM_READY_MODE; - return -EINVAL; - } - if (params->xrun_mode > SND_PCM_XRUN_LAST) { - params->fail_mask = 1 << SND_PCM_SW_PARAM_XRUN_MODE; - return -EINVAL; - } return 0; } @@ -330,7 +312,6 @@ snd_pcm_fast_ops_t snd_pcm_null_fast_ops = { readn: snd_pcm_null_readn, avail_update: snd_pcm_null_avail_update, mmap_forward: snd_pcm_null_mmap_forward, - set_avail_min: snd_pcm_null_set_avail_min, }; int snd_pcm_null_open(snd_pcm_t **pcmp, char *name, int stream, int mode) diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c index 8e4bf9b7..324e62c4 100644 --- a/src/pcm/pcm_params.c +++ b/src/pcm/pcm_params.c @@ -20,7 +20,8 @@ */ #include "pcm_local.h" -#include "interval_inline.h" +#define INTERVAL_INLINE +#define MASK_INLINE #include "interval.h" #include "mask.h" @@ -38,60 +39,75 @@ static inline unsigned int sub(unsigned int a, unsigned int b) return 0; } -static inline int is_mask(int var) +static inline int hw_is_mask(int var) { return var >= SND_PCM_HW_PARAM_FIRST_MASK && var <= SND_PCM_HW_PARAM_LAST_MASK; } -static inline int is_interval(int var) +static inline int hw_is_interval(int var) { return var >= SND_PCM_HW_PARAM_FIRST_INTERVAL && var <= SND_PCM_HW_PARAM_LAST_INTERVAL; } -static inline mask_t *params_mask(snd_pcm_hw_params_t *params, +static inline mask_t *hw_param_mask(snd_pcm_hw_params_t *params, unsigned int var) { - assert(is_mask(var)); + assert(hw_is_mask(var)); return (mask_t*)¶ms->masks[var - SND_PCM_HW_PARAM_FIRST_MASK]; } -static inline interval_t *params_interval(snd_pcm_hw_params_t *params, +static inline interval_t *hw_param_interval(snd_pcm_hw_params_t *params, unsigned int var) { - assert(is_interval(var)); + assert(hw_is_interval(var)); return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL]; } -static inline const mask_t *params_mask_c(const snd_pcm_hw_params_t *params, +static inline const mask_t *hw_param_mask_c(const snd_pcm_hw_params_t *params, unsigned int var) { - return (const mask_t *)params_mask((snd_pcm_hw_params_t*) params, var); + return (const mask_t *)hw_param_mask((snd_pcm_hw_params_t*) params, var); } -static inline const interval_t *params_interval_c(const snd_pcm_hw_params_t *params, +static inline const interval_t *hw_param_interval_c(const snd_pcm_hw_params_t *params, unsigned int var) { - return (const interval_t *)params_interval((snd_pcm_hw_params_t*) params, var); + return (const interval_t *)hw_param_interval((snd_pcm_hw_params_t*) params, var); +} + +void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, unsigned int var) +{ + if (hw_is_mask(var)) { + mask_all(hw_param_mask(params, var)); + params->appl_cmask |= 1 << var; + return; + } + if (hw_is_interval(var)) { + interval_all(hw_param_interval(params, var)); + params->appl_cmask |= 1 << var; + return; + } + assert(0); +} + +int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, + unsigned int var) +{ + _snd_pcm_hw_param_any(params, var); + return snd_pcm_hw_refine(pcm, params); } void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params) { unsigned int k; memset(params, 0, sizeof(*params)); - for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++) { - mask_all(params_mask(params, k)); - params->appl_cmask |= 1 << k; - } - - for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++) { - interval_all(params_interval(params, k)); - params->appl_cmask |= 1 << k; - } - interval_setreal(params_interval(params, SND_PCM_HW_PARAM_RATE)); - interval_setreal(params_interval(params, SND_PCM_HW_PARAM_FRAGMENT_LENGTH)); - interval_setreal(params_interval(params, SND_PCM_HW_PARAM_BUFFER_LENGTH)); + for (k = 0; k <= SND_PCM_HW_PARAM_LAST; k++) + _snd_pcm_hw_param_any(params, k); + interval_setreal(hw_param_interval(params, SND_PCM_HW_PARAM_RATE)); + interval_setreal(hw_param_interval(params, SND_PCM_HW_PARAM_FRAGMENT_LENGTH)); + interval_setreal(hw_param_interval(params, SND_PCM_HW_PARAM_BUFFER_LENGTH)); params->info = ~0U; } @@ -105,17 +121,17 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) /* Return the value for field PAR if it's fixed in configuration space defined by PARAMS. Return -EINVAL otherwise */ -int snd_pcm_hw_params_value(const snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, unsigned int var) { - if (is_mask(var)) { - const mask_t *mask = params_mask_c(params, var); + if (hw_is_mask(var)) { + const mask_t *mask = hw_param_mask_c(params, var); if (!mask_single(mask)) return -EINVAL; return mask_value(mask); } - if (is_interval(var)) { - const interval_t *i = params_interval_c(params, var); + if (hw_is_interval(var)) { + const interval_t *i = hw_param_interval_c(params, var); if (!interval_single(i)) return -EINVAL; return interval_value(i); @@ -125,28 +141,28 @@ int snd_pcm_hw_params_value(const snd_pcm_hw_params_t *params, } /* Return the minimum value for field PAR. */ -unsigned int snd_pcm_hw_params_value_min(const snd_pcm_hw_params_t *params, +unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params, unsigned int var) { - if (is_mask(var)) { - return mask_min(params_mask_c(params, var)); + if (hw_is_mask(var)) { + return mask_min(hw_param_mask_c(params, var)); } - if (is_interval(var)) { - return interval_min(params_interval_c(params, var)); + if (hw_is_interval(var)) { + return interval_min(hw_param_interval_c(params, var)); } assert(0); return -EINVAL; } /* Return the maximum value for field PAR. */ -unsigned int snd_pcm_hw_params_value_max(const snd_pcm_hw_params_t *params, +unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params, unsigned int var) { - if (is_mask(var)) { - return mask_max(params_mask_c(params, var)); + if (hw_is_mask(var)) { + return mask_max(hw_param_mask_c(params, var)); } - if (is_interval(var)) { - return interval_max(params_interval_c(params, var)); + if (hw_is_interval(var)) { + return interval_max(hw_param_interval_c(params, var)); } assert(0); return -EINVAL; @@ -155,34 +171,34 @@ unsigned int snd_pcm_hw_params_value_max(const snd_pcm_hw_params_t *params, /* Return the mask for field PAR. This function can be called only for SND_PCM_HW_PARAM_ACCESS, SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. */ -const mask_t *snd_pcm_hw_params_value_mask(const snd_pcm_hw_params_t *params, +const mask_t *snd_pcm_hw_param_value_mask(const snd_pcm_hw_params_t *params, unsigned int var) { - assert(is_mask(var)); - return params_mask_c(params, var); + assert(hw_is_mask(var)); + return hw_param_mask_c(params, var); } /* Return the interval for field PAR. This function cannot be called for SND_PCM_HW_PARAM_ACCESS, SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. */ -const interval_t *snd_pcm_hw_params_value_interval(const snd_pcm_hw_params_t *params, +const interval_t *snd_pcm_hw_param_value_interval(const snd_pcm_hw_params_t *params, unsigned int var) { - assert(is_interval(var)); - return params_interval_c(params, var); + assert(hw_is_interval(var)); + return hw_param_interval_c(params, var); } /* --- Refinement functions --- */ -int _snd_pcm_hw_params_first(snd_pcm_hw_params_t *params, int hw, - unsigned int var) +int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, int hw, + unsigned int var) { int changed; - if (is_mask(var)) - changed = mask_refine_first(params_mask(params, var)); - else if (is_interval(var)) - changed = interval_refine_first(params_interval(params, var)); + if (hw_is_mask(var)) + changed = mask_refine_first(hw_param_mask(params, var)); + else if (hw_is_interval(var)) + changed = interval_refine_first(hw_param_interval(params, var)); else { assert(0); return -EINVAL; @@ -201,27 +217,27 @@ int _snd_pcm_hw_params_first(snd_pcm_hw_params_t *params, int hw, values > minimum. Reduce configuration space accordingly. Return the minimum. */ -int snd_pcm_hw_params_first(snd_pcm_t *pcm, - snd_pcm_hw_params_t *params, unsigned int var) +int snd_pcm_hw_param_first(snd_pcm_t *pcm, + snd_pcm_hw_params_t *params, unsigned int var) { - int changed = _snd_pcm_hw_params_first(params, 0, var); + int changed = _snd_pcm_hw_param_first(params, 0, var); if (changed < 0) return changed; if (changed) { int err = snd_pcm_hw_refine(pcm, params); assert(err >= 0); } - return snd_pcm_hw_params_value(params, var); + return snd_pcm_hw_param_value(params, var); } -int _snd_pcm_hw_params_last(snd_pcm_hw_params_t *params, int hw, - unsigned int var) +int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, int hw, + unsigned int var) { int changed; - if (is_mask(var)) - changed = mask_refine_last(params_mask(params, var)); - else if (is_interval(var)) - changed = interval_refine_last(params_interval(params, var)); + if (hw_is_mask(var)) + changed = mask_refine_last(hw_param_mask(params, var)); + else if (hw_is_interval(var)) + changed = interval_refine_last(hw_param_interval(params, var)); else { assert(0); return -EINVAL; @@ -240,27 +256,27 @@ int _snd_pcm_hw_params_last(snd_pcm_hw_params_t *params, int hw, values < maximum. Reduce configuration space accordingly. Return the maximum. */ -int snd_pcm_hw_params_last(snd_pcm_t *pcm, - snd_pcm_hw_params_t *params, unsigned int var) +int snd_pcm_hw_param_last(snd_pcm_t *pcm, + snd_pcm_hw_params_t *params, unsigned int var) { - int changed = _snd_pcm_hw_params_last(params, 0, var); + int changed = _snd_pcm_hw_param_last(params, 0, var); if (changed < 0) return changed; if (changed) { int err = snd_pcm_hw_refine(pcm, params); assert(err >= 0); } - return snd_pcm_hw_params_value(params, var); + return snd_pcm_hw_param_value(params, var); } -int _snd_pcm_hw_params_min(snd_pcm_hw_params_t *params, int hw, - unsigned int var, unsigned int val) +int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params, int hw, + unsigned int var, unsigned int val) { int changed; - if (is_mask(var)) - changed = mask_refine_min(params_mask(params, var), val); - else if (is_interval(var)) - changed = interval_refine_min(params_interval(params, var), val); + if (hw_is_mask(var)) + changed = mask_refine_min(hw_param_mask(params, var), val); + else if (hw_is_interval(var)) + changed = interval_refine_min(hw_param_interval(params, var), val); else { assert(0); return -EINVAL; @@ -278,10 +294,10 @@ int _snd_pcm_hw_params_min(snd_pcm_hw_params_t *params, int hw, values < VAL. Reduce configuration space accordingly. Return new minimum or -EINVAL if the configuration space is empty */ -int snd_pcm_hw_params_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val) { - int changed = _snd_pcm_hw_params_min(params, 0, var, val); + int changed = _snd_pcm_hw_param_min(params, 0, var, val); if (changed < 0) return changed; if (changed) { @@ -289,17 +305,17 @@ int snd_pcm_hw_params_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, if (err < 0) return err; } - return snd_pcm_hw_params_value_min(params, var); + return snd_pcm_hw_param_value_min(params, var); } -int _snd_pcm_hw_params_max(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, int hw, unsigned int var, unsigned int val) { int changed; - if (is_mask(var)) - changed = mask_refine_max(params_mask(params, var), val); - else if (is_interval(var)) - changed = interval_refine_max(params_interval(params, var), val); + if (hw_is_mask(var)) + changed = mask_refine_max(hw_param_mask(params, var), val); + else if (hw_is_interval(var)) + changed = interval_refine_max(hw_param_interval(params, var), val); else { assert(0); return -EINVAL; @@ -317,10 +333,10 @@ int _snd_pcm_hw_params_max(snd_pcm_hw_params_t *params, int hw, values >= VAL + 1. Reduce configuration space accordingly. Return new maximum or -EINVAL if the configuration space is empty */ -int snd_pcm_hw_params_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val) { - int changed = _snd_pcm_hw_params_max(params, 0, var, val); + int changed = _snd_pcm_hw_param_max(params, 0, var, val); if (changed < 0) return changed; if (changed) { @@ -328,16 +344,16 @@ int snd_pcm_hw_params_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, if (err < 0) return err; } - return snd_pcm_hw_params_value_max(params, var); + return snd_pcm_hw_param_value_max(params, var); } -int _snd_pcm_hw_params_minmax(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_minmax(snd_pcm_hw_params_t *params, int hw, unsigned int var, unsigned int min, unsigned int max) { int changed, c1, c2; - if (is_mask(var)) { - mask_t *mask = params_mask(params, var); + if (hw_is_mask(var)) { + mask_t *mask = hw_param_mask(params, var); c1 = mask_refine_min(mask, min); if (c1 < 0) changed = c1; @@ -349,8 +365,8 @@ int _snd_pcm_hw_params_minmax(snd_pcm_hw_params_t *params, int hw, changed = (c1 || c2); } } - else if (is_interval(var)) { - interval_t *i = params_interval(params, var); + else if (hw_is_interval(var)) { + interval_t *i = hw_param_interval(params, var); c1 = interval_refine_min(i, min); if (c1 < 0) changed = c1; @@ -378,11 +394,11 @@ int _snd_pcm_hw_params_minmax(snd_pcm_hw_params_t *params, int hw, values < MIN and all values > MAX. Reduce configuration space accordingly. Return 0 or -EINVAL if the configuration space is empty */ -int snd_pcm_hw_params_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int min, unsigned int max) { - int changed = _snd_pcm_hw_params_minmax(params, 0, var, min, max); + int changed = _snd_pcm_hw_param_minmax(params, 0, var, min, max); if (changed < 0) return changed; if (changed) { @@ -393,14 +409,14 @@ int snd_pcm_hw_params_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, return 0; } -int _snd_pcm_hw_params_set(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params, int hw, unsigned int var, unsigned int val) { int changed; - if (is_mask(var)) - changed = mask_refine_set(params_mask(params, var), val); - else if (is_interval(var)) - changed = interval_refine_set(params_interval(params, var), val); + if (hw_is_mask(var)) + changed = mask_refine_set(hw_param_mask(params, var), val); + else if (hw_is_interval(var)) + changed = interval_refine_set(hw_param_interval(params, var), val); else { assert(0); return -EINVAL; @@ -418,10 +434,10 @@ int _snd_pcm_hw_params_set(snd_pcm_hw_params_t *params, int hw, values < VAL and >= VAL +1. Reduce configuration space accordingly. Return VAL or -EINVAL if the configuration space is empty */ -int snd_pcm_hw_params_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val) { - int changed = _snd_pcm_hw_params_set(params, 0, var, val); + int changed = _snd_pcm_hw_param_set(params, 0, var, val); if (changed < 0) return changed; if (changed) { @@ -429,15 +445,15 @@ int snd_pcm_hw_params_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, if (err < 0) return err; } - return snd_pcm_hw_params_value(params, var); + return snd_pcm_hw_param_value(params, var); } -int _snd_pcm_hw_params_mask(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params, int hw, unsigned int var, const mask_t *val) { int changed; - assert(is_mask(var)); - changed = mask_refine(params_mask(params, var), val); + assert(hw_is_mask(var)); + changed = mask_refine(hw_param_mask(params, var), val); if (changed) { if (hw) params->hw_cmask |= 1 << var; @@ -454,10 +470,10 @@ int _snd_pcm_hw_params_mask(snd_pcm_hw_params_t *params, int hw, Return 0 on success or -EINVAL if the configuration space is empty */ -int snd_pcm_hw_params_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, const mask_t *val) +int snd_pcm_hw_param_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, + unsigned int var, const mask_t *val) { - int changed = _snd_pcm_hw_params_mask(params, 0, var, val); + int changed = _snd_pcm_hw_param_mask(params, 0, var, val); if (changed < 0) return changed; if (changed) { @@ -474,7 +490,7 @@ int snd_pcm_hw_params_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. Return the value found. */ -int snd_pcm_hw_params_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val) { snd_pcm_hw_params_t save; @@ -482,14 +498,14 @@ int snd_pcm_hw_params_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int max1 = val, min2 = add(val, 1); unsigned int hw_cmask; save = *params; - v = snd_pcm_hw_params_max(pcm, params, var, max1); + v = snd_pcm_hw_param_max(pcm, params, var, max1); if (v >= 0) { int v1; snd_pcm_hw_params_t params1; if (val == (unsigned int)v) goto _end; params1 = save; - v1 = snd_pcm_hw_params_min(pcm, ¶ms1, var, min2); + v1 = snd_pcm_hw_param_min(pcm, ¶ms1, var, min2); if (v1 < 0) goto _end; if (val - v > v1 - val) { @@ -498,12 +514,12 @@ int snd_pcm_hw_params_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, } } else { *params = save; - v = snd_pcm_hw_params_min(pcm, params, var, min2); + v = snd_pcm_hw_param_min(pcm, params, var, min2); assert(v >= 0); } _end: hw_cmask = params->hw_cmask; - v = snd_pcm_hw_params_set(pcm, params, var, v); + v = snd_pcm_hw_param_set(pcm, params, var, v); params->hw_cmask |= hw_cmask; assert(v >= 0); return v; @@ -516,7 +532,7 @@ int snd_pcm_hw_params_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. Return the value found. */ -int snd_pcm_hw_params_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int var, unsigned int val, unsigned int old) { @@ -532,14 +548,14 @@ int snd_pcm_hw_params_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, min2 = add(old, 1); } save = *params; - v = snd_pcm_hw_params_max(pcm, params, var, max1); + v = snd_pcm_hw_param_max(pcm, params, var, max1); if (v >= 0) { int v1; snd_pcm_hw_params_t params1; if (val == (unsigned int)v) goto _end; params1 = save; - v1 = snd_pcm_hw_params_min(pcm, ¶ms1, var, min2); + v1 = snd_pcm_hw_param_min(pcm, ¶ms1, var, min2); if (v1 < 0) goto _end; if (val - v > v1 - val) { @@ -548,25 +564,25 @@ int snd_pcm_hw_params_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, } } else { *params = save; - v = snd_pcm_hw_params_min(pcm, params, var, min2); + v = snd_pcm_hw_param_min(pcm, params, var, min2); if (v < 0) return v; } _end: - v = snd_pcm_hw_params_set(pcm, params, var, v); + v = snd_pcm_hw_param_set(pcm, params, var, v); return v; } /* ---- end of refinement functions ---- */ -int snd_pcm_hw_params_empty(const snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_empty(const snd_pcm_hw_params_t *params, unsigned int var) { - if (is_mask(var)) - return mask_empty(params_mask_c(params, var)); - if (is_interval(var)) - return interval_empty(params_interval_c(params, var)); + if (hw_is_mask(var)) + return mask_empty(hw_param_mask_c(params, var)); + if (hw_is_interval(var)) + return interval_empty(hw_param_interval_c(params, var)); assert(0); return -EINVAL; } @@ -623,267 +639,208 @@ void snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) int err; unsigned int hw_cmask = params->hw_cmask; - err = snd_pcm_hw_params_first(pcm, params, SND_PCM_HW_PARAM_ACCESS); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_ACCESS); assert(err >= 0); hw_cmask |= params->hw_cmask; - err = snd_pcm_hw_params_first(pcm, params, SND_PCM_HW_PARAM_FORMAT); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_FORMAT); assert(err >= 0); hw_cmask |= params->hw_cmask; - err = snd_pcm_hw_params_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT); assert(err >= 0); hw_cmask |= params->hw_cmask; - err = snd_pcm_hw_params_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS); assert(err >= 0); hw_cmask |= params->hw_cmask; - err = snd_pcm_hw_params_first(pcm, params, SND_PCM_HW_PARAM_RATE); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_RATE); assert(err >= 0); hw_cmask |= params->hw_cmask; - err = snd_pcm_hw_params_first(pcm, params, SND_PCM_HW_PARAM_FRAGMENT_SIZE); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_FRAGMENT_SIZE); assert(err >= 0); hw_cmask |= params->hw_cmask; - err = snd_pcm_hw_params_last(pcm, params, SND_PCM_HW_PARAM_FRAGMENTS); + err = snd_pcm_hw_param_last(pcm, params, SND_PCM_HW_PARAM_FRAGMENTS); assert(err >= 0); hw_cmask |= params->hw_cmask; params->hw_cmask = hw_cmask; } -int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) -{ - int err; - assert(pcm && params); - params->hw_cmask = 0; - err = pcm->ops->hw_refine(pcm->op_arg, params); - params->appl_cmask = 0; - return err; -} - -/* Install one of the configurations present in configuration - space defined by PARAMS. - The configuration choosen is that obtained fixing in this order: - first access - first format - first subformat - min channels - min rate - min fragment_size - max fragments - Return 0 on success or a negative number expressing the error. -*/ -int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) -{ - int err; - err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - snd_pcm_hw_params_choose(pcm, params); - if (pcm->mmap_channels) { - err = snd_pcm_munmap(pcm); - if (err < 0) - return err; - } - err = pcm->ops->hw_params(pcm->op_arg, params); - if (err < 0) - goto _mmap; - - pcm->setup = 1; - pcm->access = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_ACCESS); - pcm->format = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT); - pcm->subformat = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_SUBFORMAT); - pcm->channels = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_CHANNELS); - pcm->rate = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_RATE); - pcm->fragment_size = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FRAGMENT_SIZE); - pcm->fragments = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FRAGMENTS); - pcm->bits_per_sample = snd_pcm_format_physical_width(pcm->format); - pcm->bits_per_frame = pcm->bits_per_sample * pcm->channels; - pcm->buffer_size = pcm->fragment_size * pcm->fragments; - - pcm->info = params->info; - pcm->msbits = params->msbits; - pcm->rate_num = params->rate_num; - pcm->rate_den = params->rate_den; - pcm->fifo_size = params->fifo_size; - - /* Default sw params */ - pcm->start_mode = SND_PCM_START_DATA; - pcm->ready_mode = SND_PCM_READY_FRAGMENT; - pcm->xrun_mode = SND_PCM_XRUN_FRAGMENT; - pcm->avail_min = pcm->fragment_size; - pcm->xfer_min = pcm->fragment_size; - pcm->xfer_align = pcm->fragment_size; - pcm->time = 0; - pcm->boundary = LONG_MAX - pcm->buffer_size * 2 - LONG_MAX % pcm->buffer_size; - - _mmap: - if (pcm->setup && - (pcm->mmap_rw || - (pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED || - pcm->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED || - pcm->access == SND_PCM_ACCESS_MMAP_COMPLEX))) { - int err; - err = snd_pcm_mmap(pcm); - if (err < 0) - return err; - } - if (err >= 0) - snd_pcm_prepare(pcm); - return err; -} - /* Strategies */ -struct _snd_pcm_strategy { +struct _snd_pcm_hw_strategy { unsigned int badness_min, badness_max; int (*choose_param)(const snd_pcm_hw_params_t *params, snd_pcm_t *pcm, - const snd_pcm_strategy_t *strategy); + const snd_pcm_hw_strategy_t *strategy); int (*next_value)(snd_pcm_hw_params_t *params, unsigned int param, int value, snd_pcm_t *pcm, - const snd_pcm_strategy_t *strategy); + const snd_pcm_hw_strategy_t *strategy); int (*min_badness)(const snd_pcm_hw_params_t *params, unsigned int max_badness, snd_pcm_t *pcm, - const snd_pcm_strategy_t *strategy); + const snd_pcm_hw_strategy_t *strategy); void *private; - void (*free)(snd_pcm_strategy_t *strategy); + void (*free)(snd_pcm_hw_strategy_t *strategy); }; /* Independent badness */ -typedef struct _snd_pcm_strategy_simple snd_pcm_strategy_simple_t; +typedef struct _snd_pcm_hw_strategy_simple snd_pcm_hw_strategy_simple_t; -struct _snd_pcm_strategy_simple { +struct _snd_pcm_hw_strategy_simple { int valid; unsigned int order; int (*next_value)(snd_pcm_hw_params_t *params, unsigned int param, int value, snd_pcm_t *pcm, - const snd_pcm_strategy_simple_t *par); + const snd_pcm_hw_strategy_simple_t *par); unsigned int (*min_badness)(const snd_pcm_hw_params_t *params, unsigned int param, snd_pcm_t *pcm, - const snd_pcm_strategy_simple_t *par); + const snd_pcm_hw_strategy_simple_t *par); void *private; - void (*free)(snd_pcm_strategy_simple_t *strategy); + void (*free)(snd_pcm_hw_strategy_simple_t *strategy); }; -typedef struct _snd_pcm_strategy_simple_near { +typedef struct _snd_pcm_hw_strategy_simple_near { int best; unsigned int mul; -} snd_pcm_strategy_simple_near_t; +} snd_pcm_hw_strategy_simple_near_t; -typedef struct _snd_pcm_strategy_simple_choices { +typedef struct _snd_pcm_hw_strategy_simple_choices { unsigned int count; /* choices need to be sorted on ascending badness */ - snd_pcm_strategy_simple_choices_list_t *choices; -} snd_pcm_strategy_simple_choices_t; + snd_pcm_hw_strategy_simple_choices_list_t *choices; +} snd_pcm_hw_strategy_simple_choices_t; -int snd_pcm_hw_params_test(const snd_pcm_hw_params_t *params, +int snd_pcm_hw_param_test(const snd_pcm_hw_params_t *params, unsigned int var, unsigned int val) { - if (is_mask(var)) { - const mask_t *mask = params_mask_c(params, var); + if (hw_is_mask(var)) { + const mask_t *mask = hw_param_mask_c(params, var); return mask_test(mask, val); } - if (is_interval(var)) { - const interval_t *i = params_interval_c(params, var); + if (hw_is_interval(var)) { + const interval_t *i = hw_param_interval_c(params, var); return interval_test(i, val); } assert(0); return -EINVAL; } -unsigned int snd_pcm_hw_params_count(const snd_pcm_hw_params_t *params, +unsigned int snd_pcm_hw_param_count(const snd_pcm_hw_params_t *params, unsigned int var) { - if (is_mask(var)) { - const mask_t *mask = params_mask_c(params, var); + if (hw_is_mask(var)) { + const mask_t *mask = hw_param_mask_c(params, var); return mask_count(mask); } - if (is_interval(var)) { - const interval_t *i = params_interval_c(params, var); + if (hw_is_interval(var)) { + const interval_t *i = hw_param_interval_c(params, var); return interval_max(i) - interval_min(i) + 1; } assert(0); return 0; } -void snd_pcm_hw_params_copy(snd_pcm_hw_params_t *params, unsigned int var, +int _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params, int hw, + unsigned int var, + const snd_pcm_hw_params_t *src) +{ + int changed = 0; + if (hw_is_mask(var)) { + mask_t *d = hw_param_mask(params, var); + const mask_t *s = hw_param_mask_c(src, var); + changed = mask_refine(d, s); + } else if (hw_is_interval(var)) { + interval_t *d = hw_param_interval(params, var); + const interval_t *s = hw_param_interval_c(src, var); + changed = interval_refine(d, s); + } else + assert(0); + if (changed) { + if (hw) + params->hw_cmask |= 1 << var; + else + params->appl_cmask |= 1 << var; + } + return changed; +} + +void snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, unsigned int var, const snd_pcm_hw_params_t *src) { - if (is_mask(var)) { - mask_t *d = params_mask(params, var); - const mask_t *s = params_mask_c(src, var); + if (hw_is_mask(var)) { + mask_t *d = hw_param_mask(params, var); + const mask_t *s = hw_param_mask_c(src, var); mask_copy(d, s); } - if (is_interval(var)) { - interval_t *d = params_interval(params, var); - const interval_t *s = params_interval_c(src, var); + if (hw_is_interval(var)) { + interval_t *d = hw_param_interval(params, var); + const interval_t *s = hw_param_interval_c(src, var); interval_copy(d, s); } assert(0); } -void snd_pcm_hw_params_dump(const snd_pcm_hw_params_t *params, - unsigned int var, FILE *fp) +void snd_pcm_hw_param_dump(const snd_pcm_hw_params_t *params, + unsigned int var, FILE *fp) { - if (is_mask(var)) { - const mask_t *mask = params_mask_c(params, var); + static const char *(*funcs[])(unsigned int k) = { + [SND_PCM_HW_PARAM_ACCESS] = snd_pcm_access_name, + [SND_PCM_HW_PARAM_FORMAT] = snd_pcm_format_name, + [SND_PCM_HW_PARAM_SUBFORMAT] = snd_pcm_subformat_name, + }; + if (hw_is_mask(var)) { + const mask_t *mask = hw_param_mask_c(params, var); if (mask_empty(mask)) fputs(" NONE", fp); + else if (mask_full(mask)) + fputs(" ALL", fp); else { unsigned int k; for (k = 0; k <= MASK_MAX; ++k) { if (mask_test(mask, k)) { + const char *(*f)(unsigned int k); putc(' ', fp); - switch (var) { - case SND_PCM_HW_PARAM_ACCESS: - fputs(snd_pcm_access_name(k), fp); - break; - case SND_PCM_HW_PARAM_FORMAT: - fputs(snd_pcm_format_name(k), fp); - break; - case SND_PCM_HW_PARAM_SUBFORMAT: - fputs(snd_pcm_subformat_name(k), fp); - break; - default: - assert(0); - } + assert(var < sizeof(funcs) / sizeof(funcs[0])); + f = funcs[k]; + assert(f); + fputs(f(k), fp); } } } return; } - if (is_interval(var)) { - interval_print(params_interval_c(params, var), fp); + if (hw_is_interval(var)) { + interval_print(hw_param_interval_c(params, var), fp); return; } assert(0); } -int snd_pcm_dump_hw_params(snd_pcm_hw_params_t *params, FILE *fp) +int snd_pcm_hw_params_dump(snd_pcm_hw_params_t *params, FILE *fp) { unsigned int k; for (k = 0; k <= SND_PCM_HW_PARAM_LAST; k++) { fprintf(fp, "%s: ", snd_pcm_hw_param_name(k)); - snd_pcm_hw_params_dump(params, k, fp); + snd_pcm_hw_param_dump(params, k, fp); putc('\n', fp); } return 0; } int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - const snd_pcm_strategy_t *strategy, - unsigned int badness_min, - unsigned int badness_max) + const snd_pcm_hw_strategy_t *strategy, + unsigned int badness_min, + unsigned int badness_max) { snd_pcm_hw_params_t best_params; int var; @@ -893,7 +850,7 @@ int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_hw_params_t params1; #if 0 printf("\nBadness: %d\n", badness); - snd_pcm_dump_hw_params(params, stdout); + snd_pcm_hw_params_dump(params, stdout); #endif if (badness < 0) return badness; @@ -930,9 +887,9 @@ int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, return best_badness; } -void snd_pcm_strategy_simple_free(snd_pcm_strategy_t *strategy) +void snd_pcm_hw_strategy_simple_free(snd_pcm_hw_strategy_t *strategy) { - snd_pcm_strategy_simple_t *pars = strategy->private; + snd_pcm_hw_strategy_simple_t *pars = strategy->private; int k; for (k = 0; k <= SND_PCM_HW_PARAM_LAST; ++k) { if (pars[k].valid && pars[k].free) @@ -941,21 +898,21 @@ void snd_pcm_strategy_simple_free(snd_pcm_strategy_t *strategy) free(pars); } -int snd_pcm_strategy_simple_choose_param(const snd_pcm_hw_params_t *params, +int snd_pcm_hw_strategy_simple_choose_param(const snd_pcm_hw_params_t *params, snd_pcm_t *pcm ATTRIBUTE_UNUSED, - const snd_pcm_strategy_t *strategy) + const snd_pcm_hw_strategy_t *strategy) { unsigned int var; int best_var = -1; - const snd_pcm_strategy_simple_t *pars = strategy->private; + const snd_pcm_hw_strategy_simple_t *pars = strategy->private; unsigned int min_choices = UINT_MAX; unsigned int min_order = UINT_MAX; for (var = 0; var <= SND_PCM_HW_PARAM_LAST; ++var) { - const snd_pcm_strategy_simple_t *p = &pars[var]; + const snd_pcm_hw_strategy_simple_t *p = &pars[var]; unsigned int choices; if (!p->valid) continue; - choices = snd_pcm_hw_params_count(params, var); + choices = snd_pcm_hw_param_count(params, var); if (choices == 1) continue; assert(choices != 0); @@ -970,26 +927,26 @@ int snd_pcm_strategy_simple_choose_param(const snd_pcm_hw_params_t *params, return best_var; } -int snd_pcm_strategy_simple_next_value(snd_pcm_hw_params_t *params, +int snd_pcm_hw_strategy_simple_next_value(snd_pcm_hw_params_t *params, unsigned int var, int value, snd_pcm_t *pcm, - const snd_pcm_strategy_t *strategy) + const snd_pcm_hw_strategy_t *strategy) { - const snd_pcm_strategy_simple_t *pars = strategy->private; + const snd_pcm_hw_strategy_simple_t *pars = strategy->private; assert(pars[var].valid); return pars[var].next_value(params, var, value, pcm, &pars[var]); } -int snd_pcm_strategy_simple_min_badness(const snd_pcm_hw_params_t *params, +int snd_pcm_hw_strategy_simple_min_badness(const snd_pcm_hw_params_t *params, unsigned int max_badness, snd_pcm_t *pcm, - const snd_pcm_strategy_t *strategy) + const snd_pcm_hw_strategy_t *strategy) { unsigned int var; unsigned int badness = 0; - const snd_pcm_strategy_simple_t *pars = strategy->private; + const snd_pcm_hw_strategy_simple_t *pars = strategy->private; for (var = 0; var <= SND_PCM_HW_PARAM_LAST; ++var) { unsigned int b; if (!pars[var].valid) @@ -1003,20 +960,20 @@ int snd_pcm_strategy_simple_min_badness(const snd_pcm_hw_params_t *params, } -void snd_pcm_strategy_simple_near_free(snd_pcm_strategy_simple_t *par) +void snd_pcm_hw_strategy_simple_near_free(snd_pcm_hw_strategy_simple_t *par) { - snd_pcm_strategy_simple_near_t *p = par->private; + snd_pcm_hw_strategy_simple_near_t *p = par->private; free(p); } -unsigned int snd_pcm_strategy_simple_near_min_badness(const snd_pcm_hw_params_t *params, +unsigned int snd_pcm_hw_strategy_simple_near_min_badness(const snd_pcm_hw_params_t *params, unsigned int var, snd_pcm_t *pcm, - const snd_pcm_strategy_simple_t *par) + const snd_pcm_hw_strategy_simple_t *par) { - const snd_pcm_strategy_simple_near_t *p = par->private; + const snd_pcm_hw_strategy_simple_near_t *p = par->private; snd_pcm_hw_params_t params1 = *params; - int value = snd_pcm_hw_params_near(pcm, ¶ms1, var, p->best); + int value = snd_pcm_hw_param_near(pcm, ¶ms1, var, p->best); int diff; assert(value >= 0); diff = p->best - value; @@ -1025,48 +982,48 @@ unsigned int snd_pcm_strategy_simple_near_min_badness(const snd_pcm_hw_params_t return diff * p->mul; } -int snd_pcm_strategy_simple_near_next_value(snd_pcm_hw_params_t *params, +int snd_pcm_hw_strategy_simple_near_next_value(snd_pcm_hw_params_t *params, unsigned int var, int value, snd_pcm_t *pcm, - const snd_pcm_strategy_simple_t *par) + const snd_pcm_hw_strategy_simple_t *par) { - const snd_pcm_strategy_simple_near_t *p = par->private; + const snd_pcm_hw_strategy_simple_near_t *p = par->private; if (value < 0) - return snd_pcm_hw_params_near(pcm, params, var, p->best); + return snd_pcm_hw_param_near(pcm, params, var, p->best); else - return snd_pcm_hw_params_next(pcm, params, var, p->best, value); + return snd_pcm_hw_param_next(pcm, params, var, p->best, value); } -void snd_pcm_strategy_simple_choices_free(snd_pcm_strategy_simple_t *par) +void snd_pcm_hw_strategy_simple_choices_free(snd_pcm_hw_strategy_simple_t *par) { - snd_pcm_strategy_simple_choices_t *p = par->private; + snd_pcm_hw_strategy_simple_choices_t *p = par->private; // free(p->choices); free(p); } -unsigned int snd_pcm_strategy_simple_choices_min_badness(const snd_pcm_hw_params_t *params, +unsigned int snd_pcm_hw_strategy_simple_choices_min_badness(const snd_pcm_hw_params_t *params, unsigned int var, snd_pcm_t *pcm ATTRIBUTE_UNUSED, - const snd_pcm_strategy_simple_t *par) + const snd_pcm_hw_strategy_simple_t *par) { - const snd_pcm_strategy_simple_choices_t *p = par->private; + const snd_pcm_hw_strategy_simple_choices_t *p = par->private; unsigned int k; for (k = 0; k < p->count; ++k) { - if (snd_pcm_hw_params_test(params, var, p->choices[k].value)) + if (snd_pcm_hw_param_test(params, var, p->choices[k].value)) return p->choices[k].badness; } assert(0); return UINT_MAX; } -int snd_pcm_strategy_simple_choices_next_value(snd_pcm_hw_params_t *params, +int snd_pcm_hw_strategy_simple_choices_next_value(snd_pcm_hw_params_t *params, unsigned int var, int value, snd_pcm_t *pcm, - const snd_pcm_strategy_simple_t *par) + const snd_pcm_hw_strategy_simple_t *par) { - const snd_pcm_strategy_simple_choices_t *p = par->private; + const snd_pcm_hw_strategy_simple_choices_t *p = par->private; unsigned int k = 0; if (value >= 0) { for (; k < p->count; ++k) { @@ -1078,9 +1035,9 @@ int snd_pcm_strategy_simple_choices_next_value(snd_pcm_hw_params_t *params, } for (; k < p->count; ++k) { unsigned int v = p->choices[k].value; - if (snd_pcm_hw_params_test(params, var, v)) { + if (snd_pcm_hw_param_test(params, var, v)) { snd_pcm_hw_params_t save = *params; - int err = snd_pcm_hw_params_set(pcm, params, var, v); + int err = snd_pcm_hw_param_set(pcm, params, var, v); if (err < 0) { *params = save; continue; @@ -1091,7 +1048,7 @@ int snd_pcm_strategy_simple_choices_next_value(snd_pcm_hw_params_t *params, return -1; } -int snd_pcm_strategy_free(snd_pcm_strategy_t *strategy) +int snd_pcm_hw_strategy_free(snd_pcm_hw_strategy_t *strategy) { if (strategy->free) strategy->free(strategy); @@ -1099,12 +1056,12 @@ int snd_pcm_strategy_free(snd_pcm_strategy_t *strategy) return 0; } -int snd_pcm_strategy_simple(snd_pcm_strategy_t **strategyp, +int snd_pcm_hw_strategy_simple(snd_pcm_hw_strategy_t **strategyp, unsigned int badness_min, unsigned int badness_max) { - snd_pcm_strategy_simple_t *data; - snd_pcm_strategy_t *s; + snd_pcm_hw_strategy_simple_t *data; + snd_pcm_hw_strategy_t *s; assert(strategyp); data = calloc(SND_PCM_HW_PARAM_LAST + 1, sizeof(*data)); if (!data) @@ -1114,25 +1071,25 @@ int snd_pcm_strategy_simple(snd_pcm_strategy_t **strategyp, free(data); return -ENOMEM; } - s->choose_param = snd_pcm_strategy_simple_choose_param; - s->next_value = snd_pcm_strategy_simple_next_value; - s->min_badness = snd_pcm_strategy_simple_min_badness; + s->choose_param = snd_pcm_hw_strategy_simple_choose_param; + s->next_value = snd_pcm_hw_strategy_simple_next_value; + s->min_badness = snd_pcm_hw_strategy_simple_min_badness; s->badness_min = badness_min; s->badness_max = badness_max; s->private = data; - s->free = snd_pcm_strategy_simple_free; + s->free = snd_pcm_hw_strategy_simple_free; *strategyp = s; return 0; } -int snd_pcm_strategy_simple_near(snd_pcm_strategy_t *strategy, +int snd_pcm_hw_strategy_simple_near(snd_pcm_hw_strategy_t *strategy, int order, unsigned int var, unsigned int best, unsigned int mul) { - snd_pcm_strategy_simple_t *s = strategy->private; - snd_pcm_strategy_simple_near_t *data; + snd_pcm_hw_strategy_simple_t *s = strategy->private; + snd_pcm_hw_strategy_simple_near_t *data; assert(strategy); assert(var <= SND_PCM_HW_PARAM_LAST); assert(!s->valid); @@ -1144,21 +1101,21 @@ int snd_pcm_strategy_simple_near(snd_pcm_strategy_t *strategy, s += var; s->order = order; s->valid = 1; - s->next_value = snd_pcm_strategy_simple_near_next_value; - s->min_badness = snd_pcm_strategy_simple_near_min_badness; + s->next_value = snd_pcm_hw_strategy_simple_near_next_value; + s->min_badness = snd_pcm_hw_strategy_simple_near_min_badness; s->private = data; - s->free = snd_pcm_strategy_simple_near_free; + s->free = snd_pcm_hw_strategy_simple_near_free; return 0; } -int snd_pcm_strategy_simple_choices(snd_pcm_strategy_t *strategy, +int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy, int order, unsigned int var, unsigned int count, - snd_pcm_strategy_simple_choices_list_t *choices) + snd_pcm_hw_strategy_simple_choices_list_t *choices) { - snd_pcm_strategy_simple_t *s = strategy->private; - snd_pcm_strategy_simple_choices_t *data; + snd_pcm_hw_strategy_simple_t *s = strategy->private; + snd_pcm_hw_strategy_simple_choices_t *data; assert(strategy); assert(var <= SND_PCM_HW_PARAM_LAST); assert(!s->valid); @@ -1170,10 +1127,10 @@ int snd_pcm_strategy_simple_choices(snd_pcm_strategy_t *strategy, s += var; s->valid = 1; s->order = order; - s->next_value = snd_pcm_strategy_simple_choices_next_value; - s->min_badness = snd_pcm_strategy_simple_choices_min_badness; + s->next_value = snd_pcm_hw_strategy_simple_choices_next_value; + s->min_badness = snd_pcm_hw_strategy_simple_choices_min_badness; s->private = data; - s->free = snd_pcm_strategy_simple_choices_free; + s->free = snd_pcm_hw_strategy_simple_choices_free; return 0; } @@ -1190,13 +1147,13 @@ int snd_pcm_hw_params_try_explain_failure1(snd_pcm_t *pcm, for (var = 0; var <= SND_PCM_HW_PARAM_LAST; var++) { int err; i = *success; - snd_pcm_hw_params_copy(&i, var, fail); + snd_pcm_hw_param_copy(&i, var, fail); err = snd_pcm_hw_refine(pcm, &i); if (err == 0 && snd_pcm_hw_params_try_explain_failure1(pcm, fail, &i, depth - 1, fp) < 0) continue; fprintf(fp, "%s: ", snd_pcm_hw_param_name(var)); - snd_pcm_hw_params_dump(fail, var, fp); + snd_pcm_hw_param_dump(fail, var, fp); putc('\n', fp); return 0; } @@ -1215,7 +1172,7 @@ int snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm, int done = 0; assert(pcm && fail); for (var = 0; var <= SND_PCM_HW_PARAM_LAST; var++) { - if (!snd_pcm_hw_params_empty(fail, var)) + if (!snd_pcm_hw_param_empty(fail, var)) continue; fprintf(fp, "%s is empty\n", snd_pcm_hw_param_name(var)); done = 1; @@ -1250,35 +1207,35 @@ struct _snd_pcm_hw_rule { int snd_pcm_hw_rule_mul(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) { - return interval_mul(params_interval(params, rule->var), - params_interval(params, rule->deps[0]), - params_interval(params, rule->deps[1])); + return interval_mul(hw_param_interval(params, rule->var), + hw_param_interval(params, rule->deps[0]), + hw_param_interval(params, rule->deps[1])); } int snd_pcm_hw_rule_div(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) { - return interval_div(params_interval(params, rule->var), - params_interval(params, rule->deps[0]), - params_interval(params, rule->deps[1])); + return interval_div(hw_param_interval(params, rule->var), + hw_param_interval(params, rule->deps[0]), + hw_param_interval(params, rule->deps[1])); } int snd_pcm_hw_rule_muldivk(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) { - return interval_muldivk(params_interval(params, rule->var), + return interval_muldivk(hw_param_interval(params, rule->var), (unsigned long) rule->private, - params_interval(params, rule->deps[0]), - params_interval(params, rule->deps[1])); + hw_param_interval(params, rule->deps[0]), + hw_param_interval(params, rule->deps[1])); } int snd_pcm_hw_rule_mulkdiv(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) { - return interval_mulkdiv(params_interval(params, rule->var), + return interval_mulkdiv(hw_param_interval(params, rule->var), (unsigned long) rule->private, - params_interval(params, rule->deps[0]), - params_interval(params, rule->deps[1])); + hw_param_interval(params, rule->deps[0]), + hw_param_interval(params, rule->deps[1])); } int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params, @@ -1286,8 +1243,8 @@ int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params, { int changed = 0; unsigned int k; - mask_t *mask = params_mask(params, rule->var); - interval_t *i = params_interval(params, rule->deps[0]); + mask_t *mask = hw_param_mask(params, rule->var); + interval_t *i = hw_param_interval(params, rule->deps[0]); for (k = 0; k <= SND_PCM_FORMAT_LAST; ++k) { int bits; if (!mask_test(mask, k)) @@ -1311,8 +1268,8 @@ int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params, { unsigned int min, max; unsigned int k; - interval_t *i = params_interval(params, rule->var); - mask_t *mask = params_mask(params, rule->deps[0]); + interval_t *i = hw_param_interval(params, rule->var); + mask_t *mask = hw_param_mask(params, rule->deps[0]); int c, changed = 0; min = UINT_MAX; max = 0; @@ -1341,7 +1298,7 @@ int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params, return changed; } -snd_pcm_hw_rule_t snd_pcm_hw_rules[] = { +static snd_pcm_hw_rule_t refine_rules[] = { { var: SND_PCM_HW_PARAM_FORMAT, func: snd_pcm_hw_rule_format, @@ -1482,18 +1439,96 @@ snd_pcm_hw_rule_t snd_pcm_hw_rules[] = { }, }; -#define RULES (sizeof(snd_pcm_hw_rules) / sizeof(snd_pcm_hw_rules[0])) +#define RULES (sizeof(refine_rules) / sizeof(refine_rules[0])) + +static mask_t refine_masks[SND_PCM_HW_PARAM_LAST_MASK - SND_PCM_HW_PARAM_FIRST_MASK + 1] = { + [SND_PCM_HW_PARAM_ACCESS - SND_PCM_HW_PARAM_FIRST_MASK] = { + bits: (1 << (SND_PCM_ACCESS_LAST + 1)) - 1, + }, + [SND_PCM_HW_PARAM_FORMAT - SND_PCM_HW_PARAM_FIRST_MASK] = { + bits: 0x81ffffff, + }, + [SND_PCM_HW_PARAM_SUBFORMAT - SND_PCM_HW_PARAM_FIRST_MASK] = { + bits: (1 << (SND_PCM_SUBFORMAT_LAST + 1)) - 1, + }, +}; + +static interval_t refine_intervals[SND_PCM_HW_PARAM_LAST_INTERVAL - SND_PCM_HW_PARAM_FIRST_INTERVAL + 1] = { + [SND_PCM_HW_PARAM_CHANNELS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_RATE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_FRAGMENT_LENGTH - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_FRAGMENT_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_FRAGMENTS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_BUFFER_LENGTH - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_BUFFER_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_SAMPLE_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_FRAME_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_FRAGMENT_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, + [SND_PCM_HW_PARAM_BUFFER_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 1, max: UINT_MAX, + openmin: 0, openmax: 0, real: 0, empty: 0, + }, +}; + + int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) { unsigned int k; interval_t *i; - snd_pcm_hw_rule_t *rules = snd_pcm_hw_rules; unsigned int rstamps[RULES]; unsigned int vstamps[SND_PCM_HW_PARAM_LAST + 1]; unsigned int stamp = 2; int err, changed; + for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++) { + if (!params->appl_cmask & (1 << k)) + continue; + err = mask_refine(hw_param_mask(params, k), + &refine_masks[k - SND_PCM_HW_PARAM_FIRST_MASK]); + if (err < 0) + return err; + } + + for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++) { + if (!params->appl_cmask & (1 << k)) + continue; + err = interval_refine(hw_param_interval(params, k), + &refine_intervals[k - SND_PCM_HW_PARAM_FIRST_INTERVAL]); + if (err < 0) + return err; + } + for (k = 0; k < RULES; k++) rstamps[k] = 0; for (k = 0; k <= SND_PCM_HW_PARAM_LAST; k++) @@ -1504,7 +1539,7 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) while (changed) { changed = 0; for (k = 0; k < RULES; k++) { - snd_pcm_hw_rule_t *r = &rules[k]; + snd_pcm_hw_rule_t *r = &refine_rules[k]; unsigned int d; int doit = 0; #ifdef RULES_DEBUG @@ -1519,7 +1554,7 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) if (!doit) continue; #ifdef RULES_DEBUG - i = params_interval(params, r->var); + i = hw_param_interval(params, r->var); fprintf(stderr, "Rule %d: %u ", k, r->var); interval_print(i, stderr); #endif @@ -1540,13 +1575,13 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) } } if (!params->msbits) { - i = params_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS); + i = hw_param_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS); if (interval_single(i)) params->msbits = interval_value(i); } if (!params->rate_den) { - i = params_interval(params, SND_PCM_HW_PARAM_RATE); + i = hw_param_interval(params, SND_PCM_HW_PARAM_RATE); if (interval_single(i)) { params->rate_num = interval_value(i); params->rate_den = 1; @@ -1555,23 +1590,6 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) return 0; } -int snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params, unsigned int var, - const snd_pcm_hw_params_t *src) -{ - if (is_mask(var)) { - mask_t *d = params_mask(params, var); - const mask_t *s = params_mask_c(src, var); - return mask_refine(d, s); - } - if (is_interval(var)) { - interval_t *d = params_interval(params, var); - const interval_t *s = params_interval_c(src, var); - return interval_refine(d, s); - } - assert(0); - return -EINVAL; -} - int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params, snd_pcm_hw_params_t *sparams, int (*func)(snd_pcm_t *slave, @@ -1594,7 +1612,7 @@ int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params, continue; if (!(client_from_slave & (1 << k))) continue; - changed = snd_pcm_hw_params_refine(params, k, sparams); + changed = _snd_pcm_hw_param_refine(params, 1, k, sparams); if (changed) { hw_cmask |= 1 << k; slave_from_client |= 1 << k; @@ -1624,7 +1642,7 @@ int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params, continue; if (!(slave_from_client & (1 << k))) continue; - changed = snd_pcm_hw_params_refine(sparams, k, params); + changed = _snd_pcm_hw_param_refine(sparams, 1, k, params); if (changed) { slave_refine |= 1 << k; client_from_slave |= 1 << k; @@ -1660,7 +1678,7 @@ int snd_pcm_hw_params2(snd_pcm_hw_params_t *params, int changed; if (!(links & (1 << k))) continue; - changed = snd_pcm_hw_params_refine(sparams, k, params); + changed = _snd_pcm_hw_param_refine(sparams, 0, k, params); if (changed < 0) return changed; } @@ -1675,11 +1693,327 @@ int snd_pcm_hw_params2(snd_pcm_hw_params_t *params, continue; if (!(sparams->hw_cmask & (1 << k))) continue; - changed = snd_pcm_hw_params_refine(params, k, sparams); - if (changed) - params->hw_cmask |= 1 << k; + changed = _snd_pcm_hw_param_refine(params, 1, k, sparams); + } + return err; +} + +int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) +{ + assert(pcm && params); + assert(pcm->setup); + params->start_mode = pcm->start_mode; + params->ready_mode = pcm->ready_mode; + params->xrun_mode = pcm->xrun_mode; + params->silence_mode = pcm->silence_mode; + params->tstamp_mode = pcm->tstamp_mode; + params->avail_min = pcm->avail_min; + params->xfer_align = pcm->xfer_align; + params->silence_threshold = pcm->silence_threshold; + params->silence_size = pcm->silence_size; + params->boundary = pcm->boundary; + return 0; +} + +int snd_pcm_sw_params_default(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) +{ + assert(pcm && params); + assert(pcm->setup); + params->start_mode = SND_PCM_START_DATA; + params->ready_mode = SND_PCM_READY_FRAGMENT; + params->xrun_mode = SND_PCM_XRUN_FRAGMENT; + params->silence_mode = SND_PCM_SILENCE_FRAGMENT; + params->tstamp_mode = SND_PCM_TSTAMP_NONE; + params->avail_min = pcm->fragment_size; + params->xfer_align = pcm->fragment_size; + params->silence_threshold = 0; + params->silence_size = 0; + params->boundary = LONG_MAX - pcm->buffer_size * 2 - LONG_MAX % pcm->buffer_size; + return 0; +} + +int snd_pcm_sw_param_value(snd_pcm_sw_params_t *params, unsigned int var) +{ + switch (var) { + case SND_PCM_SW_PARAM_START_MODE: + return params->start_mode; + case SND_PCM_SW_PARAM_READY_MODE: + return params->ready_mode; + case SND_PCM_SW_PARAM_XRUN_MODE: + return params->xrun_mode; + case SND_PCM_SW_PARAM_SILENCE_MODE: + return params->silence_mode; + case SND_PCM_SW_PARAM_TSTAMP_MODE: + return params->tstamp_mode; + case SND_PCM_SW_PARAM_AVAIL_MIN: + return params->avail_min; + case SND_PCM_SW_PARAM_XFER_ALIGN: + return params->xfer_align; + case SND_PCM_SW_PARAM_SILENCE_THRESHOLD: + return params->silence_threshold; + case SND_PCM_SW_PARAM_SILENCE_SIZE: + return params->silence_size; + default: + assert(0); + return -EINVAL; + } +} + +int snd_pcm_sw_param_set(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, + unsigned int var, unsigned int val) +{ + switch (var) { + case SND_PCM_SW_PARAM_START_MODE: + assert(val <= SND_PCM_START_LAST); + params->start_mode = val; + break; + case SND_PCM_SW_PARAM_READY_MODE: + assert(val <= SND_PCM_READY_LAST); + params->ready_mode = val; + break; + case SND_PCM_SW_PARAM_XRUN_MODE: + assert(val <= SND_PCM_XRUN_LAST); + params->xrun_mode = val; + break; + case SND_PCM_SW_PARAM_SILENCE_MODE: + assert(val <= SND_PCM_SILENCE_LAST); + params->silence_mode = val; + break; + case SND_PCM_SW_PARAM_TSTAMP_MODE: + assert(val <= SND_PCM_TSTAMP_LAST); + params->tstamp_mode = val; + break; + case SND_PCM_SW_PARAM_AVAIL_MIN: + assert(val > 0); + params->avail_min = val; + break; + case SND_PCM_SW_PARAM_XFER_ALIGN: + assert(val > 0 && val % pcm->min_align == 0); + params->xfer_align = val; + break; + case SND_PCM_SW_PARAM_SILENCE_THRESHOLD: + assert(val + params->silence_size <= pcm->buffer_size); + params->silence_threshold = val; + break; + case SND_PCM_SW_PARAM_SILENCE_SIZE: + assert(val + params->silence_threshold <= pcm->buffer_size); + params->silence_size = val; + break; + default: + assert(0); + return -EINVAL; + } + return val; +} + +int snd_pcm_sw_param_near(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, + unsigned int var, unsigned int val) +{ + switch (var) { + case SND_PCM_SW_PARAM_START_MODE: + assert(val <= SND_PCM_START_LAST); + params->start_mode = val; + break; + case SND_PCM_SW_PARAM_READY_MODE: + assert(val <= SND_PCM_READY_LAST); + params->ready_mode = val; + break; + case SND_PCM_SW_PARAM_XRUN_MODE: + assert(val <= SND_PCM_XRUN_LAST); + params->xrun_mode = val; + break; + case SND_PCM_SW_PARAM_SILENCE_MODE: + assert(val <= SND_PCM_SILENCE_LAST); + params->silence_mode = val; + break; + case SND_PCM_SW_PARAM_TSTAMP_MODE: + assert(val <= SND_PCM_TSTAMP_LAST); + params->tstamp_mode = val; + break; + case SND_PCM_SW_PARAM_AVAIL_MIN: + if (val == 0) + val = pcm->min_align; + params->avail_min = val; + break; + case SND_PCM_SW_PARAM_XFER_ALIGN: + { + size_t r = val % pcm->min_align; + if (r >= (pcm->min_align + 1) / 2) + val += pcm->min_align - r; + else + val -= r; + if (val == 0) + val = pcm->min_align; + params->xfer_align = val; + break; + } + case SND_PCM_SW_PARAM_SILENCE_THRESHOLD: + if (val > pcm->buffer_size - params->silence_size) + val = pcm->buffer_size - params->silence_size; + params->silence_threshold = val; + break; + case SND_PCM_SW_PARAM_SILENCE_SIZE: + if (val > pcm->buffer_size - params->silence_threshold) + val = pcm->buffer_size - params->silence_threshold; + params->silence_size = val; + break; + default: + assert(0); + return -EINVAL; + } + return val; +} + +void snd_pcm_sw_param_dump(const snd_pcm_sw_params_t *params, + unsigned int var, FILE *fp) +{ + switch (var) { + case SND_PCM_SW_PARAM_START_MODE: + fputs(snd_pcm_start_mode_name(params->start_mode), fp); + break; + case SND_PCM_SW_PARAM_READY_MODE: + fputs(snd_pcm_ready_mode_name(params->ready_mode), fp); + break; + case SND_PCM_SW_PARAM_XRUN_MODE: + fputs(snd_pcm_xrun_mode_name(params->xrun_mode), fp); + break; + case SND_PCM_SW_PARAM_SILENCE_MODE: + fputs(snd_pcm_silence_mode_name(params->silence_mode), fp); + break; + case SND_PCM_SW_PARAM_TSTAMP_MODE: + fputs(snd_pcm_tstamp_mode_name(params->tstamp_mode), fp); + break; + case SND_PCM_SW_PARAM_AVAIL_MIN: + fprintf(fp, "%ld", (long) params->avail_min); + break; + case SND_PCM_SW_PARAM_XFER_ALIGN: + fprintf(fp, "%ld", (long) params->xfer_align); + break; + case SND_PCM_SW_PARAM_SILENCE_THRESHOLD: + fprintf(fp, "%ld", (long) params->silence_threshold); + break; + case SND_PCM_SW_PARAM_SILENCE_SIZE: + fprintf(fp, "%ld", (long) params->silence_size); + break; + default: + assert(0); + } +} + +int snd_pcm_sw_params_dump(snd_pcm_sw_params_t *params, FILE *fp) +{ + unsigned int k; + for (k = 0; k <= SND_PCM_SW_PARAM_LAST; k++) { + fprintf(fp, "%s: ", snd_pcm_sw_param_name(k)); + snd_pcm_sw_param_dump(params, k, fp); + putc('\n', fp); + } + return 0; +} + + +int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) +{ + int err; + assert(pcm && params); + params->hw_cmask = 0; + err = pcm->ops->hw_refine(pcm->op_arg, params); + params->appl_cmask = 0; + return err; +} + +/* Install one of the configurations present in configuration + space defined by PARAMS. + The configuration choosen is that obtained fixing in this order: + first access + first format + first subformat + min channels + min rate + min fragment_size + max fragments + Return 0 on success or a negative number expressing the error. +*/ +int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) +{ + int err; + snd_pcm_sw_params_t sw; + int fb, min_align; + err = snd_pcm_hw_refine(pcm, params); + if (err < 0) + return err; + snd_pcm_hw_params_choose(pcm, params); + if (pcm->mmap_channels) { + err = snd_pcm_munmap(pcm); + if (err < 0) + return err; + } + err = pcm->ops->hw_params(pcm->op_arg, params); + if (err < 0) + goto _mmap; + + pcm->setup = 1; + pcm->access = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_ACCESS); + pcm->format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT); + pcm->subformat = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_SUBFORMAT); + pcm->channels = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS); + pcm->rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE); + pcm->fragment_size = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FRAGMENT_SIZE); + pcm->fragments = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FRAGMENTS); + pcm->bits_per_sample = snd_pcm_format_physical_width(pcm->format); + pcm->bits_per_frame = pcm->bits_per_sample * pcm->channels; + fb = pcm->bits_per_frame; + min_align = 1; + while (fb % 8) { + fb *= 2; + min_align *= 2; + } + pcm->min_align = min_align; + pcm->buffer_size = pcm->fragment_size * pcm->fragments; + + pcm->info = params->info; + pcm->msbits = params->msbits; + pcm->rate_num = params->rate_num; + pcm->rate_den = params->rate_den; + pcm->fifo_size = params->fifo_size; + /* Default sw params */ + snd_pcm_sw_params_default(pcm, &sw); + err = snd_pcm_sw_params(pcm, &sw); + assert(err >= 0); + + _mmap: + if (pcm->setup && + (pcm->mmap_rw || + (pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED || + pcm->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED || + pcm->access == SND_PCM_ACCESS_MMAP_COMPLEX))) { + int err; + err = snd_pcm_mmap(pcm); + if (err < 0) + return err; } + if (err >= 0) + err = snd_pcm_prepare(pcm); return err; } +int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) +{ + int err; + err = pcm->ops->sw_params(pcm->op_arg, params); + if (err < 0) + return err; + pcm->start_mode = params->start_mode; + pcm->ready_mode = params->ready_mode; + pcm->xrun_mode = params->xrun_mode; + pcm->silence_mode = params->silence_mode; + pcm->tstamp_mode = params->tstamp_mode; + pcm->avail_min = params->avail_min; + pcm->xfer_align = params->xfer_align; + pcm->silence_threshold = params->silence_threshold; + pcm->silence_size = params->silence_size; + pcm->boundary = params->boundary; + return 0; +} + diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 7eb8df33..5255493d 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -214,13 +214,13 @@ static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, mask_load(mmap_mask, SND_PCM_ACCBIT_MMAP); mask_load(fmtplug_mask, SND_PCM_FMTBIT_PLUG); - err = _snd_pcm_hw_params_min(params, 1, SND_PCM_HW_PARAM_CHANNELS, 1); + err = _snd_pcm_hw_param_min(params, 1, SND_PCM_HW_PARAM_CHANNELS, 1); if (err < 0) return err; - err = _snd_pcm_hw_params_min(params, 1, SND_PCM_HW_PARAM_RATE, RATE_MIN); + err = _snd_pcm_hw_param_min(params, 1, SND_PCM_HW_PARAM_RATE, RATE_MIN); if (err < 0) return err; - err = _snd_pcm_hw_params_max(params, 1, SND_PCM_HW_PARAM_RATE, RATE_MAX); + err = _snd_pcm_hw_param_max(params, 1, SND_PCM_HW_PARAM_RATE, RATE_MAX); if (err < 0) return err; @@ -230,41 +230,41 @@ static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, if (err < 0) return err; - rate_min = snd_pcm_hw_params_value_min(params, SND_PCM_HW_PARAM_RATE); - rate_max = snd_pcm_hw_params_value_max(params, SND_PCM_HW_PARAM_RATE); + rate_min = snd_pcm_hw_param_value_min(params, SND_PCM_HW_PARAM_RATE); + rate_max = snd_pcm_hw_param_value_max(params, SND_PCM_HW_PARAM_RATE); tmp = *sparams; - srate_min = snd_pcm_hw_params_near(slave, &tmp, + srate_min = snd_pcm_hw_param_near(slave, &tmp, SND_PCM_HW_PARAM_RATE, rate_min); if (srate_min < rate_max) { tmp = *sparams; - srate_max = snd_pcm_hw_params_near(slave, &tmp, + srate_max = snd_pcm_hw_param_near(slave, &tmp, SND_PCM_HW_PARAM_RATE, rate_max); } else srate_max = srate_min; - err = snd_pcm_hw_params_minmax(slave, sparams, + err = snd_pcm_hw_param_minmax(slave, sparams, SND_PCM_HW_PARAM_RATE, srate_min, srate_max); assert(err >= 0); - channels_min = snd_pcm_hw_params_value_min(params, SND_PCM_HW_PARAM_CHANNELS); - channels_max = snd_pcm_hw_params_value_max(params, SND_PCM_HW_PARAM_CHANNELS); + channels_min = snd_pcm_hw_param_value_min(params, SND_PCM_HW_PARAM_CHANNELS); + channels_max = snd_pcm_hw_param_value_max(params, SND_PCM_HW_PARAM_CHANNELS); tmp = *sparams; - schannels_min = snd_pcm_hw_params_near(slave, &tmp, + schannels_min = snd_pcm_hw_param_near(slave, &tmp, SND_PCM_HW_PARAM_CHANNELS, channels_min); if (schannels_min < channels_max) { tmp = *sparams; - schannels_max = snd_pcm_hw_params_near(slave, &tmp, + schannels_max = snd_pcm_hw_param_near(slave, &tmp, SND_PCM_HW_PARAM_CHANNELS, channels_max); } else schannels_max = schannels_min; - err = snd_pcm_hw_params_minmax(slave, sparams, + err = snd_pcm_hw_param_minmax(slave, sparams, SND_PCM_HW_PARAM_CHANNELS, schannels_min, schannels_max); assert(err >= 0); - format_mask = snd_pcm_hw_params_value_mask(params, + format_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_FORMAT); - sformat_mask = snd_pcm_hw_params_value_mask(sparams, + sformat_mask = snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_FORMAT); mask_none(tmp_mask); for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) { @@ -279,7 +279,7 @@ static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, mask_t *m = alloca(mask_sizeof()); mask_all(m); mask_reset(m, format); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, m); + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, m); if (err < 0) return err; continue; @@ -288,10 +288,10 @@ static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, mask_set(tmp_mask, f); } - err = _snd_pcm_hw_params_mask(sparams, 0, + err = _snd_pcm_hw_param_mask(sparams, 0, SND_PCM_HW_PARAM_FORMAT, tmp_mask); assert(err >= 0); - sformat_mask = snd_pcm_hw_params_value_mask(sparams, + sformat_mask = snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_FORMAT); same_rate = (rate_min == rate_max && @@ -321,30 +321,30 @@ static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, } if (same_rate && same_channels && same_format) { - const mask_t *access_mask = snd_pcm_hw_params_value_mask(params, SND_PCM_HW_PARAM_ACCESS); - mask_copy(tmp_mask, snd_pcm_hw_params_value_mask(sparams, SND_PCM_HW_PARAM_ACCESS)); + const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS); + mask_copy(tmp_mask, snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_ACCESS)); mask_intersect(tmp_mask, access_mask); if (!mask_empty(tmp_mask)) - _snd_pcm_hw_params_mask(sparams, 0, + _snd_pcm_hw_param_mask(sparams, 0, SND_PCM_HW_PARAM_ACCESS, access_mask); else - _snd_pcm_hw_params_mask(sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(sparams, 0, SND_PCM_HW_PARAM_ACCESS, mmap_mask); } else { - err = _snd_pcm_hw_params_mask(params, 1, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, accplug_mask); if (err < 0) return err; - err = _snd_pcm_hw_params_mask(params, 1, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, fmtplug_mask); if (err < 0) return err; - _snd_pcm_hw_params_mask(sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(sparams, 0, SND_PCM_HW_PARAM_ACCESS, mmap_mask); - _snd_pcm_hw_params_mask(sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_mask(sparams, 0, SND_PCM_HW_PARAM_FORMAT, fmtplug_mask); } err = snd_pcm_hw_refine2(params, sparams, @@ -584,15 +584,15 @@ static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) int err = snd_pcm_plug_hw_refine1(pcm, params, &sparams); assert(err >= 0); - clt_params.access = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_ACCESS); - clt_params.format = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT); - clt_params.channels = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_CHANNELS); - clt_params.rate = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_RATE); + clt_params.access = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_ACCESS); + clt_params.format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT); + clt_params.channels = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS); + clt_params.rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE); - slv_params.access = snd_pcm_hw_params_first(slave, &sparams, SND_PCM_HW_PARAM_ACCESS); - slv_params.format = snd_pcm_hw_params_value(&sparams, SND_PCM_HW_PARAM_FORMAT); - slv_params.channels = snd_pcm_hw_params_value(&sparams, SND_PCM_HW_PARAM_CHANNELS); - slv_params.rate = snd_pcm_hw_params_value(&sparams, SND_PCM_HW_PARAM_RATE); + slv_params.access = snd_pcm_hw_param_first(slave, &sparams, SND_PCM_HW_PARAM_ACCESS); + slv_params.format = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_FORMAT); + slv_params.channels = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_CHANNELS); + slv_params.rate = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_RATE); snd_pcm_plug_clear(pcm); err = snd_pcm_plug_insert_plugins(pcm, &clt_params, &slv_params); @@ -612,18 +612,21 @@ static int snd_pcm_plug_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) { snd_pcm_plug_t *plug = pcm->private; snd_pcm_t *slave = plug->req_slave; - size_t avail_min, xfer_min, xfer_align; + size_t avail_min, xfer_align, silence_threshold, silence_size; int err; avail_min = params->avail_min; - xfer_min = params->xfer_min; xfer_align = params->xfer_align; + silence_threshold = params->silence_threshold; + silence_size = params->silence_size; params->avail_min = muldiv_near(params->avail_min, slave->rate, pcm->rate); - params->xfer_min = muldiv_near(params->xfer_min, slave->rate, pcm->rate); params->xfer_align = muldiv_near(params->xfer_align, slave->rate, pcm->rate); + params->silence_threshold = muldiv_near(params->silence_threshold, slave->rate, pcm->rate); + params->silence_size = muldiv_near(params->silence_size, slave->rate, pcm->rate); err = snd_pcm_sw_params(slave, params); params->avail_min = avail_min; - params->xfer_min = xfer_min; params->xfer_align = xfer_align; + params->silence_threshold = silence_threshold; + params->silence_size = silence_size; params->boundary = LONG_MAX - pcm->buffer_size * 2 - LONG_MAX % pcm->buffer_size; return err; } diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index f7b53696..ac4b4b04 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -166,7 +166,11 @@ ssize_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, size_t frames) frames -= n; } if (frames > 0) { - ssize_t err = snd_pcm_rewind(plugin->slave, frames); + ssize_t err; + /* FIXME: rate plugin */ + if (plugin->slave_frames) + frames = plugin->slave_frames(pcm, frames); + err = snd_pcm_rewind(plugin->slave, frames); if (err < 0) { if (n <= 0) return err; @@ -305,13 +309,6 @@ ssize_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) return err; } -int snd_pcm_plugin_set_avail_min(snd_pcm_t *pcm, size_t frames) -{ - snd_pcm_plugin_t *plugin = pcm->private; - snd_pcm_t *slave = plugin->slave; - return snd_pcm_set_avail_min(slave, frames); -} - int snd_pcm_plugin_mmap(snd_pcm_t *pcm) { snd_pcm_plugin_t *plug = pcm->private; @@ -415,6 +412,5 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = { readn: snd_pcm_plugin_readn, avail_update: snd_pcm_plugin_avail_update, mmap_forward: snd_pcm_plugin_mmap_forward, - set_avail_min: snd_pcm_plugin_set_avail_min, }; diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h index 24e68915..06d14cc0 100644 --- a/src/pcm/pcm_plugin.h +++ b/src/pcm/pcm_plugin.h @@ -25,6 +25,7 @@ typedef struct { snd_pcm_xfer_areas_func_t read; snd_pcm_xfer_areas_func_t write; ssize_t (*client_frames)(snd_pcm_t *pcm, ssize_t frames); + ssize_t (*slave_frames)(snd_pcm_t *pcm, ssize_t frames); int (*init)(snd_pcm_t *pcm); int shmid; size_t appl_ptr, hw_ptr; @@ -35,6 +36,7 @@ int snd_pcm_plugin_card(snd_pcm_t *pcm); int snd_pcm_plugin_nonblock(snd_pcm_t *pcm, int nonblock); int snd_pcm_plugin_async(snd_pcm_t *pcm, int sig, pid_t pid); int snd_pcm_plugin_info(snd_pcm_t *pcm, snd_pcm_info_t * info); +int snd_pcm_plugin_sw_refine(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); int snd_pcm_plugin_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); int snd_pcm_plugin_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info); int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status); diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index e82ee1ad..9f616ea1 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -249,37 +249,37 @@ static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN); mask_load(format_mask, SND_PCM_FMTBIT_LINEAR); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; - err = _snd_pcm_hw_params_min(params, 1, + err = _snd_pcm_hw_param_min(params, 1, SND_PCM_HW_PARAM_RATE, RATE_MIN); if (err < 0) return err; - err = _snd_pcm_hw_params_max(params, 1, + err = _snd_pcm_hw_param_max(params, 1, SND_PCM_HW_PARAM_RATE, RATE_MAX); if (err < 0) return err; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); if (rate->sformat >= 0) { - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, rate->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); } else links |= (SND_PCM_HW_PARBIT_FORMAT | SND_PCM_HW_PARBIT_SUBFORMAT | SND_PCM_HW_PARBIT_SAMPLE_BITS | SND_PCM_HW_PARBIT_FRAME_BITS); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_RATE, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_RATE, rate->srate); err = snd_pcm_hw_refine2(params, &sparams, @@ -306,19 +306,19 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); if (rate->sformat >= 0) { - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, rate->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); } else links |= (SND_PCM_HW_PARBIT_FORMAT | SND_PCM_HW_PARBIT_SUBFORMAT | SND_PCM_HW_PARBIT_SAMPLE_BITS | SND_PCM_HW_PARBIT_FRAME_BITS); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_RATE, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_RATE, rate->srate); err = snd_pcm_hw_params2(params, &sparams, @@ -327,15 +327,15 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { - src_format = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT); + src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT); dst_format = slave->format; - src_rate = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_RATE); + src_rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE); dst_rate = slave->rate; } else { src_format = slave->format; - dst_format = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT); + dst_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT); src_rate = slave->rate; - dst_rate = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_RATE); + dst_rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE); } rate->get_idx = get_index(src_format, SND_PCM_FORMAT_S16); rate->put_idx = put_index(SND_PCM_FORMAT_S16, dst_format); @@ -349,7 +349,7 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) rate->pitch = (((u_int64_t)dst_rate * DIV) + src_rate / 2) / src_rate; if (rate->states) free(rate->states); - rate->states = malloc(snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_CHANNELS) * sizeof(*rate->states)); + rate->states = malloc(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS) * sizeof(*rate->states)); return 0; } @@ -357,18 +357,21 @@ static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) { snd_pcm_rate_t *rate = pcm->private; snd_pcm_t *slave = rate->plug.slave; - size_t avail_min, xfer_min, xfer_align; + size_t avail_min, xfer_align, silence_threshold, silence_size; int err; avail_min = params->avail_min; - xfer_min = params->xfer_min; xfer_align = params->xfer_align; + silence_threshold = params->silence_threshold; + silence_size = params->silence_size; params->avail_min = muldiv_near(params->avail_min, slave->rate, pcm->rate); - params->xfer_min = muldiv_near(params->xfer_min, slave->rate, pcm->rate); params->xfer_align = muldiv_near(params->xfer_align, slave->rate, pcm->rate); + params->silence_threshold = muldiv_near(params->silence_threshold, slave->rate, pcm->rate); + params->silence_size = muldiv_near(params->silence_size, slave->rate, pcm->rate); err = snd_pcm_sw_params(slave, params); params->avail_min = avail_min; - params->xfer_min = xfer_min; params->xfer_align = xfer_align; + params->silence_threshold = silence_threshold; + params->silence_size = silence_size; params->boundary = LONG_MAX - pcm->buffer_size * 2 - LONG_MAX % pcm->buffer_size; return err; } @@ -502,6 +505,16 @@ ssize_t snd_pcm_rate_client_frames(snd_pcm_t *pcm, ssize_t frames) return muldiv_down(frames, rate->pitch, DIV); } +ssize_t snd_pcm_rate_slave_frames(snd_pcm_t *pcm, ssize_t frames) +{ + snd_pcm_rate_t *rate = pcm->private; + /* Round toward zero */ + if (pcm->stream == SND_PCM_STREAM_PLAYBACK) + return muldiv_down(frames, rate->pitch, DIV); + else + return muldiv_down(frames, DIV, rate->pitch); +} + static void snd_pcm_rate_dump(snd_pcm_t *pcm, FILE *fp) { snd_pcm_rate_t *rate = pcm->private; @@ -551,6 +564,7 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, char *name, int sformat, int srate, snd_ rate->plug.read = snd_pcm_rate_read_areas; rate->plug.write = snd_pcm_rate_write_areas; rate->plug.client_frames = snd_pcm_rate_client_frames; + rate->plug.slave_frames = snd_pcm_rate_slave_frames; rate->plug.init = snd_pcm_rate_init; rate->plug.slave = slave; rate->plug.close_slave = close_slave; diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c index ad33740c..8d02cd22 100644 --- a/src/pcm/pcm_route.c +++ b/src/pcm/pcm_route.c @@ -443,32 +443,32 @@ static int snd_pcm_route_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN); mask_load(format_mask, SND_PCM_FMTBIT_LINEAR); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; - err = _snd_pcm_hw_params_min(params, 1, SND_PCM_HW_PARAM_CHANNELS, 1); + err = _snd_pcm_hw_param_min(params, 1, SND_PCM_HW_PARAM_CHANNELS, 1); if (err < 0) return err; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); if (route->sformat >= 0) { - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, route->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); } else links |= (SND_PCM_HW_PARBIT_FORMAT | SND_PCM_HW_PARBIT_SUBFORMAT | SND_PCM_HW_PARBIT_SAMPLE_BITS); if (route->schannels >= 0) { - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, route->schannels); } else { links |= SND_PCM_HW_PARBIT_CHANNELS; @@ -502,20 +502,20 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); if (route->sformat >= 0) { - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, route->sformat); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, SND_PCM_SUBFORMAT_STD); } else links |= (SND_PCM_HW_PARBIT_FORMAT | SND_PCM_HW_PARBIT_SUBFORMAT | SND_PCM_HW_PARBIT_SAMPLE_BITS); if (route->schannels >= 0) { - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, - route->schannels); + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, + route->schannels); } else { links |= SND_PCM_HW_PARBIT_CHANNELS; if (route->sformat < 0) @@ -530,11 +530,11 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { - src_format = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT); + src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT); dst_format = slave->format; } else { src_format = slave->format; - dst_format = snd_pcm_hw_params_value(params, SND_PCM_HW_PARAM_FORMAT); + dst_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT); } route->params.get_idx = get_index(src_format, SND_PCM_FORMAT_U16); route->params.put_idx = put_index(SND_PCM_FORMAT_U32, dst_format); diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c index ccb3870a..e649ffdf 100644 --- a/src/pcm/pcm_share.c +++ b/src/pcm/pcm_share.c @@ -77,6 +77,7 @@ typedef struct { size_t running_count; size_t safety_threshold; size_t silence_frames; + snd_pcm_sw_params_t sw_params; size_t hw_ptr; int poll[2]; int polling; @@ -367,8 +368,11 @@ void *snd_pcm_share_slave_thread(void *data) if (avail_min < 0) avail_min += spcm->boundary; // printf("avail_min=%d\n", avail_min); - if ((size_t)avail_min != spcm->avail_min) - snd_pcm_set_avail_min(spcm, avail_min); + if ((size_t)avail_min != spcm->avail_min) { + snd_pcm_sw_param_near(spcm, &slave->sw_params, SND_PCM_SW_PARAM_AVAIL_MIN, avail_min); + err = snd_pcm_sw_params(spcm, &slave->sw_params); + assert(err >= 0); + } slave->polling = 1; Pthread_mutex_unlock(&slave->mutex); err = poll(pfd, 2, -1); @@ -402,6 +406,7 @@ static void _snd_pcm_share_update(snd_pcm_t *pcm) if (missing < INT_MAX) { size_t hw_ptr; ssize_t avail_min; + int err; hw_ptr = slave->hw_ptr + missing; hw_ptr += spcm->fragment_size - 1; if (hw_ptr >= spcm->boundary) @@ -412,8 +417,11 @@ static void _snd_pcm_share_update(snd_pcm_t *pcm) avail_min += spcm->buffer_size; if (avail_min < 0) avail_min += spcm->boundary; - if ((size_t)avail_min < spcm->avail_min) - snd_pcm_set_avail_min(spcm, avail_min); + if ((size_t)avail_min < spcm->avail_min) { + snd_pcm_sw_param_near(spcm, &slave->sw_params, SND_PCM_SW_PARAM_AVAIL_MIN, avail_min); + err = snd_pcm_sw_params(spcm, &slave->sw_params); + assert(err >= 0); + } } } @@ -458,29 +466,29 @@ static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_CHANNELS, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_CHANNELS, share->channels_count); if (err < 0) return err; if (slave->format >= 0) { - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_FORMAT, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FORMAT, slave->format); if (err < 0) return err; } if (slave->rate >= 0) { - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_RATE, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_RATE, slave->rate); if (err < 0) return err; } _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, slave->channels_count); err = snd_pcm_hw_refine2(params, &sparams, snd_pcm_hw_refine, slave->pcm, @@ -494,7 +502,7 @@ static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) SND_PCM_HW_PARBIT_FRAGMENTS); if (err < 0) return err; - mmap_mask = snd_pcm_hw_params_value_mask(&sparams, SND_PCM_HW_PARAM_ACCESS); + mmap_mask = snd_pcm_hw_param_value_mask(&sparams, SND_PCM_HW_PARAM_ACCESS); mask_all(access_mask); mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED); if (!mask_test(mmap_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) @@ -502,7 +510,7 @@ static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) if (!mask_test(mmap_mask, SND_PCM_ACCESS_MMAP_COMPLEX) && !mask_test(mmap_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED)) mask_reset(access_mask, SND_PCM_ACCESS_MMAP_COMPLEX); - err = _snd_pcm_hw_params_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; @@ -519,23 +527,23 @@ static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) Pthread_mutex_lock(&slave->mutex); if (slave->setup_count > 1 || (slave->setup_count == 1 && !pcm->setup)) { - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_FORMAT, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FORMAT, spcm->format); if (err < 0) goto _err; - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, spcm->subformat); if (err < 0) goto _err; - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_RATE, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_RATE, spcm->rate); if (err < 0) goto _err; - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_FRAGMENT_SIZE, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FRAGMENT_SIZE, spcm->fragment_size); if (err < 0) goto _err; - err = _snd_pcm_hw_params_set(params, 1, SND_PCM_HW_PARAM_FRAGMENTS, + err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FRAGMENTS, spcm->fragments); _err: if (err < 0) { @@ -548,9 +556,9 @@ static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_params_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, + _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, share->channels_count); err = snd_pcm_hw_params2(params, &sparams, snd_pcm_hw_params, slave->pcm, @@ -564,6 +572,7 @@ static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) SND_PCM_HW_PARBIT_FRAGMENTS); if (err < 0) goto _end; + snd_pcm_sw_params_current(slave->pcm, &slave->sw_params); /* >= 30 ms */ slave->safety_threshold = slave->pcm->rate * 30 / 1000; slave->safety_threshold += slave->pcm->fragment_size - 1; @@ -579,20 +588,8 @@ static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) return err; } -static int snd_pcm_share_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params) +static int snd_pcm_share_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params ATTRIBUTE_UNUSED) { - if (params->start_mode > SND_PCM_START_LAST) { - params->fail_mask = 1 << SND_PCM_SW_PARAM_START_MODE; - return -EINVAL; - } - if (params->ready_mode > SND_PCM_READY_LAST) { - params->fail_mask = 1 << SND_PCM_SW_PARAM_READY_MODE; - return -EINVAL; - } - if (params->xrun_mode > SND_PCM_XRUN_LAST) { - params->fail_mask = 1 << SND_PCM_SW_PARAM_XRUN_MODE; - return -EINVAL; - } return 0; } @@ -895,18 +892,6 @@ static ssize_t snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames) return ret; } -static int snd_pcm_share_set_avail_min(snd_pcm_t *pcm, size_t frames) -{ - snd_pcm_share_t *share = pcm->private; - snd_pcm_share_slave_t *slave = share->slave; - Pthread_mutex_lock(&slave->mutex); - pcm->avail_min = frames; - share->avail_min = frames; - _snd_pcm_share_update(pcm); - Pthread_mutex_unlock(&slave->mutex); - return 0; -} - /* Warning: take the mutex before to call this */ static void _snd_pcm_share_stop(snd_pcm_t *pcm, int state) { @@ -1117,7 +1102,6 @@ snd_pcm_fast_ops_t snd_pcm_share_fast_ops = { rewind: snd_pcm_share_rewind, avail_update: snd_pcm_share_avail_update, mmap_forward: snd_pcm_share_mmap_forward, - set_avail_min: snd_pcm_share_set_avail_min, }; int snd_pcm_share_open(snd_pcm_t **pcmp, char *name, char *sname, diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c index 285f1233..aecec8c6 100644 --- a/src/pcm/pcm_shm.c +++ b/src/pcm/pcm_shm.c @@ -171,14 +171,14 @@ static int _snd_pcm_shm_hw_refine(snd_pcm_t *pcm, static int snd_pcm_shm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) { snd_pcm_hw_params_t sparams; - const mask_t *access_mask = snd_pcm_hw_params_value_mask(params, SND_PCM_HW_PARAM_ACCESS); + const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS); mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); if (!mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) && !mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) mask_intersect(saccess_mask, access_mask); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); return snd_pcm_hw_refine2(params, &sparams, _snd_pcm_shm_hw_refine, pcm, @@ -201,14 +201,14 @@ static int _snd_pcm_shm_hw_params(snd_pcm_t *pcm, static int snd_pcm_shm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) { snd_pcm_hw_params_t sparams; - const mask_t *access_mask = snd_pcm_hw_params_value_mask(params, SND_PCM_HW_PARAM_ACCESS); + const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS); mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); if (!mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) && !mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) mask_intersect(saccess_mask, access_mask); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_params_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, saccess_mask); return snd_pcm_hw_params2(params, &sparams, _snd_pcm_shm_hw_params, pcm, @@ -408,15 +408,6 @@ static ssize_t snd_pcm_shm_mmap_forward(snd_pcm_t *pcm, size_t size) return snd_pcm_shm_action(pcm); } -static int snd_pcm_shm_set_avail_min(snd_pcm_t *pcm, size_t frames) -{ - snd_pcm_shm_t *shm = pcm->private; - volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; - ctrl->cmd = SND_PCM_IOCTL_SET_AVAIL_MIN; - ctrl->u.set_avail_min.frames = frames; - return snd_pcm_shm_action(pcm); -} - static int snd_pcm_shm_poll_descriptor(snd_pcm_t *pcm) { snd_pcm_shm_t *shm = pcm->private; @@ -484,7 +475,6 @@ snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = { readn: snd_pcm_mmap_readn, avail_update: snd_pcm_shm_avail_update, mmap_forward: snd_pcm_shm_mmap_forward, - set_avail_min: snd_pcm_shm_set_avail_min, }; static int make_local_socket(const char *filename)