From ddb7209e9a05fb1a36b68da55f0bffe352e524cd Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 30 Nov 2001 17:36:45 +0000 Subject: [PATCH] Added snd_*_poll_descriptors_revents functions. --- include/control.h | 1 + include/hwdep.h | 1 + include/mixer.h | 1 + include/pcm.h | 3 ++- include/rawmidi.h | 1 + include/seq.h | 1 + include/timer.h | 1 + src/control/control.c | 22 ++++++++++++++-- src/hwdep/hwdep.c | 24 ++++++++++++++--- src/mixer/mixer.c | 22 ++++++++++++++++ src/pcm/pcm.c | 27 ++++++++++++++++--- src/rawmidi/rawmidi.c | 20 +++++++++++++- src/seq/seq.c | 22 ++++++++++++++-- src/timer/timer.c | 24 ++++++++++++++--- test/pcm.c | 61 +++++++++++++++++++++++++++++-------------- 15 files changed, 195 insertions(+), 36 deletions(-) diff --git a/include/control.h b/include/control.h index 0567e1a2..2e5dca31 100644 --- a/include/control.h +++ b/include/control.h @@ -201,6 +201,7 @@ int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl, snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler); int snd_ctl_poll_descriptors_count(snd_ctl_t *ctl); int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int space); +int snd_ctl_poll_descriptors_revents(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe); int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info); int snd_ctl_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t * list); diff --git a/include/hwdep.h b/include/hwdep.h index 54be9bc4..0e33e78b 100644 --- a/include/hwdep.h +++ b/include/hwdep.h @@ -81,6 +81,7 @@ typedef struct _snd_hwdep snd_hwdep_t; int snd_hwdep_open(snd_hwdep_t **hwdep, const char *name, int mode); int snd_hwdep_close(snd_hwdep_t *hwdep); int snd_hwdep_poll_descriptors(snd_hwdep_t *hwdep, struct pollfd *pfds, unsigned int space); +int snd_hwdep_poll_descriptors_revents(snd_hwdep_t *hwdep, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); int snd_hwdep_nonblock(snd_hwdep_t *hwdep, int nonblock); int snd_hwdep_info(snd_hwdep_t *hwdep, snd_hwdep_info_t * info); int snd_hwdep_ioctl(snd_hwdep_t *hwdep, unsigned int request, void * arg); diff --git a/include/mixer.h b/include/mixer.h index 3b1aa740..cd4714de 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -90,6 +90,7 @@ int snd_mixer_attach(snd_mixer_t *mixer, const char *name); int snd_mixer_detach(snd_mixer_t *mixer, const char *name); int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer); int snd_mixer_poll_descriptors(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int space); +int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); int snd_mixer_load(snd_mixer_t *mixer); void snd_mixer_free(snd_mixer_t *mixer); int snd_mixer_wait(snd_mixer_t *mixer, int timeout); diff --git a/include/pcm.h b/include/pcm.h index 2782b343..a1cfc829 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -362,6 +362,7 @@ snd_pcm_type_t snd_pcm_type(snd_pcm_t *pcm); snd_pcm_stream_t snd_pcm_stream(snd_pcm_t *pcm); int snd_pcm_poll_descriptors_count(snd_pcm_t *pcm); int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space); +int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock); int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm, snd_async_callback_t callback, void *private_data); @@ -710,7 +711,7 @@ void snd_pcm_subformat_mask_copy(snd_pcm_subformat_mask_t *dst, const snd_pcm_su void snd_pcm_subformat_mask_none(snd_pcm_subformat_mask_t *mask); void snd_pcm_subformat_mask_any(snd_pcm_subformat_mask_t *mask); int snd_pcm_subformat_mask_test(const snd_pcm_subformat_mask_t *mask, snd_pcm_subformat_t val); -int snd_pcm_subformat_mask_empty(const snd_pcm_format_mask_t *mask); +int snd_pcm_subformat_mask_empty(const snd_pcm_subformat_mask_t *mask); void snd_pcm_subformat_mask_set(snd_pcm_subformat_mask_t *mask, snd_pcm_subformat_t val); void snd_pcm_subformat_mask_reset(snd_pcm_subformat_mask_t *mask, snd_pcm_subformat_t val); diff --git a/include/rawmidi.h b/include/rawmidi.h index ba355841..579da4b5 100644 --- a/include/rawmidi.h +++ b/include/rawmidi.h @@ -84,6 +84,7 @@ int snd_rawmidi_open_lconf(snd_rawmidi_t **in_rmidi, snd_rawmidi_t **out_rmidi, int snd_rawmidi_close(snd_rawmidi_t *rmidi); int snd_rawmidi_poll_descriptors_count(snd_rawmidi_t *rmidi); int snd_rawmidi_poll_descriptors(snd_rawmidi_t *rmidi, struct pollfd *pfds, unsigned int space); +int snd_rawmidi_poll_descriptors_revents(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int nfds, unsigned short *revent); int snd_rawmidi_nonblock(snd_rawmidi_t *rmidi, int nonblock); size_t snd_rawmidi_info_sizeof(void); /** \hideinitializer diff --git a/include/seq.h b/include/seq.h index 3cdd1cee..c0980c5a 100644 --- a/include/seq.h +++ b/include/seq.h @@ -90,6 +90,7 @@ snd_seq_type_t snd_seq_type(snd_seq_t *seq); int snd_seq_close(snd_seq_t *handle); int snd_seq_poll_descriptors_count(snd_seq_t *handle, short events); int snd_seq_poll_descriptors(snd_seq_t *handle, struct pollfd *pfds, unsigned int space, short events); +int snd_seq_poll_descriptors_revents(snd_seq_t *seq, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); int snd_seq_nonblock(snd_seq_t *handle, int nonblock); int snd_seq_client_id(snd_seq_t *handle); diff --git a/include/timer.h b/include/timer.h index b6bd11e5..5af762b2 100644 --- a/include/timer.h +++ b/include/timer.h @@ -110,6 +110,7 @@ int snd_timer_open_lconf(snd_timer_t **handle, const char *name, int mode, snd_c int snd_timer_close(snd_timer_t *handle); int snd_timer_poll_descriptors_count(snd_timer_t *handle); int snd_timer_poll_descriptors(snd_timer_t *handle, struct pollfd *pfds, unsigned int space); +int snd_timer_poll_descriptors_revents(snd_timer_t *timer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); int snd_timer_info(snd_timer_t *handle, snd_timer_info_t *timer); int snd_timer_params(snd_timer_t *handle, snd_timer_params_t *params); int snd_timer_status(snd_timer_t *handle, snd_timer_status_t *status); diff --git a/src/control/control.c b/src/control/control.c index c8292a09..db0d8375 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -160,15 +160,33 @@ int snd_ctl_poll_descriptors_count(snd_ctl_t *ctl) */ int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int space) { - assert(ctl); + assert(ctl && pfds); if (space > 0) { pfds->fd = ctl->poll_fd; - pfds->events = POLLIN; + pfds->events = POLLIN|POLLERR; return 1; } return 0; } +/** + * \brief get returned events from poll descriptors + * \param ctl CTL handle + * \param pfds array of poll descriptors + * \param nfds count of poll descriptors + * \param revents returned events + * \return zero if success, otherwise a negative error code + */ +int snd_ctl_poll_descriptors_revents(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) +{ + assert(ctl && pfds && revents); + if (nfds == 1) { + *revents = pfds->revents; + return 0; + } + return -EINVAL; +} + /** * \brief Ask to be informed about events (poll, #snd_ctl_async, #snd_ctl_read) * \param ctl CTL handle diff --git a/src/hwdep/hwdep.c b/src/hwdep/hwdep.c index bf014d87..cba186b5 100644 --- a/src/hwdep/hwdep.c +++ b/src/hwdep/hwdep.c @@ -260,13 +260,13 @@ int snd_hwdep_poll_descriptors(snd_hwdep_t *hwdep, struct pollfd *pfds, unsigned pfds->fd = hwdep->poll_fd; switch (hwdep->mode & O_ACCMODE) { case O_WRONLY: - pfds->events = POLLOUT; + pfds->events = POLLOUT|POLLERR; break; case O_RDONLY: - pfds->events = POLLIN; + pfds->events = POLLIN|POLLERR; break; case O_RDWR: - pfds->events = POLLOUT|POLLIN; + pfds->events = POLLOUT|POLLIN|POLLERR; break; default: return -EIO; @@ -276,6 +276,24 @@ int snd_hwdep_poll_descriptors(snd_hwdep_t *hwdep, struct pollfd *pfds, unsigned return 0; } +/** + * \brief get returned events from poll descriptors + * \param hwdep HwDep handle + * \param pfds array of poll descriptors + * \param nfds count of poll descriptors + * \param revents returned events + * \return zero if success, otherwise a negative error code + */ +int snd_hwdep_poll_descriptors_revents(snd_hwdep_t *hwdep, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) +{ + assert(hwdep && pfds && revents); + if (nfds == 1) { + *revents = pfds->revents; + return 0; + } + return -EINVAL; +} + /** * \brief set nonblock mode * \param hwdep HwDep handle diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c index 0053aed8..71f5539e 100644 --- a/src/mixer/mixer.c +++ b/src/mixer/mixer.c @@ -599,6 +599,28 @@ int snd_mixer_poll_descriptors(snd_mixer_t *mixer, struct pollfd *pfds, unsigned return count; } +/** + * \brief get returned events from poll descriptors + * \param mixer Mixer handle + * \param pfds array of poll descriptors + * \param nfds count of poll descriptors + * \param revents returned events + * \return zero if success, otherwise a negative error code + */ +int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) +{ + unsigned int idx; + unsigned short res; + assert(mixer && pfds && revents); + if (nfds == 0) + return -EINVAL; + res = 0; + for (idx = 0; idx < nfds; idx++) + res |= pfds->revents & (POLLIN|POLLERR); + *revents = res; + return 0; +} + /** * \brief Wait for a mixer to become ready (i.e. at least one event pending) * \param mixer Mixer handle diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index ba9b56de..b221f925 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -1003,14 +1003,33 @@ int snd_pcm_poll_descriptors_count(snd_pcm_t *pcm) */ int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space) { - assert(pcm); - if (space >= 1) { + assert(pcm && pfds); + if (space >= 1 && pfds) { pfds->fd = pcm->poll_fd; - pfds->events = pcm->stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN; - } + pfds->events = pcm->stream == SND_PCM_STREAM_PLAYBACK ? (POLLOUT|POLLERR) : (POLLIN|POLLERR); + } else + return 0; return 1; } +/** + * \brief get returned events from poll descriptors + * \param pcm PCM handle + * \param pfds array of poll descriptors + * \param nfds count of poll descriptors + * \param revents returned events + * \return zero if success, otherwise a negative error code + */ +int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) +{ + assert(pcm && pfds && revents); + if (nfds == 1) { + *revents = pfds->revents; + return 0; + } + return -EINVAL; +} + #ifndef DOC_HIDDEN #define STATE(v) [SND_PCM_STATE_##v] = #v #define STREAM(v) [SND_PCM_STREAM_##v] = #v diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c index bef3d50d..c6652a23 100644 --- a/src/rawmidi/rawmidi.c +++ b/src/rawmidi/rawmidi.c @@ -313,12 +313,30 @@ int snd_rawmidi_poll_descriptors(snd_rawmidi_t *rawmidi, struct pollfd *pfds, un assert(rawmidi); if (space >= 1) { pfds->fd = rawmidi->poll_fd; - pfds->events = rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT ? POLLOUT : POLLIN; + pfds->events = rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT ? (POLLOUT|POLLERR) : (POLLIN|POLLERR); return 1; } return 0; } +/** + * \brief get returned events from poll descriptors + * \param pcm rawmidi RawMidi handle + * \param pfds array of poll descriptors + * \param nfds count of poll descriptors + * \param revents returned events + * \return zero if success, otherwise a negative error code + */ +int snd_rawmidi_poll_descriptors_revents(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) +{ + assert(rawmidi && pfds && revents); + if (nfds == 1) { + *revents = pfds->revents; + return 0; + } + return -EINVAL; +} + /** * \brief set nonblock mode * \param rawmidi RawMidi handle diff --git a/src/seq/seq.c b/src/seq/seq.c index 98b3cced..66e52b3a 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -305,11 +305,11 @@ int snd_seq_poll_descriptors(snd_seq_t *seq, struct pollfd *pfds, unsigned int s assert(seq); if ((events & POLLIN) && space >= 1) { assert(seq->streams & SND_SEQ_OPEN_INPUT); - revents |= POLLIN; + revents |= POLLIN|POLLERR; } if ((events & POLLOUT) && space >= 1) { assert(seq->streams & SND_SEQ_OPEN_INPUT); - revents |= POLLOUT; + revents |= POLLOUT|POLLERR; } if (!revents) return 0; @@ -318,6 +318,24 @@ int snd_seq_poll_descriptors(snd_seq_t *seq, struct pollfd *pfds, unsigned int s return 1; } +/** + * \brief get returned events from poll descriptors + * \param seq sequencer handle + * \param pfds array of poll descriptors + * \param nfds count of poll descriptors + * \param revents returned events + * \return zero if success, otherwise a negative error code + */ +int snd_seq_poll_descriptors_revents(snd_seq_t *seq, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) +{ + assert(seq && pfds && revents); + if (nfds == 1) { + *revents = pfds->revents; + return 0; + } + return -EINVAL; +} + /** * \brief Set nonblock mode * \param seq sequencer handle diff --git a/src/timer/timer.c b/src/timer/timer.c index 5ccc1cb1..352c10e3 100644 --- a/src/timer/timer.c +++ b/src/timer/timer.c @@ -261,13 +261,13 @@ int snd_timer_poll_descriptors(snd_timer_t *timer, struct pollfd *pfds, unsigned pfds->fd = timer->poll_fd; switch (timer->mode & O_ACCMODE) { case O_WRONLY: - pfds->events = POLLOUT; + pfds->events = POLLOUT|POLLERR; break; case O_RDONLY: - pfds->events = POLLIN; + pfds->events = POLLIN|POLLERR; break; case O_RDWR: - pfds->events = POLLOUT|POLLIN; + pfds->events = POLLOUT|POLLIN|POLLERR; break; default: return -EIO; @@ -277,6 +277,24 @@ int snd_timer_poll_descriptors(snd_timer_t *timer, struct pollfd *pfds, unsigned return 0; } +/** + * \brief get returned events from poll descriptors + * \param timer timer handle + * \param pfds array of poll descriptors + * \param nfds count of poll descriptors + * \param revents returned events + * \return zero if success, otherwise a negative error code + */ +int snd_timer_poll_descriptors_revents(snd_timer_t *timer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) +{ + assert(timer && pfds && revents); + if (nfds == 1) { + *revents = pfds->revents; + return 0; + } + return -EINVAL; +} + /** * \brief set nonblock mode * \param timer timer handle diff --git a/test/pcm.c b/test/pcm.c index 2851feca..7344b0bf 100644 --- a/test/pcm.c +++ b/test/pcm.c @@ -226,22 +226,17 @@ static int write_loop(snd_pcm_t *handle, * Transfer method - write and wait for room in buffer using poll */ -static int wait_for_poll(struct pollfd *ufds, int count) +static int wait_for_poll(snd_pcm_t *handle, struct pollfd *ufds, unsigned int count) { - int i; - unsigned int events; + unsigned short revents; while (1) { poll(ufds, count, -1); - for (i = 0; i < count; i++) { - events = ufds[i].revents; - if (events & POLLERR) { - printf("Poll - POLLERR detected\n"); - return -EIO; - } - if (events & POLLOUT) - return 0; - } + snd_pcm_poll_descriptors_revents(handle, ufds, count, &revents); + if (revents & POLLERR) + return -EIO; + if (revents & POLLOUT) + return 0; } } @@ -252,7 +247,7 @@ static int write_and_poll_loop(snd_pcm_t *handle, struct pollfd *ufds; double phase = 0; signed short *ptr; - int err, count, cptr; + int err, count, cptr, init; count = snd_pcm_poll_descriptors_count (handle); if (count <= 0) { @@ -270,11 +265,24 @@ static int write_and_poll_loop(snd_pcm_t *handle, return err; } + init = 1; while (1) { - err = wait_for_poll(ufds, count); - if (err < 0) { - printf("Wait for poll failed\n"); - return err; + if (!init) { + err = wait_for_poll(handle, ufds, count); + if (err < 0) { + if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN || + snd_pcm_state(handle) == SND_PCM_STATE_SUSPENDED) { + err = snd_pcm_state(handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE; + if (xrun_recovery(handle, err) < 0) { + printf("Write error: %s\n", snd_strerror(err)); + exit(EXIT_FAILURE); + } + init = 1; + } else { + printf("Wait for poll failed\n"); + return err; + } + } } generate_sine(areas, 0, period_size, &phase); @@ -287,18 +295,31 @@ static int write_and_poll_loop(snd_pcm_t *handle, printf("Write error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } + init = 1; break; /* skip one period */ } + if (snd_pcm_state(handle) == SND_PCM_STATE_RUNNING) + init = 0; ptr += err * channels; cptr -= err; if (cptr == 0) break; /* it is possible, that initial buffer cannot store */ /* all data from last period, so wait awhile */ - err = wait_for_poll(ufds, count); + err = wait_for_poll(handle, ufds, count); if (err < 0) { - printf("Wait for poll failed\n"); - return err; + if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN || + snd_pcm_state(handle) == SND_PCM_STATE_SUSPENDED) { + err = snd_pcm_state(handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE; + if (xrun_recovery(handle, err) < 0) { + printf("Write error: %s\n", snd_strerror(err)); + exit(EXIT_FAILURE); + } + init = 1; + } else { + printf("Wait for poll failed\n"); + return err; + } } } }