summaryrefslogtreecommitdiffstats
path: root/polyp/polyp.c
diff options
context:
space:
mode:
Diffstat (limited to 'polyp/polyp.c')
-rw-r--r--polyp/polyp.c324
1 files changed, 103 insertions, 221 deletions
diff --git a/polyp/polyp.c b/polyp/polyp.c
index f10221c..f5e5cac 100644
--- a/polyp/polyp.c
+++ b/polyp/polyp.c
@@ -19,177 +19,71 @@
*/
#include <stdio.h>
+#include <unistd.h>
#include <signal.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <pthread.h>
+#include <sys/poll.h>
#include "polyp.h"
-enum {
- COMMAND_POLL = 'p',
- COMMAND_QUIT = 'q',
- COMMAND_POLL_DONE = 'P',
- COMMAND_POLL_FAILED = 'F',
-};
-
-static int write_command(snd_polyp_t *p, char command)
-{
- if (write(p->main_fd, &command, 1) != 1)
- return -errno;
- return 0;
-}
-
-static int write_reply(snd_polyp_t *p, char reply)
-{
- if (write(p->thread_fd, &reply, 1) != 1)
- return -errno;
- return 0;
-}
-
-static int read_command(snd_polyp_t *p)
-{
- char command;
-
- if (read(p->thread_fd, &command, 1) != 1)
- return -errno;
-
- return command;
-}
-
-static int read_reply(snd_polyp_t *p)
-{
- char reply;
-
- if (read(p->main_fd, &reply, 1) != 1)
- return -errno;
-
- return reply;
-}
-
-static void* thread_func(void *data)
+int polyp_check_connection(snd_polyp_t *p)
{
- snd_polyp_t *p = (snd_polyp_t*)data;
- sigset_t mask;
- char command;
- int ret;
-
- sigfillset(&mask);
- pthread_sigmask(SIG_BLOCK, &mask, NULL);
-
- do {
- command = read_command(p);
- if (command < 0)
- break;
+ pa_context_state_t state;
- switch (command) {
- case COMMAND_POLL:
- do {
- ret = pa_mainloop_poll(p->mainloop);
- } while ((ret < 0) && (errno == EINTR));
+ assert(p && p->context && p->mainloop);
- ret = write_reply(p, (ret < 0) ? COMMAND_POLL_FAILED : COMMAND_POLL_DONE);
- if (ret < 0)
- return NULL;
+ state = pa_context_get_state(p->context);
- break;
- }
- } while (command != COMMAND_QUIT);
+ if (state != PA_CONTEXT_READY)
+ return -EIO;
- return NULL;
+ return 0;
}
-int polyp_start_poll(snd_polyp_t *p)
+void polyp_stream_state_cb(pa_stream *s, void * userdata)
{
- int err;
+ snd_polyp_t *p = userdata;
+ assert(s);
assert(p);
- if (p->state == POLYP_STATE_POLLING)
- return 0;
-
- assert(p->state == POLYP_STATE_READY);
-
- err = pa_mainloop_prepare(p->mainloop, -1);
- if (err < 0)
- return err;
-
- err = write_command(p, COMMAND_POLL);
- if (err < 0)
- return err;
-
- p->state = POLYP_STATE_POLLING;
-
- return 0;
+ pa_threaded_mainloop_signal(p->mainloop, 0);
}
-int polyp_finish_poll(snd_polyp_t *p)
+void polyp_stream_success_cb(pa_stream *s, int success, void *userdata)
{
- char reply;
- int err;
+ snd_polyp_t *p = userdata;
+ assert(s);
assert(p);
- if (p->state == POLYP_STATE_READY)
- return 0;
-
- assert(p->state == POLYP_STATE_POLLING);
-
- p->state = POLYP_STATE_READY;
-
- pa_mainloop_wakeup(p->mainloop);
-
- reply = read_reply(p);
-
- if (reply == COMMAND_POLL_DONE) {
- err = pa_mainloop_dispatch(p->mainloop);
- if (err < 0)
- return err;
- } else
- return -EIO;
-
- return 0;
+ pa_threaded_mainloop_signal(p->mainloop, 0);
}
-int polyp_check_connection(snd_polyp_t *p)
+void polyp_context_success_cb(pa_context *c, int success, void *userdata)
{
- pa_context_state_t state;
-
- assert(p && p->context);
+ snd_polyp_t *p = userdata;
- state = pa_context_get_state(p->context);
-
- if (state != PA_CONTEXT_READY)
- return -EIO;
+ assert(c);
+ assert(p);
- return 0;
+ pa_threaded_mainloop_signal(p->mainloop, 0);
}
int polyp_wait_operation(snd_polyp_t *p, pa_operation *o)
{
- int err;
+ assert(p && o && (p->state == POLYP_STATE_READY) && p->mainloop);
- assert(p && o && (p->state == POLYP_STATE_READY));
-
- while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
- p->state = POLYP_STATE_POLLING;
- err = pa_mainloop_iterate(p->mainloop, 1, NULL);
- p->state = POLYP_STATE_READY;
- if (err < 0)
- return err;
- }
+ while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(p->mainloop);
return 0;
}
int polyp_wait_stream_state(snd_polyp_t *p, pa_stream *stream, pa_stream_state_t target)
{
- int err;
pa_stream_state_t state;
- assert(p && stream && (p->state == POLYP_STATE_READY));
+ assert(p && stream && (p->state == POLYP_STATE_READY) && p->mainloop);
while (1) {
state = pa_stream_get_state(stream);
@@ -200,34 +94,72 @@ int polyp_wait_stream_state(snd_polyp_t *p, pa_stream *stream, pa_stream_state_t
if (state == target)
break;
- p->state = POLYP_STATE_POLLING;
- err = pa_mainloop_iterate(p->mainloop, 1, NULL);
- p->state = POLYP_STATE_READY;
- if (err < 0)
- return -EIO;
+ pa_threaded_mainloop_wait(p->mainloop);
}
return 0;
}
+static void context_state_cb(pa_context *c, void *userdata) {
+ snd_polyp_t *p = userdata;
+ assert(c);
+
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_READY:
+ case PA_CONTEXT_TERMINATED:
+ case PA_CONTEXT_FAILED:
+ pa_threaded_mainloop_signal(p->mainloop, 0);
+ break;
+
+ case PA_CONTEXT_UNCONNECTED:
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+ }
+}
+
snd_polyp_t *polyp_new()
{
snd_polyp_t *p;
+ int fd[2] = { -1, -1 };
+ char proc[PATH_MAX], buf[PATH_MAX + 20];
p = calloc(1, sizeof(snd_polyp_t));
assert(p);
p->state = POLYP_STATE_INIT;
- p->main_fd = -1;
- p->thread_fd = -1;
- p->thread_running = 0;
+ if (pipe(fd)) {
+ free(p);
+ return NULL;
+ }
+
+ p->main_fd = fd[0];
+ p->thread_fd = fd[1];
+
+ fcntl(fd[0], F_SETFL, O_NONBLOCK);
+ fcntl(fd[1], F_SETFL, O_NONBLOCK);
- p->mainloop = pa_mainloop_new();
+ signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */
+
+ p->mainloop = pa_threaded_mainloop_new();
assert(p->mainloop);
- p->context = pa_context_new(pa_mainloop_get_api(p->mainloop),
- "ALSA Plugin");
+ if (pa_threaded_mainloop_start(p->mainloop) < 0) {
+ pa_threaded_mainloop_free(p->mainloop);
+ close(fd[0]);
+ close(fd[1]);
+ free(p);
+ return NULL;
+ }
+
+ if (pa_get_binary_name(proc, sizeof(proc)))
+ snprintf(buf, sizeof(buf), "ALSA plug-in [%s]", pa_path_get_filename(proc));
+ else
+ snprintf(buf, sizeof(buf), "ALSA plug-in");
+
+ p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), buf);
assert(p->context);
return p;
@@ -235,22 +167,13 @@ snd_polyp_t *polyp_new()
void polyp_free(snd_polyp_t *p)
{
- if (p->thread_running) {
- assert(p->mainloop && p->thread);
- write_command(p, COMMAND_QUIT);
- pa_mainloop_wakeup(p->mainloop);
- pthread_join(p->thread, NULL);
- }
+ pa_threaded_mainloop_stop(p->mainloop);
- if (p->context)
- pa_context_unref(p->context);
- if (p->mainloop)
- pa_mainloop_free(p->mainloop);
+ pa_context_unref(p->context);
+ pa_threaded_mainloop_free(p->mainloop);
- if (p->thread_fd >= 0)
- close(p->thread_fd);
- if (p->main_fd >= 0)
- close(p->main_fd);
+ close(p->thread_fd);
+ close(p->main_fd);
free(p);
}
@@ -258,70 +181,52 @@ void polyp_free(snd_polyp_t *p)
int polyp_connect(snd_polyp_t *p, const char *server)
{
int err;
- pa_context_state_t state;
assert(p && p->context && p->mainloop && (p->state == POLYP_STATE_INIT));
+ pa_threaded_mainloop_lock(p->mainloop);
+
err = pa_context_connect(p->context, server, 0, NULL);
if (err < 0)
goto error;
- while (1) {
- state = pa_context_get_state(p->context);
+ pa_context_set_state_callback(p->context, context_state_cb, p);
- if (state == PA_CONTEXT_FAILED)
- goto error;
+ pa_threaded_mainloop_wait(p->mainloop);
- if (state == PA_CONTEXT_READY)
- break;
+ if (pa_context_get_state(p->context) != PA_CONTEXT_READY)
+ goto error;
- err = pa_mainloop_iterate(p->mainloop, 1, NULL);
- if (err < 0)
- return -EIO;
- }
+ pa_threaded_mainloop_unlock(p->mainloop);
- p->state = POLYP_STATE_CONNECTED;
+ p->state = POLYP_STATE_READY;
return 0;
error:
fprintf(stderr, "*** POLYPAUDIO: Unable to connect: %s\n",
pa_strerror(pa_context_errno(p->context)));
+
+ pa_threaded_mainloop_unlock(p->mainloop);
+
return -ECONNREFUSED;
}
-int polyp_start_thread(snd_polyp_t *p)
+void polyp_poll_activate(snd_polyp_t *p)
{
- int err;
- int fd[2] = { -1, -1 };
-
- assert(p && (p->state == POLYP_STATE_CONNECTED));
-
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
- perror("socketpair()");
- return -errno;
- }
-
- p->thread_fd = fd[0];
- p->main_fd = fd[1];
-
- p->thread_running = 0;
+ assert(p);
- err = pthread_create(&p->thread, NULL, thread_func, p);
- if (err) {
- SNDERR("pthread_create(): %s", strerror(err));
- close(fd[0]);
- close(fd[1]);
- p->main_fd = -1;
- p->thread_fd = -1;
- return -err;
- }
+ write(p->thread_fd, "a", 1);
+}
- p->thread_running = 1;
+void polyp_poll_deactivate(snd_polyp_t *p)
+{
+ char buf[10];
- p->state = POLYP_STATE_READY;
+ assert(p);
- return 0;
+ /* Drain the pipe */
+ while (read(p->main_fd, buf, sizeof(buf)) > 0);
}
int polyp_poll_descriptors_count(snd_polyp_t *p)
@@ -336,22 +241,12 @@ int polyp_poll_descriptors_count(snd_polyp_t *p)
int polyp_poll_descriptors(snd_polyp_t *p, struct pollfd *pfd, unsigned int space)
{
- int err;
-
assert(p);
- err = polyp_finish_poll(p);
- if (err < 0)
- return err;
-
- err = polyp_start_poll(p);
- if (err < 0)
- return err;
-
assert(space >= 1);
pfd[0].fd = p->main_fd;
- pfd[0].events = POLL_IN;
+ pfd[0].events = POLLIN;
pfd[0].revents = 0;
return 1;
@@ -359,20 +254,7 @@ int polyp_poll_descriptors(snd_polyp_t *p, struct pollfd *pfd, unsigned int spac
int polyp_poll_revents(snd_polyp_t *p, struct pollfd *pfd, unsigned int nfds, unsigned short *revents)
{
- int err;
-
assert(p);
- err = polyp_finish_poll(p);
- if (err < 0)
- return err;
-
- err = polyp_check_connection(p);
- if (err < 0)
- return err;
-
- /*
- * The application might redo the poll immediatly.
- */
- return polyp_poll_descriptors(p, pfd, nfds);
+ return 1;
}