[alsa-devel] [PATCH] Add async support to ioplug
Takashi Iwai
tiwai at suse.de
Tue May 20 13:10:35 CEST 2008
Hi,
the patch below adds a framework to support async on ioplug. Now
an external ioplug plugin can implement appropriate async methods if
possible.
The async callback is just a copy of snd_pcm_async(). When sig >= 0,
activate the async, and with a negative value, deactivate async.
The test patch to alsa-plugins will follow.
Takashi
---
diff -r 8b22022a861d include/local.h
--- a/include/local.h Fri May 09 16:02:02 2008 +0200
+++ b/include/local.h Tue May 20 09:02:35 2008 +0200
@@ -149,7 +149,13 @@
void *private_data;
struct list_head glist;
struct list_head hlist;
+ int no_signal;
};
+
+int _snd_async_add_handler(snd_async_handler_t **handler, int fd,
+ snd_async_callback_t callback,
+ void *private_data, int no_signal);
+void _snd_async_call_handlers(int fd);
typedef enum _snd_set_mode {
SND_CHANGE,
diff -r 8b22022a861d include/pcm_ioplug.h
--- a/include/pcm_ioplug.h Fri May 09 16:02:02 2008 +0200
+++ b/include/pcm_ioplug.h Tue May 20 09:02:35 2008 +0200
@@ -66,7 +66,7 @@
*/
#define SND_PCM_IOPLUG_VERSION_MAJOR 1 /**< Protocol major version */
#define SND_PCM_IOPLUG_VERSION_MINOR 0 /**< Protocol minor version */
-#define SND_PCM_IOPLUG_VERSION_TINY 1 /**< Protocol tiny version */
+#define SND_PCM_IOPLUG_VERSION_TINY 2 /**< Protocol tiny version */
/**
* IO-plugin protocol version
*/
@@ -114,6 +114,10 @@
unsigned int rate; /**< rate; filled after hw_params is called */
snd_pcm_uframes_t period_size; /**< period size; filled after hw_params is called */
snd_pcm_uframes_t buffer_size; /**< buffer size; filled after hw_params is called */
+ /**
+ * fields added by version 1.0.2
+ */
+ unsigned int no_signal_async; /**< async support without signal */
};
/** Callback table of ioplug */
@@ -189,6 +193,10 @@
* get the delay for the running PCM; optional
*/
int (*delay)(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp);
+ /**
+ * set up async handler; optional; added in version 1.0.2
+ */
+ int (*async)(snd_pcm_ioplug_t *io, int sig, pid_t pid);
};
@@ -212,6 +220,9 @@
/* change PCM status */
int snd_pcm_ioplug_set_state(snd_pcm_ioplug_t *ioplug, snd_pcm_state_t state);
+/* call async handlers */
+void snd_pcm_ioplug_call_async_handlers(snd_pcm_ioplug_t *ioplug);
+
/** \} */
#endif /* __ALSA_PCM_IOPLUG_H */
diff -r 8b22022a861d src/async.c
--- a/src/async.c Fri May 09 16:02:02 2008 +0200
+++ b/src/async.c Tue May 20 09:02:35 2008 +0200
@@ -48,19 +48,48 @@
#endif
static LIST_HEAD(snd_async_handlers);
+static int sig_count;
-static void snd_async_handler(int signo ATTRIBUTE_UNUSED, siginfo_t *siginfo, void *context ATTRIBUTE_UNUSED)
+#ifndef DOC_HIDDEN
+void _snd_async_call_handlers(int fd)
{
- int fd;
struct list_head *i;
- //assert(siginfo->si_code == SI_SIGIO);
- fd = siginfo->si_fd;
list_for_each(i, &snd_async_handlers) {
snd_async_handler_t *h = list_entry(i, snd_async_handler_t, glist);
if (h->fd == fd && h->callback)
h->callback(h);
}
}
+#endif
+
+static void snd_async_handler(int signo ATTRIBUTE_UNUSED, siginfo_t *siginfo, void *context ATTRIBUTE_UNUSED)
+{
+ int fd;
+ //assert(siginfo->si_code == SI_SIGIO);
+ fd = siginfo->si_fd;
+ _snd_async_call_handlers(fd);
+}
+
+#ifndef DOC_HIDDEN
+int _snd_async_add_handler(snd_async_handler_t **handler, int fd,
+ snd_async_callback_t callback,
+ void *private_data, int no_signal)
+{
+ snd_async_handler_t *h;
+ assert(handler);
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+ h->fd = fd;
+ h->callback = callback;
+ h->private_data = private_data;
+ list_add_tail(&h->glist, &snd_async_handlers);
+ INIT_LIST_HEAD(&h->hlist);
+ h->no_signal = no_signal;
+ *handler = h;
+ return 0;
+}
+#endif
/**
* \brief Registers an async handler.
@@ -94,20 +123,13 @@
int snd_async_add_handler(snd_async_handler_t **handler, int fd,
snd_async_callback_t callback, void *private_data)
{
- snd_async_handler_t *h;
- int was_empty;
- assert(handler);
- h = malloc(sizeof(*h));
- if (!h)
- return -ENOMEM;
- h->fd = fd;
- h->callback = callback;
- h->private_data = private_data;
- was_empty = list_empty(&snd_async_handlers);
- list_add_tail(&h->glist, &snd_async_handlers);
- INIT_LIST_HEAD(&h->hlist);
- *handler = h;
- if (was_empty) {
+ int err;
+
+ err = _snd_async_add_handler(handler, fd, callback, private_data, 0);
+ if (err < 0)
+ return err;
+
+ if (!sig_count) {
int err;
struct sigaction act;
memset(&act, 0, sizeof(act));
@@ -116,10 +138,15 @@
sigemptyset(&act.sa_mask);
err = sigaction(snd_async_signo, &act, NULL);
if (err < 0) {
+ err = -errno;
SYSERR("sigaction");
- return -errno;
+ list_del(&(*handler)->glist);
+ free(*handler);
+ *handler = NULL;
+ return err;
}
}
+ sig_count++;
return 0;
}
@@ -133,15 +160,18 @@
int err = 0;
assert(handler);
list_del(&handler->glist);
- if (list_empty(&snd_async_handlers)) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- act.sa_flags = 0;
- act.sa_handler = SIG_DFL;
- err = sigaction(snd_async_signo, &act, NULL);
- if (err < 0) {
- SYSERR("sigaction");
- return -errno;
+ if (!handler->no_signal) {
+ sig_count--;
+ if (!sig_count) {
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+ act.sa_flags = 0;
+ act.sa_handler = SIG_DFL;
+ err = sigaction(snd_async_signo, &act, NULL);
+ if (err < 0) {
+ SYSERR("sigaction");
+ /* return -errno; */
+ }
}
}
if (handler->type == SND_ASYNC_HANDLER_GENERIC)
diff -r 8b22022a861d src/pcm/pcm.c
--- a/src/pcm/pcm.c Fri May 09 16:02:02 2008 +0200
+++ b/src/pcm/pcm.c Tue May 20 09:02:36 2008 +0200
@@ -1984,8 +1984,10 @@
int err;
int was_empty;
snd_async_handler_t *h;
- err = snd_async_add_handler(&h, _snd_pcm_async_descriptor(pcm),
- callback, private_data);
+
+ err = _snd_async_add_handler(&h, _snd_pcm_async_descriptor(pcm),
+ callback, private_data,
+ pcm->no_signal_async);
if (err < 0)
return err;
h->type = SND_ASYNC_HANDLER_PCM;
diff -r 8b22022a861d src/pcm/pcm_ioplug.c
--- a/src/pcm/pcm_ioplug.c Fri May 09 16:02:02 2008 +0200
+++ b/src/pcm/pcm_ioplug.c Tue May 20 09:02:36 2008 +0200
@@ -698,11 +698,15 @@
return 0;
}
-static int snd_pcm_ioplug_async(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
- int sig ATTRIBUTE_UNUSED,
- pid_t pid ATTRIBUTE_UNUSED)
+static int snd_pcm_ioplug_async(snd_pcm_t *pcm, int sig, pid_t pid)
{
- return -ENOSYS;
+ ioplug_priv_t *io = pcm->private_data;
+
+ if (io->data->version >= 0x010002 &&
+ io->data->callback->async)
+ return io->data->callback->async(io->data, sig, pid);
+ else
+ return -ENOSYS;
}
static int snd_pcm_ioplug_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
@@ -1037,6 +1041,9 @@
ioplug->pcm->poll_events = ioplug->poll_events;
ioplug->pcm->monotonic = (ioplug->flags & SND_PCM_IOPLUG_FLAG_MONOTONIC) != 0;
ioplug->pcm->mmap_rw = ioplug->mmap_rw;
+ if (ioplug->version >= 0x010002)
+ ioplug->pcm->no_signal_async = ioplug->no_signal_async;
+
return 0;
}
@@ -1070,3 +1077,16 @@
ioplug->state = state;
return 0;
}
+
+/**
+ * \brief Call the associated async handlers
+ * \param ioplug the ioplug handle
+ *
+ * Call the async handlers associated with the given ioplug.
+ * This function is usually called from the plugin's async handling
+ * routine appropriately.
+ */
+void snd_pcm_ioplug_call_async_handlers(snd_pcm_ioplug_t *ioplug)
+{
+ _snd_async_call_handlers(ioplug->poll_fd);
+}
diff -r 8b22022a861d src/pcm/pcm_local.h
--- a/src/pcm/pcm_local.h Fri May 09 16:02:02 2008 +0200
+++ b/src/pcm/pcm_local.h Tue May 20 09:02:36 2008 +0200
@@ -220,6 +220,7 @@
* use the mmaped buffer of the slave
*/
unsigned int donot_close: 1; /* don't close this PCM */
+ unsigned int no_signal_async :1; /* async without signal */
snd_pcm_channel_info_t *mmap_channels;
snd_pcm_channel_area_t *running_areas;
snd_pcm_channel_area_t *stopped_areas;
More information about the Alsa-devel
mailing list