diff options
author | Abramo Bagnara <abramo@alsa-project.org> | 2001-01-15 11:06:53 +0000 |
---|---|---|
committer | Abramo Bagnara <abramo@alsa-project.org> | 2001-01-15 11:06:53 +0000 |
commit | cc90e325579c7dbdf70c2b5f70e5290a97df48b4 (patch) | |
tree | baeb502b76a20d1928e7a6ac0089dcf45d3801ae | |
parent | 7b06e6f7622b0f95e44d2fe50f20e934d569a4ba (diff) | |
download | alsa-lib-cc90e325579c7dbdf70c2b5f70e5290a97df48b4.tar.gz |
New PCM model with fragment concept removal and two interrupt sources
Renamed size_t/ssize_t to snd_pcm_sframes_t/snd_pcm_uframes_t
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | include/pcm.h | 171 | ||||
-rw-r--r-- | src/pcm/interval.c | 219 | ||||
-rw-r--r-- | src/pcm/interval.h | 31 | ||||
-rw-r--r-- | src/pcm/interval_inline.h | 61 | ||||
-rw-r--r-- | src/pcm/mask.h | 5 | ||||
-rw-r--r-- | src/pcm/mask_inline.h | 18 | ||||
-rw-r--r-- | src/pcm/pcm.c | 164 | ||||
-rw-r--r-- | src/pcm/pcm_adpcm.c | 141 | ||||
-rw-r--r-- | src/pcm/pcm_alaw.c | 141 | ||||
-rw-r--r-- | src/pcm/pcm_copy.c | 61 | ||||
-rw-r--r-- | src/pcm/pcm_file.c | 60 | ||||
-rw-r--r-- | src/pcm/pcm_hw.c | 61 | ||||
-rw-r--r-- | src/pcm/pcm_linear.c | 115 | ||||
-rw-r--r-- | src/pcm/pcm_local.h | 201 | ||||
-rw-r--r-- | src/pcm/pcm_misc.c | 6 | ||||
-rw-r--r-- | src/pcm/pcm_mmap.c | 102 | ||||
-rw-r--r-- | src/pcm/pcm_mulaw.c | 137 | ||||
-rw-r--r-- | src/pcm/pcm_multi.c | 121 | ||||
-rw-r--r-- | src/pcm/pcm_null.c | 22 | ||||
-rw-r--r-- | src/pcm/pcm_params.c | 1158 | ||||
-rw-r--r-- | src/pcm/pcm_plug.c | 293 | ||||
-rw-r--r-- | src/pcm/pcm_plugin.c | 70 | ||||
-rw-r--r-- | src/pcm/pcm_plugin.h | 22 | ||||
-rw-r--r-- | src/pcm/pcm_rate.c | 168 | ||||
-rw-r--r-- | src/pcm/pcm_route.c | 148 | ||||
-rw-r--r-- | src/pcm/pcm_share.c | 286 | ||||
-rw-r--r-- | src/pcm/pcm_shm.c | 50 | ||||
-rw-r--r-- | src/rawmidi/rawmidi_hw.c | 2 |
29 files changed, 2281 insertions, 1754 deletions
@@ -1,3 +1,4 @@ +H change functions that take a FILE* to take a char * and a maximum size M think about xrun recovery helpers M add abstraction layer to timer, hwdep L move OSS emulation to user space? (pseudo device driver and daemon) diff --git a/include/pcm.h b/include/pcm.h index 9e38827b..cd138ba5 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -47,8 +47,8 @@ int snd_pcm_open(snd_pcm_t **pcm, char *name, /* Obsolete functions */ #define snd_pcm_write snd_pcm_writei #define snd_pcm_read snd_pcm_readi -ssize_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, int count); -ssize_t snd_pcm_readv(snd_pcm_t *pcm, const struct iovec *vector, int count); +snd_pcm_sframes_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, int count); +snd_pcm_sframes_t snd_pcm_readv(snd_pcm_t *pcm, const struct iovec *vector, int count); snd_pcm_type_t snd_pcm_type(snd_pcm_t *pcm); @@ -69,12 +69,12 @@ int snd_pcm_drop(snd_pcm_t *pcm); int snd_pcm_drain(snd_pcm_t *pcm); int snd_pcm_pause(snd_pcm_t *pcm, int enable); int snd_pcm_state(snd_pcm_t *pcm); -int snd_pcm_delay(snd_pcm_t *pcm, ssize_t *delayp); -ssize_t snd_pcm_rewind(snd_pcm_t *pcm, size_t frames); -ssize_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, size_t size); -ssize_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, size_t size); -ssize_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, size_t size); -ssize_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, size_t size); +int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); +snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames); +snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_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); @@ -85,13 +85,13 @@ int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2); int snd_pcm_unlink(snd_pcm_t *pcm); int snd_pcm_wait(snd_pcm_t *pcm, int timeout); -ssize_t snd_pcm_avail_update(snd_pcm_t *pcm); -int snd_pcm_set_avail_min(snd_pcm_t *pcm, size_t size); +snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm); +int snd_pcm_set_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t size); typedef struct _mask mask_t; size_t mask_sizeof(); void mask_none(mask_t *mask); -void mask_all(mask_t *mask); +void mask_any(mask_t *mask); void mask_load(mask_t *mask, unsigned int msk); int mask_empty(const mask_t *mask); void mask_set(mask_t *mask, unsigned int val); @@ -99,48 +99,59 @@ void mask_reset(mask_t *mask, unsigned int val); void mask_copy(mask_t *mask, const mask_t *v); int mask_test(const mask_t *mask, unsigned int val); void mask_intersect(mask_t *mask, const mask_t *v); +void mask_union(mask_t *mask, const mask_t *v); 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_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var); + snd_pcm_hw_param_t var); +int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var); int snd_pcm_hw_param_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int par); + snd_pcm_hw_param_t var, int *dir); int snd_pcm_hw_param_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int par); + snd_pcm_hw_param_t var, int *dir); 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_param_t var, unsigned int val, + int *dir); int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val); + snd_pcm_hw_param_t var, + unsigned int val, int *dir); int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val); + snd_pcm_hw_param_t var, unsigned int val, int *dir); 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); + snd_pcm_hw_param_t var, + unsigned int *min, int *mindir, + unsigned int *max, int *maxdir); int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val); + snd_pcm_hw_param_t var, unsigned int val, int dir); int snd_pcm_hw_param_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, const mask_t *mask); + snd_pcm_hw_param_t var, const mask_t *mask); int snd_pcm_hw_param_min_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val); + snd_pcm_hw_param_t var, + unsigned int val, int *dir); int snd_pcm_hw_param_max_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val); + snd_pcm_hw_param_t var, + unsigned int val, int *dir); int snd_pcm_hw_param_minmax_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int min, unsigned int max); + snd_pcm_hw_param_t var, + unsigned int *min, int *mindir, + unsigned int *max, int *maxdir); int snd_pcm_hw_param_set_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val); + snd_pcm_hw_param_t var, unsigned int val, int dir); int snd_pcm_hw_param_mask_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, const mask_t *mask); + snd_pcm_hw_param_t var, const mask_t *mask); int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, - unsigned int var); + snd_pcm_hw_param_t var, int *dir); const mask_t *snd_pcm_hw_param_value_mask(const snd_pcm_hw_params_t *params, - unsigned int var); + snd_pcm_hw_param_t var); const interval_t *snd_pcm_hw_param_value_interval(const snd_pcm_hw_params_t *params, - unsigned int var); + snd_pcm_hw_param_t var); unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params, - unsigned int var); + snd_pcm_hw_param_t var, int *dir); unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params, - unsigned int var); + snd_pcm_hw_param_t var, int *dir); int snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm, snd_pcm_hw_params_t *fail, snd_pcm_hw_params_t *success, @@ -174,73 +185,73 @@ 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, + snd_pcm_hw_param_t var, unsigned int best, unsigned int mul); int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy, int order, - unsigned int param, + snd_pcm_hw_param_t var, 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 +typedef enum _snd_pcm_sw_param { + SND_PCM_SW_PARAM_START_MODE, + SND_PCM_SW_PARAM_XRUN_MODE, + SND_PCM_SW_PARAM_TSTAMP_MODE, + SND_PCM_SW_PARAM_PERIOD_STEP, + SND_PCM_SW_PARAM_SLEEP_MIN, + SND_PCM_SW_PARAM_AVAIL_MIN, + SND_PCM_SW_PARAM_XFER_ALIGN, + SND_PCM_SW_PARAM_SILENCE_THRESHOLD, + SND_PCM_SW_PARAM_SILENCE_SIZE, + SND_PCM_SW_PARAM_LAST = SND_PCM_SW_PARAM_SILENCE_SIZE, +} snd_pcm_sw_param_t; 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_param_set(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_sw_param_t var, unsigned int val); +int snd_pcm_sw_param_near(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_sw_param_t var, unsigned int val); +int snd_pcm_sw_param_value(snd_pcm_sw_params_t *params, snd_pcm_sw_param_t 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); const snd_pcm_channel_area_t *snd_pcm_mmap_running_areas(snd_pcm_t *pcm); const snd_pcm_channel_area_t *snd_pcm_mmap_stopped_areas(snd_pcm_t *pcm); -ssize_t snd_pcm_mmap_forward(snd_pcm_t *pcm, size_t size); -size_t snd_pcm_mmap_offset(snd_pcm_t *pcm); -size_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, size_t size); -ssize_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, size_t size); -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); +snd_pcm_sframes_t snd_pcm_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size); +snd_pcm_uframes_t snd_pcm_mmap_offset(snd_pcm_t *pcm); +snd_pcm_uframes_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_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_format_description(unsigned int format); +const char *snd_pcm_stream_name(snd_pcm_stream_t stream); +const char *snd_pcm_hw_param_name(snd_pcm_hw_param_t var); +const char *snd_pcm_sw_param_name(snd_pcm_sw_param_t var); +const char *snd_pcm_access_name(snd_pcm_access_t access); +const char *snd_pcm_format_name(snd_pcm_format_t format); +const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat); +const char *snd_pcm_format_description(snd_pcm_format_t 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); +const char *snd_pcm_start_mode_name(snd_pcm_start_t mode); +const char *snd_pcm_xrun_mode_name(snd_pcm_xrun_t mode); +const char *snd_pcm_tstamp_mode_name(snd_pcm_tstamp_t mode); +const char *snd_pcm_state_name(snd_pcm_state_t state); -int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, size_t dst_offset, - size_t samples, int format); -int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_channels, size_t dst_offset, - size_t vcount, size_t frames, int format); -int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_channel, size_t src_offset, - const snd_pcm_channel_area_t *dst_channel, size_t dst_offset, - size_t samples, int format); -int snd_pcm_areas_copy(const snd_pcm_channel_area_t *src_channels, size_t src_offset, - const snd_pcm_channel_area_t *dst_channels, size_t dst_offset, - size_t channels, size_t frames, int format); +int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, snd_pcm_uframes_t dst_offset, + unsigned int samples, int format); +int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_channels, snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int format); +int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_channel, snd_pcm_uframes_t src_offset, + const snd_pcm_channel_area_t *dst_channel, snd_pcm_uframes_t dst_offset, + unsigned int samples, int format); +int snd_pcm_areas_copy(const snd_pcm_channel_area_t *src_channels, snd_pcm_uframes_t src_offset, + const snd_pcm_channel_area_t *dst_channels, snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int format); -ssize_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes); -ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, ssize_t frames); -ssize_t snd_pcm_bytes_to_samples(snd_pcm_t *pcm, ssize_t bytes); -ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, ssize_t samples); +snd_pcm_sframes_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes); +ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, snd_pcm_sframes_t frames); +int snd_pcm_bytes_to_samples(snd_pcm_t *pcm, ssize_t bytes); +ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, int samples); /* misc */ @@ -259,7 +270,7 @@ u_int8_t snd_pcm_format_silence(int format); u_int16_t snd_pcm_format_silence_16(int format); u_int32_t snd_pcm_format_silence_32(int format); u_int64_t snd_pcm_format_silence_64(int format); -ssize_t snd_pcm_format_set_silence(int format, void *buf, size_t count); +int snd_pcm_format_set_silence(int format, void *buf, unsigned int samples); #ifdef __cplusplus } diff --git a/src/pcm/interval.c b/src/pcm/interval.c index 2a5283d9..0e2793b9 100644 --- a/src/pcm/interval.c +++ b/src/pcm/interval.c @@ -58,6 +58,8 @@ static inline unsigned int div_up(unsigned int a, unsigned int b) static inline unsigned int mul(unsigned int a, unsigned int b) { + if (a == 0) + return 0; if (div_down(UINT_MAX, a) < b) return UINT_MAX; return a * b; @@ -89,10 +91,9 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, return n; } -int interval_refine_min(interval_t *i, unsigned int min) +int interval_refine_min(interval_t *i, unsigned int min, int openmin) { int changed = 0; - int openmin = 0; assert(!interval_empty(i)); if (i->min < min) { i->min = min; @@ -102,24 +103,22 @@ int interval_refine_min(interval_t *i, unsigned int min) i->openmin = 1; changed = 1; } - if (!i->real) { + if (i->integer) { if (i->openmin) { i->min++; i->openmin = 0; } } if (interval_checkempty(i)) { - i->empty = 1; + interval_none(i); return -EINVAL; } return changed; } -int interval_refine_max(interval_t *i, unsigned int max) +int interval_refine_max(interval_t *i, unsigned int max, int openmax) { int changed = 0; - int openmax = 1; - max = add(max, 1); assert(!interval_empty(i)); if (i->max > max) { i->max = max; @@ -129,14 +128,14 @@ int interval_refine_max(interval_t *i, unsigned int max) i->openmax = 1; changed = 1; } - if (!i->real) { + if (i->integer) { if (i->openmax) { i->max--; i->openmax = 0; } } if (interval_checkempty(i)) { - i->empty = 1; + interval_none(i); return -EINVAL; } return changed; @@ -163,7 +162,11 @@ int interval_refine(interval_t *i, const interval_t *v) i->openmax = 1; changed = 1; } - if (!i->real) { + if (!i->integer && v->integer) { + i->integer = 1; + changed = 1; + } + if (i->integer) { if (i->openmin) { i->min++; i->openmin = 0; @@ -172,9 +175,10 @@ int interval_refine(interval_t *i, const interval_t *v) i->max--; i->openmax = 0; } - } + } else if (!i->openmin && !i->openmax && i->min == i->max) + i->integer = 1; if (interval_checkempty(i)) { - i->empty = 1; + interval_none(i); return -EINVAL; } return changed; @@ -183,8 +187,7 @@ int interval_refine(interval_t *i, const interval_t *v) int interval_refine_first(interval_t *i) { assert(!interval_empty(i)); - if (i->min == i->max || - (i->min + 1 == i->max && i->openmin && i->openmax)) + if (interval_single(i)) return 0; i->max = i->min; i->openmax = i->openmin; @@ -196,8 +199,7 @@ int interval_refine_first(interval_t *i) int interval_refine_last(interval_t *i) { assert(!interval_empty(i)); - if (i->min == i->max || - (i->min + 1 == i->max && i->openmin && i->openmax)) + if (interval_single(i)) return 0; i->min = i->max; i->openmin = i->openmax; @@ -209,107 +211,154 @@ int interval_refine_last(interval_t *i) int interval_refine_set(interval_t *i, unsigned int val) { interval_t t; - t.min = val; - t.openmin = 0; - t.max = add(val, 1); - t.openmax = 1; + t.empty = 0; + t.min = t.max = val; + t.openmin = t.openmax = 0; + t.integer = 1; return interval_refine(i, &t); } -/* a <- b + c */ -int interval_add(interval_t *a, const interval_t *b, const interval_t *c) +void interval_add(const interval_t *a, const interval_t *b, 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); + if (a->empty || b->empty) { + interval_none(c); + return; + } + c->empty = 0; + c->min = add(a->min, b->min); + c->openmin = (a->openmin || b->openmin); + c->max = add(a->max, b->max); + c->openmax = (a->openmax || b->openmax); + c->integer = (a->integer && b->integer); } -/* a <- b - c */ -int interval_sub(interval_t *a, const interval_t *b, const interval_t *c) +void interval_sub(const interval_t *a, const interval_t *b, 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); + if (a->empty || b->empty) { + interval_none(c); + return; + } + c->empty = 0; + c->min = sub(a->min, b->max); + c->openmin = (a->openmin || b->openmax); + c->max = add(a->max, b->min); + c->openmax = (a->openmax || b->openmin); + c->integer = (a->integer && b->integer); } -/* a <- b * c */ -int interval_mul(interval_t *a, const interval_t *b, const interval_t *c) +void interval_mul(const interval_t *a, const interval_t *b, interval_t *c) { - interval_t t; - assert(!a->empty && !b->empty && !c->empty); - t.min = mul(b->min, c->min); - t.openmin = (b->openmin || c->openmin); - t.max = mul(b->max, c->max); - t.openmax = (b->openmax || c->openmax); - return interval_refine(a, &t); + if (a->empty || b->empty) { + interval_none(c); + return; + } + c->empty = 0; + c->min = mul(a->min, b->min); + c->openmin = (a->openmin || b->openmin); + c->max = mul(a->max, b->max); + c->openmax = (a->openmax || b->openmax); + c->integer = (a->integer && b->integer); } -/* a <- b / c */ -int interval_div(interval_t *a, const interval_t *b, const interval_t *c) +void interval_div(const interval_t *a, const interval_t *b, interval_t *c) { - interval_t t; unsigned int r; - assert(!a->empty && !b->empty && !c->empty); - t.min = div32(b->min, c->max, &r); - t.openmin = (r || b->openmin || c->openmax); - t.max = div32(b->max, c->min, &r); - if (r) { - t.max++; - t.openmax = 1; - } else - t.openmax = (b->openmax || c->openmin); - return interval_refine(a, &t); + if (a->empty || b->empty) { + interval_none(c); + return; + } + c->empty = 0; + c->min = div32(a->min, b->max, &r); + c->openmin = (r || a->openmin || b->openmax); + if (b->min > 0) { + c->max = div32(a->max, b->min, &r); + if (r) { + c->max++; + c->openmax = 1; + } else + c->openmax = (a->openmax || b->openmin); + } else { + c->max = UINT_MAX; + c->openmax = 0; + } + c->integer = 0; } - -/* a <- b * c / k */ -int interval_muldivk(interval_t *a, unsigned int k, - const interval_t *b, const interval_t *c) +/* a * b / c */ +void interval_muldiv(const interval_t *a, const interval_t *b, + const interval_t *c, interval_t *d) { - interval_t t; unsigned int r; - assert(!a->empty && !b->empty && !c->empty); - t.min = muldiv32(b->min, c->min, k, &r); - t.openmin = (r || b->openmin || c->openmin); - t.max = muldiv32(b->max, c->max, k, &r); + if (a->empty || b->empty || c->empty) { + interval_none(d); + return; + } + d->empty = 0; + d->min = muldiv32(a->min, b->min, c->max, &r); + d->openmin = (r || a->openmin || b->openmin || c->openmax); + d->max = muldiv32(a->max, b->max, c->min, &r); if (r) { - t.max++; - t.openmax = 1; + d->max++; + d->openmax = 1; } else - t.openmax = (b->openmax || c->openmax); - return interval_refine(a, &t); + d->openmax = (a->openmax || b->openmax || c->openmin); + d->integer = 0; } -/* a <- b * k / c */ -int interval_mulkdiv(interval_t *a, unsigned int k, - const interval_t *b, const interval_t *c) +/* a * b / k */ +void interval_muldivk(const interval_t *a, const interval_t *b, + unsigned int k, interval_t *c) { - interval_t t; unsigned int r; - assert(!a->empty && !b->empty && !c->empty); - t.min = muldiv32(b->min, k, c->max, &r); - t.openmin = (r || b->openmin || c->openmax); - t.max = muldiv32(b->max, k, c->min, &r); + if (a->empty || b->empty) { + interval_none(c); + return; + } + c->empty = 0; + c->min = muldiv32(a->min, b->min, k, &r); + c->openmin = (r || a->openmin || b->openmin); + c->max = muldiv32(a->max, b->max, k, &r); if (r) { - t.max++; - t.openmax = 1; + c->max++; + c->openmax = 1; } else - t.openmax = (b->openmax || c->openmin); - return interval_refine(a, &t); + c->openmax = (a->openmax || b->openmax); + c->integer = 0; +} + +/* a * k / b */ +void interval_mulkdiv(const interval_t *a, unsigned int k, + const interval_t *b, interval_t *c) +{ + unsigned int r; + if (a->empty || b->empty) { + interval_none(c); + return; + } + c->empty = 0; + c->min = muldiv32(a->min, k, b->max, &r); + c->openmin = (r || a->openmin || b->openmax); + if (b->min > 0) { + c->max = muldiv32(a->max, k, b->min, &r); + if (r) { + c->max++; + c->openmax = 1; + } else + c->openmax = (a->openmax || b->openmin); + } else { + c->max = UINT_MAX; + c->openmax = 0; + } + c->integer = 0; } void interval_print(const interval_t *i, FILE *fp) { if (interval_empty(i)) fprintf(fp, "NONE"); + else if (i->min == 0 && i->openmin == 0 && + i->max == UINT_MAX && i->openmax == 0) + fprintf(fp, "ALL"); else if (interval_single(i)) fprintf(fp, "%u", interval_value(i)); else diff --git a/src/pcm/interval.h b/src/pcm/interval.h index 8c6e0d8d..2f549b42 100644 --- a/src/pcm/interval.h +++ b/src/pcm/interval.h @@ -24,8 +24,9 @@ #ifdef INTERVAL_INLINE #include "interval_inline.h" #else -void interval_all(interval_t *i); -void interval_setreal(interval_t *i); +void interval_any(interval_t *i); +void interval_none(interval_t *i); +int interval_setinteger(interval_t *i); int interval_empty(const interval_t *i); int interval_single(const interval_t *i); int interval_value(const interval_t *i); @@ -33,20 +34,24 @@ int interval_min(const interval_t *i); int interval_max(const interval_t *i); int interval_test(const 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); +void interval_round(interval_t *i); +int interval_always_eq(const interval_t *i1, const interval_t *i2); +int interval_never_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_add(const interval_t *a, const interval_t *b, interval_t *c); +void interval_sub(const interval_t *a, const interval_t *b, interval_t *c); +void interval_mul(const interval_t *a, const interval_t *b, interval_t *c); +void interval_div(const interval_t *a, const interval_t *b, interval_t *c); +void interval_muldiv(const interval_t *a, const interval_t *b, + const interval_t *c, interval_t *d); +void interval_muldivk(const interval_t *a, const interval_t *b, + unsigned int k, interval_t *c); +void interval_mulkdiv(const interval_t *a, unsigned int k, + const interval_t *b, interval_t *c); void interval_print(const interval_t *i, FILE *fp); -int interval_refine_min(interval_t *i, unsigned int min); -int interval_refine_max(interval_t *i, unsigned int max); +int interval_refine_min(interval_t *i, unsigned int min, int openmin); +int interval_refine_max(interval_t *i, unsigned int max, int openmax); int interval_refine(interval_t *i, const interval_t *v); int interval_refine_first(interval_t *i); int interval_refine_last(interval_t *i); diff --git a/src/pcm/interval_inline.h b/src/pcm/interval_inline.h index ae78bcf6..a14c83eb 100644 --- a/src/pcm/interval_inline.h +++ b/src/pcm/interval_inline.h @@ -25,10 +25,19 @@ #define INLINE extern inline #endif -INLINE void interval_all(interval_t *i) +INLINE void interval_any(interval_t *i) { - i->min = 1; + i->min = 0; + i->openmin = 0; i->max = UINT_MAX; + i->openmax = 0; + i->integer = 0; + i->empty = 0; +} + +INLINE void interval_none(interval_t *i) +{ + i->empty = 1; } INLINE int interval_checkempty(const interval_t *i) @@ -63,12 +72,8 @@ INLINE int interval_min(const interval_t *i) INLINE int interval_max(const interval_t *i) { - unsigned int v; assert(!interval_empty(i)); - v = i->max; - if (i->openmax) - v--; - return v; + return i->max; } INLINE int interval_test(const interval_t *i, unsigned int val) @@ -82,18 +87,42 @@ INLINE void interval_copy(interval_t *d, const interval_t *s) *d = *s; } -INLINE void interval_setreal(interval_t *i) +INLINE int interval_setinteger(interval_t *i) +{ + if (i->integer) + return 0; + if (i->openmin && i->openmax && i->min == i->max) + return -EINVAL; + i->integer = 1; + return 1; +} + +INLINE void interval_round(interval_t *i) { - i->real = 1; + assert(!interval_empty(i)); + if (i->integer) + return; + i->openmin = 0; + i->openmax = 0; + i->integer = 1; +} + +INLINE int interval_always_eq(const interval_t *i1, const interval_t *i2) +{ + return interval_single(i1) && interval_single(i2) && + interval_value(i1) == interval_value(i2); } -INLINE int interval_eq(const interval_t *i1, const interval_t *i2) +INLINE int interval_never_eq(const interval_t *i1, const interval_t *i2) { - if (i1->empty) - return i2->empty; - if (i2->empty) - return i1->empty; - return i1->min == i2->min && i1->openmin == i2->openmin && - i1->max == i2->max && i1->openmax == i2->openmax; + + return (i1->max < i2->min || + (i1->max == i2->min && + (i1->openmax || i1->openmin)) || + i1->min > i2->max || + (i1->min == i2->max && + (i1->openmin || i2->openmax))); } + + diff --git a/src/pcm/mask.h b/src/pcm/mask.h index 8a654619..b6e6792c 100644 --- a/src/pcm/mask.h +++ b/src/pcm/mask.h @@ -31,7 +31,7 @@ #include "mask_inline.h" #else void mask_none(mask_t *mask); -void mask_all(mask_t *mask); +void mask_any(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); @@ -40,6 +40,7 @@ void mask_reset(mask_t *mask, unsigned int val); void mask_copy(mask_t *mask, const mask_t *v); int mask_test(const mask_t *mask, unsigned int val); void mask_intersect(mask_t *mask, const mask_t *v); +void mask_union(mask_t *mask, const mask_t *v); unsigned int mask_count(const mask_t *mask); unsigned int mask_min(const mask_t *mask); unsigned int mask_max(const mask_t *mask); @@ -55,4 +56,6 @@ 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); +int mask_always_eq(const mask_t *m1, const mask_t *m2); +int mask_never_eq(const mask_t *m1, const mask_t *m2); #endif diff --git a/src/pcm/mask_inline.h b/src/pcm/mask_inline.h index 44892110..5f3e1a1a 100644 --- a/src/pcm/mask_inline.h +++ b/src/pcm/mask_inline.h @@ -82,7 +82,7 @@ INLINE void mask_none(mask_t *mask) mask_bits(mask) = 0; } -INLINE void mask_all(mask_t *mask) +INLINE void mask_any(mask_t *mask) { mask_bits(mask) = ~0U; } @@ -154,6 +154,11 @@ INLINE void mask_intersect(mask_t *mask, const mask_t *v) mask_bits(mask) &= mask_bits(v); } +INLINE void mask_union(mask_t *mask, const mask_t *v) +{ + mask_bits(mask) |= mask_bits(v); +} + INLINE int mask_eq(const mask_t *mask, const mask_t *v) { return mask_bits(mask) == mask_bits(v); @@ -243,3 +248,14 @@ INLINE int mask_value(const mask_t *mask) assert(!mask_empty(mask)); return mask_min(mask); } + +INLINE int mask_always_eq(const mask_t *m1, const mask_t *m2) +{ + return mask_single(m1) && mask_single(m2) && + mask_value(m1) == mask_value(m2); +} + +INLINE int mask_never_eq(const mask_t *m1, const mask_t *m2) +{ + return (mask_bits(m1) & mask_bits(m2)) == 0; +} diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index b94d3208..2cbce95e 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -106,7 +106,7 @@ int snd_pcm_state(snd_pcm_t *pcm) return pcm->fast_ops->state(pcm->fast_op_arg); } -int snd_pcm_delay(snd_pcm_t *pcm, ssize_t *delayp) +int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { assert(pcm); assert(pcm->setup); @@ -156,7 +156,7 @@ int snd_pcm_pause(snd_pcm_t *pcm, int enable) } -ssize_t snd_pcm_rewind(snd_pcm_t *pcm, size_t frames) +snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { assert(pcm); assert(pcm->setup); @@ -164,7 +164,7 @@ ssize_t snd_pcm_rewind(snd_pcm_t *pcm, size_t frames) return pcm->fast_ops->rewind(pcm->fast_op_arg, frames); } -ssize_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, size_t size) +snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { assert(pcm); assert(size == 0 || buffer); @@ -173,7 +173,7 @@ ssize_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, size_t size) return _snd_pcm_writei(pcm, buffer, size); } -ssize_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, size_t size) +snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { assert(pcm); assert(size == 0 || bufs); @@ -182,7 +182,7 @@ ssize_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, size_t size) return _snd_pcm_writen(pcm, bufs, size); } -ssize_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, size_t size) +snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) { assert(pcm); assert(size == 0 || buffer); @@ -191,7 +191,7 @@ ssize_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, size_t size) return _snd_pcm_readi(pcm, buffer, size); } -ssize_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, size_t size) +snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { assert(pcm); assert(size == 0 || bufs); @@ -200,7 +200,7 @@ ssize_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, size_t size) return _snd_pcm_readn(pcm, bufs, size); } -ssize_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, int count) +snd_pcm_sframes_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, int count) { void **bufs; int k; @@ -215,7 +215,7 @@ ssize_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, int count) return snd_pcm_writen(pcm, bufs, vector[0].iov_len); } -ssize_t snd_pcm_readv(snd_pcm_t *pcm, const struct iovec *vector, int count) +snd_pcm_sframes_t snd_pcm_readv(snd_pcm_t *pcm, const struct iovec *vector, int count) { void **bufs; int k; @@ -310,25 +310,26 @@ char *snd_pcm_hw_param_names[] = { HW_PARAM(ACCESS), HW_PARAM(FORMAT), HW_PARAM(SUBFORMAT), + HW_PARAM(SAMPLE_BITS), + HW_PARAM(FRAME_BITS), HW_PARAM(CHANNELS), HW_PARAM(RATE), - HW_PARAM(FRAGMENT_LENGTH), - HW_PARAM(FRAGMENT_SIZE), - HW_PARAM(FRAGMENTS), - HW_PARAM(BUFFER_LENGTH), + HW_PARAM(PERIOD_TIME), + HW_PARAM(PERIOD_SIZE), + HW_PARAM(PERIOD_BYTES), + HW_PARAM(PERIODS), + HW_PARAM(BUFFER_TIME), HW_PARAM(BUFFER_SIZE), - HW_PARAM(SAMPLE_BITS), - HW_PARAM(FRAME_BITS), - HW_PARAM(FRAGMENT_BYTES), HW_PARAM(BUFFER_BYTES), + HW_PARAM(TICK_TIME), }; 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(PERIOD_STEP), + SW_PARAM(SLEEP_MIN), SW_PARAM(AVAIL_MIN), SW_PARAM(XFER_ALIGN), SW_PARAM(SILENCE_THRESHOLD), @@ -414,20 +415,9 @@ char *snd_pcm_start_mode_names[] = { START(DATA), }; -char *snd_pcm_ready_mode_names[] = { - READY(FRAGMENT), - READY(ASAP), -}; - char *snd_pcm_xrun_mode_names[] = { - XRUN(FRAGMENT), - XRUN(ASAP), XRUN(NONE), -}; - -char *snd_pcm_silence_mode_names[] = { - SILENCE(FRAGMENT), - SILENCE(ASAP), + XRUN(STOP), }; char *snd_pcm_tstamp_mode_names[] = { @@ -435,25 +425,25 @@ char *snd_pcm_tstamp_mode_names[] = { TSTAMP(MMAP), }; -const char *snd_pcm_stream_name(unsigned int stream) +const char *snd_pcm_stream_name(snd_pcm_stream_t stream) { assert(stream <= SND_PCM_STREAM_LAST); return snd_pcm_stream_names[stream]; } -const char *snd_pcm_access_name(unsigned int access) +const char *snd_pcm_access_name(snd_pcm_access_t access) { assert(access <= SND_PCM_ACCESS_LAST); return snd_pcm_access_names[access]; } -const char *snd_pcm_format_name(unsigned int format) +const char *snd_pcm_format_name(snd_pcm_format_t format) { assert(format <= SND_PCM_FORMAT_LAST); return snd_pcm_format_names[format]; } -const char *snd_pcm_format_description(unsigned int format) +const char *snd_pcm_format_description(snd_pcm_format_t format) { assert(format <= SND_PCM_FORMAT_LAST); return snd_pcm_format_descriptions[format]; @@ -469,55 +459,43 @@ int snd_pcm_format_value(const char* name) return -1; } -const char *snd_pcm_subformat_name(unsigned int subformat) +const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat) { assert(subformat <= SND_PCM_SUBFORMAT_LAST); return snd_pcm_subformat_names[subformat]; } -const char *snd_pcm_hw_param_name(unsigned int param) +const char *snd_pcm_hw_param_name(snd_pcm_hw_param_t 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) +const char *snd_pcm_sw_param_name(snd_pcm_sw_param_t 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) +const char *snd_pcm_start_mode_name(snd_pcm_start_t 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) +const char *snd_pcm_xrun_mode_name(snd_pcm_xrun_t 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) +const char *snd_pcm_tstamp_mode_name(snd_pcm_tstamp_t mode) { assert(mode <= SND_PCM_TSTAMP_LAST); return snd_pcm_tstamp_mode_names[mode]; } -const char *snd_pcm_state_name(unsigned int state) +const char *snd_pcm_state_name(snd_pcm_state_t state) { assert(state <= SND_PCM_STATE_LAST); return snd_pcm_state_names[state]; @@ -536,8 +514,10 @@ int snd_pcm_dump_hw_setup(snd_pcm_t *pcm, FILE *fp) 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); fprintf(fp, "msbits : %u\n", pcm->msbits); - fprintf(fp, "fragment_size: %lu\n", (long)pcm->fragment_size); - fprintf(fp, "fragments : %u\n", pcm->fragments); + fprintf(fp, "buffer_size : %lu\n", pcm->buffer_size); + fprintf(fp, "period_size : %lu\n", pcm->period_size); + fprintf(fp, "period_time : %u\n", pcm->period_time); + fprintf(fp, "tick_time : %u\n", pcm->tick_time); return 0; } @@ -548,9 +528,9 @@ int snd_pcm_dump_sw_setup(snd_pcm_t *pcm, FILE *fp) assert(pcm->setup); 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, "period_step : %ld\n", (long)pcm->period_step); + fprintf(fp, "sleep_min : %ld\n", (long)pcm->sleep_min); fprintf(fp, "avail_min : %ld\n", (long)pcm->avail_min); fprintf(fp, "xfer_align : %ld\n", (long)pcm->xfer_align); fprintf(fp, "silence_threshold: %ld\n", (long)pcm->silence_threshold); @@ -588,28 +568,28 @@ int snd_pcm_dump(snd_pcm_t *pcm, FILE *fp) return 0; } -ssize_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes) +snd_pcm_sframes_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes) { assert(pcm); assert(pcm->setup); return bytes * 8 / pcm->bits_per_frame; } -ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, ssize_t frames) +ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, snd_pcm_sframes_t frames) { assert(pcm); assert(pcm->setup); return frames * pcm->bits_per_frame / 8; } -ssize_t snd_pcm_bytes_to_samples(snd_pcm_t *pcm, ssize_t bytes) +int snd_pcm_bytes_to_samples(snd_pcm_t *pcm, ssize_t bytes) { assert(pcm); assert(pcm->setup); return bytes * 8 / pcm->bits_per_sample; } -ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, ssize_t samples) +ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, int samples) { assert(pcm); assert(pcm->setup); @@ -788,20 +768,20 @@ int snd_pcm_wait(snd_pcm_t *pcm, int timeout) return 0; } -ssize_t snd_pcm_avail_update(snd_pcm_t *pcm) +snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm) { return pcm->fast_ops->avail_update(pcm->fast_op_arg); } -ssize_t snd_pcm_mmap_forward(snd_pcm_t *pcm, size_t size) +snd_pcm_sframes_t snd_pcm_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size) { assert(size > 0); assert(size <= snd_pcm_mmap_avail(pcm)); return pcm->fast_ops->mmap_forward(pcm->fast_op_arg, size); } -int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offset, - size_t samples, int format) +int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t dst_offset, + unsigned int samples, int format) { /* FIXME: sub byte resolution and odd dst_offset */ char *dst; @@ -814,7 +794,7 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offs width = snd_pcm_format_physical_width(format); silence = snd_pcm_format_silence_64(format); if (dst_area->step == (unsigned int) width) { - size_t dwords = samples * width / 64; + unsigned int dwords = samples * width / 64; samples -= dwords * 64 / width; while (dwords-- > 0) *((u_int64_t*)dst)++ = silence; @@ -882,8 +862,8 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offs return 0; } -int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_areas, size_t dst_offset, - size_t channels, size_t frames, int format) +int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int format) { int width = snd_pcm_format_physical_width(format); while (channels > 0) { @@ -923,9 +903,9 @@ int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_areas, size_t dst_of } -int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, size_t src_offset, - const snd_pcm_channel_area_t *dst_area, size_t dst_offset, - size_t samples, int format) +int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, snd_pcm_uframes_t src_offset, + const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t dst_offset, + unsigned int samples, int format) { /* FIXME: sub byte resolution and odd dst_offset */ char *src, *dst; @@ -1018,9 +998,9 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, size_t src_offset, return 0; } -int snd_pcm_areas_copy(const snd_pcm_channel_area_t *src_areas, size_t src_offset, - const snd_pcm_channel_area_t *dst_areas, size_t dst_offset, - size_t channels, size_t frames, int format) +int snd_pcm_areas_copy(const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset, + const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int format) { int width = snd_pcm_format_physical_width(format); while (channels > 0) { @@ -1065,12 +1045,12 @@ int snd_pcm_areas_copy(const snd_pcm_channel_area_t *src_areas, size_t src_offse return 0; } -ssize_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, size_t size, +snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, + snd_pcm_uframes_t offset, snd_pcm_uframes_t size, snd_pcm_xfer_areas_func_t func) { - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; int state = snd_pcm_state(pcm); assert(size > 0); assert(state >= SND_PCM_STATE_PREPARED); @@ -1082,15 +1062,15 @@ ssize_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, state = SND_PCM_STATE_RUNNING; } while (xfer < size) { - ssize_t avail; - size_t frames; + snd_pcm_sframes_t avail; + snd_pcm_uframes_t frames; again: avail = snd_pcm_avail_update(pcm); if (avail < 0) { err = avail; break; } - if ((size_t)avail < pcm->avail_min) { + if ((snd_pcm_uframes_t)avail < pcm->avail_min) { if (state != SND_PCM_STATE_RUNNING) { err = -EPIPE; break; @@ -1106,12 +1086,12 @@ ssize_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, goto again; } frames = size - xfer; - if (frames > (size_t)avail) + if (frames > (snd_pcm_uframes_t)avail) frames = avail; err = func(pcm, areas, offset, frames, 0); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); xfer += err; offset += err; } @@ -1120,18 +1100,18 @@ ssize_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, return err; } -ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, size_t size, +snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, + snd_pcm_uframes_t offset, snd_pcm_uframes_t size, snd_pcm_xfer_areas_func_t func) { - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; int state = snd_pcm_state(pcm); assert(size > 0); assert(state >= SND_PCM_STATE_PREPARED); while (xfer < size) { - ssize_t avail; - size_t frames; + snd_pcm_sframes_t avail; + snd_pcm_uframes_t frames; again: if (state == SND_PCM_STATE_XRUN) { err = -EPIPE; @@ -1142,7 +1122,7 @@ ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, err = avail; break; } - if ((size_t)avail < pcm->avail_min) { + if ((snd_pcm_uframes_t)avail < pcm->avail_min) { if (state != SND_PCM_STATE_RUNNING) { err = -EPIPE; break; @@ -1158,12 +1138,12 @@ ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, goto again; } frames = size - xfer; - if (frames > (size_t)avail) + if (frames > (snd_pcm_uframes_t)avail) frames = avail; err = func(pcm, areas, offset, frames, 0); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); xfer += err; offset += err; if (state == SND_PCM_STATE_PREPARED && @@ -1179,7 +1159,7 @@ ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, return err; } -size_t _snd_pcm_mmap_hw_ptr(snd_pcm_t *pcm) +snd_pcm_uframes_t _snd_pcm_mmap_hw_ptr(snd_pcm_t *pcm) { return *pcm->hw_ptr; } diff --git a/src/pcm/pcm_adpcm.c b/src/pcm/pcm_adpcm.c index 41acc108..31c3f76c 100644 --- a/src/pcm/pcm_adpcm.c +++ b/src/pcm/pcm_adpcm.c @@ -57,10 +57,10 @@ typedef struct { } adpcm_state_t; typedef void (*adpcm_f)(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int getputidx, + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int getputidx, adpcm_state_t *states); typedef struct { @@ -196,23 +196,23 @@ static int adpcm_decoder(unsigned char code, adpcm_state_t * state) } static void adpcm_decode(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int putidx, + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int putidx, adpcm_state_t *states) { #define PUT16_LABELS #include "plugin_ops.h" #undef PUT16_LABELS void *put = put16_labels[putidx]; - size_t channel; + unsigned int channel; for (channel = 0; channel < channels; ++channel, ++states) { char *src; int srcbit; char *dst; int src_step, srcbit_step, dst_step; - size_t frames1; + snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; #if 0 @@ -257,24 +257,24 @@ static void adpcm_decode(const snd_pcm_channel_area_t *src_areas, } static void adpcm_encode(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int getidx, + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int getidx, adpcm_state_t *states) { #define GET16_LABELS #include "plugin_ops.h" #undef GET16_LABELS void *get = get16_labels[getidx]; - size_t channel; + unsigned int channel; int16_t sample = 0; for (channel = 0; channel < channels; ++channel, ++states) { char *src; char *dst; int dstbit; int src_step, dst_step, dstbit_step; - size_t frames1; + snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; #if 0 @@ -334,51 +334,58 @@ static int snd_pcm_adpcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_adpcm_t *adpcm = pcm->private; snd_pcm_t *slave = adpcm->plug.slave; int err; + unsigned int cmask, lcmask; snd_pcm_hw_params_t sparams; mask_t *access_mask = alloca(mask_sizeof()); 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_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_mask(params, 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_param_mask(params, 1, + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; } else { - err = _snd_pcm_hw_param_set(params, 1, - SND_PCM_HW_PARAM_FORMAT, - SND_PCM_FORMAT_IMA_ADPCM); + err = _snd_pcm_hw_param_set(params, + SND_PCM_HW_PARAM_FORMAT, + SND_PCM_FORMAT_IMA_ADPCM, 0); if (err < 0) return err; } - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); if (err < 0) return err; + lcmask = params->cmask; + params->cmask |= cmask; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - adpcm->sformat); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + adpcm->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave, + snd_pcm_generic_hw_link, slave, SND_PCM_HW_PARBIT_CHANNELS | SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); + params->cmask |= lcmask; if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); @@ -391,31 +398,39 @@ static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) snd_pcm_t *slave = adpcm->plug.slave; int err; snd_pcm_hw_params_t sparams; + unsigned int links; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - adpcm->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 | - SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + adpcm->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); + links = SND_PCM_HW_PARBIT_CHANNELS | + SND_PCM_HW_PARBIT_RATE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_BUFFER_SIZE | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME; + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); if (err < 0) return err; 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_param_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, 0), SND_PCM_FORMAT_S16); adpcm->func = adpcm_encode; } else { adpcm->getput_idx = put_index(SND_PCM_FORMAT_S16, adpcm->sformat); @@ -423,7 +438,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_param_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, 0)); adpcm->func = adpcm_decode; } else { adpcm->getput_idx = get_index(adpcm->sformat, SND_PCM_FORMAT_S16); @@ -432,7 +447,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_param_value(params, SND_PCM_HW_PARAM_CHANNELS) * sizeof(*adpcm->states)); + adpcm->states = malloc(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS, 0) * sizeof(*adpcm->states)); return 0; } @@ -447,21 +462,21 @@ static int snd_pcm_adpcm_init(snd_pcm_t *pcm) return 0; } -static ssize_t snd_pcm_adpcm_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_adpcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_adpcm_t *adpcm = pcm->private; snd_pcm_t *slave = adpcm->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); adpcm->func(areas, offset, snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), pcm->channels, frames, @@ -469,7 +484,7 @@ static ssize_t snd_pcm_adpcm_write_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); @@ -482,21 +497,21 @@ static ssize_t snd_pcm_adpcm_write_areas(snd_pcm_t *pcm, return err; } -static ssize_t snd_pcm_adpcm_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_adpcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_adpcm_t *adpcm = pcm->private; snd_pcm_t *slave = adpcm->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); adpcm->func(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), areas, offset, pcm->channels, frames, @@ -504,7 +519,7 @@ static ssize_t snd_pcm_adpcm_read_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); diff --git a/src/pcm/pcm_alaw.c b/src/pcm/pcm_alaw.c index feb60008..1be95dbf 100644 --- a/src/pcm/pcm_alaw.c +++ b/src/pcm/pcm_alaw.c @@ -24,10 +24,10 @@ #include "pcm_plugin.h" typedef void (*alaw_f)(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int getputidx); + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int getputidx); typedef struct { /* This field need to be the first */ @@ -121,21 +121,21 @@ static int alaw_to_s16(unsigned char a_val) } static void alaw_decode(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int putidx) + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int putidx) { #define PUT16_LABELS #include "plugin_ops.h" #undef PUT16_LABELS void *put = put16_labels[putidx]; - size_t channel; + unsigned int channel; for (channel = 0; channel < channels; ++channel) { char *src; char *dst; int src_step, dst_step; - size_t frames1; + snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; #if 0 @@ -166,22 +166,22 @@ static void alaw_decode(const snd_pcm_channel_area_t *src_areas, } static void alaw_encode(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int getidx) + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int getidx) { #define GET16_LABELS #include "plugin_ops.h" #undef GET16_LABELS void *get = get16_labels[getidx]; - size_t channel; + unsigned int channel; int16_t sample = 0; for (channel = 0; channel < channels; ++channel) { char *src; char *dst; int src_step, dst_step; - size_t frames1; + snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; #if 0 @@ -216,51 +216,58 @@ static int snd_pcm_alaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_alaw_t *alaw = pcm->private; snd_pcm_t *slave = alaw->plug.slave; int err; + unsigned int cmask, lcmask; snd_pcm_hw_params_t sparams; mask_t *access_mask = alloca(mask_sizeof()); 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_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_mask(params, 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_param_mask(params, 1, + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; } else { - err = _snd_pcm_hw_param_set(params, 1, + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT, - SND_PCM_FORMAT_A_LAW); + SND_PCM_FORMAT_A_LAW, 0); if (err < 0) return err; } - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); if (err < 0) return err; + lcmask = params->cmask; + params->cmask |= cmask; _snd_pcm_hw_params_any(&sparams); - _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, - alaw->sformat); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, + saccess_mask); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + alaw->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave, + snd_pcm_generic_hw_link, slave, SND_PCM_HW_PARBIT_CHANNELS | SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); + params->cmask |= lcmask; if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); @@ -273,31 +280,39 @@ static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) snd_pcm_t *slave = alaw->plug.slave; int err; snd_pcm_hw_params_t sparams; + unsigned int links; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _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, - alaw->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 | - SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, + saccess_mask); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + alaw->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); + links = SND_PCM_HW_PARBIT_CHANNELS | + SND_PCM_HW_PARBIT_RATE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_BUFFER_SIZE | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME; + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); if (err < 0) return err; 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_param_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, 0), SND_PCM_FORMAT_S16); alaw->func = alaw_encode; } else { alaw->getput_idx = put_index(SND_PCM_FORMAT_S16, alaw->sformat); @@ -305,7 +320,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_param_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, 0)); alaw->func = alaw_decode; } else { alaw->getput_idx = get_index(alaw->sformat, SND_PCM_FORMAT_S16); @@ -315,21 +330,21 @@ static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) return 0; } -static ssize_t snd_pcm_alaw_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_alaw_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_alaw_t *alaw = pcm->private; snd_pcm_t *slave = alaw->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); alaw->func(areas, offset, snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), pcm->channels, frames, @@ -337,7 +352,7 @@ static ssize_t snd_pcm_alaw_write_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); @@ -350,21 +365,21 @@ static ssize_t snd_pcm_alaw_write_areas(snd_pcm_t *pcm, return err; } -static ssize_t snd_pcm_alaw_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_alaw_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_alaw_t *alaw = pcm->private; snd_pcm_t *slave = alaw->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); alaw->func(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), areas, offset, pcm->channels, frames, @@ -372,7 +387,7 @@ static ssize_t snd_pcm_alaw_read_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); diff --git a/src/pcm/pcm_copy.c b/src/pcm/pcm_copy.c index cdba7cce..e2bb724e 100644 --- a/src/pcm/pcm_copy.c +++ b/src/pcm/pcm_copy.c @@ -33,21 +33,27 @@ static int snd_pcm_copy_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_copy_t *copy = pcm->private; snd_pcm_t *slave = copy->plug.slave; int err; + unsigned int cmask, lcmask; snd_pcm_hw_params_t sparams; mask_t *access_mask = alloca(mask_sizeof()); 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_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, - access_mask); + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS, + access_mask); if (err < 0) return err; + lcmask = params->cmask; + params->cmask |= cmask; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave, + snd_pcm_generic_hw_link, slave, ~SND_PCM_HW_PARBIT_ACCESS); + params->cmask |= lcmask; if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); @@ -59,37 +65,44 @@ static int snd_pcm_copy_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_copy_t *copy = pcm->private; snd_pcm_t *slave = copy->plug.slave; int err; + unsigned int links; snd_pcm_hw_params_t sparams; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - err = snd_pcm_hw_params2(params, &sparams, - snd_pcm_hw_params, slave, - ~SND_PCM_HW_PARBIT_ACCESS); + links = ~SND_PCM_HW_PARBIT_ACCESS; + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); return err; } -static ssize_t snd_pcm_copy_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_copy_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_copy_t *copy = pcm->private; snd_pcm_t *slave = copy->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); snd_pcm_areas_copy(areas, offset, snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), @@ -97,7 +110,7 @@ static ssize_t snd_pcm_copy_write_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); @@ -110,28 +123,28 @@ static ssize_t snd_pcm_copy_write_areas(snd_pcm_t *pcm, return err; } -static ssize_t snd_pcm_copy_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_copy_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_copy_t *copy = pcm->private; snd_pcm_t *slave = copy->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); snd_pcm_areas_copy(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), areas, offset, pcm->channels, frames, pcm->format); err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index 2f573d25..ca2f8c80 100644 --- a/src/pcm/pcm_file.c +++ b/src/pcm/pcm_file.c @@ -33,9 +33,9 @@ typedef struct { char *fname; int fd; int format; - size_t appl_ptr; - size_t file_ptr_bytes; - size_t wbuf_size; + snd_pcm_uframes_t appl_ptr; + snd_pcm_uframes_t file_ptr_bytes; + snd_pcm_uframes_t wbuf_size; size_t wbuf_size_bytes; size_t wbuf_used_bytes; char *wbuf; @@ -48,7 +48,7 @@ static void snd_pcm_file_write_bytes(snd_pcm_t *pcm, size_t bytes) snd_pcm_file_t *file = pcm->private; assert(bytes <= file->wbuf_used_bytes); while (bytes > 0) { - ssize_t err; + snd_pcm_sframes_t err; size_t n = bytes; size_t cont = file->wbuf_size_bytes - file->file_ptr_bytes; if (n > cont) @@ -63,20 +63,20 @@ static void snd_pcm_file_write_bytes(snd_pcm_t *pcm, size_t bytes) file->file_ptr_bytes += err; if (file->file_ptr_bytes == file->wbuf_size_bytes) file->file_ptr_bytes = 0; - if ((size_t)err != n) + if ((snd_pcm_uframes_t)err != n) break; } } static void snd_pcm_file_add_frames(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, size_t frames) + snd_pcm_uframes_t offset, snd_pcm_uframes_t frames) { snd_pcm_file_t *file = pcm->private; while (frames > 0) { - size_t n = frames; - size_t cont = file->wbuf_size - file->appl_ptr; - size_t avail = file->wbuf_size - snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes); + snd_pcm_uframes_t n = frames; + snd_pcm_uframes_t cont = file->wbuf_size - file->appl_ptr; + snd_pcm_uframes_t avail = file->wbuf_size - snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes); if (n > cont) n = cont; if (n > avail) @@ -157,7 +157,7 @@ static int snd_pcm_file_state(snd_pcm_t *pcm) return snd_pcm_state(file->slave); } -static int snd_pcm_file_delay(snd_pcm_t *pcm, ssize_t *delayp) +static int snd_pcm_file_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { snd_pcm_file_t *file = pcm->private; return snd_pcm_delay(file->slave, delayp); @@ -216,13 +216,13 @@ static int snd_pcm_file_pause(snd_pcm_t *pcm, int enable) return snd_pcm_pause(file->slave, enable); } -static ssize_t snd_pcm_file_rewind(snd_pcm_t *pcm, size_t frames) +static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_file_t *file = pcm->private; - ssize_t err = snd_pcm_rewind(file->slave, frames); + snd_pcm_sframes_t err = snd_pcm_rewind(file->slave, frames); if (err > 0) { - size_t n = snd_pcm_frames_to_bytes(pcm, frames); - ssize_t ptr; + snd_pcm_uframes_t n = snd_pcm_frames_to_bytes(pcm, frames); + snd_pcm_sframes_t ptr; assert(n >= file->wbuf_used_bytes); ptr = file->appl_ptr - err; if (ptr < 0) @@ -232,11 +232,11 @@ static ssize_t snd_pcm_file_rewind(snd_pcm_t *pcm, size_t frames) return err; } -static ssize_t snd_pcm_file_writei(snd_pcm_t *pcm, const void *buffer, size_t size) +static snd_pcm_sframes_t snd_pcm_file_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { snd_pcm_file_t *file = pcm->private; snd_pcm_channel_area_t areas[pcm->channels]; - ssize_t n = snd_pcm_writei(file->slave, buffer, size); + snd_pcm_sframes_t n = snd_pcm_writei(file->slave, buffer, size); if (n > 0) { snd_pcm_areas_from_buf(pcm, areas, (void*) buffer); snd_pcm_file_add_frames(pcm, areas, 0, n); @@ -244,11 +244,11 @@ static ssize_t snd_pcm_file_writei(snd_pcm_t *pcm, const void *buffer, size_t si return n; } -static ssize_t snd_pcm_file_writen(snd_pcm_t *pcm, void **bufs, size_t size) +static snd_pcm_sframes_t snd_pcm_file_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { snd_pcm_file_t *file = pcm->private; snd_pcm_channel_area_t areas[pcm->channels]; - ssize_t n = snd_pcm_writen(file->slave, bufs, size); + snd_pcm_sframes_t n = snd_pcm_writen(file->slave, bufs, size); if (n > 0) { snd_pcm_areas_from_bufs(pcm, areas, bufs); snd_pcm_file_add_frames(pcm, areas, 0, n); @@ -256,11 +256,11 @@ static ssize_t snd_pcm_file_writen(snd_pcm_t *pcm, void **bufs, size_t size) return n; } -static ssize_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, size_t size) +static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) { snd_pcm_file_t *file = pcm->private; snd_pcm_channel_area_t areas[pcm->channels]; - ssize_t n = snd_pcm_readi(file->slave, buffer, size); + snd_pcm_sframes_t n = snd_pcm_readi(file->slave, buffer, size); if (n > 0) { snd_pcm_areas_from_buf(pcm, areas, buffer); snd_pcm_file_add_frames(pcm, areas, 0, n); @@ -268,11 +268,11 @@ static ssize_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, size_t size) return n; } -static ssize_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, size_t size) +static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { snd_pcm_file_t *file = pcm->private; snd_pcm_channel_area_t areas[pcm->channels]; - ssize_t n = snd_pcm_writen(file->slave, bufs, size); + snd_pcm_sframes_t n = snd_pcm_writen(file->slave, bufs, size); if (n > 0) { snd_pcm_areas_from_bufs(pcm, areas, bufs); snd_pcm_file_add_frames(pcm, areas, 0, n); @@ -280,17 +280,17 @@ static ssize_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, size_t size) return n; } -static ssize_t snd_pcm_file_mmap_forward(snd_pcm_t *pcm, size_t size) +static snd_pcm_sframes_t snd_pcm_file_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size) { snd_pcm_file_t *file = pcm->private; - size_t ofs = snd_pcm_mmap_offset(pcm); - ssize_t n = snd_pcm_mmap_forward(file->slave, size); - size_t xfer = 0; + snd_pcm_uframes_t ofs = snd_pcm_mmap_offset(pcm); + snd_pcm_sframes_t n = snd_pcm_mmap_forward(file->slave, size); + snd_pcm_uframes_t xfer = 0; if (n <= 0) return n; - while (xfer < (size_t)n) { - size_t frames = size - xfer; - size_t cont = pcm->buffer_size - ofs; + while (xfer < (snd_pcm_uframes_t)n) { + snd_pcm_uframes_t frames = size - xfer; + snd_pcm_uframes_t cont = pcm->buffer_size - ofs; if (frames > cont) frames = cont; snd_pcm_file_add_frames(pcm, snd_pcm_mmap_areas(file->slave), ofs, frames); @@ -302,7 +302,7 @@ static ssize_t snd_pcm_file_mmap_forward(snd_pcm_t *pcm, size_t size) return n; } -static ssize_t snd_pcm_file_avail_update(snd_pcm_t *pcm) +static snd_pcm_sframes_t snd_pcm_file_avail_update(snd_pcm_t *pcm) { snd_pcm_file_t *file = pcm->private; return snd_pcm_avail_update(file->slave); diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index ebe34b5e..f64e037f 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -153,10 +153,10 @@ 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->period_step == pcm->period_step && + params->sleep_min == pcm->sleep_min && params->xfer_align == pcm->xfer_align && params->silence_threshold == pcm->silence_threshold && params->silence_size == pcm->silence_size) { @@ -210,7 +210,7 @@ static int snd_pcm_hw_state(snd_pcm_t *pcm) return hw->mmap_status->state; } -static int snd_pcm_hw_delay(snd_pcm_t *pcm, ssize_t *delayp) +static int snd_pcm_hw_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { snd_pcm_hw_t *hw = pcm->private; int fd = hw->fd; @@ -291,27 +291,20 @@ static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable) return 0; } -static ssize_t snd_pcm_hw_rewind(snd_pcm_t *pcm, size_t frames) +static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { - ssize_t hw_avail; - if (pcm->xrun_mode == SND_PCM_XRUN_ASAP) { - ssize_t d; - int err = snd_pcm_hw_delay(pcm, &d); - if (err < 0) - return 0; + snd_pcm_hw_t *hw = pcm->private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_REWIND, &frames) < 0) { + SYSERR("SND_PCM_IOCTL_REWIND failed"); + return -errno; } - hw_avail = snd_pcm_mmap_hw_avail(pcm); - if (hw_avail <= 0) - return 0; - if (frames > (size_t)hw_avail) - frames = hw_avail; - snd_pcm_mmap_appl_backward(pcm, frames); - return frames; + return 0; } -static ssize_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, size_t size) +static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { - ssize_t result; + snd_pcm_sframes_t result; snd_pcm_hw_t *hw = pcm->private; int fd = hw->fd; snd_xferi_t xferi; @@ -323,9 +316,9 @@ static ssize_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, size_t size return xferi.result; } -static ssize_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, size_t size) +static snd_pcm_sframes_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { - ssize_t result; + snd_pcm_sframes_t result; snd_pcm_hw_t *hw = pcm->private; int fd = hw->fd; snd_xfern_t xfern; @@ -337,9 +330,9 @@ static ssize_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, size_t size) return xfern.result; } -static ssize_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, size_t size) +static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) { - ssize_t result; + snd_pcm_sframes_t result; snd_pcm_hw_t *hw = pcm->private; int fd = hw->fd; snd_xferi_t xferi; @@ -351,9 +344,9 @@ static ssize_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, size_t size) return xferi.result; } -ssize_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, size_t size) +snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { - ssize_t result; + snd_pcm_sframes_t result; snd_pcm_hw_t *hw = pcm->private; int fd = hw->fd; snd_xfern_t xfern; @@ -419,7 +412,7 @@ static int snd_pcm_hw_mmap(snd_pcm_t *pcm) { snd_pcm_hw_t *hw = pcm->private; if (!(pcm->info & SND_PCM_INFO_MMAP)) { - size_t size = snd_pcm_frames_to_bytes(pcm, pcm->buffer_size); + snd_pcm_uframes_t size = snd_pcm_frames_to_bytes(pcm, pcm->buffer_size); int id = shmget(IPC_PRIVATE, size, 0666); if (id < 0) { SYSERR("shmget failed"); @@ -455,7 +448,7 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm) return 0; } -static ssize_t snd_pcm_hw_mmap_forward(snd_pcm_t *pcm, size_t size) +static snd_pcm_sframes_t snd_pcm_hw_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size) { if (!(pcm->info & SND_PCM_INFO_MMAP) && pcm->stream == SND_PCM_STREAM_PLAYBACK) @@ -464,17 +457,19 @@ static ssize_t snd_pcm_hw_mmap_forward(snd_pcm_t *pcm, size_t size) return size; } -static ssize_t snd_pcm_hw_avail_update(snd_pcm_t *pcm) +static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm) { - size_t avail; - ssize_t err; + snd_pcm_uframes_t avail; + snd_pcm_sframes_t err; +#if 0 if (pcm->ready_mode == SND_PCM_READY_ASAP || pcm->xrun_mode == SND_PCM_XRUN_ASAP) { - ssize_t d; + snd_pcm_sframes_t d; int err = snd_pcm_hw_delay(pcm, &d); if (err < 0) return err; } +#endif if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { avail = snd_pcm_mmap_playback_avail(pcm); } else { @@ -484,7 +479,7 @@ static ssize_t snd_pcm_hw_avail_update(snd_pcm_t *pcm) err = snd_pcm_read_mmap(pcm, avail); if (err < 0) return err; - assert((size_t)err == avail); + assert((snd_pcm_uframes_t)err == avail); return err; } } @@ -605,7 +600,7 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdev ret = -errno; goto _err; } - if (info.subdevice != subdevice) { + if (info.subdevice != (unsigned int) subdevice) { close(fd); goto __again; } diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c index 560c24ed..4c30e9e9 100644 --- a/src/pcm/pcm_linear.c +++ b/src/pcm/pcm_linear.c @@ -30,9 +30,9 @@ typedef struct { int sformat; } snd_pcm_linear_t; -static void linear_transfer(const snd_pcm_channel_area_t *src_areas, size_t src_offset, - const snd_pcm_channel_area_t *dst_areas, size_t dst_offset, - size_t channels, size_t frames, int convidx) +static void linear_transfer(const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset, + const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int convidx) { #define CONV_LABELS #include "plugin_ops.h" @@ -43,7 +43,7 @@ static void linear_transfer(const snd_pcm_channel_area_t *src_areas, size_t src_ char *src; char *dst; int src_step, dst_step; - size_t frames1; + snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; #if 0 @@ -77,6 +77,7 @@ static int snd_pcm_linear_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_linear_t *linear = pcm->private; snd_pcm_t *slave = linear->plug.slave; int err; + unsigned int cmask, lcmask; snd_pcm_hw_params_t sparams; mask_t *access_mask = alloca(mask_sizeof()); mask_t *format_mask = alloca(mask_sizeof()); @@ -84,35 +85,41 @@ 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_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; - err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); if (err < 0) return err; + lcmask = params->cmask; + params->cmask |= cmask; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - linear->sformat); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + linear->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave, + snd_pcm_generic_hw_link, slave, SND_PCM_HW_PARBIT_CHANNELS | SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); + params->cmask |= lcmask; if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); @@ -124,60 +131,68 @@ static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_linear_t *linear = pcm->private; snd_pcm_t *slave = linear->plug.slave; int err; + unsigned int links; snd_pcm_hw_params_t sparams; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - linear->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 | - SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + linear->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); + links = SND_PCM_HW_PARBIT_CHANNELS | + SND_PCM_HW_PARBIT_RATE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_BUFFER_SIZE | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME; + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); if (err < 0) 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_param_value(params, SND_PCM_HW_PARAM_FORMAT), + linear->conv_idx = conv_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0), linear->sformat); else linear->conv_idx = conv_index(linear->sformat, - snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT)); + snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0)); return 0; } -static ssize_t snd_pcm_linear_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_linear_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_linear_t *linear = pcm->private; snd_pcm_t *slave = linear->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); linear_transfer(areas, offset, snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), pcm->channels, frames, linear->conv_idx); err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); @@ -190,28 +205,28 @@ static ssize_t snd_pcm_linear_write_areas(snd_pcm_t *pcm, return err; } -static ssize_t snd_pcm_linear_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_linear_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_linear_t *linear = pcm->private; snd_pcm_t *slave = linear->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); linear_transfer(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), areas, offset, pcm->channels, frames, linear->conv_idx); err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 7fba5fd3..c465d96c 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -71,14 +71,14 @@ typedef struct { int (*drain)(snd_pcm_t *pcm); int (*pause)(snd_pcm_t *pcm, int enable); int (*state)(snd_pcm_t *pcm); - int (*delay)(snd_pcm_t *pcm, ssize_t *delayp); - ssize_t (*rewind)(snd_pcm_t *pcm, size_t frames); - ssize_t (*writei)(snd_pcm_t *pcm, const void *buffer, size_t size); - ssize_t (*writen)(snd_pcm_t *pcm, void **bufs, size_t size); - ssize_t (*readi)(snd_pcm_t *pcm, void *buffer, size_t size); - 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 (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); + snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames); + snd_pcm_sframes_t (*writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); + snd_pcm_sframes_t (*writen)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); + snd_pcm_sframes_t (*readi)(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size); + snd_pcm_sframes_t (*readn)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); + snd_pcm_sframes_t (*avail_update)(snd_pcm_t *pcm); + snd_pcm_sframes_t (*mmap_forward)(snd_pcm_t *pcm, snd_pcm_uframes_t size); } snd_pcm_fast_ops_t; struct _snd_pcm { @@ -93,30 +93,31 @@ struct _snd_pcm { unsigned int subformat; /* subformat */ unsigned int channels; /* channels */ unsigned int rate; /* rate in Hz */ - size_t fragment_size; /* fragment size */ - unsigned int fragments; /* fragments */ - unsigned int start_mode; /* start 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 */ - unsigned int silence_mode; /* Silence filling mode */ - size_t silence_threshold; /* Silence filling happens when + snd_pcm_uframes_t period_size; + unsigned int period_time; /* period duration */ + unsigned int tick_time; + snd_pcm_start_t start_mode; /* start mode */ + snd_pcm_xrun_t xrun_mode; /* xrun detection mode */ + snd_pcm_tstamp_t tstamp_mode; /* timestamp mode */ + unsigned int period_step; + unsigned int sleep_min; + snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */ + snd_pcm_uframes_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 */ - size_t boundary; /* pointers wrap point */ + snd_pcm_uframes_t silence_size; /* Silence filling size */ + snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ + snd_pcm_uframes_t boundary; /* pointers wrap point */ unsigned int info; /* Info for returned setup */ unsigned int msbits; /* used most significant bits */ unsigned int rate_num; /* rate numerator */ unsigned int rate_den; /* rate denominator */ - size_t fifo_size; /* chip FIFO size in frames */ - size_t buffer_size; - size_t bits_per_sample; - size_t bits_per_frame; - size_t *appl_ptr; - size_t min_align; - volatile size_t *hw_ptr; + snd_pcm_uframes_t fifo_size; /* chip FIFO size in frames */ + snd_pcm_uframes_t buffer_size; + unsigned int bits_per_sample; + unsigned int bits_per_frame; + snd_pcm_uframes_t *appl_ptr; + snd_pcm_uframes_t min_align; + volatile snd_pcm_uframes_t *hw_ptr; int mmap_rw; snd_pcm_channel_info_t *mmap_channels; snd_pcm_channel_area_t *running_areas; @@ -142,52 +143,52 @@ void snd_pcm_areas_from_bufs(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas, void int snd_pcm_mmap(snd_pcm_t *pcm); int snd_pcm_munmap(snd_pcm_t *pcm); int snd_pcm_mmap_ready(snd_pcm_t *pcm); -ssize_t snd_pcm_mmap_appl_ptr(snd_pcm_t *pcm, off_t offset); -void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, size_t frames); -void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, size_t frames); -void snd_pcm_mmap_hw_backward(snd_pcm_t *pcm, size_t frames); -void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, size_t frames); -size_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm); -size_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, size_t frames); -size_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, size_t frames); - -typedef ssize_t (*snd_pcm_xfer_areas_func_t)(snd_pcm_t *pcm, +snd_pcm_sframes_t snd_pcm_mmap_appl_ptr(snd_pcm_t *pcm, off_t offset); +void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, snd_pcm_uframes_t frames); +void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames); +void snd_pcm_mmap_hw_backward(snd_pcm_t *pcm, snd_pcm_uframes_t frames); +void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames); +snd_pcm_uframes_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm); +snd_pcm_uframes_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames); +snd_pcm_uframes_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames); + +typedef snd_pcm_sframes_t (*snd_pcm_xfer_areas_func_t)(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, size_t size, - size_t *slave_sizep); + snd_pcm_uframes_t offset, snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep); -ssize_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, size_t size, +snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, + snd_pcm_uframes_t offset, snd_pcm_uframes_t size, snd_pcm_xfer_areas_func_t func); -ssize_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, size_t size, +snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, + snd_pcm_uframes_t offset, snd_pcm_uframes_t size, 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); +snd_pcm_sframes_t snd_pcm_read_mmap(snd_pcm_t *pcm, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_write_mmap(snd_pcm_t *pcm, snd_pcm_uframes_t size); 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); -static inline size_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm) +static inline snd_pcm_uframes_t snd_pcm_mmap_playback_avail(snd_pcm_t *pcm) { - ssize_t avail; + snd_pcm_sframes_t avail; avail = *pcm->hw_ptr + pcm->buffer_size - *pcm->appl_ptr; if (avail < 0) avail += pcm->boundary; return avail; } -static inline size_t snd_pcm_mmap_capture_avail(snd_pcm_t *pcm) +static inline snd_pcm_uframes_t snd_pcm_mmap_capture_avail(snd_pcm_t *pcm) { - ssize_t avail; + snd_pcm_sframes_t avail; avail = *pcm->hw_ptr - *pcm->appl_ptr; if (avail < 0) avail += pcm->boundary; return avail; } -static inline size_t snd_pcm_mmap_avail(snd_pcm_t *pcm) +static inline snd_pcm_uframes_t snd_pcm_mmap_avail(snd_pcm_t *pcm) { - ssize_t avail; + snd_pcm_sframes_t avail; avail = *pcm->hw_ptr - *pcm->appl_ptr; if (pcm->stream == SND_PCM_STREAM_PLAYBACK) avail += pcm->buffer_size; @@ -196,27 +197,19 @@ static inline size_t snd_pcm_mmap_avail(snd_pcm_t *pcm) return avail; } -static inline ssize_t snd_pcm_mmap_playback_hw_avail(snd_pcm_t *pcm) +static inline snd_pcm_sframes_t snd_pcm_mmap_playback_hw_avail(snd_pcm_t *pcm) { - ssize_t avail; - avail = *pcm->hw_ptr + pcm->buffer_size - *pcm->appl_ptr; - if (avail < 0) - avail += pcm->boundary; - return pcm->buffer_size - avail; + return pcm->buffer_size - snd_pcm_mmap_playback_avail(pcm); } -static inline ssize_t snd_pcm_mmap_capture_hw_avail(snd_pcm_t *pcm) +static inline snd_pcm_sframes_t snd_pcm_mmap_capture_hw_avail(snd_pcm_t *pcm) { - ssize_t avail; - avail = *pcm->hw_ptr - *pcm->appl_ptr; - if (avail < 0) - avail += pcm->boundary; - return pcm->buffer_size - avail; + return pcm->buffer_size - snd_pcm_mmap_capture_avail(pcm); } -static inline ssize_t snd_pcm_mmap_hw_avail(snd_pcm_t *pcm) +static inline snd_pcm_sframes_t snd_pcm_mmap_hw_avail(snd_pcm_t *pcm) { - ssize_t avail; + snd_pcm_sframes_t avail; avail = *pcm->hw_ptr - *pcm->appl_ptr; if (pcm->stream == SND_PCM_STREAM_PLAYBACK) avail += pcm->buffer_size; @@ -228,7 +221,7 @@ static inline ssize_t snd_pcm_mmap_hw_avail(snd_pcm_t *pcm) #define snd_pcm_mmap_playback_delay snd_pcm_mmap_playback_hw_avail #define snd_pcm_mmap_capture_delay snd_pcm_mmap_capture_avail -static inline ssize_t snd_pcm_mmap_delay(snd_pcm_t *pcm) +static inline snd_pcm_sframes_t snd_pcm_mmap_delay(snd_pcm_t *pcm) { if (pcm->stream == SND_PCM_STREAM_PLAYBACK) return snd_pcm_mmap_playback_delay(pcm); @@ -236,35 +229,35 @@ static inline ssize_t snd_pcm_mmap_delay(snd_pcm_t *pcm) return snd_pcm_mmap_capture_delay(pcm); } -static inline void *snd_pcm_channel_area_addr(const snd_pcm_channel_area_t *area, size_t offset) +static inline void *snd_pcm_channel_area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset) { - size_t bitofs = area->first + area->step * offset; + unsigned int bitofs = area->first + area->step * offset; assert(bitofs % 8 == 0); return area->addr + bitofs / 8; } -static inline size_t snd_pcm_channel_area_step(const snd_pcm_channel_area_t *area) +static inline unsigned int snd_pcm_channel_area_step(const snd_pcm_channel_area_t *area) { assert(area->step % 8 == 0); return area->step / 8; } -static inline ssize_t _snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, size_t size) +static inline snd_pcm_sframes_t _snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { return pcm->fast_ops->writei(pcm->fast_op_arg, buffer, size); } -static inline ssize_t _snd_pcm_writen(snd_pcm_t *pcm, void **bufs, size_t size) +static inline snd_pcm_sframes_t _snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { return pcm->fast_ops->writen(pcm->fast_op_arg, bufs, size); } -static inline ssize_t _snd_pcm_readi(snd_pcm_t *pcm, void *buffer, size_t size) +static inline snd_pcm_sframes_t _snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) { return pcm->fast_ops->readi(pcm->fast_op_arg, buffer, size); } -static inline ssize_t _snd_pcm_readn(snd_pcm_t *pcm, void **bufs, size_t size) +static inline snd_pcm_sframes_t _snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { return pcm->fast_ops->readn(pcm->fast_op_arg, bufs, size); } @@ -308,45 +301,71 @@ 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_param_mask(snd_pcm_hw_params_t *params, int hw, +int _snd_pcm_hw_param_refine_interval(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const interval_t *val); +int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params, unsigned int var, const mask_t *mask); -int _snd_pcm_hw_param_first(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, +int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, unsigned int var); -int _snd_pcm_hw_param_set(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 _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, int hw, - unsigned int var, unsigned int val); +int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, + unsigned int var); +int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params, + unsigned int var, unsigned int val, int dir); +int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params, + unsigned int var, unsigned int val, int dir); +int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, + unsigned int var, unsigned int val, int dir); +int snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const snd_pcm_hw_params_t *src); +int snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params, + unsigned int vars, + const snd_pcm_hw_params_t *src); +int snd_pcm_generic_hw_link(snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *sparams, + snd_pcm_t *slave, + unsigned long links); int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params, snd_pcm_hw_params_t *sparams, - int (*func)(snd_pcm_t *slave, - snd_pcm_hw_params_t *params), + int (*func)(snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *sparams, + snd_pcm_t *slave, + unsigned long private), snd_pcm_t *slave, - unsigned int links); + unsigned long private); int snd_pcm_hw_params2(snd_pcm_hw_params_t *params, snd_pcm_hw_params_t *sparams, int (*func)(snd_pcm_t *slave, snd_pcm_hw_params_t *sparams), snd_pcm_t *slave, unsigned int links); +void snd_pcm_hw_param_near_copy(snd_pcm_t *pcm, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const snd_pcm_hw_params_t *src); +int snd_pcm_hw_param_always_eq(const snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const snd_pcm_hw_params_t *params1); +int snd_pcm_hw_param_never_eq(const snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const snd_pcm_hw_params_t *params1); #define SND_PCM_HW_PARBIT_ACCESS (1 << SND_PCM_HW_PARAM_ACCESS) #define SND_PCM_HW_PARBIT_FORMAT (1 << SND_PCM_HW_PARAM_FORMAT) #define SND_PCM_HW_PARBIT_SUBFORMAT (1 << SND_PCM_HW_PARAM_SUBFORMAT) #define SND_PCM_HW_PARBIT_CHANNELS (1 << SND_PCM_HW_PARAM_CHANNELS) #define SND_PCM_HW_PARBIT_RATE (1 << SND_PCM_HW_PARAM_RATE) -#define SND_PCM_HW_PARBIT_FRAGMENT_LENGTH (1 << SND_PCM_HW_PARAM_FRAGMENT_LENGTH) -#define SND_PCM_HW_PARBIT_FRAGMENT_SIZE (1 << SND_PCM_HW_PARAM_FRAGMENT_SIZE) -#define SND_PCM_HW_PARBIT_FRAGMENTS (1 << SND_PCM_HW_PARAM_FRAGMENTS) -#define SND_PCM_HW_PARBIT_BUFFER_LENGTH (1 << SND_PCM_HW_PARAM_BUFFER_LENGTH) +#define SND_PCM_HW_PARBIT_PERIOD_TIME (1 << SND_PCM_HW_PARAM_PERIOD_TIME) +#define SND_PCM_HW_PARBIT_PERIOD_SIZE (1 << SND_PCM_HW_PARAM_PERIOD_SIZE) +#define SND_PCM_HW_PARBIT_PERIODS (1 << SND_PCM_HW_PARAM_PERIODS) +#define SND_PCM_HW_PARBIT_BUFFER_TIME (1 << SND_PCM_HW_PARAM_BUFFER_TIME) #define SND_PCM_HW_PARBIT_BUFFER_SIZE (1 << SND_PCM_HW_PARAM_BUFFER_SIZE) #define SND_PCM_HW_PARBIT_SAMPLE_BITS (1 << SND_PCM_HW_PARAM_SAMPLE_BITS) #define SND_PCM_HW_PARBIT_FRAME_BITS (1 << SND_PCM_HW_PARAM_FRAME_BITS) -#define SND_PCM_HW_PARBIT_FRAGMENT_BYTES (1 << SND_PCM_HW_PARAM_FRAGMENT_BYTES) +#define SND_PCM_HW_PARBIT_PERIOD_BYTES (1 << SND_PCM_HW_PARAM_PERIOD_BYTES) #define SND_PCM_HW_PARBIT_BUFFER_BYTES (1 << SND_PCM_HW_PARAM_BUFFER_BYTES) +#define SND_PCM_HW_PARBIT_TICK_TIME (1 << SND_PCM_HW_PARAM_TICK_TIME) #define SND_PCM_ACCBIT_MMAP ((1 << SND_PCM_ACCESS_MMAP_INTERLEAVED) | \ diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c index 5d0f0c20..fa7b7e7b 100644 --- a/src/pcm/pcm_misc.c +++ b/src/pcm/pcm_misc.c @@ -360,14 +360,14 @@ u_int8_t snd_pcm_format_silence(int format) return (u_int8_t)snd_pcm_format_silence_64(format); } -ssize_t snd_pcm_format_set_silence(int format, void *data, size_t samples) +int snd_pcm_format_set_silence(int format, void *data, unsigned int samples) { if (samples == 0) return 0; switch (snd_pcm_format_width(format)) { case 4: { u_int8_t silence = snd_pcm_format_silence_64(format); - size_t samples1; + unsigned int samples1; if (samples % 2 != 0) return -EINVAL; samples1 = samples / 2; @@ -405,9 +405,9 @@ ssize_t snd_pcm_format_set_silence(int format, void *data, size_t samples) static int linear_formats[4*2*2] = { SND_PCM_FORMAT_S8, - SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U8, + SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE, SND_PCM_FORMAT_U16_LE, diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c index 0ade84ab..d362aae6 100644 --- a/src/pcm/pcm_mmap.c +++ b/src/pcm/pcm_mmap.c @@ -52,10 +52,10 @@ const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm) return pcm->running_areas; } -size_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, size_t frames) +snd_pcm_uframes_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { - size_t cont; - size_t avail = snd_pcm_mmap_playback_avail(pcm); + snd_pcm_uframes_t cont; + snd_pcm_uframes_t avail = snd_pcm_mmap_playback_avail(pcm); if (avail < frames) frames = avail; cont = pcm->buffer_size - *pcm->appl_ptr % pcm->buffer_size; @@ -64,10 +64,10 @@ size_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, size_t frames) return frames; } -size_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, size_t frames) +snd_pcm_uframes_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { - size_t cont; - size_t avail = snd_pcm_mmap_capture_avail(pcm); + snd_pcm_uframes_t cont; + snd_pcm_uframes_t avail = snd_pcm_mmap_capture_avail(pcm); if (avail < frames) frames = avail; cont = pcm->buffer_size - *pcm->appl_ptr % pcm->buffer_size; @@ -76,7 +76,7 @@ size_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, size_t frames) return frames; } -size_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, size_t frames) +snd_pcm_uframes_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { assert(pcm); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) @@ -85,73 +85,73 @@ size_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, size_t frames) return snd_pcm_mmap_capture_xfer(pcm, frames); } -size_t snd_pcm_mmap_offset(snd_pcm_t *pcm) +snd_pcm_uframes_t snd_pcm_mmap_offset(snd_pcm_t *pcm) { assert(pcm); return *pcm->appl_ptr % pcm->buffer_size; } -size_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm) +snd_pcm_uframes_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm) { assert(pcm); return *pcm->hw_ptr % pcm->buffer_size; } -void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, size_t frames) +void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { - ssize_t appl_ptr = *pcm->appl_ptr; + snd_pcm_sframes_t appl_ptr = *pcm->appl_ptr; appl_ptr -= frames; if (appl_ptr < 0) appl_ptr += pcm->boundary; *pcm->appl_ptr = appl_ptr; } -void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, size_t frames) +void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { - size_t appl_ptr = *pcm->appl_ptr; + snd_pcm_uframes_t appl_ptr = *pcm->appl_ptr; appl_ptr += frames; if (appl_ptr >= pcm->boundary) appl_ptr -= pcm->boundary; *pcm->appl_ptr = appl_ptr; } -void snd_pcm_mmap_hw_backward(snd_pcm_t *pcm, size_t frames) +void snd_pcm_mmap_hw_backward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { - ssize_t hw_ptr = *pcm->hw_ptr; + snd_pcm_sframes_t hw_ptr = *pcm->hw_ptr; hw_ptr -= frames; if (hw_ptr < 0) hw_ptr += pcm->boundary; *pcm->hw_ptr = hw_ptr; } -void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, size_t frames) +void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { - size_t hw_ptr = *pcm->hw_ptr; + snd_pcm_uframes_t hw_ptr = *pcm->hw_ptr; hw_ptr += frames; if (hw_ptr >= pcm->boundary) hw_ptr -= pcm->boundary; *pcm->hw_ptr = hw_ptr; } -ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, +snd_pcm_sframes_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { - size_t xfer; + snd_pcm_uframes_t xfer; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; xfer = 0; while (xfer < size) { - size_t frames = snd_pcm_mmap_playback_xfer(pcm, size - xfer); - ssize_t err; + snd_pcm_uframes_t frames = snd_pcm_mmap_playback_xfer(pcm, size - xfer); + snd_pcm_sframes_t err; snd_pcm_areas_copy(areas, offset, snd_pcm_mmap_areas(pcm), snd_pcm_mmap_offset(pcm), pcm->channels, frames, pcm->format); err = snd_pcm_mmap_forward(pcm, frames); - assert(err == (ssize_t)frames); + assert(err == (snd_pcm_sframes_t)frames); offset += frames; xfer += frames; } @@ -160,25 +160,25 @@ ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, return xfer; } -ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, +snd_pcm_sframes_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { - size_t xfer; + snd_pcm_uframes_t xfer; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; xfer = 0; while (xfer < size) { - size_t frames = snd_pcm_mmap_capture_xfer(pcm, size - xfer); - ssize_t err; + snd_pcm_uframes_t frames = snd_pcm_mmap_capture_xfer(pcm, size - xfer); + snd_pcm_sframes_t err; snd_pcm_areas_copy(snd_pcm_mmap_areas(pcm), snd_pcm_mmap_offset(pcm), areas, offset, pcm->channels, frames, pcm->format); err = snd_pcm_mmap_forward(pcm, frames); - assert(err == (ssize_t)frames); + assert(err == (snd_pcm_sframes_t)frames); offset += frames; xfer += frames; } @@ -187,7 +187,7 @@ ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, return xfer; } -ssize_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, size_t size) +snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { snd_pcm_channel_area_t areas[pcm->channels]; snd_pcm_areas_from_buf(pcm, areas, (void*)buffer); @@ -195,7 +195,7 @@ ssize_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, size_t size) snd_pcm_mmap_write_areas); } -ssize_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, size_t size) +snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { snd_pcm_channel_area_t areas[pcm->channels]; snd_pcm_areas_from_bufs(pcm, areas, bufs); @@ -203,7 +203,7 @@ ssize_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, size_t size) snd_pcm_mmap_write_areas); } -ssize_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, size_t size) +snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) { snd_pcm_channel_area_t areas[pcm->channels]; snd_pcm_areas_from_buf(pcm, areas, buffer); @@ -211,7 +211,7 @@ ssize_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, size_t size) snd_pcm_mmap_read_areas); } -ssize_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, size_t size) +snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { snd_pcm_channel_area_t areas[pcm->channels]; snd_pcm_areas_from_bufs(pcm, areas, bufs); @@ -421,15 +421,15 @@ int snd_pcm_munmap(snd_pcm_t *pcm) return 0; } -ssize_t snd_pcm_write_mmap(snd_pcm_t *pcm, size_t size) +snd_pcm_sframes_t snd_pcm_write_mmap(snd_pcm_t *pcm, snd_pcm_uframes_t size) { - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; assert(size > 0); while (xfer < size) { - size_t frames = size - xfer; - size_t offset = snd_pcm_mmap_hw_offset(pcm); - size_t cont = pcm->buffer_size - offset; + snd_pcm_uframes_t frames = size - xfer; + snd_pcm_uframes_t offset = snd_pcm_mmap_hw_offset(pcm); + snd_pcm_uframes_t cont = pcm->buffer_size - offset; if (cont < frames) frames = cont; switch (pcm->access) { @@ -442,7 +442,7 @@ ssize_t snd_pcm_write_mmap(snd_pcm_t *pcm, size_t size) } case SND_PCM_ACCESS_MMAP_NONINTERLEAVED: { - size_t channels = pcm->channels; + unsigned int channels = pcm->channels; unsigned int c; void *bufs[channels]; const snd_pcm_channel_area_t *areas = snd_pcm_mmap_areas(pcm); @@ -467,15 +467,15 @@ ssize_t snd_pcm_write_mmap(snd_pcm_t *pcm, size_t size) return err; } -ssize_t snd_pcm_read_mmap(snd_pcm_t *pcm, size_t size) +snd_pcm_sframes_t snd_pcm_read_mmap(snd_pcm_t *pcm, snd_pcm_uframes_t size) { - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; assert(size > 0); while (xfer < size) { - size_t frames = size - xfer; - size_t offset = snd_pcm_mmap_hw_offset(pcm); - size_t cont = pcm->buffer_size - offset; + snd_pcm_uframes_t frames = size - xfer; + snd_pcm_uframes_t offset = snd_pcm_mmap_hw_offset(pcm); + snd_pcm_uframes_t cont = pcm->buffer_size - offset; if (cont < frames) frames = cont; switch (pcm->access) { @@ -488,7 +488,7 @@ ssize_t snd_pcm_read_mmap(snd_pcm_t *pcm, size_t size) } case SND_PCM_ACCESS_MMAP_NONINTERLEAVED: { - size_t channels = pcm->channels; + snd_pcm_uframes_t channels = pcm->channels; unsigned int c; void *bufs[channels]; const snd_pcm_channel_area_t *areas = snd_pcm_mmap_areas(pcm); diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c index 5f663464..ff67c6d3 100644 --- a/src/pcm/pcm_mulaw.c +++ b/src/pcm/pcm_mulaw.c @@ -24,10 +24,10 @@ #include "pcm_plugin.h" typedef void (*mulaw_f)(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int getputidx); + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int getputidx); typedef struct { /* This field need to be the first */ @@ -138,21 +138,21 @@ static int ulaw_to_s16(unsigned char u_val) } static void mulaw_decode(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int putidx) + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int putidx) { #define PUT16_LABELS #include "plugin_ops.h" #undef PUT16_LABELS void *put = put16_labels[putidx]; - size_t channel; + unsigned int channel; for (channel = 0; channel < channels; ++channel) { char *src; char *dst; int src_step, dst_step; - size_t frames1; + snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; #if 0 @@ -183,22 +183,22 @@ static void mulaw_decode(const snd_pcm_channel_area_t *src_areas, } static void mulaw_encode(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t channels, size_t frames, int getidx) + snd_pcm_uframes_t dst_offset, + unsigned int channels, snd_pcm_uframes_t frames, int getidx) { #define GET16_LABELS #include "plugin_ops.h" #undef GET16_LABELS void *get = get16_labels[getidx]; - size_t channel; + unsigned int channel; int16_t sample = 0; for (channel = 0; channel < channels; ++channel) { char *src; char *dst; int src_step, dst_step; - size_t frames1; + snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; #if 0 @@ -233,51 +233,58 @@ static int snd_pcm_mulaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_mulaw_t *mulaw = pcm->private; snd_pcm_t *slave = mulaw->plug.slave; int err; + unsigned int cmask, lcmask; snd_pcm_hw_params_t sparams; mask_t *access_mask = alloca(mask_sizeof()); 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_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_mask(params, 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_param_mask(params, 1, + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; } else { - err = _snd_pcm_hw_param_set(params, 1, + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT, - SND_PCM_FORMAT_MU_LAW); + SND_PCM_FORMAT_MU_LAW, 0); if (err < 0) return err; } - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); if (err < 0) return err; + lcmask = params->cmask; + params->cmask |= cmask; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 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); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + mulaw->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave, + snd_pcm_generic_hw_link, slave, SND_PCM_HW_PARBIT_CHANNELS | SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); + params->cmask |= lcmask; if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); @@ -289,32 +296,40 @@ static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) snd_pcm_mulaw_t *mulaw = pcm->private; snd_pcm_t *slave = mulaw->plug.slave; int err; + unsigned int links; snd_pcm_hw_params_t sparams; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, 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 | - SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + mulaw->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); + links = SND_PCM_HW_PARBIT_CHANNELS | + SND_PCM_HW_PARBIT_RATE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_BUFFER_SIZE | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME; + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); if (err < 0) return err; 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_param_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, 0), SND_PCM_FORMAT_S16); mulaw->func = mulaw_encode; } else { mulaw->getput_idx = put_index(SND_PCM_FORMAT_S16, mulaw->sformat); @@ -322,7 +337,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_param_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, 0)); mulaw->func = mulaw_decode; } else { mulaw->getput_idx = get_index(mulaw->sformat, SND_PCM_FORMAT_S16); @@ -332,21 +347,21 @@ static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) return 0; } -static ssize_t snd_pcm_mulaw_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_mulaw_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_mulaw_t *mulaw = pcm->private; snd_pcm_t *slave = mulaw->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); mulaw->func(areas, offset, snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), pcm->channels, frames, @@ -354,7 +369,7 @@ static ssize_t snd_pcm_mulaw_write_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); @@ -367,21 +382,21 @@ static ssize_t snd_pcm_mulaw_write_areas(snd_pcm_t *pcm, return err; } -static ssize_t snd_pcm_mulaw_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_mulaw_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_mulaw_t *mulaw = pcm->private; snd_pcm_t *slave = mulaw->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); mulaw->func(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), areas, offset, pcm->channels, frames, @@ -389,7 +404,7 @@ static ssize_t snd_pcm_mulaw_read_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index 4cb55f8d..28719ae8 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -40,16 +40,16 @@ typedef struct { } snd_pcm_multi_channel_t; typedef struct { - size_t slaves_count; + unsigned int slaves_count; snd_pcm_multi_slave_t *slaves; - size_t channels_count; + unsigned int channels_count; snd_pcm_multi_channel_t *channels; } snd_pcm_multi_t; static int snd_pcm_multi_close(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - size_t i; + unsigned int i; int ret = 0; for (i = 0; i < multi->slaves_count; ++i) { int err; @@ -102,7 +102,8 @@ static int snd_pcm_multi_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) unsigned int k; snd_pcm_hw_params_t sparams; int changed = 0; - int err; + int err = 0; + unsigned int cmask, lcmask; 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) || @@ -122,38 +123,50 @@ static int snd_pcm_multi_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) } } - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_CHANNELS, - multi->channels_count); + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS, + multi->channels_count, 0); if (err < 0) return err; + lcmask = params->cmask; + cmask |= params->cmask; + changed = 0; do { for (k = 0; k < multi->slaves_count; ++k) { snd_pcm_t *slave = multi->slaves[k].pcm; + params->cmask = cmask; _snd_pcm_hw_params_any(&sparams); - _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_CHANNELS, - multi->slaves[k].channels_count); + _snd_pcm_hw_param_mask(&sparams, + SND_PCM_HW_PARAM_ACCESS, + saccess_mask); + _snd_pcm_hw_param_set(&sparams, + SND_PCM_HW_PARAM_CHANNELS, + multi->slaves[k].channels_count, 0); err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave, + snd_pcm_generic_hw_link, slave, SND_PCM_HW_PARBIT_FORMAT | SND_PCM_HW_PARBIT_SUBFORMAT | SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_PERIOD_TIME | SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_BUFFER_LENGTH | - SND_PCM_HW_PARBIT_FRAGMENTS); - if (err < 0) - return err; - if (params->hw_cmask) + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_TICK_TIME); + if (params->cmask) { changed++; + lcmask |= params->cmask; + cmask |= params->cmask; + } + if (err < 0) + goto _end; } } while (changed && multi->slaves_count > 1); - return 0; + _end: + params->cmask = lcmask; + return err; } static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) @@ -163,6 +176,16 @@ static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) int err; const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS); mask_t *saccess_mask = alloca(mask_sizeof()); + unsigned int links; + links = SND_PCM_HW_PARBIT_FORMAT | + SND_PCM_HW_PARBIT_SUBFORMAT | + SND_PCM_HW_PARBIT_RATE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_SIZE | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_TICK_TIME; if (mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) || mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); @@ -183,20 +206,18 @@ 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_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - _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, - SND_PCM_HW_PARBIT_FORMAT | - SND_PCM_HW_PARBIT_SUBFORMAT | - SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_BUFFER_LENGTH | - SND_PCM_HW_PARBIT_FRAGMENTS); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS, + multi->slaves[k].channels_count, 0); + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); if (err < 0) return err; err = snd_pcm_areas_silence(slave->running_areas, 0, slave->channels, slave->buffer_size, slave->format); @@ -239,14 +260,14 @@ static int snd_pcm_multi_state(snd_pcm_t *pcm) return snd_pcm_state(slave); } -static int snd_pcm_multi_delay(snd_pcm_t *pcm, ssize_t *delayp) +static int snd_pcm_multi_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { snd_pcm_multi_t *multi = pcm->private; snd_pcm_t *slave = multi->slaves[0].pcm; return snd_pcm_delay(slave, delayp); } -static ssize_t snd_pcm_multi_avail_update(snd_pcm_t *pcm) +static snd_pcm_sframes_t snd_pcm_multi_avail_update(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; snd_pcm_t *slave = multi->slaves[0].pcm; @@ -303,15 +324,15 @@ static int snd_pcm_multi_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *in return err; } -static ssize_t snd_pcm_multi_rewind(snd_pcm_t *pcm, size_t frames) +static snd_pcm_sframes_t snd_pcm_multi_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_multi_t *multi = pcm->private; unsigned int i; - size_t pos[multi->slaves_count]; + snd_pcm_uframes_t pos[multi->slaves_count]; memset(pos, 0, sizeof(pos)); for (i = 0; i < multi->slaves_count; ++i) { snd_pcm_t *slave_i = multi->slaves[i].pcm; - ssize_t f = snd_pcm_rewind(slave_i, frames); + snd_pcm_sframes_t f = snd_pcm_rewind(slave_i, frames); if (f < 0) return f; pos[i] = f; @@ -320,28 +341,28 @@ static ssize_t snd_pcm_multi_rewind(snd_pcm_t *pcm, size_t frames) /* Realign the pointers */ for (i = 0; i < multi->slaves_count; ++i) { snd_pcm_t *slave_i = multi->slaves[i].pcm; - size_t f = pos[i] - frames; + snd_pcm_uframes_t f = pos[i] - frames; if (f > 0) snd_pcm_mmap_appl_forward(slave_i, f); } return frames; } -static ssize_t snd_pcm_multi_mmap_forward(snd_pcm_t *pcm, size_t size) +static snd_pcm_sframes_t snd_pcm_multi_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size) { snd_pcm_multi_t *multi = pcm->private; unsigned int i; for (i = 0; i < multi->slaves_count; ++i) { snd_pcm_t *slave = multi->slaves[i].pcm; - ssize_t frames = snd_pcm_mmap_forward(slave, size); + snd_pcm_sframes_t frames = snd_pcm_mmap_forward(slave, size); if (frames < 0) return frames; if (i == 0) { size = frames; continue; } - if ((size_t) frames != size) + if ((snd_pcm_uframes_t) frames != size) return -EBADFD; } return size; @@ -422,9 +443,9 @@ snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = { }; int snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, - size_t slaves_count, - snd_pcm_t **slaves_pcm, size_t *schannels_count, - size_t channels_count, + unsigned int slaves_count, + snd_pcm_t **slaves_pcm, unsigned int *schannels_count, + unsigned int channels_count, int *sidxs, unsigned int *schannels, int close_slaves) { @@ -505,11 +526,11 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, char **slaves_id = NULL; char **slaves_name = NULL; snd_pcm_t **slaves_pcm = NULL; - size_t *slaves_channels = NULL; + unsigned int *slaves_channels = NULL; unsigned int *channels_sidx = NULL; unsigned int *channels_schannel = NULL; - size_t slaves_count = 0; - size_t channels_count = 0; + unsigned int slaves_count = 0; + unsigned int channels_count = 0; snd_config_foreach(i, conf) { snd_config_t *n = snd_config_entry(i); if (strcmp(n->id, "comment") == 0) @@ -667,7 +688,7 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, err = -EINVAL; goto _free; } - if (slave < 0 || (size_t)slave >= slaves_count) { + if (slave < 0 || (unsigned int)slave >= slaves_count) { ERR("Invalid or missing sidx"); err = -EINVAL; goto _free; diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c index 3390e49c..f2e6e148 100644 --- a/src/pcm/pcm_null.c +++ b/src/pcm/pcm_null.c @@ -29,8 +29,8 @@ typedef struct { snd_timestamp_t trigger_time; int state; int shmid; - size_t appl_ptr; - size_t hw_ptr; + snd_pcm_uframes_t appl_ptr; + snd_pcm_uframes_t hw_ptr; int poll_fd; } snd_pcm_null_t; @@ -88,7 +88,7 @@ static int snd_pcm_null_state(snd_pcm_t *pcm) return null->state; } -static int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, ssize_t *delayp) +static int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp) { *delayp = 0; return 0; @@ -149,7 +149,7 @@ static int snd_pcm_null_pause(snd_pcm_t *pcm, int enable) return 0; } -static ssize_t snd_pcm_null_rewind(snd_pcm_t *pcm, size_t frames) +static snd_pcm_sframes_t snd_pcm_null_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_null_t *null = pcm->private; switch (null->state) { @@ -163,7 +163,7 @@ static ssize_t snd_pcm_null_rewind(snd_pcm_t *pcm, size_t frames) } } -static ssize_t snd_pcm_null_fwd(snd_pcm_t *pcm, size_t size) +static snd_pcm_sframes_t snd_pcm_null_fwd(snd_pcm_t *pcm, snd_pcm_uframes_t size) { snd_pcm_null_t *null = pcm->private; switch (null->state) { @@ -177,7 +177,7 @@ static ssize_t snd_pcm_null_fwd(snd_pcm_t *pcm, size_t size) } } -static ssize_t snd_pcm_null_writei(snd_pcm_t *pcm, const void *buffer ATTRIBUTE_UNUSED, size_t size) +static snd_pcm_sframes_t snd_pcm_null_writei(snd_pcm_t *pcm, const void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) { snd_pcm_null_t *null = pcm->private; if (null->state == SND_PCM_STATE_PREPARED && @@ -187,7 +187,7 @@ static ssize_t snd_pcm_null_writei(snd_pcm_t *pcm, const void *buffer ATTRIBUTE_ return snd_pcm_null_fwd(pcm, size); } -static ssize_t snd_pcm_null_writen(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, size_t size) +static snd_pcm_sframes_t snd_pcm_null_writen(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) { snd_pcm_null_t *null = pcm->private; if (null->state == SND_PCM_STATE_PREPARED && @@ -197,7 +197,7 @@ static ssize_t snd_pcm_null_writen(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, return snd_pcm_null_fwd(pcm, size); } -static ssize_t snd_pcm_null_readi(snd_pcm_t *pcm, void *buffer ATTRIBUTE_UNUSED, size_t size) +static snd_pcm_sframes_t snd_pcm_null_readi(snd_pcm_t *pcm, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) { snd_pcm_null_t *null = pcm->private; if (null->state == SND_PCM_STATE_PREPARED && @@ -208,7 +208,7 @@ static ssize_t snd_pcm_null_readi(snd_pcm_t *pcm, void *buffer ATTRIBUTE_UNUSED, return snd_pcm_null_fwd(pcm, size); } -static ssize_t snd_pcm_null_readn(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, size_t size) +static snd_pcm_sframes_t snd_pcm_null_readn(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) { snd_pcm_null_t *null = pcm->private; if (null->state == SND_PCM_STATE_PREPARED && @@ -219,12 +219,12 @@ static ssize_t snd_pcm_null_readn(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, return snd_pcm_null_fwd(pcm, size); } -static ssize_t snd_pcm_null_mmap_forward(snd_pcm_t *pcm, size_t size) +static snd_pcm_sframes_t snd_pcm_null_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size) { return snd_pcm_null_fwd(pcm, size); } -static ssize_t snd_pcm_null_avail_update(snd_pcm_t *pcm) +static snd_pcm_sframes_t snd_pcm_null_avail_update(snd_pcm_t *pcm) { return pcm->buffer_size; } diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c index 0d126f11..154a53aa 100644 --- a/src/pcm/pcm_params.c +++ b/src/pcm/pcm_params.c @@ -25,18 +25,51 @@ #include "interval.h" #include "mask.h" -static inline unsigned int add(unsigned int a, unsigned int b) -{ - if (a >= UINT_MAX - b) - return UINT_MAX; - return a + b; -} - -static inline unsigned int sub(unsigned int a, unsigned int b) -{ - if (a > b) - return a - b; - return 0; +static void approx_sub(int a, int adir, + int b, int bdir, + int *c, int *cdir) +{ + adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0); + bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0); + *c = a - b; + *cdir = adir - bdir; + if (*cdir == -2) { + assert(*c > INT_MIN); + (*c)--; + } else if (*cdir == 2) { + assert(*c < INT_MAX); + (*c)++; + } +} + +static int approx_lt(unsigned int a, int adir, + unsigned int b, int bdir) +{ + assert(a > 0 || adir >= 0); + assert(b > 0 || bdir >= 0); + if (adir < 0) { + a--; + adir = 1; + } else if (adir > 0) + adir = 1; + if (bdir < 0) { + b--; + bdir = 1; + } else if (bdir > 0) + bdir = 1; + return a < b || (a == b && adir < bdir); +} + +/* Return 1 if max is nearer to best than min */ +static int approx_nearer(int min, int mindir, + int best, int bestdir, + int max, int maxdir) +{ + int dmin, dmindir; + int dmax, dmaxdir; + approx_sub(best, bestdir, min, mindir, &dmin, &dmindir); + approx_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir); + return approx_lt(dmax, dmaxdir, dmin, dmindir); } static inline int hw_is_mask(int var) @@ -52,48 +85,48 @@ static inline int hw_is_interval(int var) } static inline mask_t *hw_param_mask(snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var) { assert(hw_is_mask(var)); return (mask_t*)¶ms->masks[var - SND_PCM_HW_PARAM_FIRST_MASK]; } static inline interval_t *hw_param_interval(snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var) { assert(hw_is_interval(var)); return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL]; } static inline const mask_t *hw_param_mask_c(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var) { return (const mask_t *)hw_param_mask((snd_pcm_hw_params_t*) params, var); } static inline const interval_t *hw_param_interval_c(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t 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) +void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var) { if (hw_is_mask(var)) { - mask_all(hw_param_mask(params, var)); - params->appl_cmask |= 1 << var; + mask_any(hw_param_mask(params, var)); + params->cmask |= 1 << var; return; } if (hw_is_interval(var)) { - interval_all(hw_param_interval(params, var)); - params->appl_cmask |= 1 << var; + interval_any(hw_param_interval(params, var)); + params->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_t var) { _snd_pcm_hw_param_any(params, var); return snd_pcm_hw_refine(pcm, params); @@ -105,9 +138,6 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params) memset(params, 0, sizeof(*params)); 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; } @@ -122,18 +152,22 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) defined by PARAMS. Return -EINVAL otherwise */ int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var, int *dir) { if (hw_is_mask(var)) { const mask_t *mask = hw_param_mask_c(params, var); if (!mask_single(mask)) return -EINVAL; + if (dir) + *dir = 0; return mask_value(mask); } if (hw_is_interval(var)) { const interval_t *i = hw_param_interval_c(params, var); if (!interval_single(i)) return -EINVAL; + if (dir) + *dir = i->openmin; return interval_value(i); } assert(0); @@ -142,13 +176,18 @@ int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, /* Return the minimum value for field PAR. */ unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var, int *dir) { if (hw_is_mask(var)) { + if (dir) + *dir = 0; return mask_min(hw_param_mask_c(params, var)); } if (hw_is_interval(var)) { - return interval_min(hw_param_interval_c(params, var)); + const interval_t *i = hw_param_interval_c(params, var); + if (dir) + *dir = i->openmin; + return interval_min(i); } assert(0); return -EINVAL; @@ -156,13 +195,18 @@ unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params, /* Return the maximum value for field PAR. */ unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var, int *dir) { if (hw_is_mask(var)) { + if (dir) + *dir = 0; return mask_max(hw_param_mask_c(params, var)); } if (hw_is_interval(var)) { - return interval_max(hw_param_interval_c(params, var)); + const interval_t *i = hw_param_interval_c(params, var); + if (dir) + *dir = - (int) i->openmax; + return interval_max(i); } assert(0); return -EINVAL; @@ -172,7 +216,7 @@ unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params, 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_param_value_mask(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var) { assert(hw_is_mask(var)); return hw_param_mask_c(params, var); @@ -182,17 +226,58 @@ const mask_t *snd_pcm_hw_param_value_mask(const snd_pcm_hw_params_t *params, 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_param_value_interval(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var) { assert(hw_is_interval(var)); return hw_param_interval_c(params, var); } - /* --- Refinement functions --- */ -int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, int hw, - unsigned int var) +int _snd_pcm_hw_param_refine_interval(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const interval_t *val) +{ + int changed; + assert(hw_is_interval(var)); + changed = interval_refine(hw_param_interval(params, var), val); + if (changed) + params->cmask |= 1 << var; + return changed; +} + +int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var) +{ + int changed; + assert(hw_is_interval(var)); + changed = interval_setinteger(hw_param_interval(params, var)); + if (changed) + params->cmask |= 1 << var; + return changed; +} + +/* Inside configuration space defined by PARAMS remove from PAR all + non integer values. Reduce configuration space accordingly. + Return -EINVAL if the configuration space is empty +*/ +int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var) +{ + int changed = _snd_pcm_hw_param_setinteger(params, var); + if (changed < 0) + return changed; + if (changed) { + int err = snd_pcm_hw_refine(pcm, params); + if (err < 0) + return err; + } + return 0; +} + +int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var) { int changed; if (hw_is_mask(var)) @@ -203,12 +288,8 @@ int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, int hw, assert(0); return -EINVAL; } - if (changed) { - if (hw) - params->hw_cmask |= 1 << var; - else - params->appl_cmask |= 1 << var; - } + if (changed) + params->cmask |= 1 << var; return changed; } @@ -218,20 +299,21 @@ int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, int hw, Return the minimum. */ int snd_pcm_hw_param_first(snd_pcm_t *pcm, - snd_pcm_hw_params_t *params, unsigned int var) + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, int *dir) { - int changed = _snd_pcm_hw_param_first(params, 0, var); + int changed = _snd_pcm_hw_param_first(params, var); if (changed < 0) return changed; if (changed) { int err = snd_pcm_hw_refine(pcm, params); assert(err >= 0); } - return snd_pcm_hw_param_value(params, var); + return snd_pcm_hw_param_value(params, var, dir); } -int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, int hw, - unsigned int var) +int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var) { int changed; if (hw_is_mask(var)) @@ -242,12 +324,8 @@ int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, int hw, assert(0); return -EINVAL; } - if (changed) { - if (hw) - params->hw_cmask |= 1 << var; - else - params->appl_cmask |= 1 << var; - } + if (changed) + params->cmask |= 1 << var; return changed; } @@ -257,36 +335,44 @@ int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, int hw, Return the maximum. */ int snd_pcm_hw_param_last(snd_pcm_t *pcm, - snd_pcm_hw_params_t *params, unsigned int var) + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, int *dir) { - int changed = _snd_pcm_hw_param_last(params, 0, var); + int changed = _snd_pcm_hw_param_last(params, var); if (changed < 0) return changed; if (changed) { int err = snd_pcm_hw_refine(pcm, params); assert(err >= 0); } - return snd_pcm_hw_param_value(params, var); + return snd_pcm_hw_param_value(params, var, dir); } -int _snd_pcm_hw_param_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, + snd_pcm_hw_param_t var, unsigned int val, int dir) { int changed; + int open = 0; + if (dir) { + if (dir > 0) { + open = 1; + } else if (dir < 0) { + if (val > 0) { + open = 1; + val--; + } + } + } if (hw_is_mask(var)) - changed = mask_refine_min(hw_param_mask(params, var), val); + changed = mask_refine_min(hw_param_mask(params, var), val + !!open); else if (hw_is_interval(var)) - changed = interval_refine_min(hw_param_interval(params, var), val); + changed = interval_refine_min(hw_param_interval(params, var), val, open); else { assert(0); return -EINVAL; } - if (changed) { - if (hw) - params->hw_cmask |= 1 << var; - else - params->appl_cmask |= 1 << var; - } + if (changed) + params->cmask |= 1 << var; return changed; } @@ -295,9 +381,9 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params, int hw, Return new minimum or -EINVAL if the configuration space is empty */ int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_hw_param_t var, unsigned int val, int *dir) { - int changed = _snd_pcm_hw_param_min(params, 0, var, val); + int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); if (changed < 0) return changed; if (changed) { @@ -305,39 +391,49 @@ int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, if (err < 0) return err; } - return snd_pcm_hw_param_value_min(params, var); + return snd_pcm_hw_param_value_min(params, var, dir); } int snd_pcm_hw_param_min_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_hw_param_t var, + unsigned int val, int *dir) { snd_pcm_hw_params_t save; int err; save = *params; - err = snd_pcm_hw_param_min(pcm, params, var, val); + err = snd_pcm_hw_param_min(pcm, params, var, val, dir); if (err < 0) *params = save; return err; } -int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, int hw, - unsigned int var, unsigned int val) +int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, unsigned int val, int dir) { int changed; - 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); + int open = 0; + if (dir) { + if (dir < 0) { + open = 1; + } else if (dir > 0) { + open = 1; + val++; + } + } + if (hw_is_mask(var)) { + if (val == 0 && open) { + mask_none(hw_param_mask(params, var)); + changed = -EINVAL; + } else + changed = mask_refine_max(hw_param_mask(params, var), val - !!open); + } else if (hw_is_interval(var)) + changed = interval_refine_max(hw_param_interval(params, var), val, open); else { assert(0); return -EINVAL; } - if (changed) { - if (hw) - params->hw_cmask |= 1 << var; - else - params->appl_cmask |= 1 << var; - } + if (changed) + params->cmask |= 1 << var; return changed; } @@ -346,9 +442,9 @@ int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, int hw, Return new maximum or -EINVAL if the configuration space is empty */ int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_hw_param_t var, unsigned int val, int *dir) { - int changed = _snd_pcm_hw_param_max(params, 0, var, val); + int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); if (changed < 0) return changed; if (changed) { @@ -356,46 +452,72 @@ int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, if (err < 0) return err; } - return snd_pcm_hw_param_value_max(params, var); + return snd_pcm_hw_param_value_max(params, var, dir); } int snd_pcm_hw_param_max_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_hw_param_t var, + unsigned int val, int *dir) { snd_pcm_hw_params_t save; int err; save = *params; - err = snd_pcm_hw_param_max(pcm, params, var, val); + err = snd_pcm_hw_param_max(pcm, params, var, val, dir); if (err < 0) *params = save; return err; } -int _snd_pcm_hw_param_minmax(snd_pcm_hw_params_t *params, int hw, - unsigned int var, - unsigned int min, unsigned int max) +int _snd_pcm_hw_param_minmax(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + unsigned int min, int mindir, + unsigned int max, int maxdir) { int changed, c1, c2; + int openmin = 0, openmax = 0; + if (mindir) { + if (mindir > 0) { + openmin = 1; + } else if (mindir < 0) { + if (min > 0) { + openmin = 1; + min--; + } + } + } + if (maxdir) { + if (maxdir < 0) { + openmax = 1; + } else if (maxdir > 0) { + openmax = 1; + max++; + } + } if (hw_is_mask(var)) { mask_t *mask = hw_param_mask(params, var); - c1 = mask_refine_min(mask, min); - if (c1 < 0) - changed = c1; - else { - c2 = mask_refine_max(mask, max); - if (c2 < 0) - changed = c2; - else - changed = (c1 || c2); + if (max == 0 && openmax) { + mask_none(mask); + changed = -EINVAL; + } else { + c1 = mask_refine_min(mask, min + !!openmin); + if (c1 < 0) + changed = c1; + else { + c2 = mask_refine_max(mask, max - !!openmax); + if (c2 < 0) + changed = c2; + else + changed = (c1 || c2); + } } } else if (hw_is_interval(var)) { interval_t *i = hw_param_interval(params, var); - c1 = interval_refine_min(i, min); + c1 = interval_refine_min(i, min, openmin); if (c1 < 0) changed = c1; else { - c2 = interval_refine_max(i, max); + c2 = interval_refine_max(i, max, openmax); if (c2 < 0) changed = c2; else @@ -405,12 +527,8 @@ int _snd_pcm_hw_param_minmax(snd_pcm_hw_params_t *params, int hw, assert(0); return -EINVAL; } - if (changed) { - if (hw) - params->hw_cmask |= 1 << var; - else - params->appl_cmask |= 1 << var; - } + if (changed) + params->cmask |= 1 << var; return changed; } @@ -419,10 +537,13 @@ int _snd_pcm_hw_param_minmax(snd_pcm_hw_params_t *params, int hw, Return 0 or -EINVAL if the configuration space is empty */ 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) + snd_pcm_hw_param_t var, + unsigned int *min, int *mindir, + unsigned int *max, int *maxdir) { - int changed = _snd_pcm_hw_param_minmax(params, 0, var, min, max); + int changed = _snd_pcm_hw_param_minmax(params, var, + *min, mindir ? *mindir : 0, + *max, maxdir ? *maxdir : 0); if (changed < 0) return changed; if (changed) { @@ -430,51 +551,82 @@ int snd_pcm_hw_param_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, if (err < 0) return err; } + *min = snd_pcm_hw_param_value_min(params, var, mindir); + *max = snd_pcm_hw_param_value_max(params, var, maxdir); return 0; } int snd_pcm_hw_param_minmax_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, - unsigned int min, unsigned int max) + snd_pcm_hw_param_t var, + unsigned int *min, int *mindir, + unsigned int *max, int *maxdir) { snd_pcm_hw_params_t save; int err; save = *params; - err = snd_pcm_hw_param_minmax(pcm, params, var, min, max); + err = snd_pcm_hw_param_minmax(pcm, params, var, + min, mindir, + max, maxdir); if (err < 0) *params = save; return err; } -int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params, int hw, - unsigned int var, unsigned int val) +int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, unsigned int val, int dir) { int changed; - 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 { + if (hw_is_mask(var)) { + mask_t *m = hw_param_mask(params, var); + if (val == 0 && dir < 0) { + changed = -EINVAL; + mask_none(m); + } else { + if (dir > 0) + val++; + else if (dir < 0) + val--; + changed = mask_refine_set(hw_param_mask(params, var), val); + } + } else if (hw_is_interval(var)) { + interval_t *i = hw_param_interval(params, var); + if (val == 0 && dir < 0) { + changed = -EINVAL; + interval_none(i); + } else if (dir == 0) + changed = interval_refine_set(i, val); + else { + interval_t t; + t.openmin = 1; + t.openmax = 1; + t.empty = 0; + t.integer = 0; + if (dir < 0) { + t.min = val - 1; + t.max = val; + } else { + t.min = val; + t.max = val+1; + } + changed = interval_refine(i, &t); + } + } else { assert(0); return -EINVAL; } - if (changed) { - if (hw) - params->hw_cmask |= 1 << var; - else - params->appl_cmask |= 1 << var; - } + if (changed) + params->cmask |= 1 << var; return changed; } /* Inside configuration space defined by PARAMS remove from PAR all - values < VAL and >= VAL +1. Reduce configuration space accordingly. + values != VAL. Reduce configuration space accordingly. Return VAL or -EINVAL if the configuration space is empty */ int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_hw_param_t var, unsigned int val, int dir) { - int changed = _snd_pcm_hw_param_set(params, 0, var, val); + int changed = _snd_pcm_hw_param_set(params, var, val, dir); if (changed < 0) return changed; if (changed) { @@ -482,33 +634,29 @@ int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, if (err < 0) return err; } - return snd_pcm_hw_param_value(params, var); + return snd_pcm_hw_param_value(params, var, 0); } int snd_pcm_hw_param_set_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_hw_param_t var, unsigned int val, int dir) { snd_pcm_hw_params_t save; int err; save = *params; - err = snd_pcm_hw_param_set(pcm, params, var, val); + err = snd_pcm_hw_param_set(pcm, params, var, val, dir); if (err < 0) *params = save; return err; } -int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params, int hw, - unsigned int var, const mask_t *val) +int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, const mask_t *val) { int changed; assert(hw_is_mask(var)); changed = mask_refine(hw_param_mask(params, var), val); - if (changed) { - if (hw) - params->hw_cmask |= 1 << var; - else - params->appl_cmask |= 1 << var; - } + if (changed) + params->cmask |= 1 << var; return changed; } @@ -520,9 +668,9 @@ int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params, int hw, if the configuration space is empty */ int snd_pcm_hw_param_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, const mask_t *val) + snd_pcm_hw_param_t var, const mask_t *val) { - int changed = _snd_pcm_hw_param_mask(params, 0, var, val); + int changed = _snd_pcm_hw_param_mask(params, var, val); if (changed < 0) return changed; if (changed) { @@ -534,7 +682,7 @@ int snd_pcm_hw_param_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, } int snd_pcm_hw_param_mask_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - unsigned int var, const mask_t *val) + snd_pcm_hw_param_t var, const mask_t *val) { snd_pcm_hw_params_t save; int err; @@ -552,93 +700,180 @@ int snd_pcm_hw_param_mask_try(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, Return the value found. */ 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_param_t var, unsigned int best, int *dir) { snd_pcm_hw_params_t save; int v; - unsigned int max1 = val, min2 = add(val, 1); - unsigned int hw_cmask; + unsigned int saved_min; + int last = 0; + unsigned int cmask; + int min, max; + int mindir, maxdir; + int valdir = dir ? *dir : 0; + /* FIXME */ + if (best > INT_MAX) + best = INT_MAX; + min = max = best; + mindir = maxdir = valdir; + if (maxdir > 0) + maxdir = 0; + else if (maxdir == 0) + maxdir = -1; + else { + maxdir = 1; + max--; + } save = *params; - v = snd_pcm_hw_param_max(pcm, params, var, max1); - if (v >= 0) { - int v1; + saved_min = min; + min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir); + if (min >= 0) { snd_pcm_hw_params_t params1; - if (val == (unsigned int)v) + if (max < 0) + goto _end; + if ((unsigned int)min = saved_min && mindir == valdir) goto _end; params1 = save; - v1 = snd_pcm_hw_param_min(pcm, ¶ms1, var, min2); - if (v1 < 0) + max = snd_pcm_hw_param_max(pcm, ¶ms1, var, max, &maxdir); + if (max < 0) goto _end; - if (val - v > v1 - val) { + if (approx_nearer(max, maxdir, best, valdir, min, mindir)) { *params = params1; - v = v1; + last = 1; } } else { *params = save; - v = snd_pcm_hw_param_min(pcm, params, var, min2); - assert(v >= 0); + max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); + assert(max >= 0); + last = 1; } _end: - hw_cmask = params->hw_cmask; - v = snd_pcm_hw_param_set(pcm, params, var, v); - params->hw_cmask |= hw_cmask; + cmask = params->cmask; + if (last) + v = snd_pcm_hw_param_last(pcm, params, var, dir); + else + v = snd_pcm_hw_param_first(pcm, params, var, dir); + params->cmask |= cmask; assert(v >= 0); return v; } /* Inside configuration space defined by PARAMS set PAR to the available value - nearest to VAL after OLD (values less than VAL are returned first). + nearest to BEST after VAL (on equal difference values less than BEST are + returned first). Reduce configuration space accordingly. This function cannot be called for SND_PCM_HW_PARAM_ACCESS, SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. Return the value found. */ 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) + snd_pcm_hw_param_t var, + unsigned int best, int bestdir, + unsigned int val, int *dir) { snd_pcm_hw_params_t save; int v; - unsigned int max1, min2; - int diff = old - val; - if (diff < 0) { - max1 = sub(old, 1); - min2 = add(val, -diff); + int last = 0; + unsigned int cmask; + int min, max; + int mindir, maxdir; + int diff, diffdir; + int valdir = dir ? *dir : 0; + /* FIXME */ + if (best > INT_MAX) + best = INT_MAX; + approx_sub(val, valdir, best, bestdir, &diff, &diffdir); + if (diff < 0 || (diff == 0 && diffdir < 0)) { + min = best - diff; + mindir = bestdir - diffdir; + max = val; + maxdir = bestdir - 1; } else { - max1 = sub(val, diff + 1); - min2 = add(old, 1); - } + min = val; + mindir = bestdir + 1; + max = best + diff; + maxdir = bestdir + diffdir + 1; + } + min += mindir / 2; + mindir %= 2; + max += maxdir / 2; + maxdir %= 2; save = *params; - v = snd_pcm_hw_param_max(pcm, params, var, max1); - if (v >= 0) { - int v1; + if (min >= 0 && + (min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir)) >= 0) { snd_pcm_hw_params_t params1; - if (val == (unsigned int)v) + if (max < 0) goto _end; params1 = save; - v1 = snd_pcm_hw_param_min(pcm, ¶ms1, var, min2); - if (v1 < 0) + max = snd_pcm_hw_param_max(pcm, ¶ms1, var, max, &maxdir); + if (max < 0) goto _end; - if (val - v > v1 - val) { + if (approx_nearer(max, maxdir, best, bestdir, min, mindir)) { *params = params1; - v = v1; + last = 1; } } else { + if (max < 0) + return -EINVAL; *params = save; - v = snd_pcm_hw_param_min(pcm, params, var, min2); - if (v < 0) - return v; + max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); + if (max < 0) + return max; + last = 1; } _end: - v = snd_pcm_hw_param_set(pcm, params, var, v); + cmask = params->cmask; + if (last) + v = snd_pcm_hw_param_last(pcm, params, var, dir); + else + v = snd_pcm_hw_param_first(pcm, params, var, dir); + params->cmask |= cmask; + assert(v >= 0); return v; } +void snd_pcm_hw_param_near_minmax(snd_pcm_t *pcm, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + unsigned int min, int *mindir, + unsigned int max, int *maxdir) +{ + snd_pcm_hw_params_t tmp; + int err; + if (!approx_lt(min, *mindir, max, *maxdir)) { + snd_pcm_hw_param_near(pcm, params, var, min, mindir); + return; + } + tmp = *params; + min = snd_pcm_hw_param_near(pcm, &tmp, var, min, mindir); + if (approx_lt(min, *mindir, max, *maxdir)) { + tmp = *params; + max = snd_pcm_hw_param_near(pcm, &tmp, var, max, maxdir); + } else { + max = min; + *maxdir = *mindir; + } + err = snd_pcm_hw_param_minmax(pcm, params, var, &min, mindir, + &max, maxdir); + assert(err >= 0); +} + +void snd_pcm_hw_param_near_copy(snd_pcm_t *pcm, + snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const snd_pcm_hw_params_t *src) +{ + unsigned int min, max; + int mindir, maxdir; + min = snd_pcm_hw_param_value_min(src, var, &mindir); + max = snd_pcm_hw_param_value_max(src, var, &maxdir); + snd_pcm_hw_param_near_minmax(pcm, params, var, + min, &mindir, max, &maxdir); +} /* ---- end of refinement functions ---- */ int snd_pcm_hw_param_empty(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var) { if (hw_is_mask(var)) return mask_empty(hw_param_mask_c(params, var)); @@ -648,6 +883,35 @@ int snd_pcm_hw_param_empty(const snd_pcm_hw_params_t *params, return -EINVAL; } +int snd_pcm_hw_param_always_eq(const snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const snd_pcm_hw_params_t *params1) +{ + if (hw_is_mask(var)) + return mask_always_eq(hw_param_mask_c(params, var), + hw_param_mask_c(params1, var)); + if (hw_is_interval(var)) + return interval_always_eq(hw_param_interval_c(params, var), + hw_param_interval_c(params1, var)); + assert(0); + return -EINVAL; +} + +int snd_pcm_hw_param_never_eq(const snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const snd_pcm_hw_params_t *params1) +{ + if (hw_is_mask(var)) + return mask_never_eq(hw_param_mask_c(params, var), + hw_param_mask_c(params1, var)); + if (hw_is_interval(var)) + return interval_never_eq(hw_param_interval_c(params, var), + hw_param_interval_c(params1, var)); + assert(0); + return -EINVAL; +} + + /* Return rate numerator/denumerator obtainable for configuration space defined by PARAMS */ int snd_pcm_hw_params_info_rate(const snd_pcm_hw_params_t *params, @@ -692,43 +956,48 @@ int snd_pcm_hw_params_info_fifo_size(const snd_pcm_hw_params_t *params) first subformat min channels min rate - min fragment size - max fragments + min period time + max buffer size + min tick time */ 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; + unsigned int cmask = params->cmask; - err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_ACCESS); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, 0); assert(err >= 0); - hw_cmask |= params->hw_cmask; + cmask |= params->cmask; - err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_FORMAT); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_FORMAT, 0); assert(err >= 0); - hw_cmask |= params->hw_cmask; + cmask |= params->cmask; - err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, 0); assert(err >= 0); - hw_cmask |= params->hw_cmask; + cmask |= params->cmask; - err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS, 0); assert(err >= 0); - hw_cmask |= params->hw_cmask; + cmask |= params->cmask; - err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_RATE); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_RATE, 0); assert(err >= 0); - hw_cmask |= params->hw_cmask; + cmask |= params->cmask; - err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_FRAGMENT_SIZE); + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, 0); assert(err >= 0); - hw_cmask |= params->hw_cmask; + cmask |= params->cmask; - err = snd_pcm_hw_param_last(pcm, params, SND_PCM_HW_PARAM_FRAGMENTS); + err = snd_pcm_hw_param_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, 0); assert(err >= 0); - hw_cmask |= params->hw_cmask; + cmask |= params->cmask; - params->hw_cmask = hw_cmask; + err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_TICK_TIME, 0); + assert(err >= 0); + cmask |= params->cmask; + + params->cmask = cmask; } /* Strategies */ @@ -740,7 +1009,7 @@ struct _snd_pcm_hw_strategy { const snd_pcm_hw_strategy_t *strategy); int (*next_value)(snd_pcm_hw_params_t *params, unsigned int param, - int value, + int value, int *dir, snd_pcm_t *pcm, const snd_pcm_hw_strategy_t *strategy); int (*min_badness)(const snd_pcm_hw_params_t *params, @@ -759,7 +1028,7 @@ struct _snd_pcm_hw_strategy_simple { unsigned int order; int (*next_value)(snd_pcm_hw_params_t *params, unsigned int param, - int value, + int value, int *dir, snd_pcm_t *pcm, const snd_pcm_hw_strategy_simple_t *par); unsigned int (*min_badness)(const snd_pcm_hw_params_t *params, @@ -782,7 +1051,7 @@ typedef struct _snd_pcm_hw_strategy_simple_choices { } snd_pcm_hw_strategy_simple_choices_t; int snd_pcm_hw_param_test(const snd_pcm_hw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_hw_param_t var, unsigned int val) { if (hw_is_mask(var)) { const mask_t *mask = hw_param_mask_c(params, var); @@ -797,7 +1066,7 @@ int snd_pcm_hw_param_test(const snd_pcm_hw_params_t *params, } unsigned int snd_pcm_hw_param_count(const snd_pcm_hw_params_t *params, - unsigned int var) + snd_pcm_hw_param_t var) { if (hw_is_mask(var)) { const mask_t *mask = hw_param_mask_c(params, var); @@ -811,9 +1080,9 @@ unsigned int snd_pcm_hw_param_count(const snd_pcm_hw_params_t *params, return 0; } -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 snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + const snd_pcm_hw_params_t *src) { int changed = 0; if (hw_is_mask(var)) { @@ -826,16 +1095,12 @@ int _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params, int hw, changed = interval_refine(d, s); } else assert(0); - if (changed) { - if (hw) - params->hw_cmask |= 1 << var; - else - params->appl_cmask |= 1 << var; - } + if (changed) + params->cmask |= 1 << var; return changed; } -void snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, unsigned int var, +void snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var, const snd_pcm_hw_params_t *src) { if (hw_is_mask(var)) { @@ -852,7 +1117,7 @@ void snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, unsigned int var, } void snd_pcm_hw_param_dump(const snd_pcm_hw_params_t *params, - unsigned int var, FILE *fp) + snd_pcm_hw_param_t var, FILE *fp) { static const char *(*funcs[])(unsigned int k) = { [SND_PCM_HW_PARAM_ACCESS] = snd_pcm_access_name, @@ -905,7 +1170,7 @@ int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, { snd_pcm_hw_params_t best_params; int var; - int value; + int value, dir; unsigned int best_badness; int badness = strategy->min_badness(params, badness_max, pcm, strategy); snd_pcm_hw_params_t params1; @@ -923,14 +1188,14 @@ int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, best_badness = UINT_MAX; value = -1; while (1) { - unsigned int hw_cmask; + unsigned int cmask; params1 = *params; - value = strategy->next_value(¶ms1, var, value, pcm, strategy); + value = strategy->next_value(¶ms1, var, value, &dir, pcm, strategy); if (value < 0) break; - hw_cmask = params1.hw_cmask; + cmask = params1.cmask; badness = snd_pcm_hw_params_strategy(pcm, ¶ms1, strategy, badness_min, badness_max); - params1.hw_cmask |= hw_cmask; + params1.cmask |= cmask; if (badness >= 0) { if ((unsigned int) badness <= badness_min) { *params = params1; @@ -963,7 +1228,7 @@ int snd_pcm_hw_strategy_simple_choose_param(const snd_pcm_hw_params_t *params, snd_pcm_t *pcm ATTRIBUTE_UNUSED, const snd_pcm_hw_strategy_t *strategy) { - unsigned int var; + snd_pcm_hw_param_t var; int best_var = -1; const snd_pcm_hw_strategy_simple_t *pars = strategy->private; unsigned int min_choices = UINT_MAX; @@ -989,14 +1254,14 @@ int snd_pcm_hw_strategy_simple_choose_param(const 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_hw_strategy_t *strategy) + snd_pcm_hw_param_t var, + int value, int *dir, + snd_pcm_t *pcm, + const snd_pcm_hw_strategy_t *strategy) { 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]); + return pars[var].next_value(params, var, value, dir, pcm, &pars[var]); } @@ -1005,7 +1270,7 @@ int snd_pcm_hw_strategy_simple_min_badness(const snd_pcm_hw_params_t *params, snd_pcm_t *pcm, const snd_pcm_hw_strategy_t *strategy) { - unsigned int var; + snd_pcm_hw_param_t var; unsigned int badness = 0; const snd_pcm_hw_strategy_simple_t *pars = strategy->private; for (var = 0; var <= SND_PCM_HW_PARAM_LAST; ++var) { @@ -1028,13 +1293,13 @@ void snd_pcm_hw_strategy_simple_near_free(snd_pcm_hw_strategy_simple_t *par) } unsigned int snd_pcm_hw_strategy_simple_near_min_badness(const snd_pcm_hw_params_t *params, - unsigned int var, + snd_pcm_hw_param_t var, snd_pcm_t *pcm, const snd_pcm_hw_strategy_simple_t *par) { const snd_pcm_hw_strategy_simple_near_t *p = par->private; snd_pcm_hw_params_t params1 = *params; - int value = snd_pcm_hw_param_near(pcm, ¶ms1, var, p->best); + int value = snd_pcm_hw_param_near(pcm, ¶ms1, var, p->best, 0); int diff; assert(value >= 0); diff = p->best - value; @@ -1044,16 +1309,17 @@ unsigned int snd_pcm_hw_strategy_simple_near_min_badness(const snd_pcm_hw_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_hw_strategy_simple_t *par) + snd_pcm_hw_param_t var, + int value, int *dir, + snd_pcm_t *pcm, + const snd_pcm_hw_strategy_simple_t *par) { const snd_pcm_hw_strategy_simple_near_t *p = par->private; - if (value < 0) - return snd_pcm_hw_param_near(pcm, params, var, p->best); - else - return snd_pcm_hw_param_next(pcm, params, var, p->best, value); + if (value < 0) { + *dir = 0; + return snd_pcm_hw_param_near(pcm, params, var, p->best, dir); + } else + return snd_pcm_hw_param_next(pcm, params, var, p->best, 0, value, dir); } void snd_pcm_hw_strategy_simple_choices_free(snd_pcm_hw_strategy_simple_t *par) @@ -1064,7 +1330,7 @@ void snd_pcm_hw_strategy_simple_choices_free(snd_pcm_hw_strategy_simple_t *par) } unsigned int snd_pcm_hw_strategy_simple_choices_min_badness(const snd_pcm_hw_params_t *params, - unsigned int var, + snd_pcm_hw_param_t var, snd_pcm_t *pcm ATTRIBUTE_UNUSED, const snd_pcm_hw_strategy_simple_t *par) { @@ -1079,10 +1345,10 @@ unsigned int snd_pcm_hw_strategy_simple_choices_min_badness(const snd_pcm_hw_par } 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_hw_strategy_simple_t *par) + snd_pcm_hw_param_t var, + int value, int *dir, + snd_pcm_t *pcm, + const snd_pcm_hw_strategy_simple_t *par) { const snd_pcm_hw_strategy_simple_choices_t *p = par->private; unsigned int k = 0; @@ -1098,11 +1364,12 @@ int snd_pcm_hw_strategy_simple_choices_next_value(snd_pcm_hw_params_t *params, unsigned int v = p->choices[k].value; if (snd_pcm_hw_param_test(params, var, v)) { snd_pcm_hw_params_t save = *params; - int err = snd_pcm_hw_param_set(pcm, params, var, v); + int err = snd_pcm_hw_param_set(pcm, params, var, v, 0); if (err < 0) { *params = save; continue; } + *dir = 0; return v; } } @@ -1145,7 +1412,7 @@ int snd_pcm_hw_strategy_simple(snd_pcm_hw_strategy_t **strategyp, int snd_pcm_hw_strategy_simple_near(snd_pcm_hw_strategy_t *strategy, int order, - unsigned int var, + snd_pcm_hw_param_t var, unsigned int best, unsigned int mul) { @@ -1171,7 +1438,7 @@ int snd_pcm_hw_strategy_simple_near(snd_pcm_hw_strategy_t *strategy, int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy, int order, - unsigned int var, + snd_pcm_hw_param_t var, unsigned int count, snd_pcm_hw_strategy_simple_choices_list_t *choices) { @@ -1201,7 +1468,7 @@ int snd_pcm_hw_params_try_explain_failure1(snd_pcm_t *pcm, unsigned int depth, FILE *fp) { - unsigned int var; + snd_pcm_hw_param_t var; snd_pcm_hw_params_t i; if (depth < 1) return -ENOENT; @@ -1229,7 +1496,7 @@ int snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm, { snd_pcm_hw_params_t i, any; int err; - unsigned int var; + snd_pcm_hw_param_t var; int done = 0; assert(pcm && fail); for (var = 0; var <= SND_PCM_HW_PARAM_LAST; var++) { @@ -1268,35 +1535,39 @@ 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(hw_param_interval(params, rule->var), - hw_param_interval(params, rule->deps[0]), - hw_param_interval(params, rule->deps[1])); + interval_t t; + interval_mul(hw_param_interval_c(params, rule->deps[0]), + hw_param_interval_c(params, rule->deps[1]), &t); + return interval_refine(hw_param_interval(params, rule->var), &t); } int snd_pcm_hw_rule_div(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) { - return interval_div(hw_param_interval(params, rule->var), - hw_param_interval(params, rule->deps[0]), - hw_param_interval(params, rule->deps[1])); + interval_t t; + interval_div(hw_param_interval_c(params, rule->deps[0]), + hw_param_interval_c(params, rule->deps[1]), &t); + return interval_refine(hw_param_interval(params, rule->var), &t); } int snd_pcm_hw_rule_muldivk(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) { - return interval_muldivk(hw_param_interval(params, rule->var), - (unsigned long) rule->private, - hw_param_interval(params, rule->deps[0]), - hw_param_interval(params, rule->deps[1])); + interval_t t; + interval_muldivk(hw_param_interval_c(params, rule->deps[0]), + hw_param_interval_c(params, rule->deps[1]), + (unsigned long) rule->private, &t); + return interval_refine(hw_param_interval(params, rule->var), &t); } int snd_pcm_hw_rule_mulkdiv(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) { - return interval_mulkdiv(hw_param_interval(params, rule->var), - (unsigned long) rule->private, - hw_param_interval(params, rule->deps[0]), - hw_param_interval(params, rule->deps[1])); + interval_t t; + interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]), + (unsigned long) rule->private, + hw_param_interval_c(params, rule->deps[1]), &t); + return interval_refine(hw_param_interval(params, rule->var), &t); } int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params, @@ -1346,12 +1617,12 @@ int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params, if (max < (unsigned)bits) max = bits; } - c = interval_refine_min(i, min); + c = interval_refine_min(i, min, 0); if (c < 0) return c; if (c) changed = 1; - c = interval_refine_max(i, max); + c = interval_refine_max(i, max, 0); if (c < 0) return c; if (c) @@ -1389,8 +1660,8 @@ static snd_pcm_hw_rule_t refine_rules[] = { { var: SND_PCM_HW_PARAM_FRAME_BITS, func: snd_pcm_hw_rule_mulkdiv, - deps: { SND_PCM_HW_PARAM_FRAGMENT_BYTES, - SND_PCM_HW_PARAM_FRAGMENT_SIZE, -1 }, + deps: { SND_PCM_HW_PARAM_PERIOD_BYTES, + SND_PCM_HW_PARAM_PERIOD_SIZE, -1 }, private: (void*) 8, }, { @@ -1410,50 +1681,50 @@ static snd_pcm_hw_rule_t refine_rules[] = { { var: SND_PCM_HW_PARAM_RATE, func: snd_pcm_hw_rule_mulkdiv, - deps: { SND_PCM_HW_PARAM_FRAGMENT_SIZE, - SND_PCM_HW_PARAM_FRAGMENT_LENGTH, -1 }, + deps: { SND_PCM_HW_PARAM_PERIOD_SIZE, + SND_PCM_HW_PARAM_PERIOD_TIME, -1 }, private: (void*) 1000000, }, { var: SND_PCM_HW_PARAM_RATE, func: snd_pcm_hw_rule_mulkdiv, deps: { SND_PCM_HW_PARAM_BUFFER_SIZE, - SND_PCM_HW_PARAM_BUFFER_LENGTH, -1 }, + SND_PCM_HW_PARAM_BUFFER_TIME, -1 }, private: (void*) 1000000, }, { - var: SND_PCM_HW_PARAM_FRAGMENTS, + var: SND_PCM_HW_PARAM_PERIODS, func: snd_pcm_hw_rule_div, deps: { SND_PCM_HW_PARAM_BUFFER_SIZE, - SND_PCM_HW_PARAM_FRAGMENT_SIZE, -1 }, + SND_PCM_HW_PARAM_PERIOD_SIZE, -1 }, private: 0, }, { - var: SND_PCM_HW_PARAM_FRAGMENT_SIZE, + var: SND_PCM_HW_PARAM_PERIOD_SIZE, func: snd_pcm_hw_rule_div, deps: { SND_PCM_HW_PARAM_BUFFER_SIZE, - SND_PCM_HW_PARAM_FRAGMENTS, -1 }, + SND_PCM_HW_PARAM_PERIODS, -1 }, private: 0, }, { - var: SND_PCM_HW_PARAM_FRAGMENT_SIZE, + var: SND_PCM_HW_PARAM_PERIOD_SIZE, func: snd_pcm_hw_rule_mulkdiv, - deps: { SND_PCM_HW_PARAM_FRAGMENT_BYTES, + deps: { SND_PCM_HW_PARAM_PERIOD_BYTES, SND_PCM_HW_PARAM_FRAME_BITS, -1 }, private: (void*) 8, }, { - var: SND_PCM_HW_PARAM_FRAGMENT_SIZE, + var: SND_PCM_HW_PARAM_PERIOD_SIZE, func: snd_pcm_hw_rule_muldivk, - deps: { SND_PCM_HW_PARAM_FRAGMENT_LENGTH, + deps: { SND_PCM_HW_PARAM_PERIOD_TIME, SND_PCM_HW_PARAM_RATE, -1 }, private: (void*) 1000000, }, { var: SND_PCM_HW_PARAM_BUFFER_SIZE, func: snd_pcm_hw_rule_mul, - deps: { SND_PCM_HW_PARAM_FRAGMENT_SIZE, - SND_PCM_HW_PARAM_FRAGMENTS, -1 }, + deps: { SND_PCM_HW_PARAM_PERIOD_SIZE, + SND_PCM_HW_PARAM_PERIODS, -1 }, private: 0, }, { @@ -1466,14 +1737,14 @@ static snd_pcm_hw_rule_t refine_rules[] = { { var: SND_PCM_HW_PARAM_BUFFER_SIZE, func: snd_pcm_hw_rule_muldivk, - deps: { SND_PCM_HW_PARAM_BUFFER_LENGTH, + deps: { SND_PCM_HW_PARAM_BUFFER_TIME, SND_PCM_HW_PARAM_RATE, -1 }, private: (void*) 1000000, }, { - var: SND_PCM_HW_PARAM_FRAGMENT_BYTES, + var: SND_PCM_HW_PARAM_PERIOD_BYTES, func: snd_pcm_hw_rule_muldivk, - deps: { SND_PCM_HW_PARAM_FRAGMENT_SIZE, + deps: { SND_PCM_HW_PARAM_PERIOD_SIZE, SND_PCM_HW_PARAM_FRAME_BITS, -1 }, private: (void*) 8, }, @@ -1485,14 +1756,14 @@ static snd_pcm_hw_rule_t refine_rules[] = { private: (void*) 8, }, { - var: SND_PCM_HW_PARAM_FRAGMENT_LENGTH, + var: SND_PCM_HW_PARAM_PERIOD_TIME, func: snd_pcm_hw_rule_mulkdiv, - deps: { SND_PCM_HW_PARAM_FRAGMENT_SIZE, + deps: { SND_PCM_HW_PARAM_PERIOD_SIZE, SND_PCM_HW_PARAM_RATE, -1 }, private: (void*) 1000000, }, { - var: SND_PCM_HW_PARAM_BUFFER_LENGTH, + var: SND_PCM_HW_PARAM_BUFFER_TIME, func: snd_pcm_hw_rule_mulkdiv, deps: { SND_PCM_HW_PARAM_BUFFER_SIZE, SND_PCM_HW_PARAM_RATE, -1 }, @@ -1515,49 +1786,53 @@ static mask_t refine_masks[SND_PCM_HW_PARAM_LAST_MASK - SND_PCM_HW_PARAM_FIRST_M }; 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] = { + [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, + openmin: 0, openmax: 0, integer: 1, empty: 0, }, - [SND_PCM_HW_PARAM_RATE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + [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, + openmin: 0, openmax: 0, integer: 1, empty: 0, }, - [SND_PCM_HW_PARAM_FRAGMENT_LENGTH - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + [SND_PCM_HW_PARAM_CHANNELS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { min: 1, max: UINT_MAX, - openmin: 0, openmax: 0, real: 0, empty: 0, + openmin: 0, openmax: 0, integer: 1, empty: 0, }, - [SND_PCM_HW_PARAM_FRAGMENT_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + [SND_PCM_HW_PARAM_RATE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { min: 1, max: UINT_MAX, - openmin: 0, openmax: 0, real: 0, empty: 0, + openmin: 0, openmax: 0, integer: 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_PERIOD_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 0, max: UINT_MAX, + openmin: 0, openmax: 0, integer: 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_PERIOD_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 0, max: UINT_MAX, + openmin: 0, openmax: 0, integer: 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_PERIOD_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 0, max: UINT_MAX, + openmin: 0, openmax: 0, integer: 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_PERIODS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 0, max: UINT_MAX, + openmin: 0, openmax: 0, integer: 0, empty: 0, }, - [SND_PCM_HW_PARAM_FRAME_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + [SND_PCM_HW_PARAM_BUFFER_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { min: 1, max: UINT_MAX, - openmin: 0, openmax: 0, real: 0, empty: 0, + openmin: 0, openmax: 0, integer: 0, empty: 0, }, - [SND_PCM_HW_PARAM_FRAGMENT_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + [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, + openmin: 0, openmax: 0, integer: 1, 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, + openmin: 0, openmax: 0, integer: 1, empty: 0, + }, + [SND_PCM_HW_PARAM_TICK_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = { + min: 0, max: UINT_MAX, + openmin: 0, openmax: 0, integer: 0, empty: 0, }, }; @@ -1573,7 +1848,7 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) 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)) + if (!(params->cmask & (1 << k))) continue; err = mask_refine(hw_param_mask(params, k), &refine_masks[k - SND_PCM_HW_PARAM_FIRST_MASK]); @@ -1582,7 +1857,7 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) } for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++) { - if (!params->appl_cmask & (1 << k)) + if (!(params->cmask & (1 << k))) continue; err = interval_refine(hw_param_interval(params, k), &refine_intervals[k - SND_PCM_HW_PARAM_FIRST_INTERVAL]); @@ -1593,9 +1868,8 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) for (k = 0; k < RULES; k++) rstamps[k] = 0; for (k = 0; k <= SND_PCM_HW_PARAM_LAST; k++) - vstamps[k] = (params->appl_cmask & (1 << k)) ? 1 : 0; - params->appl_cmask = 0; - params->hw_cmask = 0; + vstamps[k] = (params->cmask & (1 << k)) ? 1 : 0; + params->cmask = 0; changed = 1; while (changed) { changed = 0; @@ -1626,7 +1900,7 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) #endif rstamps[k] = stamp; if (err && r->var >= 0) { - params->hw_cmask |= 1 << r->var; + params->cmask |= 1 << r->var; vstamps[r->var] = stamp; changed = 1; } @@ -1651,111 +1925,66 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params) return 0; } -int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params, - snd_pcm_hw_params_t *sparams, - int (*func)(snd_pcm_t *slave, - snd_pcm_hw_params_t *sparams), - snd_pcm_t *slave, - unsigned int links) -{ - unsigned int k; - int err, error = 0; - unsigned int client_from_slave = ~0U; - unsigned int client_refine = ~0U; - unsigned int slave_from_client = ~0U; - unsigned int slave_refine = ~0U; - unsigned int hw_cmask = params->hw_cmask; - - while (client_from_slave || client_refine) { - for (k = 0; k <= SND_PCM_HW_PARAM_LAST; ++k) { - int changed; - if (!(links & (1 << k))) - continue; - if (!(client_from_slave & (1 << k))) - continue; - changed = _snd_pcm_hw_param_refine(params, 1, k, sparams); - if (changed) { - hw_cmask |= 1 << k; - slave_from_client |= 1 << k; - client_refine |= 1 << k; - } - if (changed < 0) - error = changed; - } - client_from_slave = 0; - if (error) - break; - if (client_refine) { - params->appl_cmask = client_refine; - client_refine = 0; - err = _snd_pcm_hw_refine(params); - hw_cmask |= params->hw_cmask; - slave_from_client |= params->hw_cmask; - if (err < 0) { - error = err; - break; - } - } - - for (k = 0; k <= SND_PCM_HW_PARAM_LAST; ++k) { - int changed; - if (!(links & (1 << k))) - continue; - if (!(slave_from_client & (1 << k))) - continue; - changed = _snd_pcm_hw_param_refine(sparams, 1, k, params); - if (changed) { - slave_refine |= 1 << k; - client_from_slave |= 1 << k; - } - if (changed < 0) - error = changed; - } - slave_from_client = 0; - if (error) - continue; - if (slave_refine) { - sparams->appl_cmask = slave_refine; - slave_refine = 0; - error = func(slave, sparams); - client_from_slave |= sparams->hw_cmask; - } - } - params->appl_cmask = 0; - params->hw_cmask = hw_cmask; - return error; -} - -int snd_pcm_hw_params2(snd_pcm_hw_params_t *params, - snd_pcm_hw_params_t *sparams, - int (*func)(snd_pcm_t *slave, - snd_pcm_hw_params_t *sparams), - snd_pcm_t *slave, - unsigned int links) +int snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params, + unsigned int vars, + const snd_pcm_hw_params_t *src) { + int changed, err = 0; unsigned int k; - int err; for (k = 0; k <= SND_PCM_HW_PARAM_LAST; ++k) { - int changed; - if (!(links & (1 << k))) + if (!(vars & (1 << k)) || + !((src->cmask & (1 << k)))) continue; - changed = _snd_pcm_hw_param_refine(sparams, 0, k, params); + changed = snd_pcm_hw_param_refine(params, k, src); if (changed < 0) - return changed; + err = changed; } - sparams->appl_cmask = ~0U; - err = func(slave, sparams); - if (err >= 0) - return err; + return err; +} - for (k = 0; k <= SND_PCM_HW_PARAM_LAST; ++k) { - int changed; - if (!(links & (1 << k))) - continue; - if (!(sparams->hw_cmask & (1 << k))) - continue; - changed = _snd_pcm_hw_param_refine(params, 1, k, sparams); +/* Accumulate to params->cmask */ +/* Reset sparams->cmask */ +int snd_pcm_generic_hw_link(snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *sparams, + snd_pcm_t *slave, + unsigned long links) +{ + int err1, err = 0; + err = snd_pcm_hw_params_refine(sparams, links, params); + if (err >= 0) { + unsigned int cmask = sparams->cmask; + err = snd_pcm_hw_refine(slave, sparams); + sparams->cmask |= cmask; + } + err1 = snd_pcm_hw_params_refine(params, links, sparams); + if (err1 < 0) + err = err1; + sparams->cmask = 0; + return err; +} + +int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *sparams, + int (*func)(snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *sparams, + snd_pcm_t *slave, + unsigned long private), + snd_pcm_t *slave, + unsigned long private) +{ + int err = 0; + unsigned int cmask = 0; + while (params->cmask) { + err = func(params, sparams, slave, private); + cmask |= params->cmask; + if (err < 0) + break; + err = _snd_pcm_hw_refine(params); + cmask |= params->cmask; + if (err < 0) + break; } + params->cmask = cmask; return err; } @@ -1764,10 +1993,10 @@ 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->period_step = pcm->period_step; + params->sleep_min = pcm->sleep_min; params->avail_min = pcm->avail_min; params->xfer_align = pcm->xfer_align; params->silence_threshold = pcm->silence_threshold; @@ -1781,31 +2010,31 @@ 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->xrun_mode = SND_PCM_XRUN_STOP; params->tstamp_mode = SND_PCM_TSTAMP_NONE; - params->avail_min = pcm->fragment_size; - params->xfer_align = pcm->fragment_size; + params->period_step = 1; + params->sleep_min = 0; + params->avail_min = pcm->period_size; + params->xfer_align = pcm->period_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) +int snd_pcm_sw_param_value(snd_pcm_sw_params_t *params, snd_pcm_sw_param_t 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_PERIOD_STEP: + return params->period_step; + case SND_PCM_SW_PARAM_SLEEP_MIN: + return params->sleep_min; case SND_PCM_SW_PARAM_AVAIL_MIN: return params->avail_min; case SND_PCM_SW_PARAM_XFER_ALIGN: @@ -1821,29 +2050,27 @@ int snd_pcm_sw_param_value(snd_pcm_sw_params_t *params, unsigned int var) } int snd_pcm_sw_param_set(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_sw_param_t 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_PERIOD_STEP: + params->period_step = val; + break; + case SND_PCM_SW_PARAM_SLEEP_MIN: + params->sleep_min = val; + break; case SND_PCM_SW_PARAM_AVAIL_MIN: assert(val > 0); params->avail_min = val; @@ -1868,25 +2095,17 @@ int snd_pcm_sw_param_set(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, } int snd_pcm_sw_param_near(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, - unsigned int var, unsigned int val) + snd_pcm_sw_param_t 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; @@ -1896,9 +2115,15 @@ int snd_pcm_sw_param_near(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, val = pcm->min_align; params->avail_min = val; break; + case SND_PCM_SW_PARAM_PERIOD_STEP: + params->period_step = val; + break; + case SND_PCM_SW_PARAM_SLEEP_MIN: + params->sleep_min = val; + break; case SND_PCM_SW_PARAM_XFER_ALIGN: { - size_t r = val % pcm->min_align; + snd_pcm_uframes_t r = val % pcm->min_align; if (r >= (pcm->min_align + 1) / 2) val += pcm->min_align - r; else @@ -1926,24 +2151,24 @@ int snd_pcm_sw_param_near(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, } void snd_pcm_sw_param_dump(const snd_pcm_sw_params_t *params, - unsigned int var, FILE *fp) + snd_pcm_sw_param_t 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_PERIOD_STEP: + fprintf(fp, "%d", params->period_step); + break; + case SND_PCM_SW_PARAM_SLEEP_MIN: + fprintf(fp, "%d", params->sleep_min); + break; case SND_PCM_SW_PARAM_AVAIL_MIN: fprintf(fp, "%ld", (long) params->avail_min); break; @@ -1975,12 +2200,8 @@ int snd_pcm_sw_params_dump(snd_pcm_sw_params_t *params, FILE *fp) 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; + return pcm->ops->hw_refine(pcm->op_arg, params); } /* Install one of the configurations present in configuration @@ -1991,8 +2212,8 @@ int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) first subformat min channels min rate - min fragment_size - max fragments + min period_size + max periods 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) @@ -2014,13 +2235,15 @@ int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) 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->access = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_ACCESS, 0); + pcm->format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0); + pcm->subformat = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_SUBFORMAT, 0); + pcm->channels = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS, 0); + pcm->rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE, 0); + pcm->period_time = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_PERIOD_TIME, 0); + pcm->period_size = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_PERIOD_SIZE, 0); + pcm->buffer_size = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_BUFFER_SIZE, 0); + pcm->tick_time = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_TICK_TIME, 0); 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; @@ -2030,7 +2253,6 @@ int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) min_align *= 2; } pcm->min_align = min_align; - pcm->buffer_size = pcm->fragment_size * pcm->fragments; pcm->info = params->info; pcm->msbits = params->msbits; @@ -2066,10 +2288,10 @@ int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *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->period_step = params->period_step; + pcm->sleep_min = params->sleep_min; pcm->avail_min = params->avail_min; pcm->xfer_align = params->xfer_align; pcm->silence_threshold = params->silence_threshold; diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 5255493d..9f7ba854 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -21,7 +21,7 @@ #include "pcm_local.h" #include "pcm_plugin.h" - +#include "interval.h" typedef struct { snd_pcm_t *req_slave; @@ -191,82 +191,37 @@ static int snd_pcm_plug_slave_format(int format, const mask_t *format_mask) (1 << SND_PCM_FORMAT_A_LAW) | \ (1 << SND_PCM_FORMAT_IMA_ADPCM)) -static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, - snd_pcm_hw_params_t *sparams) + +/* Accumulate to params->cmask */ +/* Reset sparams->cmask */ +static int snd_pcm_plug_hw_link(snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *sparams, + snd_pcm_t *slave, + unsigned long private ATTRIBUTE_UNUSED) { - snd_pcm_plug_t *plug = pcm->private; - snd_pcm_t *slave = plug->req_slave; - int err; + int rate_always, channels_always, format_always, access_always; + int rate_never, channels_never, format_never, access_never; + unsigned int links = (SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); const mask_t *format_mask, *sformat_mask; - unsigned int rate_min, rate_max, srate_min, srate_max; - unsigned int channels_min, channels_max, schannels_min, schannels_max; + mask_t *fmt_mask = alloca(mask_sizeof()); + mask_t *sfmt_mask = alloca(mask_sizeof()); + mask_t *access_mask = alloca(mask_sizeof()); + int err; unsigned int format; - int same_rate, same_channels, same_format; - snd_pcm_hw_params_t tmp; - unsigned int links = (SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); - mask_t *tmp_mask = alloca(mask_sizeof()); - mask_t *accplug_mask = alloca(mask_sizeof()); - mask_t *mmap_mask = alloca(mask_sizeof()); - mask_t *fmtplug_mask = alloca(mask_sizeof()); - mask_load(accplug_mask, SND_PCM_ACCBIT_PLUGIN); - mask_load(mmap_mask, SND_PCM_ACCBIT_MMAP); - mask_load(fmtplug_mask, SND_PCM_FMTBIT_PLUG); - - err = _snd_pcm_hw_param_min(params, 1, SND_PCM_HW_PARAM_CHANNELS, 1); - if (err < 0) - return err; - err = _snd_pcm_hw_param_min(params, 1, SND_PCM_HW_PARAM_RATE, RATE_MIN); - if (err < 0) - return err; - 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); - err = snd_pcm_hw_refine2(params, sparams, - snd_pcm_hw_refine, slave, links); - if (err < 0) - return err; - - 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_param_near(slave, &tmp, - SND_PCM_HW_PARAM_RATE, rate_min); - if (srate_min < rate_max) { - tmp = *sparams; - 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_param_minmax(slave, sparams, - SND_PCM_HW_PARAM_RATE, - srate_min, srate_max); - assert(err >= 0); - - 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_param_near(slave, &tmp, - SND_PCM_HW_PARAM_CHANNELS, channels_min); - if (schannels_min < channels_max) { - tmp = *sparams; - 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_param_minmax(slave, sparams, - SND_PCM_HW_PARAM_CHANNELS, - schannels_min, schannels_max); - assert(err >= 0); - + unsigned int scmask = sparams->cmask; + snd_pcm_hw_param_near_copy(slave, sparams, SND_PCM_HW_PARAM_RATE, + params); + scmask |= sparams->cmask; + snd_pcm_hw_param_near_copy(slave, sparams, SND_PCM_HW_PARAM_CHANNELS, + params); + scmask |= sparams->cmask; format_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_FORMAT); sformat_mask = snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_FORMAT); - mask_none(tmp_mask); + mask_none(sfmt_mask); + mask_none(fmt_mask); for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) { int f; if (!mask_test(format_mask, format)) @@ -275,80 +230,134 @@ static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, f = format; else { f = snd_pcm_plug_slave_format(format, sformat_mask); - if (f < 0) { - mask_t *m = alloca(mask_sizeof()); - mask_all(m); - mask_reset(m, format); - err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, m); - if (err < 0) - return err; + if (f < 0) continue; - } } - mask_set(tmp_mask, f); + mask_set(sfmt_mask, f); + mask_set(fmt_mask, format); } - err = _snd_pcm_hw_param_mask(sparams, 0, - SND_PCM_HW_PARAM_FORMAT, tmp_mask); + err = _snd_pcm_hw_param_mask(params, + SND_PCM_HW_PARAM_FORMAT, fmt_mask); + if (err < 0) + return err; + err = _snd_pcm_hw_param_mask(sparams, + SND_PCM_HW_PARAM_FORMAT, sfmt_mask); assert(err >= 0); - sformat_mask = snd_pcm_hw_param_value_mask(sparams, - SND_PCM_HW_PARAM_FORMAT); - same_rate = (rate_min == rate_max && - rate_min == srate_min && - rate_min == srate_max); - if (same_rate) + format_always = snd_pcm_hw_param_always_eq(params, + SND_PCM_HW_PARAM_FORMAT, + sparams); + format_never = (!format_always && + snd_pcm_hw_param_never_eq(params, + SND_PCM_HW_PARAM_FORMAT, + sparams)); + + channels_always = snd_pcm_hw_param_always_eq(params, + SND_PCM_HW_PARAM_CHANNELS, + sparams); + channels_never = (!channels_always && + snd_pcm_hw_param_never_eq(params, + SND_PCM_HW_PARAM_CHANNELS, + sparams)); + + rate_always = snd_pcm_hw_param_always_eq(params, + SND_PCM_HW_PARAM_RATE, + sparams); + rate_never = (!rate_always && + snd_pcm_hw_param_never_eq(params, + SND_PCM_HW_PARAM_RATE, + sparams)); + access_always = snd_pcm_hw_param_always_eq(params, + SND_PCM_HW_PARAM_ACCESS, + sparams); + access_never = (!access_always && + snd_pcm_hw_param_never_eq(params, + SND_PCM_HW_PARAM_ACCESS, + sparams)); + + if (rate_always) links |= (SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_BUFFER_TIME | SND_PCM_HW_PARBIT_BUFFER_SIZE); - same_channels = (channels_min == channels_max && - channels_min == schannels_min && - channels_min == schannels_max); - if (same_channels) + else { + interval_t t; + const interval_t *sbuffer_size, *buffer_size; + const interval_t *srate, *rate; + buffer_size = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_BUFFER_SIZE); + sbuffer_size = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_BUFFER_SIZE); + rate = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_RATE); + srate = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_RATE); + interval_muldiv(sbuffer_size, rate, srate, &t); + interval_round(&t); + err = _snd_pcm_hw_param_refine_interval(params, SND_PCM_HW_PARAM_BUFFER_SIZE, &t); + if (err < 0) + return err; + interval_muldiv(buffer_size, srate, rate, &t); + interval_round(&t); + err = _snd_pcm_hw_param_refine_interval(sparams, SND_PCM_HW_PARAM_BUFFER_SIZE, &t); + assert(err >= 0); + scmask |= sparams->cmask; + } + if (channels_always) links |= SND_PCM_HW_PARBIT_CHANNELS; - same_format = (mask_single(format_mask) && - mask_eq(format_mask, sformat_mask)); - if (same_format) { + if (format_always) { links |= (SND_PCM_HW_PARBIT_FORMAT | SND_PCM_HW_PARBIT_SUBFORMAT | SND_PCM_HW_PARBIT_SAMPLE_BITS); - if (same_channels) { + if (channels_always) { links |= SND_PCM_HW_PARBIT_FRAME_BITS; - if (same_rate) - links |= (SND_PCM_HW_PARBIT_FRAGMENT_BYTES | + if (rate_always) + links |= (SND_PCM_HW_PARBIT_PERIOD_BYTES | SND_PCM_HW_PARBIT_BUFFER_BYTES); } } - if (same_rate && same_channels && same_format) { - 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_param_mask(sparams, 0, - SND_PCM_HW_PARAM_ACCESS, - access_mask); - else - _snd_pcm_hw_param_mask(sparams, 0, SND_PCM_HW_PARAM_ACCESS, - mmap_mask); - } else { - err = _snd_pcm_hw_param_mask(params, 1, - SND_PCM_HW_PARAM_ACCESS, - accplug_mask); - if (err < 0) - return err; - err = _snd_pcm_hw_param_mask(params, 1, - SND_PCM_HW_PARAM_FORMAT, - fmtplug_mask); - if (err < 0) - return err; - _snd_pcm_hw_param_mask(sparams, 0, SND_PCM_HW_PARAM_ACCESS, - mmap_mask); - _snd_pcm_hw_param_mask(sparams, 0, SND_PCM_HW_PARAM_FORMAT, - fmtplug_mask); - } + mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN); + if (format_never || channels_never || rate_never) { + mask_t *mmap_mask = alloca(mask_sizeof()); + mask_load(mmap_mask, SND_PCM_ACCBIT_MMAP); + _snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS, + mmap_mask); + } else + mask_union(access_mask, snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_ACCESS)); + _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS, + access_mask); + sparams->cmask |= scmask; + return snd_pcm_generic_hw_link(params, sparams, slave, links); +} + +static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *sparams) +{ + snd_pcm_plug_t *plug = pcm->private; + snd_pcm_t *slave = plug->req_slave; + unsigned int cmask, lcmask; + int err; + + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_min(params, SND_PCM_HW_PARAM_CHANNELS, 1, 0); + if (err < 0) + return err; + err = _snd_pcm_hw_param_max(params, SND_PCM_HW_PARAM_CHANNELS, 1024, 0); + if (err < 0) + return err; + err = _snd_pcm_hw_param_min(params, SND_PCM_HW_PARAM_RATE, RATE_MIN, 0); + if (err < 0) + return err; + err = _snd_pcm_hw_param_max(params, SND_PCM_HW_PARAM_RATE, RATE_MAX, 0); + if (err < 0) + return err; + lcmask = params->cmask; + params->cmask |= cmask; + + _snd_pcm_hw_params_any(sparams); err = snd_pcm_hw_refine2(params, sparams, - snd_pcm_hw_refine, slave, links); + snd_pcm_plug_hw_link, slave, 0); + params->cmask |= lcmask; if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); @@ -360,7 +369,19 @@ static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, static int snd_pcm_plug_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) { snd_pcm_hw_params_t sparams; - return snd_pcm_plug_hw_refine1(pcm, params, &sparams); + int err; +#if 0 + fprintf(stderr, "Enter: client =\n"); + snd_pcm_hw_params_dump(params, stderr); +#endif + err = snd_pcm_plug_hw_refine1(pcm, params, &sparams); +#if 0 + fprintf(stderr, "Exit: client =\n"); + snd_pcm_hw_params_dump(params, stderr); + fprintf(stderr, "Exit: slave =\n"); + snd_pcm_hw_params_dump(&sparams, stderr); +#endif + return err; } static void snd_pcm_plug_clear(snd_pcm_t *pcm) @@ -584,15 +605,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_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); + clt_params.access = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_ACCESS, 0); + clt_params.format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0); + clt_params.channels = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS, 0); + clt_params.rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE, 0); - 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); + slv_params.access = snd_pcm_hw_param_first(slave, &sparams, SND_PCM_HW_PARAM_ACCESS, 0); + slv_params.format = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_FORMAT, 0); + slv_params.channels = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_CHANNELS, 0); + slv_params.rate = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_RATE, 0); snd_pcm_plug_clear(pcm); err = snd_pcm_plug_insert_plugins(pcm, &clt_params, &slv_params); @@ -612,7 +633,7 @@ 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_align, silence_threshold, silence_size; + snd_pcm_uframes_t avail_min, xfer_align, silence_threshold, silence_size; int err; avail_min = params->avail_min; xfer_align = params->xfer_align; diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index 8fa3ccad..f98d08f7 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -88,10 +88,10 @@ int snd_pcm_plugin_state(snd_pcm_t *pcm) return snd_pcm_state(plugin->slave); } -int snd_pcm_plugin_delay(snd_pcm_t *pcm, ssize_t *delayp) +int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { snd_pcm_plugin_t *plugin = pcm->private; - ssize_t sd; + snd_pcm_sframes_t sd; int err = snd_pcm_delay(plugin->slave, &sd); if (err < 0) return err; @@ -157,18 +157,18 @@ int snd_pcm_plugin_pause(snd_pcm_t *pcm, int enable) return snd_pcm_pause(plugin->slave, enable); } -ssize_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, size_t frames) +snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_plugin_t *plugin = pcm->private; - ssize_t n = snd_pcm_mmap_hw_avail(pcm); + snd_pcm_sframes_t n = snd_pcm_mmap_hw_avail(pcm); assert(n >= 0); if (n > 0) { - if ((size_t)n > frames) + if ((snd_pcm_uframes_t)n > frames) n = frames; frames -= n; } if (frames > 0) { - ssize_t err; + snd_pcm_sframes_t err; /* FIXME: rate plugin */ if (plugin->slave_frames) frames = plugin->slave_frames(pcm, frames); @@ -188,11 +188,11 @@ ssize_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, size_t frames) return n; } -ssize_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, size_t size) +snd_pcm_sframes_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { snd_pcm_plugin_t *plugin = pcm->private; snd_pcm_channel_area_t areas[pcm->channels]; - ssize_t frames; + snd_pcm_sframes_t frames; snd_pcm_areas_from_buf(pcm, areas, (void*)buffer); frames = snd_pcm_write_areas(pcm, areas, 0, size, plugin->write); if (frames > 0) @@ -200,11 +200,11 @@ ssize_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, size_t size) return frames; } -ssize_t snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, size_t size) +snd_pcm_sframes_t snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { snd_pcm_plugin_t *plugin = pcm->private; snd_pcm_channel_area_t areas[pcm->channels]; - ssize_t frames; + snd_pcm_sframes_t frames; snd_pcm_areas_from_bufs(pcm, areas, bufs); frames = snd_pcm_write_areas(pcm, areas, 0, size, plugin->write); if (frames > 0) @@ -212,11 +212,11 @@ ssize_t snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, size_t size) return frames; } -ssize_t snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, size_t size) +snd_pcm_sframes_t snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) { snd_pcm_plugin_t *plugin = pcm->private; snd_pcm_channel_area_t areas[pcm->channels]; - ssize_t frames; + snd_pcm_sframes_t frames; snd_pcm_areas_from_buf(pcm, areas, buffer); frames = snd_pcm_read_areas(pcm, areas, 0, size, plugin->read); if (frames > 0) @@ -224,11 +224,11 @@ ssize_t snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, size_t size) return frames; } -ssize_t snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, size_t size) +snd_pcm_sframes_t snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { snd_pcm_plugin_t *plugin = pcm->private; snd_pcm_channel_area_t areas[pcm->channels]; - ssize_t frames; + snd_pcm_sframes_t frames; snd_pcm_areas_from_bufs(pcm, areas, bufs); frames = snd_pcm_read_areas(pcm, areas, 0, size, plugin->read); if (frames > 0) @@ -236,14 +236,14 @@ ssize_t snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, size_t size) return frames; } -ssize_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, size_t client_size) +snd_pcm_sframes_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t client_size) { snd_pcm_plugin_t *plugin = pcm->private; snd_pcm_t *slave = plugin->slave; - size_t client_xfer = 0; - size_t slave_xfer = 0; - ssize_t err = 0; - ssize_t slave_size; + snd_pcm_uframes_t client_xfer = 0; + snd_pcm_uframes_t slave_xfer = 0; + snd_pcm_sframes_t err = 0; + snd_pcm_sframes_t slave_size; if (pcm->stream == SND_PCM_STREAM_CAPTURE) { snd_pcm_mmap_appl_forward(pcm, client_size); // snd_pcm_plugin_avail_update(pcm); @@ -253,11 +253,11 @@ ssize_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, size_t client_size) if (slave_size <= 0) return slave_size; while (client_xfer < client_size && - slave_xfer < (size_t)slave_size) { - size_t slave_frames = slave_size - slave_xfer; - size_t client_frames = client_size - client_xfer; - size_t offset = snd_pcm_mmap_hw_offset(pcm); - size_t cont = pcm->buffer_size - offset; + slave_xfer < (snd_pcm_uframes_t)slave_size) { + snd_pcm_uframes_t slave_frames = slave_size - slave_xfer; + snd_pcm_uframes_t client_frames = client_size - client_xfer; + snd_pcm_uframes_t offset = snd_pcm_mmap_hw_offset(pcm); + snd_pcm_uframes_t cont = pcm->buffer_size - offset; if (cont < client_frames) client_frames = cont; err = plugin->write(pcm, pcm->running_areas, offset, @@ -273,15 +273,15 @@ ssize_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, size_t client_size) return err; } -ssize_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) +snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) { snd_pcm_plugin_t *plugin = pcm->private; snd_pcm_t *slave = plugin->slave; - size_t client_xfer; - size_t slave_xfer = 0; - ssize_t err = 0; - size_t client_size; - ssize_t slave_size = snd_pcm_avail_update(slave); + snd_pcm_uframes_t client_xfer; + snd_pcm_uframes_t slave_xfer = 0; + snd_pcm_sframes_t err = 0; + snd_pcm_uframes_t client_size; + snd_pcm_sframes_t slave_size = snd_pcm_avail_update(slave); if (slave_size <= 0) return slave_size; if (pcm->stream == SND_PCM_STREAM_PLAYBACK || @@ -291,12 +291,12 @@ ssize_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) plugin->client_frames(pcm, slave_size) : slave_size; client_xfer = snd_pcm_mmap_capture_avail(pcm); client_size = pcm->buffer_size; - while (slave_xfer < (size_t)slave_size && + while (slave_xfer < (snd_pcm_uframes_t)slave_size && client_xfer < client_size) { - size_t slave_frames = slave_size - slave_xfer; - size_t client_frames = client_size - client_xfer; - size_t offset = snd_pcm_mmap_hw_offset(pcm); - size_t cont = pcm->buffer_size - offset; + snd_pcm_uframes_t slave_frames = slave_size - slave_xfer; + snd_pcm_uframes_t client_frames = client_size - client_xfer; + snd_pcm_uframes_t offset = snd_pcm_mmap_hw_offset(pcm); + snd_pcm_uframes_t cont = pcm->buffer_size - offset; if (cont < client_frames) client_frames = cont; err = plugin->read(pcm, pcm->running_areas, offset, diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h index 06d14cc0..ef723353 100644 --- a/src/pcm/pcm_plugin.h +++ b/src/pcm/pcm_plugin.h @@ -24,11 +24,11 @@ typedef struct { int close_slave; 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); + snd_pcm_sframes_t (*client_frames)(snd_pcm_t *pcm, snd_pcm_sframes_t frames); + snd_pcm_sframes_t (*slave_frames)(snd_pcm_t *pcm, snd_pcm_sframes_t frames); int (*init)(snd_pcm_t *pcm); int shmid; - size_t appl_ptr, hw_ptr; + snd_pcm_uframes_t appl_ptr, hw_ptr; } snd_pcm_plugin_t; int snd_pcm_plugin_close(snd_pcm_t *pcm); @@ -41,19 +41,19 @@ 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); int snd_pcm_plugin_state(snd_pcm_t *pcm); -int snd_pcm_plugin_delay(snd_pcm_t *pcm, ssize_t *delayp); +int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); int snd_pcm_plugin_prepare(snd_pcm_t *pcm); int snd_pcm_plugin_start(snd_pcm_t *pcm); int snd_pcm_plugin_drop(snd_pcm_t *pcm); int snd_pcm_plugin_drain(snd_pcm_t *pcm); int snd_pcm_plugin_pause(snd_pcm_t *pcm, int enable); -ssize_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, size_t frames); -ssize_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, size_t size); -ssize_t snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, size_t size); -ssize_t snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, size_t size); -ssize_t snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, size_t size); -ssize_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, size_t size); -ssize_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm); +snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames); +snd_pcm_sframes_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size); +snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm); int snd_pcm_plugin_mmap_status(snd_pcm_t *pcm); int snd_pcm_plugin_mmap_control(snd_pcm_t *pcm); int snd_pcm_plugin_mmap(snd_pcm_t *pcm); diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 9f616ea1..351d853f 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -32,11 +32,11 @@ typedef struct { unsigned int pos; } rate_state_t; -typedef size_t (*rate_f)(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, size_t src_frames, +typedef snd_pcm_uframes_t (*rate_f)(const snd_pcm_channel_area_t *src_areas, + snd_pcm_uframes_t src_offset, snd_pcm_uframes_t src_frames, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, size_t *dst_framesp, - size_t channels, + snd_pcm_uframes_t dst_offset, snd_pcm_uframes_t *dst_framesp, + unsigned int channels, int getidx, int putidx, unsigned int arg, rate_state_t *states); @@ -53,11 +53,11 @@ typedef struct { rate_state_t *states; } snd_pcm_rate_t; -static size_t resample_expand(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, size_t src_frames, +static snd_pcm_uframes_t resample_expand(const snd_pcm_channel_area_t *src_areas, + snd_pcm_uframes_t src_offset, snd_pcm_uframes_t src_frames, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, size_t *dst_framesp, - size_t channels, + snd_pcm_uframes_t dst_offset, snd_pcm_uframes_t *dst_framesp, + unsigned int channels, int getidx, int putidx, unsigned int get_threshold, rate_state_t *states) @@ -70,9 +70,9 @@ static size_t resample_expand(const snd_pcm_channel_area_t *src_areas, void *get = get16_labels[getidx]; void *put = put16_labels[putidx]; unsigned int channel; - size_t src_frames1 = 0; - size_t dst_frames1 = 0; - size_t dst_frames = *dst_framesp; + snd_pcm_uframes_t src_frames1 = 0; + snd_pcm_uframes_t dst_frames1 = 0; + snd_pcm_uframes_t dst_frames = *dst_framesp; int16_t sample = 0; if (src_frames == 0 || @@ -135,11 +135,11 @@ static size_t resample_expand(const snd_pcm_channel_area_t *src_areas, return src_frames1; } -static size_t resample_shrink(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, size_t src_frames, +static snd_pcm_uframes_t resample_shrink(const snd_pcm_channel_area_t *src_areas, + snd_pcm_uframes_t src_offset, snd_pcm_uframes_t src_frames, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, size_t *dst_framesp, - size_t channels, + snd_pcm_uframes_t dst_offset, snd_pcm_uframes_t *dst_framesp, + unsigned int channels, int getidx, int putidx, unsigned int get_increment, rate_state_t *states) @@ -152,9 +152,9 @@ static size_t resample_shrink(const snd_pcm_channel_area_t *src_areas, void *get = get16_labels[getidx]; void *put = put16_labels[putidx]; unsigned int channel; - size_t src_frames1 = 0; - size_t dst_frames1 = 0; - size_t dst_frames = *dst_framesp; + snd_pcm_uframes_t src_frames1 = 0; + snd_pcm_uframes_t dst_frames1 = 0; + snd_pcm_uframes_t dst_frames = *dst_framesp; int16_t sample = 0; if (src_frames == 0 || @@ -238,52 +238,60 @@ static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_rate_t *rate = pcm->private; snd_pcm_t *slave = rate->plug.slave; int err; + unsigned int cmask, lcmask; snd_pcm_hw_params_t sparams; unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); mask_t *access_mask = alloca(mask_sizeof()); mask_t *format_mask = alloca(mask_sizeof()); mask_t *saccess_mask = alloca(mask_sizeof()); 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_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; - err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; - err = _snd_pcm_hw_param_min(params, 1, - SND_PCM_HW_PARAM_RATE, RATE_MIN); + err = _snd_pcm_hw_param_min(params, + SND_PCM_HW_PARAM_RATE, RATE_MIN, 0); if (err < 0) return err; - err = _snd_pcm_hw_param_max(params, 1, - SND_PCM_HW_PARAM_RATE, RATE_MAX); + err = _snd_pcm_hw_param_max(params, + SND_PCM_HW_PARAM_RATE, RATE_MAX, 0); if (err < 0) return err; + lcmask = params->cmask; + params->cmask |= cmask; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); + snd_pcm_hw_param_near_copy(slave, &sparams, + SND_PCM_HW_PARAM_BUFFER_TIME, + params); if (rate->sformat >= 0) { - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - rate->sformat); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + rate->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); } 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_param_set(&sparams, 0, SND_PCM_HW_PARAM_RATE, - rate->srate); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_RATE, + rate->srate, 0); err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave, links); + snd_pcm_generic_hw_link, slave, links); + params->cmask |= lcmask; if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); @@ -297,45 +305,55 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) int err; snd_pcm_hw_params_t sparams; unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); unsigned int src_format, dst_format; unsigned int src_rate, dst_rate; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); if (rate->sformat >= 0) { - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - rate->sformat); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + rate->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); } 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_param_set(&sparams, 0, SND_PCM_HW_PARAM_RATE, - rate->srate); + + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_RATE, + rate->srate, 0); + + snd_pcm_hw_param_near_copy(slave, &sparams, + SND_PCM_HW_PARAM_BUFFER_TIME, + params); - err = snd_pcm_hw_params2(params, &sparams, - snd_pcm_hw_params, slave, links); + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); if (err < 0) 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_param_value(params, SND_PCM_HW_PARAM_FORMAT); + src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0); dst_format = slave->format; - src_rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE); + src_rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE, 0); dst_rate = slave->rate; } else { src_format = slave->format; - dst_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT); + dst_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0); src_rate = slave->rate; - dst_rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE); + dst_rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE, 0); } rate->get_idx = get_index(src_format, SND_PCM_FORMAT_S16); rate->put_idx = put_index(SND_PCM_FORMAT_S16, dst_format); @@ -349,7 +367,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_param_value(params, SND_PCM_HW_PARAM_CHANNELS) * sizeof(*rate->states)); + rate->states = malloc(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS, 0) * sizeof(*rate->states)); return 0; } @@ -357,7 +375,7 @@ 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_align, silence_threshold, silence_size; + snd_pcm_uframes_t avail_min, xfer_align, silence_threshold, silence_size; int err; avail_min = params->avail_min; xfer_align = params->xfer_align; @@ -393,18 +411,18 @@ static int snd_pcm_rate_init(snd_pcm_t *pcm) return 0; } -static ssize_t snd_pcm_rate_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_rate_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t client_offset, - size_t client_size, - size_t *slave_sizep) + snd_pcm_uframes_t client_offset, + snd_pcm_uframes_t client_size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_rate_t *rate = pcm->private; snd_pcm_t *slave = rate->plug.slave; - size_t client_xfer = 0; - size_t slave_xfer = 0; - ssize_t err = 0; - size_t slave_size; + snd_pcm_uframes_t client_xfer = 0; + snd_pcm_uframes_t slave_xfer = 0; + snd_pcm_sframes_t err = 0; + snd_pcm_uframes_t slave_size; if (slave_sizep) slave_size = *slave_sizep; else @@ -412,7 +430,7 @@ static ssize_t snd_pcm_rate_write_areas(snd_pcm_t *pcm, assert(client_size > 0 && slave_size > 0); while (client_xfer < client_size && slave_xfer < slave_size) { - size_t src_frames, dst_frames; + snd_pcm_uframes_t src_frames, dst_frames; src_frames = client_size - client_xfer; dst_frames = snd_pcm_mmap_playback_xfer(slave, slave_size - slave_xfer); src_frames = rate->func(areas, client_offset, src_frames, @@ -426,7 +444,7 @@ static ssize_t snd_pcm_rate_write_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, dst_frames); if (err < 0) break; - assert((size_t)err == dst_frames); + assert((snd_pcm_uframes_t)err == dst_frames); slave_xfer += dst_frames; } @@ -444,19 +462,19 @@ static ssize_t snd_pcm_rate_write_areas(snd_pcm_t *pcm, return err; } -static ssize_t snd_pcm_rate_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_rate_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t client_offset, - size_t client_size, - size_t *slave_sizep) + snd_pcm_uframes_t client_offset, + snd_pcm_uframes_t client_size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_rate_t *rate = pcm->private; snd_pcm_t *slave = rate->plug.slave; - size_t client_xfer = 0; - size_t slave_xfer = 0; - ssize_t err = 0; - size_t slave_size; + snd_pcm_uframes_t client_xfer = 0; + snd_pcm_uframes_t slave_xfer = 0; + snd_pcm_sframes_t err = 0; + snd_pcm_uframes_t slave_size; if (slave_sizep) slave_size = *slave_sizep; else @@ -464,7 +482,7 @@ static ssize_t snd_pcm_rate_read_areas(snd_pcm_t *pcm, assert(client_size > 0 && slave_size > 0); while (client_xfer < client_size && slave_xfer < slave_size) { - size_t src_frames, dst_frames; + snd_pcm_uframes_t src_frames, dst_frames; dst_frames = client_size - client_xfer; src_frames = snd_pcm_mmap_capture_xfer(slave, slave_size - slave_xfer); src_frames = rate->func(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), @@ -478,7 +496,7 @@ static ssize_t snd_pcm_rate_read_areas(snd_pcm_t *pcm, err = snd_pcm_mmap_forward(slave, src_frames); if (err < 0) break; - assert((size_t)err == src_frames); + assert((snd_pcm_uframes_t)err == src_frames); slave_xfer += src_frames; } if (dst_frames > 0) { @@ -495,7 +513,7 @@ static ssize_t snd_pcm_rate_read_areas(snd_pcm_t *pcm, return err; } -ssize_t snd_pcm_rate_client_frames(snd_pcm_t *pcm, ssize_t frames) +snd_pcm_sframes_t snd_pcm_rate_client_frames(snd_pcm_t *pcm, snd_pcm_sframes_t frames) { snd_pcm_rate_t *rate = pcm->private; /* Round toward zero */ @@ -505,7 +523,7 @@ 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_sframes_t snd_pcm_rate_slave_frames(snd_pcm_t *pcm, snd_pcm_sframes_t frames) { snd_pcm_rate_t *rate = pcm->private; /* Round toward zero */ diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c index 15b7eb30..c9125cb4 100644 --- a/src/pcm/pcm_route.c +++ b/src/pcm/pcm_route.c @@ -50,16 +50,16 @@ typedef struct { int conv_idx; int src_size; int dst_sfmt; - size_t ndsts; + unsigned int ndsts; ttable_dst_t *dsts; } route_params_t; typedef void (*route_f)(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_area, - size_t dst_offset, - size_t frames, + snd_pcm_uframes_t dst_offset, + snd_pcm_uframes_t frames, const ttable_dst_t *ttable, const route_params_t *params); @@ -88,10 +88,10 @@ typedef struct { static void route1_zero(const snd_pcm_channel_area_t *src_areas ATTRIBUTE_UNUSED, - size_t src_offset ATTRIBUTE_UNUSED, + snd_pcm_uframes_t src_offset ATTRIBUTE_UNUSED, const snd_pcm_channel_area_t *dst_area, - size_t dst_offset, - size_t frames, + snd_pcm_uframes_t dst_offset, + snd_pcm_uframes_t frames, const ttable_dst_t* ttable ATTRIBUTE_UNUSED, const route_params_t *params) { @@ -105,10 +105,10 @@ static void route1_zero(const snd_pcm_channel_area_t *src_areas ATTRIBUTE_UNUSED } static void route1_one(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_area, - size_t dst_offset, - size_t frames, + snd_pcm_uframes_t dst_offset, + snd_pcm_uframes_t frames, const ttable_dst_t* ttable, const route_params_t *params) { @@ -150,10 +150,10 @@ static void route1_one(const snd_pcm_channel_area_t *src_areas, } static void route1_many(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_area, - size_t dst_offset, - size_t frames, + snd_pcm_uframes_t dst_offset, + snd_pcm_uframes_t frames, const ttable_dst_t* ttable, const route_params_t *params) { @@ -383,14 +383,14 @@ static void route1_many(const snd_pcm_channel_area_t *src_areas, } static void route_transfer(const snd_pcm_channel_area_t *src_areas, - size_t src_offset, + snd_pcm_uframes_t src_offset, const snd_pcm_channel_area_t *dst_areas, - size_t dst_offset, - size_t dst_channels, - size_t frames, + snd_pcm_uframes_t dst_offset, + snd_pcm_uframes_t dst_channels, + snd_pcm_uframes_t frames, route_params_t *params) { - size_t dst_channel; + unsigned int dst_channel; ttable_dst_t *dstp; const snd_pcm_channel_area_t *dst_area; @@ -411,7 +411,7 @@ static int snd_pcm_route_close(snd_pcm_t *pcm) snd_pcm_route_t *route = pcm->private; route_params_t *params = &route->params; int err = 0; - size_t dst_channel; + unsigned int dst_channel; if (route->plug.close_slave) err = snd_pcm_close(route->plug.slave); if (params->dsts) { @@ -430,56 +430,63 @@ static int snd_pcm_route_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_route_t *route = pcm->private; snd_pcm_t *slave = route->plug.slave; int err; + unsigned int cmask, lcmask; snd_pcm_hw_params_t sparams; unsigned int links = (SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_PERIOD_TIME | SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); mask_t *access_mask = alloca(mask_sizeof()); mask_t *format_mask = alloca(mask_sizeof()); mask_t *saccess_mask = alloca(mask_sizeof()); 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_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS, access_mask); if (err < 0) return err; - err = _snd_pcm_hw_param_mask(params, 1, SND_PCM_HW_PARAM_FORMAT, + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT, format_mask); if (err < 0) return err; - err = _snd_pcm_hw_param_min(params, 1, SND_PCM_HW_PARAM_CHANNELS, 1); + err = _snd_pcm_hw_param_min(params, SND_PCM_HW_PARAM_CHANNELS, 1, 0); if (err < 0) return err; + lcmask = params->cmask; + params->cmask |= cmask; _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); if (route->sformat >= 0) { - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - route->sformat); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + route->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); } 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_param_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, - route->schannels); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS, + route->schannels, 0); } else { links |= SND_PCM_HW_PARBIT_CHANNELS; if (route->sformat < 0) links |= (SND_PCM_HW_PARBIT_FRAME_BITS | - SND_PCM_HW_PARBIT_FRAGMENT_BYTES | + SND_PCM_HW_PARBIT_PERIOD_BYTES | SND_PCM_HW_PARBIT_BUFFER_BYTES); } err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave, links); + snd_pcm_generic_hw_link, slave, links); + params->cmask |= lcmask; if (err < 0) return err; params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); @@ -492,49 +499,56 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) snd_pcm_t *slave = route->plug.slave; int err; snd_pcm_hw_params_t sparams; - unsigned int links = (SND_PCM_HW_PARBIT_FRAGMENTS | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | + unsigned int links = (SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_PERIOD_TIME | SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_BUFFER_LENGTH); + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_TICK_TIME); unsigned int src_format, dst_format; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); if (route->sformat >= 0) { - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_FORMAT, - route->sformat); - _snd_pcm_hw_param_set(&sparams, 0, SND_PCM_HW_PARAM_SUBFORMAT, - SND_PCM_SUBFORMAT_STD); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT, + route->sformat, 0); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT, + SND_PCM_SUBFORMAT_STD, 0); } 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_param_set(&sparams, 0, SND_PCM_HW_PARAM_CHANNELS, - route->schannels); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS, + route->schannels, 0); } else { links |= SND_PCM_HW_PARBIT_CHANNELS; if (route->sformat < 0) links |= (SND_PCM_HW_PARBIT_FRAME_BITS | - SND_PCM_HW_PARBIT_FRAGMENT_BYTES | + SND_PCM_HW_PARBIT_PERIOD_BYTES | SND_PCM_HW_PARBIT_BUFFER_BYTES); } - err = snd_pcm_hw_params2(params, &sparams, - snd_pcm_hw_params, slave, links); + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); if (err < 0) 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_param_value(params, SND_PCM_HW_PARAM_FORMAT); + src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0); dst_format = slave->format; } else { src_format = slave->format; - dst_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT); + dst_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0); } route->params.get_idx = get_index(src_format, SND_PCM_FORMAT_U16); route->params.put_idx = put_index(SND_PCM_FORMAT_U32, dst_format); @@ -552,28 +566,28 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) return 0; } -static ssize_t snd_pcm_route_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_route_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_route_t *route = pcm->private; snd_pcm_t *slave = route->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer); route_transfer(areas, offset, snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), slave->channels, frames, &route->params); err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); @@ -586,28 +600,28 @@ static ssize_t snd_pcm_route_write_areas(snd_pcm_t *pcm, return err; } -static ssize_t snd_pcm_route_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_route_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, - size_t offset, - size_t size, - size_t *slave_sizep) + snd_pcm_uframes_t offset, + snd_pcm_uframes_t size, + snd_pcm_uframes_t *slave_sizep) { snd_pcm_route_t *route = pcm->private; snd_pcm_t *slave = route->plug.slave; - size_t xfer = 0; - ssize_t err = 0; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err = 0; if (slave_sizep && *slave_sizep < size) size = *slave_sizep; assert(size > 0); while (xfer < size) { - size_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); + snd_pcm_uframes_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer); route_transfer(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave), areas, offset, pcm->channels, frames, &route->params); err = snd_pcm_mmap_forward(slave, frames); if (err < 0) break; - assert((size_t)err == frames); + assert((snd_pcm_uframes_t)err == frames); offset += err; xfer += err; snd_pcm_mmap_hw_forward(pcm, err); diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c index e649ffdf..ef7ac47e 100644 --- a/src/pcm/pcm_share.c +++ b/src/pcm/pcm_share.c @@ -69,16 +69,16 @@ typedef struct { snd_pcm_t *pcm; int format; int rate; - size_t channels_count; - size_t open_count; - size_t setup_count; - size_t mmap_count; - size_t prepared_count; - size_t running_count; - size_t safety_threshold; - size_t silence_frames; + unsigned int channels_count; + unsigned int open_count; + unsigned int setup_count; + unsigned int mmap_count; + unsigned int prepared_count; + unsigned int running_count; + snd_pcm_uframes_t safety_threshold; + snd_pcm_uframes_t silence_frames; snd_pcm_sw_params_t sw_params; - size_t hw_ptr; + snd_pcm_uframes_t hw_ptr; int poll[2]; int polling; pthread_t thread; @@ -91,18 +91,18 @@ typedef struct { struct list_head list; snd_pcm_t *pcm; snd_pcm_share_slave_t *slave; - size_t channels_count; + unsigned int channels_count; int *slave_channels; int xfer_mode; int xrun_mode; - size_t avail_min; + snd_pcm_uframes_t avail_min; int async_sig; pid_t async_pid; int drain_silenced; struct timeval trigger_time; int state; - size_t hw_ptr; - size_t appl_ptr; + snd_pcm_uframes_t hw_ptr; + snd_pcm_uframes_t appl_ptr; int ready; int client_socket; int slave_socket; @@ -110,9 +110,9 @@ typedef struct { static void _snd_pcm_share_stop(snd_pcm_t *pcm, int state); -static size_t snd_pcm_share_slave_avail(snd_pcm_share_slave_t *slave) +static snd_pcm_uframes_t snd_pcm_share_slave_avail(snd_pcm_share_slave_t *slave) { - ssize_t avail; + snd_pcm_sframes_t avail; snd_pcm_t *pcm = slave->pcm; avail = slave->hw_ptr - *pcm->appl_ptr; if (pcm->stream == SND_PCM_STREAM_PLAYBACK) @@ -124,15 +124,15 @@ static size_t snd_pcm_share_slave_avail(snd_pcm_share_slave_t *slave) /* Warning: take the mutex before to call this */ /* Return number of frames to mmap_forward the slave */ -static size_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave) +static snd_pcm_uframes_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave) { struct list_head *i; - size_t buffer_size, boundary; - size_t slave_appl_ptr; - ssize_t frames, safety_frames; - ssize_t min_frames, max_frames; - size_t avail, slave_avail; - size_t slave_hw_avail; + snd_pcm_uframes_t buffer_size, boundary; + snd_pcm_uframes_t slave_appl_ptr; + snd_pcm_sframes_t frames, safety_frames; + snd_pcm_sframes_t min_frames, max_frames; + snd_pcm_uframes_t avail, slave_avail; + snd_pcm_uframes_t slave_hw_avail; slave_avail = snd_pcm_share_slave_avail(slave); boundary = slave->pcm->boundary; buffer_size = slave->pcm->buffer_size; @@ -187,17 +187,17 @@ static size_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave) - draining silencing - return distance in frames to next event */ -static size_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun) +static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun) { snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; snd_pcm_t *spcm = slave->pcm; - size_t buffer_size = spcm->buffer_size; + snd_pcm_uframes_t buffer_size = spcm->buffer_size; int ready = 1, running = 0; - size_t avail = 0, slave_avail; - ssize_t hw_avail; - size_t missing = INT_MAX; - ssize_t ready_missing; + snd_pcm_uframes_t avail = 0, slave_avail; + snd_pcm_sframes_t hw_avail; + snd_pcm_uframes_t missing = INT_MAX; + snd_pcm_sframes_t ready_missing; // printf("state=%d hw_ptr=%d appl_ptr=%d slave appl_ptr=%d safety=%d silence=%d\n", share->state, slave->hw_ptr, share->appl_ptr, *slave->pcm->appl_ptr, slave->safety_threshold, slave->silence_frames); switch (share->state) { case SND_PCM_STATE_RUNNING: @@ -219,11 +219,11 @@ static size_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun) slave_avail = snd_pcm_share_slave_avail(slave); if (avail < slave_avail) { /* Some frames need still to be transferred */ - ssize_t slave_hw_avail = buffer_size - slave_avail; - ssize_t safety_missing = slave_hw_avail - slave->safety_threshold; + snd_pcm_sframes_t slave_hw_avail = buffer_size - slave_avail; + snd_pcm_sframes_t safety_missing = slave_hw_avail - slave->safety_threshold; if (safety_missing < 0) { - ssize_t err; - ssize_t frames = slave_avail - avail; + snd_pcm_sframes_t err; + snd_pcm_sframes_t frames = slave_avail - avail; if (-safety_missing <= frames) { frames = -safety_missing; missing = 1; @@ -245,7 +245,7 @@ static size_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun) _snd_pcm_share_stop(pcm, SND_PCM_STATE_SETUP); break; } - if ((size_t)hw_avail < missing) + if ((snd_pcm_uframes_t)hw_avail < missing) missing = hw_avail; running = 1; ready = 0; @@ -257,13 +257,13 @@ static size_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun) _snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN); break; } - if ((size_t)hw_avail < missing) + if ((snd_pcm_uframes_t)hw_avail < missing) missing = hw_avail; } ready_missing = share->avail_min - avail; if (ready_missing > 0) { ready = 0; - if ((size_t)ready_missing < missing) + if ((snd_pcm_uframes_t)ready_missing < missing) missing = ready_missing; } running = 1; @@ -293,12 +293,12 @@ static size_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun) !share->drain_silenced) { /* drain silencing */ if (avail >= slave->silence_frames) { - size_t offset = share->appl_ptr % buffer_size; - size_t xfer = 0; - size_t size = slave->silence_frames; + snd_pcm_uframes_t offset = share->appl_ptr % buffer_size; + snd_pcm_uframes_t xfer = 0; + snd_pcm_uframes_t size = slave->silence_frames; while (xfer < size) { - size_t frames = size - xfer; - size_t cont = buffer_size - offset; + snd_pcm_uframes_t frames = size - xfer; + snd_pcm_uframes_t cont = buffer_size - offset; if (cont < frames) frames = cont; snd_pcm_areas_silence(pcm->running_areas, offset, pcm->channels, frames, pcm->format); @@ -309,7 +309,7 @@ static size_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun) } share->drain_silenced = 1; } else { - size_t silence_missing; + snd_pcm_uframes_t silence_missing; silence_missing = slave->silence_frames - avail; if (silence_missing < missing) missing = silence_missing; @@ -319,17 +319,17 @@ static size_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun) return missing; } -static size_t _snd_pcm_share_slave_missing(snd_pcm_share_slave_t *slave) +static snd_pcm_uframes_t _snd_pcm_share_slave_missing(snd_pcm_share_slave_t *slave) { - size_t missing = INT_MAX; + snd_pcm_uframes_t missing = INT_MAX; struct list_head *i; - ssize_t avail = snd_pcm_avail_update(slave->pcm); + snd_pcm_sframes_t avail = snd_pcm_avail_update(slave->pcm); int slave_xrun = (avail == -EPIPE); slave->hw_ptr = *slave->pcm->hw_ptr; for (i = slave->clients.next; i != &slave->clients; i = i->next) { snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list); snd_pcm_t *pcm = share->pcm; - size_t m = _snd_pcm_share_missing(pcm, slave_xrun); + snd_pcm_uframes_t m = _snd_pcm_share_missing(pcm, slave_xrun); if (m < missing) missing = m; } @@ -350,25 +350,25 @@ void *snd_pcm_share_slave_thread(void *data) err = pipe(slave->poll); assert(err >= 0); while (slave->open_count > 0) { - size_t missing; + snd_pcm_uframes_t missing; // printf("begin min_missing\n"); missing = _snd_pcm_share_slave_missing(slave); // printf("min_missing=%d\n", missing); if (missing < INT_MAX) { - size_t hw_ptr; - ssize_t avail_min; + snd_pcm_uframes_t hw_ptr; + snd_pcm_sframes_t avail_min; hw_ptr = slave->hw_ptr + missing; - hw_ptr += spcm->fragment_size - 1; + hw_ptr += spcm->period_size - 1; if (hw_ptr >= spcm->boundary) hw_ptr -= spcm->boundary; - hw_ptr -= hw_ptr % spcm->fragment_size; + hw_ptr -= hw_ptr % spcm->period_size; avail_min = hw_ptr - *spcm->appl_ptr; if (spcm->stream == SND_PCM_STREAM_PLAYBACK) avail_min += spcm->buffer_size; if (avail_min < 0) avail_min += spcm->boundary; // printf("avail_min=%d\n", avail_min); - if ((size_t)avail_min != spcm->avail_min) { + if ((snd_pcm_uframes_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); @@ -395,8 +395,8 @@ static void _snd_pcm_share_update(snd_pcm_t *pcm) snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; snd_pcm_t *spcm = slave->pcm; - size_t missing; - ssize_t avail = snd_pcm_avail_update(spcm); + snd_pcm_uframes_t missing; + snd_pcm_sframes_t avail = snd_pcm_avail_update(spcm); slave->hw_ptr = *slave->pcm->hw_ptr; missing = _snd_pcm_share_missing(pcm, avail == -EPIPE); if (!slave->polling) { @@ -404,20 +404,20 @@ static void _snd_pcm_share_update(snd_pcm_t *pcm) return; } if (missing < INT_MAX) { - size_t hw_ptr; - ssize_t avail_min; + snd_pcm_uframes_t hw_ptr; + snd_pcm_sframes_t avail_min; int err; hw_ptr = slave->hw_ptr + missing; - hw_ptr += spcm->fragment_size - 1; + hw_ptr += spcm->period_size - 1; if (hw_ptr >= spcm->boundary) hw_ptr -= spcm->boundary; - hw_ptr -= hw_ptr % spcm->fragment_size; + hw_ptr -= hw_ptr % spcm->period_size; avail_min = hw_ptr - *spcm->appl_ptr; if (spcm->stream == SND_PCM_STREAM_PLAYBACK) avail_min += spcm->buffer_size; if (avail_min < 0) avail_min += spcm->boundary; - if ((size_t)avail_min < spcm->avail_min) { + if ((snd_pcm_uframes_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); @@ -461,57 +461,64 @@ static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) snd_pcm_share_slave_t *slave = share->slave; snd_pcm_hw_params_t sparams; int err; + unsigned int cmask, lcmask; mask_t *access_mask = alloca(mask_sizeof()); const mask_t *mmap_mask; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_CHANNELS, - share->channels_count); + cmask = params->cmask; + params->cmask = 0; + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS, + share->channels_count, 0); if (err < 0) return err; if (slave->format >= 0) { - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FORMAT, - slave->format); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT, + slave->format, 0); if (err < 0) return err; } if (slave->rate >= 0) { - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_RATE, - slave->rate); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_RATE, + slave->rate, 0); if (err < 0) return err; } + lcmask = params->cmask; + params->cmask |= cmask; _snd_pcm_hw_params_any(&sparams); - _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_CHANNELS, - slave->channels_count); + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, + saccess_mask); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS, + slave->channels_count, 0); err = snd_pcm_hw_refine2(params, &sparams, - snd_pcm_hw_refine, slave->pcm, + snd_pcm_generic_hw_link, slave->pcm, SND_PCM_HW_PARBIT_FORMAT | SND_PCM_HW_PARBIT_SUBFORMAT | SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_PERIOD_TIME | SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_BUFFER_LENGTH | - SND_PCM_HW_PARBIT_FRAGMENTS); + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_TICK_TIME); if (err < 0) return err; mmap_mask = snd_pcm_hw_param_value_mask(&sparams, SND_PCM_HW_PARAM_ACCESS); - mask_all(access_mask); + mask_any(access_mask); mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED); if (!mask_test(mmap_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) mask_reset(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); 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_param_mask(params, 1, SND_PCM_HW_PARAM_ACCESS, + err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS, access_mask); + params->cmask |= lcmask; if (err < 0) return err; params->info |= SND_PCM_INFO_DOUBLE; @@ -527,24 +534,29 @@ 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_param_set(params, 1, SND_PCM_HW_PARAM_FORMAT, - spcm->format); + params->cmask = 0; + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT, + spcm->format, 0); if (err < 0) goto _err; - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_SUBFORMAT, - spcm->subformat); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT, + spcm->subformat, 0); if (err < 0) goto _err; - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_RATE, - spcm->rate); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_RATE, + spcm->rate, 0); if (err < 0) goto _err; - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FRAGMENT_SIZE, - spcm->fragment_size); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_PERIOD_TIME, + spcm->period_time, 0); if (err < 0) goto _err; - err = _snd_pcm_hw_param_set(params, 1, SND_PCM_HW_PARAM_FRAGMENTS, - spcm->fragments); + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_BUFFER_SIZE, + spcm->buffer_size, 0); + if (err < 0) + goto _err; + err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_TICK_TIME, + spcm->tick_time, 0); _err: if (err < 0) { ERR("slave is already running with different setup"); @@ -553,30 +565,38 @@ static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) } } else { snd_pcm_hw_params_t sparams; + unsigned int links; mask_t *saccess_mask = alloca(mask_sizeof()); mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP); + links = SND_PCM_HW_PARBIT_FORMAT | + SND_PCM_HW_PARBIT_SUBFORMAT | + SND_PCM_HW_PARBIT_RATE | + SND_PCM_HW_PARBIT_PERIOD_SIZE | + SND_PCM_HW_PARBIT_PERIOD_TIME | + SND_PCM_HW_PARBIT_BUFFER_SIZE | + SND_PCM_HW_PARBIT_BUFFER_TIME | + SND_PCM_HW_PARBIT_PERIODS | + SND_PCM_HW_PARBIT_TICK_TIME; _snd_pcm_hw_params_any(&sparams); - _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_CHANNELS, - share->channels_count); - err = snd_pcm_hw_params2(params, &sparams, - snd_pcm_hw_params, slave->pcm, - SND_PCM_HW_PARBIT_FORMAT | - SND_PCM_HW_PARBIT_SUBFORMAT | - SND_PCM_HW_PARBIT_RATE | - SND_PCM_HW_PARBIT_FRAGMENT_SIZE | - SND_PCM_HW_PARBIT_FRAGMENT_LENGTH | - SND_PCM_HW_PARBIT_BUFFER_SIZE | - SND_PCM_HW_PARBIT_BUFFER_LENGTH | - SND_PCM_HW_PARBIT_FRAGMENTS); + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, + saccess_mask); + _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS, + share->channels_count, 0); + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = snd_pcm_hw_params(slave->pcm, &sparams); + params->cmask = 0; + sparams.cmask = ~0U; + snd_pcm_hw_params_refine(params, links, &sparams); 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; - slave->safety_threshold -= slave->safety_threshold % slave->pcm->fragment_size; + slave->safety_threshold += slave->pcm->period_size - 1; + slave->safety_threshold -= slave->safety_threshold % slave->pcm->period_size; slave->silence_frames = slave->safety_threshold; if (slave->pcm->stream == SND_PCM_STREAM_PLAYBACK) snd_pcm_areas_silence(slave->pcm->running_areas, 0, slave->pcm->channels, slave->pcm->buffer_size, slave->pcm->format); @@ -598,7 +618,7 @@ static int snd_pcm_share_status(snd_pcm_t *pcm, snd_pcm_status_t *status) snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; int err = 0; - ssize_t sd = 0, d = 0; + snd_pcm_sframes_t sd = 0, d = 0; Pthread_mutex_lock(&slave->mutex); if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { status->avail = snd_pcm_mmap_playback_avail(pcm); @@ -630,12 +650,12 @@ static int snd_pcm_share_state(snd_pcm_t *pcm) return share->state; } -static int _snd_pcm_share_delay(snd_pcm_t *pcm, ssize_t *delayp) +static int _snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; int err = 0; - ssize_t sd; + snd_pcm_sframes_t sd; switch (share->state) { case SND_PCM_STATE_XRUN: return -EPIPE; @@ -655,7 +675,7 @@ static int _snd_pcm_share_delay(snd_pcm_t *pcm, ssize_t *delayp) return 0; } -static int snd_pcm_share_delay(snd_pcm_t *pcm, ssize_t *delayp) +static int snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; @@ -666,11 +686,11 @@ static int snd_pcm_share_delay(snd_pcm_t *pcm, ssize_t *delayp) return err; } -static ssize_t snd_pcm_share_avail_update(snd_pcm_t *pcm) +static snd_pcm_sframes_t snd_pcm_share_avail_update(snd_pcm_t *pcm) { snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; - ssize_t avail; + snd_pcm_sframes_t avail; Pthread_mutex_lock(&slave->mutex); if (share->state == SND_PCM_STATE_RUNNING) { avail = snd_pcm_avail_update(slave->pcm); @@ -682,24 +702,24 @@ static ssize_t snd_pcm_share_avail_update(snd_pcm_t *pcm) } Pthread_mutex_unlock(&slave->mutex); avail = snd_pcm_mmap_avail(pcm); - if ((size_t)avail > pcm->buffer_size) + if ((snd_pcm_uframes_t)avail > pcm->buffer_size) return -EPIPE; return avail; } /* Call it with mutex held */ -static ssize_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size) +static snd_pcm_sframes_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size) { snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; - ssize_t ret = 0; - ssize_t frames; + snd_pcm_sframes_t ret = 0; + snd_pcm_sframes_t frames; if (pcm->stream == SND_PCM_STREAM_PLAYBACK && share->state == SND_PCM_STATE_RUNNING) { frames = *slave->pcm->appl_ptr - share->appl_ptr; - if (frames > (ssize_t)pcm->buffer_size) + if (frames > (snd_pcm_sframes_t)pcm->buffer_size) frames -= pcm->boundary; - else if (frames < -(ssize_t)pcm->buffer_size) + else if (frames < -(snd_pcm_sframes_t)pcm->buffer_size) frames += pcm->boundary; if (frames > 0) { /* Latecomer PCM */ @@ -710,9 +730,9 @@ static ssize_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size) } snd_pcm_mmap_appl_forward(pcm, size); if (share->state == SND_PCM_STATE_RUNNING) { - ssize_t frames = _snd_pcm_share_slave_forward(slave); + snd_pcm_sframes_t frames = _snd_pcm_share_slave_forward(slave); if (frames > 0) { - ssize_t err; + snd_pcm_sframes_t err; err = snd_pcm_mmap_forward(slave->pcm, frames); assert(err == frames); } @@ -721,11 +741,11 @@ static ssize_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size) return size; } -static ssize_t snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size) +static snd_pcm_sframes_t snd_pcm_share_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size) { snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; - ssize_t ret; + snd_pcm_sframes_t ret; Pthread_mutex_lock(&slave->mutex); ret = _snd_pcm_share_mmap_forward(pcm, size); Pthread_mutex_unlock(&slave->mutex); @@ -776,14 +796,14 @@ static int snd_pcm_share_start(snd_pcm_t *pcm) Pthread_mutex_lock(&slave->mutex); share->state = SND_PCM_STATE_RUNNING; if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { - size_t hw_avail = snd_pcm_mmap_playback_hw_avail(pcm); - size_t xfer = 0; + snd_pcm_uframes_t hw_avail = snd_pcm_mmap_playback_hw_avail(pcm); + snd_pcm_uframes_t xfer = 0; if (hw_avail == 0) { err = -EPIPE; goto _end; } if (slave->running_count) { - ssize_t sd; + snd_pcm_sframes_t sd; err = snd_pcm_delay(slave->pcm, &sd); if (err < 0) goto _end; @@ -795,9 +815,9 @@ static int snd_pcm_share_start(snd_pcm_t *pcm) share->hw_ptr = *slave->pcm->hw_ptr; share->appl_ptr = *slave->pcm->appl_ptr; while (xfer < hw_avail) { - size_t frames = hw_avail - xfer; - size_t offset = snd_pcm_mmap_offset(pcm); - size_t cont = pcm->buffer_size - offset; + snd_pcm_uframes_t frames = hw_avail - xfer; + snd_pcm_uframes_t offset = snd_pcm_mmap_offset(pcm); + snd_pcm_uframes_t cont = pcm->buffer_size - offset; if (cont < frames) frames = cont; snd_pcm_areas_copy(pcm->stopped_areas, xfer, @@ -841,11 +861,11 @@ static int snd_pcm_share_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *in return err; } -static ssize_t _snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames) +static snd_pcm_sframes_t _snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; - ssize_t n; + snd_pcm_sframes_t n; switch (share->state) { case SND_PCM_STATE_RUNNING: break; @@ -865,7 +885,7 @@ static ssize_t _snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames) n = snd_pcm_mmap_hw_avail(pcm); assert(n >= 0); if (n > 0) { - if ((size_t)n > frames) + if ((snd_pcm_uframes_t)n > frames) n = frames; frames -= n; } @@ -881,11 +901,11 @@ static ssize_t _snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames) return n; } -static ssize_t snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames) +static snd_pcm_sframes_t snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_share_t *share = pcm->private; snd_pcm_share_slave_t *slave = share->slave; - ssize_t ret; + snd_pcm_sframes_t ret; Pthread_mutex_lock(&slave->mutex); ret = _snd_pcm_share_rewind(pcm, frames); Pthread_mutex_unlock(&slave->mutex); @@ -909,7 +929,7 @@ static void _snd_pcm_share_stop(snd_pcm_t *pcm, int state) pcm->format); } else if (slave->running_count > 1) { int err; - ssize_t delay; + snd_pcm_sframes_t delay; snd_pcm_areas_silence(pcm->running_areas, 0, pcm->channels, pcm->buffer_size, pcm->format); err = snd_pcm_delay(slave->pcm, &delay); @@ -1106,8 +1126,8 @@ snd_pcm_fast_ops_t snd_pcm_share_fast_ops = { int snd_pcm_share_open(snd_pcm_t **pcmp, char *name, char *sname, int sformat, int srate, - size_t schannels_count, - size_t channels_count, int *channels_map, + unsigned int schannels_count, + unsigned int channels_count, int *channels_map, int stream, int mode) { snd_pcm_t *pcm; @@ -1291,9 +1311,9 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, int err; unsigned int idx; int *channels_map; - size_t channels_count = 0; + unsigned int channels_count = 0; long schannels_count = -1; - size_t schannel_max = 0; + unsigned int schannel_max = 0; int sformat = -1; long srate = -1; diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c index aecec8c6..c6b1e5bb 100644 --- a/src/pcm/pcm_shm.c +++ b/src/pcm/pcm_shm.c @@ -168,6 +168,27 @@ static int _snd_pcm_shm_hw_refine(snd_pcm_t *pcm, return err; } +/* Accumulate to params->cmask */ +/* Reset sparams->cmask */ +int snd_pcm_shm_hw_link(snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *sparams, + snd_pcm_t *slave, + unsigned long links) +{ + int err1, err = 0; + err = snd_pcm_hw_params_refine(sparams, links, params); + if (err >= 0) { + unsigned int cmask = sparams->cmask; + err = _snd_pcm_shm_hw_refine(slave, sparams); + sparams->cmask |= cmask; + } + err1 = snd_pcm_hw_params_refine(params, links, sparams); + if (err1 < 0) + err = err1; + sparams->cmask = 0; + return err; +} + static int snd_pcm_shm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) { snd_pcm_hw_params_t sparams; @@ -178,10 +199,10 @@ static int snd_pcm_shm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) !mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) mask_intersect(saccess_mask, access_mask); _snd_pcm_hw_params_any(&sparams); - _snd_pcm_hw_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); return snd_pcm_hw_refine2(params, &sparams, - _snd_pcm_shm_hw_refine, pcm, + snd_pcm_shm_hw_link, pcm, ~SND_PCM_HW_PARBIT_ACCESS); } @@ -201,18 +222,27 @@ 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; + unsigned int links = ~SND_PCM_HW_PARBIT_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()); + int err; 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_param_mask(&sparams, 0, SND_PCM_HW_PARAM_ACCESS, + _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS, saccess_mask); - return snd_pcm_hw_params2(params, &sparams, - _snd_pcm_shm_hw_params, pcm, - ~SND_PCM_HW_PARBIT_ACCESS); + err = snd_pcm_hw_params_refine(&sparams, links, params); + assert(err >= 0); + err = _snd_pcm_hw_refine(&sparams); + assert(err >= 0); + err = _snd_pcm_shm_hw_params(pcm, &sparams); + if (err < 0) { + snd_pcm_hw_params_refine(params, links, &sparams); + return err; + } + return 0; } static int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) @@ -310,7 +340,7 @@ static int snd_pcm_shm_state(snd_pcm_t *pcm) return snd_pcm_shm_action(pcm); } -static int snd_pcm_shm_delay(snd_pcm_t *pcm, ssize_t *delayp) +static int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) { snd_pcm_shm_t *shm = pcm->private; volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; @@ -323,7 +353,7 @@ static int snd_pcm_shm_delay(snd_pcm_t *pcm, ssize_t *delayp) return err; } -static ssize_t snd_pcm_shm_avail_update(snd_pcm_t *pcm) +static snd_pcm_sframes_t snd_pcm_shm_avail_update(snd_pcm_t *pcm) { snd_pcm_shm_t *shm = pcm->private; volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; @@ -390,7 +420,7 @@ static int snd_pcm_shm_pause(snd_pcm_t *pcm, int enable) return snd_pcm_shm_action(pcm); } -static ssize_t snd_pcm_shm_rewind(snd_pcm_t *pcm, size_t frames) +static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_shm_t *shm = pcm->private; volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; @@ -399,7 +429,7 @@ static ssize_t snd_pcm_shm_rewind(snd_pcm_t *pcm, size_t frames) return snd_pcm_shm_action(pcm); } -static ssize_t snd_pcm_shm_mmap_forward(snd_pcm_t *pcm, size_t size) +static snd_pcm_sframes_t snd_pcm_shm_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size) { snd_pcm_shm_t *shm = pcm->private; volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; diff --git a/src/rawmidi/rawmidi_hw.c b/src/rawmidi/rawmidi_hw.c index a5b5ec95..c11432ac 100644 --- a/src/rawmidi/rawmidi_hw.c +++ b/src/rawmidi/rawmidi_hw.c @@ -245,7 +245,7 @@ int snd_rawmidi_hw_open(snd_rawmidi_t **handlep, char *name, int card, int devic snd_ctl_close(ctl); return ret; } - if (info.subdevice != subdevice) { + if (info.subdevice != (unsigned int) subdevice) { close(fd); goto __again; } |