From 60fa939c216da6812d033de431a474ac9c553637 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Wed, 21 Jun 2000 14:59:20 +0000 Subject: [PATCH] pcm handle split --- include/pcm.h | 234 +++++++++++----------- src/pcm/pcm.c | 443 +++++++++++++----------------------------- src/pcm/pcm_hw.c | 374 ++++++++++++++++------------------- src/pcm/pcm_local.h | 149 +++++++------- src/pcm/pcm_mmap.c | 464 +++++++++++++++++++------------------------- 5 files changed, 692 insertions(+), 972 deletions(-) diff --git a/include/pcm.h b/include/pcm.h index 689cdfd2..0a4a0b36 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -5,12 +5,7 @@ * * ****************************************************************************/ -#define SND_PCM_OPEN_PLAYBACK 0x0001 -#define SND_PCM_OPEN_CAPTURE 0x0002 -#define SND_PCM_OPEN_DUPLEX 0x0003 -#define SND_PCM_NONBLOCK_PLAYBACK 0x1000 -#define SND_PCM_NONBLOCK_CAPTURE 0x2000 -#define SND_PCM_NONBLOCK 0x3000 +#define SND_PCM_NONBLOCK 0x0001 #ifdef __cplusplus extern "C" { @@ -18,137 +13,152 @@ extern "C" { typedef unsigned int bitset_t; -static inline size_t bitset_size(int nbits) +static inline size_t bitset_size(size_t nbits) { return (nbits + sizeof(bitset_t) * 8 - 1) / (sizeof(bitset_t) * 8); } -static inline bitset_t *bitset_alloc(int nbits) +static inline bitset_t *bitset_alloc(size_t nbits) { return (bitset_t*) calloc(bitset_size(nbits), sizeof(bitset_t)); } static inline void bitset_set(bitset_t *bitmap, unsigned int pos) { - int bits = sizeof(*bitmap) * 8; - bitmap[pos / bits] |= 1 << (pos % bits); + size_t bits = sizeof(*bitmap) * 8; + bitmap[pos / bits] |= 1U << (pos % bits); } static inline void bitset_reset(bitset_t *bitmap, unsigned int pos) { - int bits = sizeof(*bitmap) * 8; - bitmap[pos / bits] &= ~(1 << (pos % bits)); + size_t bits = sizeof(*bitmap) * 8; + bitmap[pos / bits] &= ~(1U << (pos % bits)); } static inline int bitset_get(bitset_t *bitmap, unsigned int pos) { - int bits = sizeof(*bitmap) * 8; - return !!(bitmap[pos / bits] & (1 << (pos % bits))); + size_t bits = sizeof(*bitmap) * 8; + return !!(bitmap[pos / bits] & (1U << (pos % bits))); } -static inline void bitset_copy(bitset_t *dst, bitset_t *src, unsigned int nbits) +static inline void bitset_copy(bitset_t *dst, bitset_t *src, size_t nbits) { memcpy(dst, src, bitset_size(nbits) * sizeof(bitset_t)); } -static inline void bitset_and(bitset_t *dst, bitset_t *bs, unsigned int nbits) +static inline void bitset_and(bitset_t *dst, bitset_t *bs, size_t nbits) { bitset_t *end = dst + bitset_size(nbits); while (dst < end) *dst++ &= *bs++; } -static inline void bitset_or(bitset_t *dst, bitset_t *bs, unsigned int nbits) +static inline void bitset_or(bitset_t *dst, bitset_t *bs, size_t nbits) { bitset_t *end = dst + bitset_size(nbits); while (dst < end) *dst++ |= *bs++; } -static inline void bitset_zero(bitset_t *dst, unsigned int nbits) +static inline void bitset_zero(bitset_t *dst, size_t nbits) { bitset_t *end = dst + bitset_size(nbits); while (dst < end) *dst++ = 0; } -static inline void bitset_one(bitset_t *dst, unsigned int nbits) +static inline void bitset_one(bitset_t *dst, size_t nbits) { bitset_t *end = dst + bitset_size(nbits); while (dst < end) *dst++ = ~(bitset_t)0; } +static inline size_t hweight32(bitset_t v) +{ + v = (v & 0x55555555) + ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + v = (v & 0x0F0F0F0F) + ((v >> 4) & 0x0F0F0F0F); + v = (v & 0x00FF00FF) + ((v >> 8) & 0x00FF00FF); + return (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFF); +} + +/* Count bits set */ +static inline size_t bitset_count(bitset_t *bitset, size_t nbits) +{ + bitset_t *end = bitset + bitset_size(nbits) - 1; + size_t bits = sizeof(*bitset) * 8; + size_t count = 0; + while (bitset < end) + count += hweight32(*bitset++); + count += hweight32(*bitset & ((1U << (nbits % bits)) - 1)); + return count; +} + typedef struct snd_pcm snd_pcm_t; typedef struct snd_pcm_loopback snd_pcm_loopback_t; typedef enum { SND_PCM_TYPE_HW, SND_PCM_TYPE_PLUG, SND_PCM_TYPE_MULTI } snd_pcm_type_t; -int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode); -int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode); +int snd_pcm_hw_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int stream, int mode); +int snd_pcm_hw_open(snd_pcm_t **handle, int card, int device, int stream, int mode); snd_pcm_type_t snd_pcm_type(snd_pcm_t *handle); int snd_pcm_close(snd_pcm_t *handle); -int snd_pcm_stream_close(snd_pcm_t *handle, int stream); -int snd_pcm_file_descriptor(snd_pcm_t *handle, int stream); -int snd_pcm_stream_nonblock(snd_pcm_t *handle, int stream, int nonblock); +int snd_pcm_file_descriptor(snd_pcm_t *handle); +int snd_pcm_nonblock(snd_pcm_t *handle, int nonblock); int snd_pcm_info(snd_pcm_t *handle, snd_pcm_info_t *info); -int snd_pcm_stream_info(snd_pcm_t *handle, snd_pcm_stream_info_t *info); -int snd_pcm_stream_params(snd_pcm_t *handle, snd_pcm_stream_params_t *params); -int snd_pcm_stream_setup(snd_pcm_t *handle, snd_pcm_stream_setup_t *setup); -int snd_pcm_channel_setup(snd_pcm_t *handle, int stream, snd_pcm_channel_setup_t *setup); -int snd_pcm_stream_status(snd_pcm_t *handle, snd_pcm_stream_status_t *status); -int snd_pcm_playback_prepare(snd_pcm_t *handle); -int snd_pcm_capture_prepare(snd_pcm_t *handle); -int snd_pcm_stream_prepare(snd_pcm_t *handle, int stream); -int snd_pcm_playback_go(snd_pcm_t *handle); -int snd_pcm_capture_go(snd_pcm_t *handle); -int snd_pcm_stream_go(snd_pcm_t *handle, int stream); +int snd_pcm_params(snd_pcm_t *handle, snd_pcm_params_t *params); +int snd_pcm_setup(snd_pcm_t *handle, snd_pcm_setup_t *setup); +int snd_pcm_channel_setup(snd_pcm_t *handle, snd_pcm_channel_setup_t *setup); +int snd_pcm_status(snd_pcm_t *handle, snd_pcm_status_t *status); +int snd_pcm_prepare(snd_pcm_t *handle); +int snd_pcm_go(snd_pcm_t *handle); int snd_pcm_sync_go(snd_pcm_t *handle, snd_pcm_sync_t *sync); -int snd_pcm_playback_drain(snd_pcm_t *handle); -int snd_pcm_stream_drain(snd_pcm_t *handle, int stream); -int snd_pcm_playback_flush(snd_pcm_t *handle); -int snd_pcm_capture_flush(snd_pcm_t *handle); -int snd_pcm_stream_flush(snd_pcm_t *handle, int stream); -int snd_pcm_playback_pause(snd_pcm_t *handle, int enable); -int snd_pcm_stream_pause(snd_pcm_t *handle, int stream, int enable); -int snd_pcm_stream_state(snd_pcm_t *handle, int stream); -int snd_pcm_mmap_stream_state(snd_pcm_t *handle, int stream); -ssize_t snd_pcm_stream_frame_io(snd_pcm_t *handle, int stream, int update); -ssize_t snd_pcm_mmap_stream_frame_io(snd_pcm_t *handle, int stream); -ssize_t snd_pcm_stream_frame_data(snd_pcm_t *handle, int stream, off_t offset); -ssize_t snd_pcm_mmap_stream_frame_data(snd_pcm_t *handle, int stream, off_t offset); +int snd_pcm_drain(snd_pcm_t *handle); +int snd_pcm_flush(snd_pcm_t *handle); +int snd_pcm_pause(snd_pcm_t *handle, int enable); +int snd_pcm_state(snd_pcm_t *handle); +ssize_t snd_pcm_frame_io(snd_pcm_t *handle, int update); +ssize_t snd_pcm_frame_data(snd_pcm_t *handle, off_t offset); ssize_t snd_pcm_write(snd_pcm_t *handle, const void *buffer, size_t size); ssize_t snd_pcm_read(snd_pcm_t *handle, void *buffer, size_t size); -ssize_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); -ssize_t snd_pcm_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); +ssize_t snd_pcm_writev(snd_pcm_t *handle, const struct iovec *vector, unsigned long count); +ssize_t snd_pcm_readv(snd_pcm_t *handle, const struct iovec *vector, unsigned long count); +int snd_pcm_dump_setup(snd_pcm_t *handle, FILE *fp); + +int snd_pcm_channels_mask(snd_pcm_t *handle, bitset_t *client_vmask); + +/* mmap */ +int snd_pcm_mmap(snd_pcm_t *handle, snd_pcm_mmap_status_t **status, snd_pcm_mmap_control_t **control, void **buffer); +int snd_pcm_munmap(snd_pcm_t *handle); +int snd_pcm_mmap_state(snd_pcm_t *handle); +ssize_t snd_pcm_mmap_frame_io(snd_pcm_t *handle); +ssize_t snd_pcm_mmap_frame_data(snd_pcm_t *handle, off_t offset); +int snd_pcm_mmap_status(snd_pcm_t *handle, snd_pcm_mmap_status_t **status); +int snd_pcm_mmap_control(snd_pcm_t *handle, snd_pcm_mmap_control_t **control); +int snd_pcm_mmap_data(snd_pcm_t *handle, void **buffer); +int snd_pcm_munmap_status(snd_pcm_t *handle); +int snd_pcm_munmap_control(snd_pcm_t *handle); +int snd_pcm_munmap_data(snd_pcm_t *handle); +int snd_pcm_mmap_ready(snd_pcm_t *handle); +ssize_t snd_pcm_mmap_write(snd_pcm_t *handle, const void *buffer, size_t size); +ssize_t snd_pcm_mmap_read(snd_pcm_t *handle, void *buffer, size_t size); +ssize_t snd_pcm_mmap_writev(snd_pcm_t *handle, const struct iovec *vector, unsigned long count); +ssize_t snd_pcm_mmap_readv(snd_pcm_t *handle, const struct iovec *vector, unsigned long count); +int snd_pcm_mmap_frames_avail(snd_pcm_t *handle, ssize_t *frames); +ssize_t snd_pcm_mmap_frames_xfer(snd_pcm_t *handle, size_t frames); +ssize_t snd_pcm_mmap_frames_offset(snd_pcm_t *handle); +ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *handle, snd_pcm_channel_area_t *channels, size_t frames); +ssize_t snd_pcm_mmap_write_frames(snd_pcm_t *handle, const void *buffer, size_t frames); +ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *handle, snd_pcm_channel_area_t *channels, size_t frames); +ssize_t snd_pcm_mmap_read_frames(snd_pcm_t *handle, const void *buffer, size_t frames); +int snd_pcm_mmap_get_areas(snd_pcm_t *handle, snd_pcm_channel_area_t *areas); + + const char *snd_pcm_get_format_name(int format); const char *snd_pcm_get_format_description(int format); int snd_pcm_get_format_value(const char* name); -int snd_pcm_dump_setup(snd_pcm_t *pcm, int stream, FILE *fp); - -int snd_pcm_mmap(snd_pcm_t *handle, int stream, snd_pcm_mmap_status_t **status, snd_pcm_mmap_control_t **control, void **buffer); -int snd_pcm_munmap(snd_pcm_t *handle, int stream); -int snd_pcm_mmap_status(snd_pcm_t *handle, int stream, snd_pcm_mmap_status_t **status); -int snd_pcm_mmap_control(snd_pcm_t *handle, int stream, snd_pcm_mmap_control_t **control); -int snd_pcm_mmap_data(snd_pcm_t *handle, int stream, void **buffer); -int snd_pcm_munmap_status(snd_pcm_t *handle, int stream); -int snd_pcm_munmap_control(snd_pcm_t *handle, int stream); -int snd_pcm_munmap_data(snd_pcm_t *handle, int stream); -int snd_pcm_channels_mask(snd_pcm_t *pcm, int stream, bitset_t *client_vmask); -int snd_pcm_mmap_ready(snd_pcm_t *pcm, int stream); -ssize_t snd_pcm_mmap_write(snd_pcm_t *handle, const void *buffer, size_t size); -ssize_t snd_pcm_mmap_read(snd_pcm_t *handle, void *buffer, size_t size); -ssize_t snd_pcm_mmap_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); -ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); -int snd_pcm_mmap_frames_avail(snd_pcm_t *pcm, int stream, ssize_t *frames); -ssize_t snd_pcm_mmap_frames_xfer(snd_pcm_t *pcm, int stream, size_t frames); -ssize_t snd_pcm_mmap_frames_offset(snd_pcm_t *pcm, int stream); -ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels, size_t frames); -ssize_t snd_pcm_mmap_write_frames(snd_pcm_t *pcm, const void *buffer, size_t frames); -ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels, size_t frames); -ssize_t snd_pcm_mmap_read_frames(snd_pcm_t *pcm, const void *buffer, size_t frames); -int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, int stream, snd_pcm_channel_area_t *areas); int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, size_t dst_offset, size_t samples, int format); @@ -161,10 +171,10 @@ int snd_pcm_areas_copy(const snd_pcm_channel_area_t *src_channels, size_t src_of const snd_pcm_channel_area_t *dst_channels, size_t dst_offset, size_t vcount, size_t frames, int format); -ssize_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, int stream, ssize_t bytes); -ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, int stream, ssize_t frames); -ssize_t snd_pcm_bytes_to_samples(snd_pcm_t *pcm, int stream, ssize_t bytes); -ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, int stream, ssize_t samples); +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); /* misc */ @@ -197,7 +207,7 @@ extern "C" { #endif typedef struct snd_stru_pcm_plugin snd_pcm_plugin_t; -#define snd_pcm_plugin_handle_t snd_pcm_t +#define snd_pcm_plug_t struct snd_pcm_plug typedef enum { INIT = 0, @@ -208,7 +218,6 @@ typedef enum { } snd_pcm_plugin_action_t; typedef struct snd_stru_pcm_plugin_channel { - void *aptr; /* pointer to the allocated area */ snd_pcm_channel_area_t area; unsigned int enabled:1; /* channel need to be processed */ unsigned int wanted:1; /* channel is wanted */ @@ -247,54 +256,47 @@ struct snd_stru_pcm_plugin { unsigned long *value); snd_pcm_plugin_t *prev; snd_pcm_plugin_t *next; - snd_pcm_plugin_handle_t *handle; + snd_pcm_plug_t *plug; void *private_data; void (*private_free)(snd_pcm_plugin_t *plugin, void *private_data); - snd_pcm_plugin_channel_t *src_channels; - snd_pcm_plugin_channel_t *dst_channels; + char *buf; + size_t buf_frames; + snd_pcm_plugin_channel_t *buf_channels; bitset_t *src_vmask; bitset_t *dst_vmask; char extra_data[0]; }; -int snd_pcm_plug_connect(snd_pcm_t **handle, snd_pcm_t *slave, int mode, int close_slave); -int snd_pcm_plug_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode); -int snd_pcm_plug_open(snd_pcm_t **handle, int card, int device, int mode); +int snd_pcm_plug_create(snd_pcm_t **handle, snd_pcm_t *slave, int close_slave); +int snd_pcm_plug_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int stream, int mode); +int snd_pcm_plug_open(snd_pcm_t **handle, int card, int device, int stream, int mode); int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin); -int snd_pcm_plug_clear(snd_pcm_t *handle, int stream); int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin); int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin); -#if 0 -int snd_pcm_plugin_remove_to(snd_pcm_plugin_t *plugin); -int snd_pcm_plug_remove_first(snd_pcm_t *handle, int stream); -#endif -snd_pcm_plugin_t *snd_pcm_plug_first(snd_pcm_t *handle, int stream); -snd_pcm_plugin_t *snd_pcm_plug_last(snd_pcm_t *handle, int stream); -int snd_pcm_plug_direct(snd_pcm_t *pcm, int stream); -ssize_t snd_pcm_plug_client_size(snd_pcm_t *handle, int stream, size_t drv_frames); -ssize_t snd_pcm_plug_slave_size(snd_pcm_t *handle, int stream, size_t clt_frames); +int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, size_t frames); +int snd_pcm_plug_clear(snd_pcm_plug_t *plug); +snd_pcm_plugin_t *snd_pcm_plug_first(snd_pcm_plug_t *plug); +snd_pcm_plugin_t *snd_pcm_plug_last(snd_pcm_plug_t *plug); +int snd_pcm_plug_direct(snd_pcm_plug_t *plug); +ssize_t snd_pcm_plug_client_size(snd_pcm_plug_t *plug, size_t drv_frames); +ssize_t snd_pcm_plug_slave_size(snd_pcm_plug_t *plug, size_t clt_frames); /* * Plug-In constructors */ -int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build(snd_pcm_plug_t *plug, const char *name, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, size_t extra, snd_pcm_plugin_t **ret); /* basic I/O */ -int snd_pcm_plugin_build_io(snd_pcm_plugin_handle_t *handle, - int stream, - snd_pcm_t *slave, +int snd_pcm_plugin_build_io(snd_pcm_plug_t *plug, snd_pcm_format_t *format, snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_mmap(snd_pcm_plugin_handle_t *handle, - int stream, - snd_pcm_t *slave, +int snd_pcm_plugin_build_mmap(snd_pcm_plug_t *plug, snd_pcm_format_t *format, snd_pcm_plugin_t **r_plugin); @@ -310,44 +312,36 @@ typedef int route_ttable_entry_t; #endif /* conversion plugins */ -int snd_pcm_plugin_build_interleave(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_interleave(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_linear(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_linear(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_mulaw(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_mulaw(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_alaw(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_alaw(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_adpcm(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_adpcm(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_rate(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_rate(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_route(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, route_ttable_entry_t *ttable, snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_copy(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_copy(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin); diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 882acf0b..176450a5 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -27,372 +27,219 @@ #include #include "pcm_local.h" -int snd_pcm_abstract_open(snd_pcm_t **handle, int mode, - snd_pcm_type_t type, size_t extra) +snd_pcm_type_t snd_pcm_type(snd_pcm_t *handle) { - snd_pcm_t *pcm; - assert(handle); - *handle = NULL; - - pcm = (snd_pcm_t *) calloc(1, sizeof(snd_pcm_t) + extra); - if (pcm == NULL) - return -ENOMEM; - if (mode & SND_PCM_OPEN_PLAYBACK) { - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - str->open = 1; - str->mode = (mode & SND_PCM_NONBLOCK_PLAYBACK) ? SND_PCM_NONBLOCK : 0; - } - if (mode & SND_PCM_OPEN_CAPTURE) { - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - str->open = 1; - str->mode = (mode & SND_PCM_NONBLOCK_CAPTURE) ? SND_PCM_NONBLOCK : 0; - } - pcm->type = type; - pcm->mode = mode & SND_PCM_OPEN_DUPLEX; - *handle = pcm; - return 0; + return handle->type; } -snd_pcm_type_t snd_pcm_type(snd_pcm_t *handle) +snd_pcm_type_t snd_pcm(snd_pcm_t *handle) { - return handle->type; + assert(handle); + return handle->stream; } -int snd_pcm_stream_close(snd_pcm_t *pcm, int stream) +int snd_pcm_close(snd_pcm_t *handle) { int ret = 0; int err; - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->open); - if (str->mmap_status) { - if ((err = snd_pcm_munmap_status(pcm, stream)) < 0) + assert(handle); + if (handle->mmap_status) { + if ((err = snd_pcm_munmap_status(handle)) < 0) ret = err; } - if (str->mmap_control) { - if ((err = snd_pcm_munmap_control(pcm, stream)) < 0) + if (handle->mmap_control) { + if ((err = snd_pcm_munmap_control(handle)) < 0) ret = err; } - if (str->mmap_data) { - if ((err = snd_pcm_munmap_data(pcm, stream)) < 0) + if (handle->mmap_data) { + if ((err = snd_pcm_munmap_data(handle)) < 0) ret = err; } - if ((err = pcm->ops->stream_close(pcm, stream)) < 0) + if ((err = handle->ops->close(handle->op_arg)) < 0) ret = err; - str->open = 0; - str->valid_setup = 0; + handle->valid_setup = 0; + free(handle); return ret; } -int snd_pcm_close(snd_pcm_t *pcm) -{ - int err, ret = 0; - int stream; - - assert(pcm); - for (stream = 0; stream < 2; ++stream) { - if (pcm->stream[stream].open) { - if ((err = snd_pcm_stream_close(pcm, stream)) < 0) - ret = err; - } - } - free(pcm); - return ret; -} - -int snd_pcm_stream_nonblock(snd_pcm_t *pcm, int stream, int nonblock) +int snd_pcm_nonblock(snd_pcm_t *handle, int nonblock) { int err; - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(pcm->stream[stream].open); - if ((err = pcm->ops->stream_nonblock(pcm, stream, nonblock)) < 0) + assert(handle); + if ((err = handle->ops->nonblock(handle->op_arg, nonblock)) < 0) return err; if (nonblock) - str->mode |= SND_PCM_NONBLOCK; + handle->mode |= SND_PCM_NONBLOCK; else - str->mode &= ~SND_PCM_NONBLOCK; + handle->mode &= ~SND_PCM_NONBLOCK; return 0; } -int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info) +int snd_pcm_info(snd_pcm_t *handle, snd_pcm_info_t *info) { - int stream; - assert(pcm && info); - for (stream = 0; stream < 2; ++stream) { - if (pcm->stream[stream].open) - return pcm->ops->info(pcm, stream, info); - } - assert(0); + assert(handle && info); + /* Here we pass private and not op_arg. + FIXME: find a better solution */ + return handle->ops->info(handle->private, info); } -int snd_pcm_stream_info(snd_pcm_t *pcm, snd_pcm_stream_info_t *info) -{ - assert(pcm && info); - assert(info->stream >= 0 && info->stream <= 1); - assert(pcm->stream[info->stream].open); - return pcm->ops->stream_info(pcm, info); -} - -int snd_pcm_stream_params(snd_pcm_t *pcm, snd_pcm_stream_params_t *params) +int snd_pcm_setup(snd_pcm_t *handle, snd_pcm_setup_t *setup) { int err; - snd_pcm_stream_setup_t setup; - snd_pcm_stream_t *str; - assert(pcm && params); - assert(params->stream >= 0 && params->stream <= 1); - str = &pcm->stream[params->stream]; - assert(str->open); - assert(!str->mmap_data); - if ((err = pcm->ops->stream_params(pcm, params)) < 0) - return err; - str->valid_setup = 0; - setup.stream = params->stream; - return snd_pcm_stream_setup(pcm, &setup); -} - -int snd_pcm_stream_setup(snd_pcm_t *pcm, snd_pcm_stream_setup_t *setup) -{ - int err; - snd_pcm_stream_t *str; - assert(pcm && setup); - assert(setup->stream >= 0 && setup->stream <= 1); - str = &pcm->stream[setup->stream]; - assert(str->open); - if (str->valid_setup) { - *setup = str->setup; + assert(handle && setup); + if (handle->valid_setup) { + *setup = handle->setup; return 0; } - str->setup.stream = setup->stream; - if ((err = pcm->ops->stream_setup(pcm, &str->setup)) < 0) + /* Here we pass private and not op_arg. + FIXME: find a better solution */ + if ((err = handle->ops->setup(handle->private, &handle->setup)) < 0) return err; - *setup = str->setup; - str->bits_per_sample = snd_pcm_format_physical_width(setup->format.format); - str->bits_per_frame = str->bits_per_sample * setup->format.channels; - str->valid_setup = 1; + *setup = handle->setup; + handle->bits_per_sample = snd_pcm_format_physical_width(setup->format.format); + handle->bits_per_frame = handle->bits_per_sample * setup->format.channels; + handle->valid_setup = 1; return 0; } -const snd_pcm_stream_setup_t* snd_pcm_stream_cached_setup(snd_pcm_t *pcm, int stream) -{ - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - return &str->setup; -} - -int snd_pcm_channel_setup(snd_pcm_t *pcm, int stream, snd_pcm_channel_setup_t *setup) +int snd_pcm_channel_setup(snd_pcm_t *handle, snd_pcm_channel_setup_t *setup) { - snd_pcm_stream_t *str; - assert(pcm && setup); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - return pcm->ops->channel_setup(pcm, stream, setup); + assert(handle && setup); + assert(handle->valid_setup); + return handle->ops->channel_setup(handle->op_arg, setup); } -int snd_pcm_stream_status(snd_pcm_t *pcm, snd_pcm_stream_status_t *status) +int snd_pcm_params(snd_pcm_t *handle, snd_pcm_params_t *params) { - assert(pcm && status); - assert(status->stream >= 0 && status->stream <= 1); - assert(pcm->stream[status->stream].open); - return pcm->ops->stream_status(pcm, status); -} - -int snd_pcm_stream_state(snd_pcm_t *pcm, int stream) -{ - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->open); - if (str->mmap_status) - return str->mmap_status->state; - return pcm->ops->stream_state(pcm, stream); -} - -int snd_pcm_stream_frame_io(snd_pcm_t *pcm, int stream, int update) -{ - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - if (str->mmap_status && !update) - return str->mmap_status->frame_io; - return pcm->ops->stream_frame_io(pcm, stream, update); -} - -int snd_pcm_stream_prepare(snd_pcm_t *pcm, int stream) -{ - assert(pcm); - assert(stream >= 0 && stream <= 1); - assert(pcm->stream[stream].open); - return pcm->ops->stream_prepare(pcm, stream); -} - -int snd_pcm_playback_prepare(snd_pcm_t *pcm) -{ - return snd_pcm_stream_prepare(pcm, SND_PCM_STREAM_PLAYBACK); -} - -int snd_pcm_capture_prepare(snd_pcm_t *pcm) -{ - return snd_pcm_stream_prepare(pcm, SND_PCM_STREAM_CAPTURE); -} - -int snd_pcm_stream_go(snd_pcm_t *pcm, int stream) -{ - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - return pcm->ops->stream_go(pcm, stream); + int err; + snd_pcm_setup_t setup; + assert(handle && params); + assert(!handle->mmap_data); + /* Here we pass private and not op_arg. + FIXME: find a better solution */ + if ((err = handle->ops->params(handle->private, params)) < 0) + return err; + handle->valid_setup = 0; + return snd_pcm_setup(handle, &setup); } -int snd_pcm_playback_go(snd_pcm_t *pcm) +int snd_pcm_status(snd_pcm_t *handle, snd_pcm_status_t *status) { - return snd_pcm_stream_go(pcm, SND_PCM_STREAM_PLAYBACK); + assert(handle && status); + return handle->ops->status(handle->op_arg, status); } -int snd_pcm_capture_go(snd_pcm_t *pcm) +int snd_pcm_state(snd_pcm_t *handle) { - return snd_pcm_stream_go(pcm, SND_PCM_STREAM_CAPTURE); + assert(handle); + if (handle->mmap_status) + return handle->mmap_status->state; + return handle->ops->state(handle->op_arg); } -int snd_pcm_sync_go(snd_pcm_t *pcm, snd_pcm_sync_t *sync) +int snd_pcm_frame_io(snd_pcm_t *handle, int update) { - int stream; - assert(pcm && sync); - for (stream = 0; stream < 2; ++stream) { - if (pcm->stream[stream].open) - return pcm->ops->sync_go(pcm, stream, sync); - } - assert(0); + assert(handle); + assert(handle->valid_setup); + if (handle->mmap_status && !update) + return handle->mmap_status->frame_io; + return handle->ops->frame_io(handle->op_arg, update); } -int snd_pcm_stream_drain(snd_pcm_t *pcm, int stream) +int snd_pcm_prepare(snd_pcm_t *handle) { - assert(pcm); - assert(stream >= 0 && stream <= 1); - assert(pcm->stream[stream].open); - assert(stream == SND_PCM_STREAM_PLAYBACK); - return pcm->ops->stream_drain(pcm, stream); + assert(handle); + return handle->ops->prepare(handle->op_arg); } -int snd_pcm_playback_drain(snd_pcm_t *pcm) +int snd_pcm_go(snd_pcm_t *handle) { - return snd_pcm_stream_drain(pcm, SND_PCM_STREAM_PLAYBACK); + assert(handle); + return handle->ops->go(handle->op_arg); } -int snd_pcm_stream_flush(snd_pcm_t *pcm, int stream) +int snd_pcm_sync_go(snd_pcm_t *handle, snd_pcm_sync_t *sync) { - assert(pcm); - assert(stream >= 0 && stream <= 1); - assert(pcm->stream[stream].open); - return pcm->ops->stream_flush(pcm, stream); + assert(handle); + return handle->ops->sync_go(handle->op_arg, sync); } -int snd_pcm_playback_flush(snd_pcm_t *pcm) +int snd_pcm_drain(snd_pcm_t *handle) { - return snd_pcm_stream_flush(pcm, SND_PCM_STREAM_PLAYBACK); + assert(handle); + return handle->ops->drain(handle->op_arg); } -int snd_pcm_capture_flush(snd_pcm_t *pcm) +int snd_pcm_flush(snd_pcm_t *handle) { - return snd_pcm_stream_flush(pcm, SND_PCM_STREAM_CAPTURE); + assert(handle); + return handle->ops->flush(handle->op_arg); } -int snd_pcm_stream_pause(snd_pcm_t *pcm, int stream, int enable) +int snd_pcm_pause(snd_pcm_t *handle, int enable) { - assert(pcm); - assert(stream >= 0 && stream <= 1); - assert(pcm->stream[stream].open); - assert(stream == SND_PCM_STREAM_PLAYBACK); - return pcm->ops->stream_pause(pcm, stream, enable); + assert(handle); + return handle->ops->pause(handle->op_arg, enable); } -int snd_pcm_playback_pause(snd_pcm_t *pcm, int enable) -{ - return snd_pcm_stream_pause(pcm, SND_PCM_STREAM_PLAYBACK, enable); -} -ssize_t snd_pcm_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) +ssize_t snd_pcm_frame_data(snd_pcm_t *handle, off_t offset) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - if (str->mmap_control) { + assert(handle); + assert(handle->valid_setup); + if (handle->mmap_control) { if (offset == 0) - return str->mmap_control->frame_data; - if (str->mmap_status) - return snd_pcm_mmap_stream_frame_data(pcm, stream, offset); + return handle->mmap_control->frame_data; } - return pcm->ops->stream_frame_data(pcm, stream, offset); + return handle->ops->frame_data(handle->op_arg, offset); } -ssize_t snd_pcm_write(snd_pcm_t *pcm, const void *buffer, size_t size) +ssize_t snd_pcm_write(snd_pcm_t *handle, const void *buffer, size_t size) { - snd_pcm_stream_t *str; - assert(pcm); - str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - assert(str->valid_setup); + assert(handle); assert(size == 0 || buffer); - assert(size % str->setup.frames_align == 0); - return pcm->ops->write(pcm, buffer, size); + assert(handle->valid_setup); + assert(size % handle->setup.frames_align == 0); + return handle->ops->write(handle->op_arg, buffer, size); } -ssize_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count) +ssize_t snd_pcm_writev(snd_pcm_t *handle, const struct iovec *vector, unsigned long count) { - assert(pcm); - assert(pcm->stream[SND_PCM_STREAM_PLAYBACK].valid_setup); + assert(handle); assert(count == 0 || vector); - return pcm->ops->writev(pcm, vector, count); + assert(handle->valid_setup); + return handle->ops->writev(handle->op_arg, vector, count); } -ssize_t snd_pcm_read(snd_pcm_t *pcm, void *buffer, size_t size) +ssize_t snd_pcm_read(snd_pcm_t *handle, void *buffer, size_t size) { - snd_pcm_stream_t *str; - assert(pcm); - str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - assert(str->valid_setup); + assert(handle); assert(size == 0 || buffer); - assert(size % str->setup.frames_align == 0); - return pcm->ops->read(pcm, buffer, size); + assert(handle->valid_setup); + assert(size % handle->setup.frames_align == 0); + return handle->ops->read(handle->op_arg, buffer, size); } -ssize_t snd_pcm_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count) +ssize_t snd_pcm_readv(snd_pcm_t *handle, const struct iovec *vector, unsigned long count) { - assert(pcm); - assert(pcm->stream[SND_PCM_STREAM_CAPTURE].valid_setup); + assert(handle); assert(count == 0 || vector); - return pcm->ops->readv(pcm, vector, count); + assert(handle->valid_setup); + return handle->ops->readv(handle->op_arg, vector, count); } -int snd_pcm_file_descriptor(snd_pcm_t* pcm, int stream) +int snd_pcm_file_descriptor(snd_pcm_t *handle) { - assert(pcm); - assert(stream >= 0 && stream <= 1); - assert(pcm->stream[stream].open); - return pcm->ops->file_descriptor(pcm, stream); + assert(handle); + return handle->ops->file_descriptor(handle->op_arg); } -int snd_pcm_channels_mask(snd_pcm_t *pcm, int stream, bitset_t *client_vmask) +int snd_pcm_channels_mask(snd_pcm_t *handle, bitset_t *client_vmask) { - assert(pcm); - assert(stream >= 0 && stream <= 1); - assert(pcm->stream[stream].valid_setup); - return pcm->ops->channels_mask(pcm, stream, client_vmask); + assert(handle); + assert(handle->valid_setup); + return handle->ops->channels_mask(handle->op_arg, client_vmask); } typedef struct { @@ -475,16 +322,13 @@ static assoc_t xruns[] = { XRUN(FLUSH), XRUN(DRAIN), END }; static assoc_t fills[] = { FILL(NONE), FILL(SILENCE_WHOLE), FILL(SILENCE), END }; static assoc_t onoff[] = { {0, "OFF", NULL}, {1, "ON", NULL}, {-1, "ON", NULL}, END }; -int snd_pcm_dump_setup(snd_pcm_t *pcm, int stream, FILE *fp) +int snd_pcm_dump_setup(snd_pcm_t *handle, FILE *fp) { - snd_pcm_stream_t *str; - snd_pcm_stream_setup_t *setup; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - setup = &str->setup; - fprintf(fp, "stream: %s\n", assoc(setup->stream, streams)); + snd_pcm_setup_t *setup; + assert(handle); + assert(handle->valid_setup); + setup = &handle->setup; + fprintf(fp, "stream: %s\n", assoc(handle->stream, streams)); fprintf(fp, "mode: %s\n", assoc(setup->mode, modes)); fprintf(fp, "format: %s\n", assoc(setup->format.format, fmts)); fprintf(fp, "channels: %d\n", setup->format.channels); @@ -532,42 +376,31 @@ int snd_pcm_get_format_value(const char* name) return -1; } -ssize_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, int stream, int bytes) +ssize_t snd_pcm_bytes_to_frames(snd_pcm_t *handle, int bytes) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - return bytes * 8 / str->bits_per_frame; + assert(handle); + assert(handle->valid_setup); + return bytes * 8 / handle->bits_per_frame; } -ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, int stream, int frames) +ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *handle, int frames) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - return frames * str->bits_per_frame / 8; + assert(handle); + assert(handle->valid_setup); + return frames * handle->bits_per_frame / 8; } -ssize_t snd_pcm_bytes_to_samples(snd_pcm_t *pcm, int stream, int bytes) +ssize_t snd_pcm_bytes_to_samples(snd_pcm_t *handle, int bytes) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - return bytes * 8 / str->bits_per_sample; + assert(handle); + assert(handle->valid_setup); + return bytes * 8 / handle->bits_per_sample; } -ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, int stream, int samples) +ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *handle, int samples) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - return samples * str->bits_per_sample / 8; + assert(handle); + assert(handle->valid_setup); + return samples * handle->bits_per_sample / 8; } + diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 335f901b..6ea34830 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -30,35 +30,30 @@ #include "pcm_local.h" typedef struct { + snd_pcm_t *handle; int fd; -} snd_pcm_hw_stream_t; - -typedef struct snd_pcm_hw { - int card; - int device; - int ver; - snd_pcm_hw_stream_t stream[2]; } snd_pcm_hw_t; -#define SND_FILE_PCM_PLAYBACK "/dev/snd/pcmC%iD%ip" -#define SND_FILE_PCM_CAPTURE "/dev/snd/pcmC%iD%ic" +#define SND_FILE_PCM_STREAM_PLAYBACK "/dev/snd/pcmC%iD%ip" +#define SND_FILE_PCM_STREAM_CAPTURE "/dev/snd/pcmC%iD%ic" #define SND_PCM_VERSION_MAX SND_PROTOCOL_VERSION(2, 0, 0) -static int snd_pcm_hw_stream_close(snd_pcm_t *pcm, int stream) +static int snd_pcm_hw_close(void *private) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + free(private); if (fd >= 0) if (close(fd)) return -errno; return 0; } -static int snd_pcm_hw_stream_nonblock(snd_pcm_t *pcm, int stream, int nonblock) +static int snd_pcm_hw_nonblock(void *private, int nonblock) { long flags; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; if ((flags = fcntl(fd, F_GETFL)) < 0) return -errno; @@ -71,151 +66,144 @@ static int snd_pcm_hw_stream_nonblock(snd_pcm_t *pcm, int stream, int nonblock) return 0; } -static int snd_pcm_hw_info(snd_pcm_t *pcm, int stream, snd_pcm_info_t * info) +static int snd_pcm_hw_info(void *private, snd_pcm_info_t * info) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; if (ioctl(fd, SND_PCM_IOCTL_INFO, info) < 0) return -errno; return 0; } -static int snd_pcm_hw_stream_info(snd_pcm_t *pcm, snd_pcm_stream_info_t * info) -{ - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[info->stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_INFO, info) < 0) - return -errno; - return 0; -} - -static int snd_pcm_hw_stream_params(snd_pcm_t *pcm, snd_pcm_stream_params_t * params) +static int snd_pcm_hw_params(void *private, snd_pcm_params_t * params) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[params->stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_PARAMS, params) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_PARAMS, params) < 0) return -errno; return 0; } -static int snd_pcm_hw_stream_setup(snd_pcm_t *pcm, snd_pcm_stream_setup_t * setup) +static int snd_pcm_hw_setup(void *private, snd_pcm_setup_t * setup) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[setup->stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_SETUP, setup) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_SETUP, setup) < 0) return -errno; return 0; } -static int snd_pcm_hw_channel_setup(snd_pcm_t *pcm, int stream, snd_pcm_channel_setup_t * setup) +static int snd_pcm_hw_channel_setup(void *private, snd_pcm_channel_setup_t * setup) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; if (ioctl(fd, SND_PCM_IOCTL_CHANNEL_SETUP, setup) < 0) return -errno; return 0; } -static int snd_pcm_hw_stream_status(snd_pcm_t *pcm, snd_pcm_stream_status_t * status) +static int snd_pcm_hw_status(void *private, snd_pcm_status_t * status) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[status->stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_STATUS, status) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_STATUS, status) < 0) return -errno; return 0; } -static ssize_t snd_pcm_hw_stream_state(snd_pcm_t *pcm, int stream) +static ssize_t snd_pcm_hw_state(void *private) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; - snd_pcm_stream_status_t status; - status.stream = stream; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_STATUS, status) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + snd_pcm_status_t status; + if (ioctl(fd, SND_PCM_IOCTL_STATUS, status) < 0) return -errno; return status.state; } -static ssize_t snd_pcm_hw_stream_frame_io(snd_pcm_t *pcm, int stream, int update UNUSED) +static ssize_t snd_pcm_hw_frame_io(void *private, int update UNUSED) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; - ssize_t pos = ioctl(fd, SND_PCM_IOCTL_STREAM_FRAME_IO); + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + ssize_t pos = ioctl(fd, SND_PCM_IOCTL_FRAME_IO); if (pos < 0) return -errno; return pos; } -static int snd_pcm_hw_stream_prepare(snd_pcm_t *pcm, int stream) +static int snd_pcm_hw_prepare(void *private) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_PREPARE) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_PREPARE) < 0) return -errno; return 0; } -static int snd_pcm_hw_stream_go(snd_pcm_t *pcm, int stream) +static int snd_pcm_hw_go(void *private) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_GO) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_GO) < 0) return -errno; return 0; } -static int snd_pcm_hw_sync_go(snd_pcm_t *pcm, int stream, snd_pcm_sync_t *sync) +static int snd_pcm_hw_sync_go(void *private, snd_pcm_sync_t *sync) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; if (ioctl(fd, SND_PCM_IOCTL_SYNC_GO, sync) < 0) return -errno; return 0; } -static int snd_pcm_hw_stream_drain(snd_pcm_t *pcm, int stream) +static int snd_pcm_hw_drain(void *private) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_DRAIN) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_DRAIN) < 0) return -errno; return 0; } -static int snd_pcm_hw_stream_flush(snd_pcm_t *pcm, int stream) +static int snd_pcm_hw_flush(void *private) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_FLUSH) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_FLUSH) < 0) return -errno; return 0; } -static int snd_pcm_hw_stream_pause(snd_pcm_t *pcm, int stream, int enable) +static int snd_pcm_hw_pause(void *private, int enable) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; - if (ioctl(fd, SND_PCM_IOCTL_STREAM_PAUSE, &enable) < 0) + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; + if (ioctl(fd, SND_PCM_IOCTL_PAUSE, &enable) < 0) return -errno; return 0; } -static ssize_t snd_pcm_hw_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) +static ssize_t snd_pcm_hw_frame_data(void *private, off_t offset) { ssize_t result; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[stream].fd; - result = ioctl(fd, SND_PCM_IOCTL_STREAM_FRAME_DATA, offset); + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + snd_pcm_t *handle = hw->handle; + int fd = hw->fd; + if (handle->mmap_status && handle->mmap_control) + return snd_pcm_mmap_frame_data(handle, offset); + result = ioctl(fd, SND_PCM_IOCTL_FRAME_DATA, offset); if (result < 0) return -errno; return result; } -static ssize_t snd_pcm_hw_write(snd_pcm_t *pcm, const void *buffer, size_t size) +static ssize_t snd_pcm_hw_write(void *private, const void *buffer, size_t size) { ssize_t result; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[SND_PCM_STREAM_PLAYBACK].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; snd_xfer_t xfer; xfer.buf = (char*) buffer; xfer.count = size; @@ -225,11 +213,11 @@ static ssize_t snd_pcm_hw_write(snd_pcm_t *pcm, const void *buffer, size_t size) return result; } -static ssize_t snd_pcm_hw_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count) +static ssize_t snd_pcm_hw_writev(void *private, const struct iovec *vector, unsigned long count) { ssize_t result; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[SND_PCM_STREAM_PLAYBACK].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; snd_xferv_t xferv; xferv.vector = vector; xferv.count = count; @@ -239,11 +227,11 @@ static ssize_t snd_pcm_hw_writev(snd_pcm_t *pcm, const struct iovec *vector, uns return result; } -static ssize_t snd_pcm_hw_read(snd_pcm_t *pcm, void *buffer, size_t size) +static ssize_t snd_pcm_hw_read(void *private, void *buffer, size_t size) { ssize_t result; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[SND_PCM_STREAM_CAPTURE].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; snd_xfer_t xfer; xfer.buf = buffer; xfer.count = size; @@ -253,11 +241,11 @@ static ssize_t snd_pcm_hw_read(snd_pcm_t *pcm, void *buffer, size_t size) return result; } -ssize_t snd_pcm_hw_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count) +ssize_t snd_pcm_hw_readv(void *private, const struct iovec *vector, unsigned long count) { ssize_t result; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - int fd = hw->stream[SND_PCM_STREAM_CAPTURE].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + int fd = hw->fd; snd_xferv_t xferv; xferv.vector = vector; xferv.count = count; @@ -267,95 +255,94 @@ ssize_t snd_pcm_hw_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned lo return result; } -static int snd_pcm_hw_mmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status) +static int snd_pcm_hw_mmap_status(void *private, snd_pcm_mmap_status_t **status) { void *ptr; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; ptr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ, MAP_FILE|MAP_SHARED, - hw->stream[stream].fd, SND_PCM_MMAP_OFFSET_STATUS); + hw->fd, SND_PCM_MMAP_OFFSET_STATUS); if (ptr == MAP_FAILED || ptr == NULL) return -errno; *status = ptr; return 0; } -static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control) +static int snd_pcm_hw_mmap_control(void *private, snd_pcm_mmap_control_t **control) { void *ptr; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; ptr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, - hw->stream[stream].fd, SND_PCM_MMAP_OFFSET_CONTROL); + hw->fd, SND_PCM_MMAP_OFFSET_CONTROL); if (ptr == MAP_FAILED || ptr == NULL) return -errno; *control = ptr; return 0; } -static int snd_pcm_hw_mmap_data(snd_pcm_t *pcm, int stream, void **buffer, size_t bsize) +static int snd_pcm_hw_mmap_data(void *private, void **buffer, size_t bsize) { int prot; void *daddr; - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - prot = stream == SND_PCM_STREAM_PLAYBACK ? PROT_WRITE : PROT_READ; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + prot = hw->handle->stream == SND_PCM_STREAM_PLAYBACK ? PROT_WRITE : PROT_READ; daddr = mmap(NULL, bsize, prot, MAP_FILE|MAP_SHARED, - hw->stream[stream].fd, SND_PCM_MMAP_OFFSET_DATA); + hw->fd, SND_PCM_MMAP_OFFSET_DATA); if (daddr == MAP_FAILED || daddr == NULL) return -errno; *buffer = daddr; return 0; } -static int snd_pcm_hw_munmap_status(snd_pcm_t *pcm UNUSED, int stream UNUSED, snd_pcm_mmap_status_t *status) +static int snd_pcm_hw_munmap_status(void *private UNUSED, snd_pcm_mmap_status_t *status) { if (munmap(status, sizeof(*status)) < 0) return -errno; return 0; } -static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm UNUSED, int stream UNUSED, snd_pcm_mmap_control_t *control) +static int snd_pcm_hw_munmap_control(void *private UNUSED, snd_pcm_mmap_control_t *control) { if (munmap(control, sizeof(*control)) < 0) return -errno; return 0; } -static int snd_pcm_hw_munmap_data(snd_pcm_t *pcm UNUSED, int stream UNUSED, void *buffer, size_t bsize) +static int snd_pcm_hw_munmap_data(void *private UNUSED, void *buffer, size_t bsize) { if (munmap(buffer, bsize) < 0) return -errno; return 0; } -static int snd_pcm_hw_file_descriptor(snd_pcm_t *pcm, int stream) +static int snd_pcm_hw_file_descriptor(void *private) { - snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - return hw->stream[stream].fd; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private; + return hw->fd; } -static int snd_pcm_hw_channels_mask(snd_pcm_t *pcm UNUSED, int stream UNUSED, - bitset_t *client_vmask UNUSED) +static int snd_pcm_hw_channels_mask(void *private UNUSED, + bitset_t *client_vmask UNUSED) { return 0; } struct snd_pcm_ops snd_pcm_hw_ops = { - stream_close: snd_pcm_hw_stream_close, - stream_nonblock: snd_pcm_hw_stream_nonblock, + close: snd_pcm_hw_close, + nonblock: snd_pcm_hw_nonblock, info: snd_pcm_hw_info, - stream_info: snd_pcm_hw_stream_info, - stream_params: snd_pcm_hw_stream_params, - stream_setup: snd_pcm_hw_stream_setup, + params: snd_pcm_hw_params, + setup: snd_pcm_hw_setup, channel_setup: snd_pcm_hw_channel_setup, - stream_status: snd_pcm_hw_stream_status, - stream_frame_io: snd_pcm_hw_stream_frame_io, - stream_state: snd_pcm_hw_stream_state, - stream_prepare: snd_pcm_hw_stream_prepare, - stream_go: snd_pcm_hw_stream_go, + status: snd_pcm_hw_status, + frame_io: snd_pcm_hw_frame_io, + state: snd_pcm_hw_state, + prepare: snd_pcm_hw_prepare, + go: snd_pcm_hw_go, sync_go: snd_pcm_hw_sync_go, - stream_drain: snd_pcm_hw_stream_drain, - stream_flush: snd_pcm_hw_stream_flush, - stream_pause: snd_pcm_hw_stream_pause, - stream_frame_data: snd_pcm_hw_stream_frame_data, + drain: snd_pcm_hw_drain, + flush: snd_pcm_hw_flush, + pause: snd_pcm_hw_pause, + frame_data: snd_pcm_hw_frame_data, write: snd_pcm_hw_write, writev: snd_pcm_hw_writev, read: snd_pcm_hw_read, @@ -370,122 +357,99 @@ struct snd_pcm_ops snd_pcm_hw_ops = { channels_mask: snd_pcm_hw_channels_mask, }; -static int snd_pcm_hw_open_stream(int card, int device, int stream, int subdevice, int fmode, snd_ctl_t *ctl, int *ver) +int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int subdevice, int stream, int mode) { char filename[32]; char *filefmt; - int err, fd; + int ver; + int ret = 0, fd = -1; int attempt = 0; - snd_pcm_stream_info_t info; + snd_pcm_info_t info; + int fmode; + snd_ctl_t *ctl; + snd_pcm_t *handle; + snd_pcm_hw_t *hw; + + *handlep = 0; + + if ((ret = snd_ctl_open(&ctl, card)) < 0) + return ret; + switch (stream) { case SND_PCM_STREAM_PLAYBACK: - filefmt = SND_FILE_PCM_PLAYBACK; + filefmt = SND_FILE_PCM_STREAM_PLAYBACK; break; case SND_PCM_STREAM_CAPTURE: - filefmt = SND_FILE_PCM_CAPTURE; + filefmt = SND_FILE_PCM_STREAM_CAPTURE; break; default: assert(0); } - if ((err = snd_ctl_pcm_stream_prefer_subdevice(ctl, device, stream, subdevice)) < 0) - return err; + if ((ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice)) < 0) + goto __end; sprintf(filename, filefmt, card, device); __again: if (attempt++ > 3) { - snd_ctl_close(ctl); - return -EBUSY; + ret = -EBUSY; + goto __end; } + fmode = O_RDWR; + if (mode & SND_PCM_NONBLOCK) + fmode |= O_NONBLOCK; if ((fd = open(filename, fmode)) < 0) { - err = -errno; - return err; + ret = -errno; + goto __end; } - if (ioctl(fd, SND_PCM_IOCTL_PVERSION, ver) < 0) { - err = -errno; - close(fd); - return err; + if (ioctl(fd, SND_PCM_IOCTL_PVERSION, &ver) < 0) { + ret = -errno; + goto __end; } - if (SND_PROTOCOL_INCOMPATIBLE(*ver, SND_PCM_VERSION_MAX)) { - close(fd); - return -SND_ERROR_INCOMPATIBLE_VERSION; + if (SND_PROTOCOL_INCOMPATIBLE(ver, SND_PCM_VERSION_MAX)) { + ret = -SND_ERROR_INCOMPATIBLE_VERSION; + goto __end; } if (subdevice >= 0) { memset(&info, 0, sizeof(info)); - if (ioctl(fd, SND_PCM_IOCTL_STREAM_INFO, &info) < 0) { - err = -errno; - close(fd); - return err; + if (ioctl(fd, SND_PCM_IOCTL_INFO, &info) < 0) { + ret = -errno; + goto __end; } if (info.subdevice != subdevice) { close(fd); goto __again; } } - return fd; -} - -int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode) -{ - int fmode, ver, err; - snd_pcm_t *pcm; - snd_pcm_hw_t *hw; - snd_ctl_t *ctl; - int pfd = -1, cfd = -1; - - assert(handle); - *handle = NULL; - - assert(card >= 0 && card < SND_CARDS); - if ((err = snd_ctl_open(&ctl, card)) < 0) - return err; - if (mode & SND_PCM_OPEN_PLAYBACK) { - fmode = O_RDWR; - if (mode & SND_PCM_NONBLOCK_PLAYBACK) - fmode |= O_NONBLOCK; - pfd = snd_pcm_hw_open_stream(card, device, SND_PCM_STREAM_PLAYBACK, - subdevice, fmode, ctl, &ver); - if (pfd < 0) { - snd_ctl_close(ctl); - return pfd; - } + handle = calloc(1, sizeof(snd_pcm_t)); + if (!handle) { + ret = -ENOMEM; + goto __end; } - if (mode & SND_PCM_OPEN_CAPTURE) { - fmode = O_RDWR; - if (mode & SND_PCM_NONBLOCK_CAPTURE) - fmode |= O_NONBLOCK; - cfd = snd_pcm_hw_open_stream(card, device, SND_PCM_STREAM_CAPTURE, - subdevice, fmode, ctl, &ver); - if (cfd < 0) { - if (pfd >= 0) - close(pfd); - snd_ctl_close(ctl); - return cfd; - } + hw = calloc(1, sizeof(snd_pcm_hw_t)); + if (!handle) { + free(handle); + ret = -ENOMEM; + goto __end; } + hw->handle = handle; + hw->fd = fd; + handle->type = SND_PCM_TYPE_HW; + handle->stream = stream; + handle->ops = &snd_pcm_hw_ops; + handle->op_arg = hw; + handle->mode = mode; + handle->private = hw; + *handlep = handle; + + __end: + if (ret < 0 && fd >= 0) + close(fd); snd_ctl_close(ctl); - assert(pfd >= 0 || cfd >= 0); - - err = snd_pcm_abstract_open(handle, mode, SND_PCM_TYPE_HW, sizeof(snd_pcm_hw_t)); - if (err < 0) { - if (pfd >= 0) - close(pfd); - if (cfd >= 0) - close(cfd); - return err; - } - pcm = *handle; - pcm->ops = &snd_pcm_hw_ops; - hw = (snd_pcm_hw_t*) &pcm->private; - hw->card = card; - hw->device = device; - hw->ver = ver; - hw->stream[SND_PCM_STREAM_PLAYBACK].fd = pfd; - hw->stream[SND_PCM_STREAM_CAPTURE].fd = cfd; - return 0; + return ret; } -int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode) +int snd_pcm_hw_open(snd_pcm_t **handlep, int card, int device, int stream, int mode) { - return snd_pcm_open_subdevice(handle, card, device, -1, mode); + return snd_pcm_hw_open_subdevice(handlep, card, device, -1, stream, mode); } diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 6c4e62cb..9968927e 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -21,58 +21,44 @@ #include #include "asoundlib.h" - + struct snd_pcm_ops { - int (*stream_close)(snd_pcm_t *pcm, int stream); - int (*stream_nonblock)(snd_pcm_t *pcm, int stream, int nonblock); - int (*info)(snd_pcm_t *pcm, int stream, snd_pcm_info_t *info); - int (*stream_info)(snd_pcm_t *pcm, snd_pcm_stream_info_t *info); - int (*stream_params)(snd_pcm_t *pcm, snd_pcm_stream_params_t *params); - int (*stream_setup)(snd_pcm_t *pcm, snd_pcm_stream_setup_t *setup); - int (*channel_setup)(snd_pcm_t *pcm, int stream, snd_pcm_channel_setup_t *setup); - int (*stream_status)(snd_pcm_t *pcm, snd_pcm_stream_status_t *status); - int (*stream_prepare)(snd_pcm_t *pcm, int stream); - int (*stream_go)(snd_pcm_t *pcm, int stream); - int (*sync_go)(snd_pcm_t *pcm, int stream, snd_pcm_sync_t *sync); - int (*stream_drain)(snd_pcm_t *pcm, int stream); - int (*stream_flush)(snd_pcm_t *pcm, int stream); - int (*stream_pause)(snd_pcm_t *pcm, int stream, int enable); - int (*stream_state)(snd_pcm_t *pcm, int stream); - ssize_t (*stream_frame_io)(snd_pcm_t *pcm, int stream, int update); - ssize_t (*stream_frame_data)(snd_pcm_t *pcm, int stream, off_t offset); - ssize_t (*write)(snd_pcm_t *pcm, const void *buffer, size_t size); - ssize_t (*writev)(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); - ssize_t (*read)(snd_pcm_t *pcm, void *buffer, size_t size); - ssize_t (*readv)(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); - int (*mmap_status)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status); - int (*mmap_control)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control); - int (*mmap_data)(snd_pcm_t *pcm, int stream, void **buffer, size_t bsize); - int (*munmap_status)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t *status); - int (*munmap_control)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t *control); - int (*munmap_data)(snd_pcm_t *pcm, int stream, void *buffer, size_t bsize); - int (*file_descriptor)(snd_pcm_t* pcm, int stream); - int (*channels_mask)(snd_pcm_t *pcm, int stream, bitset_t *client_vmask); + int (*close)(void *private); + int (*nonblock)(void *private, int nonblock); + int (*info)(void *private, snd_pcm_info_t *info); + int (*params)(void *private, snd_pcm_params_t *params); + int (*setup)(void *private, snd_pcm_setup_t *setup); + int (*channel_setup)(void *private, snd_pcm_channel_setup_t *setup); + int (*status)(void *private, snd_pcm_status_t *status); + int (*prepare)(void *private); + int (*go)(void *private); + int (*sync_go)(void *private, snd_pcm_sync_t *sync); + int (*drain)(void *private); + int (*flush)(void *private); + int (*pause)(void *private, int enable); + int (*state)(void *private); + ssize_t (*frame_io)(void *private, int update); + ssize_t (*frame_data)(void *private, off_t offset); + ssize_t (*write)(void *private, const void *buffer, size_t size); + ssize_t (*writev)(void *private, const struct iovec *vector, unsigned long count); + ssize_t (*read)(void *private, void *buffer, size_t size); + ssize_t (*readv)(void *private, const struct iovec *vector, unsigned long count); + int (*mmap_status)(void *private, snd_pcm_mmap_status_t **status); + int (*mmap_control)(void *private, snd_pcm_mmap_control_t **control); + int (*mmap_data)(void *private, void **buffer, size_t bsize); + int (*munmap_status)(void *private, snd_pcm_mmap_status_t *status); + int (*munmap_control)(void *private, snd_pcm_mmap_control_t *control); + int (*munmap_data)(void *private, void *buffer, size_t bsize); + int (*file_descriptor)(void *private); + int (*channels_mask)(void *private, bitset_t *client_vmask); }; -typedef struct { - snd_pcm_plugin_t *first; - snd_pcm_plugin_t *last; - void *alloc_ptr[2]; - size_t alloc_size[2]; - int alloc_lock[2]; -} snd_pcm_plug_stream_t; - -typedef struct { - int close_slave; - snd_pcm_t *slave; - snd_pcm_plug_stream_t stream[2]; -} snd_pcm_plug_t; - -typedef struct { - int open; +struct snd_pcm { + snd_pcm_type_t type; + int stream; int mode; int valid_setup; - snd_pcm_stream_setup_t setup; + snd_pcm_setup_t setup; snd_pcm_channel_area_t *channels; size_t bits_per_sample; size_t bits_per_frame; @@ -81,46 +67,48 @@ typedef struct { char *mmap_data; size_t mmap_data_size; enum { _INTERLEAVED, _NONINTERLEAVED, _COMPLEX } mmap_type; -} snd_pcm_stream_t; - -struct snd_pcm { - snd_pcm_type_t type; - int mode; struct snd_pcm_ops *ops; - snd_pcm_stream_t stream[2]; - int private[0]; + void *op_arg; + void *private; }; -int snd_pcm_abstract_open(snd_pcm_t **handle, int mode, snd_pcm_type_t type, size_t extra); - +#undef snd_pcm_plug_t +typedef struct snd_pcm_plug { + int close_slave; + snd_pcm_t *handle; + snd_pcm_t *slave; + snd_pcm_plugin_t *first; + snd_pcm_plugin_t *last; + size_t frames_alloc; +} snd_pcm_plug_t; unsigned int snd_pcm_plug_formats(unsigned int formats); -int snd_pcm_plug_slave_params(snd_pcm_stream_params_t *params, - snd_pcm_stream_info_t *slave_info, - snd_pcm_stream_params_t *slave_params); -int snd_pcm_plug_format(snd_pcm_plugin_handle_t *pcm, - snd_pcm_stream_params_t *params, - snd_pcm_stream_params_t *slave_params); - -ssize_t snd_pcm_plug_write_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plugin_channel_t *src_channels, size_t size); -ssize_t snd_pcm_plug_read_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plugin_channel_t *dst_channels_final, size_t size); -ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, int stream, - const struct iovec *vector, unsigned long count, +int snd_pcm_plug_slave_params(snd_pcm_params_t *params, + snd_pcm_info_t *slave_info, + snd_pcm_params_t *slave_params); +int snd_pcm_plug_format(snd_pcm_plug_t *plug, + snd_pcm_params_t *params, + snd_pcm_params_t *slave_params); + +ssize_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels, size_t size); +ssize_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *dst_channels_final, size_t size); +ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plug_t *plug, + const struct iovec *vector, unsigned long count, + snd_pcm_plugin_channel_t **channels); +ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug, + char *buf, size_t count, snd_pcm_plugin_channel_t **channels); -ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle, int stream, - char *buf, size_t count, - snd_pcm_plugin_channel_t **channels); -int snd_pcm_plug_playback_channels_mask(snd_pcm_plugin_handle_t *handle, - bitset_t *client_vmask); -int snd_pcm_plug_capture_channels_mask(snd_pcm_plugin_handle_t *handle, - bitset_t *client_vmask); +int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug, + bitset_t *client_vmask); +int snd_pcm_plug_capture_channels_mask(snd_pcm_plug_t *plug, + bitset_t *client_vmask); int snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin, - size_t frames, - snd_pcm_plugin_channel_t **channels); + size_t frames, + snd_pcm_plugin_channel_t **channels); -void *snd_pcm_plug_buf_alloc(snd_pcm_t *pcm, int stream, size_t size); -void snd_pcm_plug_buf_unlock(snd_pcm_t *pcm, int stream, void *ptr); +void *snd_pcm_plug_buf_alloc(snd_pcm_plug_t *plug, size_t size); +void snd_pcm_plug_buf_unlock(snd_pcm_plug_t *pcm, void *ptr); #define ROUTE_PLUGIN_RESOLUTION 16 @@ -133,7 +121,7 @@ int conv_index(int src_format, int dst_format); #define pdprintf( args... ) { ; } #endif -static inline size_t snd_pcm_mmap_playback_frames_avail(snd_pcm_stream_t *str) +static inline size_t snd_pcm_mmap_playback_frames_avail(snd_pcm_t *str) { ssize_t frames_avail; frames_avail = str->mmap_status->frame_io + str->setup.buffer_size - str->mmap_control->frame_data; @@ -142,7 +130,7 @@ static inline size_t snd_pcm_mmap_playback_frames_avail(snd_pcm_stream_t *str) return frames_avail; } -static inline size_t snd_pcm_mmap_capture_frames_avail(snd_pcm_stream_t *str) +static inline size_t snd_pcm_mmap_capture_frames_avail(snd_pcm_t *str) { ssize_t frames_avail; frames_avail = str->mmap_status->frame_io - str->mmap_control->frame_data; @@ -151,3 +139,4 @@ static inline size_t snd_pcm_mmap_capture_frames_avail(snd_pcm_stream_t *str) return frames_avail; } +#define snd_pcm_plug_stream(plug) ((plug)->handle->stream) diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c index 231fe0cc..8304975f 100644 --- a/src/pcm/pcm_mmap.c +++ b/src/pcm/pcm_mmap.c @@ -25,145 +25,119 @@ #include #include "pcm_local.h" -int snd_pcm_frames_avail(snd_pcm_t *pcm, int stream, ssize_t *frames) +int snd_pcm_frames_avail(snd_pcm_t *handle, ssize_t *frames) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_status && str->mmap_control); - if (stream == SND_PCM_STREAM_PLAYBACK) - *frames = snd_pcm_mmap_playback_frames_avail(str); + assert(handle); + assert(handle->mmap_status && handle->mmap_control); + if (handle->stream == SND_PCM_STREAM_PLAYBACK) + *frames = snd_pcm_mmap_playback_frames_avail(handle); else - *frames = snd_pcm_mmap_capture_frames_avail(str); + *frames = snd_pcm_mmap_capture_frames_avail(handle); return 0; } -static int snd_pcm_mmap_playback_ready(snd_pcm_t *pcm) +static int snd_pcm_mmap_playback_ready(snd_pcm_t *handle) { - snd_pcm_stream_t *str; - str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - if (str->mmap_status->state == SND_PCM_STATE_XRUN) + if (handle->mmap_status->state == SND_PCM_STATE_XRUN) return -EPIPE; - return snd_pcm_mmap_playback_frames_avail(str) >= str->setup.frames_min; + return snd_pcm_mmap_playback_frames_avail(handle) >= handle->setup.frames_min; } -static int snd_pcm_mmap_capture_ready(snd_pcm_t *pcm) +static int snd_pcm_mmap_capture_ready(snd_pcm_t *handle) { - snd_pcm_stream_t *str; int ret = 0; - str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - if (str->mmap_status->state == SND_PCM_STATE_XRUN) { + if (handle->mmap_status->state == SND_PCM_STATE_XRUN) { ret = -EPIPE; - if (str->setup.xrun_mode == SND_PCM_XRUN_DRAIN) + if (handle->setup.xrun_mode == SND_PCM_XRUN_DRAIN) return -EPIPE; } - if (snd_pcm_mmap_capture_frames_avail(str) >= str->setup.frames_min) + if (snd_pcm_mmap_capture_frames_avail(handle) >= handle->setup.frames_min) return 1; return ret; } -int snd_pcm_mmap_ready(snd_pcm_t *pcm, int stream) +int snd_pcm_mmap_ready(snd_pcm_t *handle) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_status && str->mmap_control); - assert(str->mmap_status->state >= SND_PCM_STATE_PREPARED); - if (stream == SND_PCM_STREAM_PLAYBACK) { - return snd_pcm_mmap_playback_ready(pcm); + assert(handle); + assert(handle->mmap_status && handle->mmap_control); + assert(handle->mmap_status->state >= SND_PCM_STATE_PREPARED); + if (handle->stream == SND_PCM_STREAM_PLAYBACK) { + return snd_pcm_mmap_playback_ready(handle); } else { - return snd_pcm_mmap_capture_ready(pcm); + return snd_pcm_mmap_capture_ready(handle); } } -static size_t snd_pcm_mmap_playback_frames_xfer(snd_pcm_t *pcm, size_t frames) +static size_t snd_pcm_mmap_playback_frames_xfer(snd_pcm_t *handle, size_t frames) { - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - snd_pcm_mmap_control_t *control = str->mmap_control; + snd_pcm_mmap_control_t *control = handle->mmap_control; size_t frames_cont; - size_t frames_avail = snd_pcm_mmap_playback_frames_avail(str); + size_t frames_avail = snd_pcm_mmap_playback_frames_avail(handle); if (frames_avail < frames) frames = frames_avail; - frames_cont = str->setup.buffer_size - control->frame_data % str->setup.buffer_size; + frames_cont = handle->setup.buffer_size - control->frame_data % handle->setup.buffer_size; if (frames_cont < frames) frames = frames_cont; return frames; } -static size_t snd_pcm_mmap_capture_frames_xfer(snd_pcm_t *pcm, size_t frames) +static size_t snd_pcm_mmap_capture_frames_xfer(snd_pcm_t *handle, size_t frames) { - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - snd_pcm_mmap_control_t *control = str->mmap_control; + snd_pcm_mmap_control_t *control = handle->mmap_control; size_t frames_cont; - size_t frames_avail = snd_pcm_mmap_capture_frames_avail(str); + size_t frames_avail = snd_pcm_mmap_capture_frames_avail(handle); if (frames_avail < frames) frames = frames_avail; - frames_cont = str->setup.buffer_size - control->frame_data % str->setup.buffer_size; + frames_cont = handle->setup.buffer_size - control->frame_data % handle->setup.buffer_size; if (frames_cont < frames) frames = frames_cont; return frames; } -ssize_t snd_pcm_mmap_frames_xfer(snd_pcm_t *pcm, int stream, size_t frames) +ssize_t snd_pcm_mmap_frames_xfer(snd_pcm_t *handle, size_t frames) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_status && str->mmap_control); - if (stream == SND_PCM_STREAM_PLAYBACK) - return snd_pcm_mmap_playback_frames_xfer(pcm, frames); + assert(handle); + assert(handle->mmap_status && handle->mmap_control); + if (handle->stream == SND_PCM_STREAM_PLAYBACK) + return snd_pcm_mmap_playback_frames_xfer(handle, frames); else - return snd_pcm_mmap_capture_frames_xfer(pcm, frames); + return snd_pcm_mmap_capture_frames_xfer(handle, frames); } -ssize_t snd_pcm_mmap_frames_offset(snd_pcm_t *pcm, int stream) +ssize_t snd_pcm_mmap_frames_offset(snd_pcm_t *handle) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_control); - return str->mmap_control->frame_data % str->setup.buffer_size; + assert(handle); + assert(handle->mmap_control); + return handle->mmap_control->frame_data % handle->setup.buffer_size; } -int snd_pcm_mmap_stream_state(snd_pcm_t *pcm, int stream) +int snd_pcm_mmap_state(snd_pcm_t *handle) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_status); - return str->mmap_status->state; + assert(handle); + assert(handle->mmap_status); + return handle->mmap_status->state; } -int snd_pcm_mmap_stream_frame_io(snd_pcm_t *pcm, int stream) +int snd_pcm_mmap_frame_io(snd_pcm_t *handle) { - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_status); - return str->mmap_status->frame_io; + assert(handle); + assert(handle->mmap_status); + return handle->mmap_status->frame_io; } -ssize_t snd_pcm_mmap_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) +ssize_t snd_pcm_mmap_frame_data(snd_pcm_t *handle, off_t offset) { - snd_pcm_stream_t *str; ssize_t frame_data; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_status && str->mmap_control); - frame_data = str->mmap_control->frame_data; + assert(handle); + assert(handle->mmap_status && handle->mmap_control); + assert(offset == 0 || handle->type == SND_PCM_TYPE_HW); + frame_data = handle->mmap_control->frame_data; if (offset == 0) return frame_data; - switch (str->mmap_status->state) { + switch (handle->mmap_status->state) { case SND_PCM_STATE_RUNNING: - if (str->setup.mode == SND_PCM_MODE_FRAME) - snd_pcm_stream_frame_io(pcm, stream, 1); + if (handle->setup.mode == SND_PCM_MODE_FRAME) + snd_pcm_frame_io(handle, 1); break; case SND_PCM_STATE_PREPARED: break; @@ -171,85 +145,83 @@ ssize_t snd_pcm_mmap_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) return -EBADFD; } if (offset < 0) { - if (offset < -(ssize_t)str->setup.buffer_size) - offset = -(ssize_t)str->setup.buffer_size; + if (offset < -(ssize_t)handle->setup.buffer_size) + offset = -(ssize_t)handle->setup.buffer_size; else - offset -= offset % str->setup.frames_align; + offset -= offset % handle->setup.frames_align; frame_data += offset; if (frame_data < 0) - frame_data += str->setup.frame_boundary; + frame_data += handle->setup.frame_boundary; } else { size_t frames_avail; - if (stream == SND_PCM_STREAM_PLAYBACK) - frames_avail = snd_pcm_mmap_playback_frames_avail(str); + if (handle->stream == SND_PCM_STREAM_PLAYBACK) + frames_avail = snd_pcm_mmap_playback_frames_avail(handle); else - frames_avail = snd_pcm_mmap_capture_frames_avail(str); + frames_avail = snd_pcm_mmap_capture_frames_avail(handle); if ((size_t)offset > frames_avail) offset = frames_avail; - offset -= offset % str->setup.frames_align; + offset -= offset % handle->setup.frames_align; frame_data += offset; - if ((size_t)frame_data >= str->setup.frame_boundary) - frame_data -= str->setup.frame_boundary; + if ((size_t)frame_data >= handle->setup.frame_boundary) + frame_data -= handle->setup.frame_boundary; } - str->mmap_control->frame_data = frame_data; + handle->mmap_control->frame_data = frame_data; return frame_data; } -ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels, size_t frames) +ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *handle, snd_pcm_channel_area_t *channels, size_t frames) { - snd_pcm_stream_t *str; snd_pcm_mmap_status_t *status; size_t offset = 0; size_t result = 0; int err; - str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - assert(str->mmap_data && str->mmap_status && str->mmap_control); - status = str->mmap_status; + assert(handle->mmap_data && handle->mmap_status && handle->mmap_control); + status = handle->mmap_status; assert(status->state >= SND_PCM_STATE_PREPARED); - if (str->setup.mode == SND_PCM_MODE_FRAGMENT) { - assert(frames % str->setup.frag_size == 0); + if (handle->setup.mode == SND_PCM_MODE_FRAGMENT) { + assert(frames % handle->setup.frag_size == 0); } else { if (status->state == SND_PCM_STATE_RUNNING && - str->mode & SND_PCM_NONBLOCK) - snd_pcm_stream_frame_io(pcm, SND_PCM_STREAM_PLAYBACK, 1); + handle->mode & SND_PCM_NONBLOCK) + snd_pcm_frame_io(handle, 1); } while (frames > 0) { ssize_t mmap_offset; size_t frames1; - int ready = snd_pcm_mmap_playback_ready(pcm); + int ready = snd_pcm_mmap_playback_ready(handle); if (ready < 0) return ready; if (!ready) { struct pollfd pfd; if (status->state != SND_PCM_STATE_RUNNING) return result > 0 ? result : -EPIPE; - if (str->mode & SND_PCM_NONBLOCK) + if (handle->mode & SND_PCM_NONBLOCK) return result > 0 ? result : -EAGAIN; - pfd.fd = snd_pcm_file_descriptor(pcm, SND_PCM_STREAM_PLAYBACK); + pfd.fd = snd_pcm_file_descriptor(handle); pfd.events = POLLOUT | POLLERR; ready = poll(&pfd, 1, 10000); if (ready < 0) return result > 0 ? result : ready; if (ready && pfd.revents & POLLERR) return result > 0 ? result : -EPIPE; - assert(snd_pcm_mmap_playback_ready(pcm)); + assert(snd_pcm_mmap_playback_ready(handle)); } - frames1 = snd_pcm_mmap_playback_frames_xfer(pcm, frames); + frames1 = snd_pcm_mmap_playback_frames_xfer(handle, frames); assert(frames1 > 0); - mmap_offset = snd_pcm_mmap_frames_offset(pcm, SND_PCM_STREAM_PLAYBACK); - snd_pcm_areas_copy(channels, offset, str->channels, mmap_offset, str->setup.format.channels, frames1, str->setup.format.format); + mmap_offset = snd_pcm_mmap_frames_offset(handle); + snd_pcm_areas_copy(channels, offset, handle->channels, mmap_offset, handle->setup.format.channels, frames1, handle->setup.format.format); if (status->state == SND_PCM_STATE_XRUN) return result > 0 ? result : -EPIPE; - snd_pcm_stream_frame_data(pcm, SND_PCM_STREAM_PLAYBACK, frames1); + snd_pcm_frame_data(handle, frames1); frames -= frames1; offset += frames1; result += frames1; if (status->state == SND_PCM_STATE_PREPARED && - (str->setup.start_mode == SND_PCM_START_DATA || - (str->setup.start_mode == SND_PCM_START_FULL && - !snd_pcm_mmap_playback_ready(pcm)))) { - err = snd_pcm_stream_go(pcm, SND_PCM_STREAM_PLAYBACK); + (handle->setup.start_mode == SND_PCM_START_DATA || + (handle->setup.start_mode == SND_PCM_START_FULL && + !snd_pcm_mmap_playback_ready(handle)))) { + err = snd_pcm_go(handle); if (err < 0) return result > 0 ? result : err; } @@ -257,44 +229,40 @@ ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channel return result; } -ssize_t snd_pcm_mmap_write(snd_pcm_t *pcm, const void *buffer, size_t frames) +ssize_t snd_pcm_mmap_write(snd_pcm_t *handle, const void *buffer, size_t frames) { - snd_pcm_stream_t *str; unsigned int nchannels; - assert(pcm); - str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - assert(str->mmap_data && str->mmap_status && str->mmap_control); + assert(handle); + assert(handle->mmap_data && handle->mmap_status && handle->mmap_control); assert(frames == 0 || buffer); - nchannels = str->setup.format.channels; - assert(str->setup.format.interleave || nchannels == 1); + nchannels = handle->setup.format.channels; + assert(handle->setup.format.interleave || nchannels == 1); { snd_pcm_channel_area_t channels[nchannels]; unsigned int channel; for (channel = 0; channel < nchannels; ++channel) { channels[channel].addr = (char*)buffer; - channels[channel].first = str->bits_per_sample * channel; - channels[channel].step = str->bits_per_frame; + channels[channel].first = handle->bits_per_sample * channel; + channels[channel].step = handle->bits_per_frame; } - return snd_pcm_mmap_write_areas(pcm, channels, frames); + return snd_pcm_mmap_write_areas(handle, channels, frames); } } -ssize_t snd_pcm_mmap_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long vcount) +ssize_t snd_pcm_mmap_writev(snd_pcm_t *handle, const struct iovec *vector, unsigned long vcount) { - snd_pcm_stream_t *str; size_t result = 0; unsigned int nchannels; - assert(pcm); - str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - assert(str->mmap_data && str->mmap_status && str->mmap_control); + assert(handle); + assert(handle->mmap_data && handle->mmap_status && handle->mmap_control); assert(vcount == 0 || vector); - nchannels = str->setup.format.channels; - if (str->setup.format.interleave) { + nchannels = handle->setup.format.channels; + if (handle->setup.format.interleave) { unsigned int b; for (b = 0; b < vcount; b++) { ssize_t ret; size_t frames = vector[b].iov_len; - ret = snd_pcm_mmap_write(pcm, vector[b].iov_base, frames); + ret = snd_pcm_mmap_write(handle, vector[b].iov_base, frames); if (ret < 0) { if (result <= 0) return ret; @@ -316,9 +284,9 @@ ssize_t snd_pcm_mmap_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned assert(vector[v].iov_len == frames); channels[v].addr = vector[v].iov_base; channels[v].first = 0; - channels[v].step = str->bits_per_sample; + channels[v].step = handle->bits_per_sample; } - ret = snd_pcm_mmap_write_areas(pcm, channels, frames); + ret = snd_pcm_mmap_write_areas(handle, channels, frames); if (ret < 0) { if (result <= 0) return ret; @@ -333,60 +301,58 @@ ssize_t snd_pcm_mmap_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned return result; } -ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels, size_t frames) +ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *handle, snd_pcm_channel_area_t *channels, size_t frames) { - snd_pcm_stream_t *str; snd_pcm_mmap_status_t *status; size_t offset = 0; size_t result = 0; int err; - str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - assert(str->mmap_data && str->mmap_status && str->mmap_control); - status = str->mmap_status; + assert(handle->mmap_data && handle->mmap_status && handle->mmap_control); + status = handle->mmap_status; assert(status->state >= SND_PCM_STATE_PREPARED); - if (str->setup.mode == SND_PCM_MODE_FRAGMENT) { - assert(frames % str->setup.frag_size == 0); + if (handle->setup.mode == SND_PCM_MODE_FRAGMENT) { + assert(frames % handle->setup.frag_size == 0); } else { if (status->state == SND_PCM_STATE_RUNNING && - str->mode & SND_PCM_NONBLOCK) - snd_pcm_stream_frame_io(pcm, SND_PCM_STREAM_CAPTURE, 1); + handle->mode & SND_PCM_NONBLOCK) + snd_pcm_frame_io(handle, 1); } if (status->state == SND_PCM_STATE_PREPARED && - str->setup.start_mode == SND_PCM_START_DATA) { - err = snd_pcm_stream_go(pcm, SND_PCM_STREAM_CAPTURE); + handle->setup.start_mode == SND_PCM_START_DATA) { + err = snd_pcm_go(handle); if (err < 0) return err; } while (frames > 0) { ssize_t mmap_offset; size_t frames1; - int ready = snd_pcm_mmap_capture_ready(pcm); + int ready = snd_pcm_mmap_capture_ready(handle); if (ready < 0) return ready; if (!ready) { struct pollfd pfd; if (status->state != SND_PCM_STATE_RUNNING) return result > 0 ? result : -EPIPE; - if (str->mode & SND_PCM_NONBLOCK) + if (handle->mode & SND_PCM_NONBLOCK) return result > 0 ? result : -EAGAIN; - pfd.fd = snd_pcm_file_descriptor(pcm, SND_PCM_STREAM_CAPTURE); + pfd.fd = snd_pcm_file_descriptor(handle); pfd.events = POLLIN | POLLERR; ready = poll(&pfd, 1, 10000); if (ready < 0) return result > 0 ? result : ready; if (ready && pfd.revents & POLLERR) return result > 0 ? result : -EPIPE; - assert(snd_pcm_mmap_capture_ready(pcm)); + assert(snd_pcm_mmap_capture_ready(handle)); } - frames1 = snd_pcm_mmap_capture_frames_xfer(pcm, frames); + frames1 = snd_pcm_mmap_capture_frames_xfer(handle, frames); assert(frames1 > 0); - mmap_offset = snd_pcm_mmap_frames_offset(pcm, SND_PCM_STREAM_CAPTURE); - snd_pcm_areas_copy(str->channels, mmap_offset, channels, offset, str->setup.format.channels, frames1, str->setup.format.format); + mmap_offset = snd_pcm_mmap_frames_offset(handle); + snd_pcm_areas_copy(handle->channels, mmap_offset, channels, offset, handle->setup.format.channels, frames1, handle->setup.format.format); if (status->state == SND_PCM_STATE_XRUN && - str->setup.xrun_mode == SND_PCM_XRUN_DRAIN) + handle->setup.xrun_mode == SND_PCM_XRUN_DRAIN) return result > 0 ? result : -EPIPE; - snd_pcm_stream_frame_data(pcm, SND_PCM_STREAM_CAPTURE, frames1); + snd_pcm_frame_data(handle, frames1); frames -= frames1; offset += frames1; result += frames1; @@ -394,44 +360,40 @@ ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels return result; } -ssize_t snd_pcm_mmap_read(snd_pcm_t *pcm, void *buffer, size_t frames) +ssize_t snd_pcm_mmap_read(snd_pcm_t *handle, void *buffer, size_t frames) { - snd_pcm_stream_t *str; unsigned int nchannels; - assert(pcm); - str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - assert(str->mmap_data && str->mmap_status && str->mmap_control); + assert(handle); + assert(handle->mmap_data && handle->mmap_status && handle->mmap_control); assert(frames == 0 || buffer); - nchannels = str->setup.format.channels; - assert(str->setup.format.interleave || nchannels == 1); + nchannels = handle->setup.format.channels; + assert(handle->setup.format.interleave || nchannels == 1); { snd_pcm_channel_area_t channels[nchannels]; unsigned int channel; for (channel = 0; channel < nchannels; ++channel) { channels[channel].addr = (char*)buffer; - channels[channel].first = str->bits_per_sample * channel; - channels[channel].step = str->bits_per_frame; + channels[channel].first = handle->bits_per_sample * channel; + channels[channel].step = handle->bits_per_frame; } - return snd_pcm_mmap_read_areas(pcm, channels, frames); + return snd_pcm_mmap_read_areas(handle, channels, frames); } } -ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned long vcount) +ssize_t snd_pcm_mmap_readv(snd_pcm_t *handle, const struct iovec *vector, unsigned long vcount) { - snd_pcm_stream_t *str; size_t result = 0; unsigned int nchannels; - assert(pcm); - str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - assert(str->mmap_data && str->mmap_status && str->mmap_control); + assert(handle); + assert(handle->mmap_data && handle->mmap_status && handle->mmap_control); assert(vcount == 0 || vector); - nchannels = str->setup.format.channels; - if (str->setup.format.interleave) { + nchannels = handle->setup.format.channels; + if (handle->setup.format.interleave) { unsigned int b; for (b = 0; b < vcount; b++) { ssize_t ret; size_t frames = vector[b].iov_len; - ret = snd_pcm_mmap_read(pcm, vector[b].iov_base, frames); + ret = snd_pcm_mmap_read(handle, vector[b].iov_base, frames); if (ret < 0) { if (result <= 0) return ret; @@ -453,9 +415,9 @@ ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned assert(vector[v].iov_len == frames); channels[v].addr = vector[v].iov_base; channels[v].first = 0; - channels[v].step = str->bits_per_sample; + channels[v].step = handle->bits_per_sample; } - ret = snd_pcm_mmap_read_areas(pcm, channels, frames); + ret = snd_pcm_mmap_read_areas(handle, channels, frames); if (ret < 0) { if (result <= 0) return ret; @@ -470,64 +432,55 @@ ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned return result; } -int snd_pcm_mmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status) +int snd_pcm_mmap_status(snd_pcm_t *handle, snd_pcm_mmap_status_t **status) { - snd_pcm_stream_t *str; int err; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - if (str->mmap_status) { + assert(handle); + assert(handle->valid_setup); + if (handle->mmap_status) { if (status) - *status = str->mmap_status; + *status = handle->mmap_status; return 0; } - if ((err = pcm->ops->mmap_status(pcm, stream, &str->mmap_status)) < 0) + if ((err = handle->ops->mmap_status(handle->op_arg, &handle->mmap_status)) < 0) return err; if (status) - *status = str->mmap_status; + *status = handle->mmap_status; return 0; } -int snd_pcm_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control) +int snd_pcm_mmap_control(snd_pcm_t *handle, snd_pcm_mmap_control_t **control) { - snd_pcm_stream_t *str; int err; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - if (str->mmap_control) { + assert(handle); + assert(handle->valid_setup); + if (handle->mmap_control) { if (control) - *control = str->mmap_control; + *control = handle->mmap_control; return 0; } - if ((err = pcm->ops->mmap_control(pcm, stream, &str->mmap_control)) < 0) + if ((err = handle->ops->mmap_control(handle->op_arg, &handle->mmap_control)) < 0) return err; if (control) - *control = str->mmap_control; + *control = handle->mmap_control; return 0; } -int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, int stream, snd_pcm_channel_area_t *areas) +int snd_pcm_mmap_get_areas(snd_pcm_t *handle, snd_pcm_channel_area_t *areas) { - snd_pcm_stream_t *str; snd_pcm_channel_setup_t s; snd_pcm_channel_area_t *a, *ap; unsigned int channel; int interleaved = 1, noninterleaved = 1; int err; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_data); - a = calloc(str->setup.format.channels, sizeof(*areas)); - for (channel = 0, ap = a; channel < str->setup.format.channels; ++channel, ++ap) { + assert(handle); + assert(handle->mmap_data); + a = calloc(handle->setup.format.channels, sizeof(*areas)); + for (channel = 0, ap = a; channel < handle->setup.format.channels; ++channel, ++ap) { s.channel = channel; - err = snd_pcm_channel_setup(pcm, stream, &s); + err = snd_pcm_channel_setup(handle, &s); if (err < 0) { free(a); return err; @@ -535,131 +488,118 @@ int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, int stream, snd_pcm_channel_area_t *a if (areas) areas[channel] = s.area; *ap = s.area; - if (ap->step != str->bits_per_sample || ap->first != 0) + if (ap->step != handle->bits_per_sample || ap->first != 0) noninterleaved = 0; if (ap->addr != a[0].addr || - ap->step != str->bits_per_frame || - ap->first != channel * str->bits_per_sample) + ap->step != handle->bits_per_frame || + ap->first != channel * handle->bits_per_sample) interleaved = 0; } if (noninterleaved) - str->mmap_type = _NONINTERLEAVED; + handle->mmap_type = _NONINTERLEAVED; else if (interleaved) - str->mmap_type = _INTERLEAVED; + handle->mmap_type = _INTERLEAVED; else - str->mmap_type = _COMPLEX; - str->channels = a; + handle->mmap_type = _COMPLEX; + handle->channels = a; return 0; } -int snd_pcm_mmap_data(snd_pcm_t *pcm, int stream, void **data) +int snd_pcm_mmap_data(snd_pcm_t *handle, void **data) { - snd_pcm_stream_t *str; - snd_pcm_stream_info_t info; + snd_pcm_info_t info; size_t bsize; int err; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - if (str->mmap_data) { + assert(handle); + assert(handle->valid_setup); + if (handle->mmap_data) { if (data) - *data = str->mmap_data; + *data = handle->mmap_data; return 0; } - info.stream = stream; - err = snd_pcm_stream_info(pcm, &info); + err = snd_pcm_info(handle, &info); if (err < 0) return err; bsize = info.mmap_size; - if (!(info.flags & SND_PCM_STREAM_INFO_MMAP)) + if (!(info.flags & SND_PCM_INFO_MMAP)) return -ENXIO; - if ((err = pcm->ops->mmap_data(pcm, stream, (void**)&str->mmap_data, bsize)) < 0) + if ((err = handle->ops->mmap_data(handle->op_arg, (void**)&handle->mmap_data, bsize)) < 0) return err; if (data) - *data = str->mmap_data; - str->mmap_data_size = bsize; - err = snd_pcm_mmap_get_areas(pcm, stream, NULL); + *data = handle->mmap_data; + handle->mmap_data_size = bsize; + err = snd_pcm_mmap_get_areas(handle, NULL); if (err < 0) return err; return 0; } -int snd_pcm_mmap(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status, snd_pcm_mmap_control_t **control, void **data) +int snd_pcm_mmap(snd_pcm_t *handle, snd_pcm_mmap_status_t **status, snd_pcm_mmap_control_t **control, void **data) { int err; - err = snd_pcm_mmap_status(pcm, stream, status); + err = snd_pcm_mmap_status(handle, status); if (err < 0) return err; - err = snd_pcm_mmap_control(pcm, stream, control); + err = snd_pcm_mmap_control(handle, control); if (err < 0) { - snd_pcm_munmap_status(pcm, stream); + snd_pcm_munmap_status(handle); return err; } - err = snd_pcm_mmap_data(pcm, stream, data); + err = snd_pcm_mmap_data(handle, data); if (err < 0) { - snd_pcm_munmap_status(pcm, stream); - snd_pcm_munmap_control(pcm, stream); + snd_pcm_munmap_status(handle); + snd_pcm_munmap_control(handle); return err; } return 0; } -int snd_pcm_munmap_status(snd_pcm_t *pcm, int stream) +int snd_pcm_munmap_status(snd_pcm_t *handle) { int err; - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_status); - if ((err = pcm->ops->munmap_status(pcm, stream, str->mmap_status)) < 0) + assert(handle); + assert(handle->mmap_status); + if ((err = handle->ops->munmap_status(handle->op_arg, handle->mmap_status)) < 0) return err; - str->mmap_status = 0; + handle->mmap_status = 0; return 0; } -int snd_pcm_munmap_control(snd_pcm_t *pcm, int stream) +int snd_pcm_munmap_control(snd_pcm_t *handle) { int err; - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_control); - if ((err = pcm->ops->munmap_control(pcm, stream, str->mmap_control)) < 0) + assert(handle); + assert(handle->mmap_control); + if ((err = handle->ops->munmap_control(handle->op_arg, handle->mmap_control)) < 0) return err; - str->mmap_control = 0; + handle->mmap_control = 0; return 0; } -int snd_pcm_munmap_data(snd_pcm_t *pcm, int stream) +int snd_pcm_munmap_data(snd_pcm_t *handle) { int err; - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->mmap_data); - if ((err = pcm->ops->munmap_data(pcm, stream, str->mmap_data, str->mmap_data_size)) < 0) + assert(handle); + assert(handle->mmap_data); + if ((err = handle->ops->munmap_data(handle->op_arg, handle->mmap_data, handle->mmap_data_size)) < 0) return err; - free(str->channels); - str->channels = 0; - str->mmap_data = 0; - str->mmap_data_size = 0; + free(handle->channels); + handle->channels = 0; + handle->mmap_data = 0; + handle->mmap_data_size = 0; return 0; } -int snd_pcm_munmap(snd_pcm_t *pcm, int stream) +int snd_pcm_munmap(snd_pcm_t *handle) { int err; - err = snd_pcm_munmap_status(pcm, stream); + err = snd_pcm_munmap_status(handle); if (err < 0) return err; - err = snd_pcm_munmap_control(pcm, stream); + err = snd_pcm_munmap_control(handle); if (err < 0) return err; - return snd_pcm_munmap_data(pcm, stream); + return snd_pcm_munmap_data(handle); } -- 2.47.1