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);
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);
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);
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);
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);
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
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);
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);
*/
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
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;
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
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
*/
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
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
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;
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
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;
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
* 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;
}
}
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) {
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);
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;
+ }
}
}
}