From 9304087e46a38f932959598720d1e048a6e1042a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 12 Jul 2006 16:47:20 +0200 Subject: Follow Polypaudio/PulseAudio name change Polypaudio recently changed its name to PulseAudio which affects the names of libraries of header files. Update the polyp, now pulse, plug-in to follow this name change. Signed-off-by: Pierre Ossman --- pulse/pulse.c | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 pulse/pulse.c (limited to 'pulse/pulse.c') diff --git a/pulse/pulse.c b/pulse/pulse.c new file mode 100644 index 0000000..fd80d9c --- /dev/null +++ b/pulse/pulse.c @@ -0,0 +1,260 @@ +/* + * ALSA <-> PulseAudio plugins + * + * Copyright (c) 2006 by Pierre Ossman + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "pulse.h" + +int pulse_check_connection(snd_pulse_t *p) +{ + pa_context_state_t state; + + assert(p && p->context && p->mainloop); + + state = pa_context_get_state(p->context); + + if (state != PA_CONTEXT_READY) + return -EIO; + + return 0; +} + +void pulse_stream_state_cb(pa_stream *s, void * userdata) +{ + snd_pulse_t *p = userdata; + + assert(s); + assert(p); + + pa_threaded_mainloop_signal(p->mainloop, 0); +} + +void pulse_stream_success_cb(pa_stream *s, int success, void *userdata) +{ + snd_pulse_t *p = userdata; + + assert(s); + assert(p); + + pa_threaded_mainloop_signal(p->mainloop, 0); +} + +void pulse_context_success_cb(pa_context *c, int success, void *userdata) +{ + snd_pulse_t *p = userdata; + + assert(c); + assert(p); + + pa_threaded_mainloop_signal(p->mainloop, 0); +} + +int pulse_wait_operation(snd_pulse_t *p, pa_operation *o) +{ + assert(p && o && (p->state == PULSE_STATE_READY) && p->mainloop); + + while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) + pa_threaded_mainloop_wait(p->mainloop); + + return 0; +} + +int pulse_wait_stream_state(snd_pulse_t *p, pa_stream *stream, pa_stream_state_t target) +{ + pa_stream_state_t state; + + assert(p && stream && (p->state == PULSE_STATE_READY) && p->mainloop); + + while (1) { + state = pa_stream_get_state(stream); + + if (state == PA_STREAM_FAILED) + return -EIO; + + if (state == target) + break; + + pa_threaded_mainloop_wait(p->mainloop); + } + + return 0; +} + +static void context_state_cb(pa_context *c, void *userdata) { + snd_pulse_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_pulse_t *pulse_new() +{ + snd_pulse_t *p; + int fd[2] = { -1, -1 }; + char proc[PATH_MAX], buf[PATH_MAX + 20]; + + p = calloc(1, sizeof(snd_pulse_t)); + assert(p); + + p->state = PULSE_STATE_INIT; + + 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); + + signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ + + p->mainloop = pa_threaded_mainloop_new(); + assert(p->mainloop); + + 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; +} + +void pulse_free(snd_pulse_t *p) +{ + pa_threaded_mainloop_stop(p->mainloop); + + pa_context_unref(p->context); + pa_threaded_mainloop_free(p->mainloop); + + close(p->thread_fd); + close(p->main_fd); + + free(p); +} + +int pulse_connect(snd_pulse_t *p, const char *server) +{ + int err; + + assert(p && p->context && p->mainloop && (p->state == PULSE_STATE_INIT)); + + pa_threaded_mainloop_lock(p->mainloop); + + err = pa_context_connect(p->context, server, 0, NULL); + if (err < 0) + goto error; + + pa_context_set_state_callback(p->context, context_state_cb, p); + + pa_threaded_mainloop_wait(p->mainloop); + + if (pa_context_get_state(p->context) != PA_CONTEXT_READY) + goto error; + + pa_threaded_mainloop_unlock(p->mainloop); + + p->state = PULSE_STATE_READY; + + return 0; + +error: + fprintf(stderr, "*** PULSEAUDIO: Unable to connect: %s\n", + pa_strerror(pa_context_errno(p->context))); + + pa_threaded_mainloop_unlock(p->mainloop); + + return -ECONNREFUSED; +} + +void pulse_poll_activate(snd_pulse_t *p) +{ + assert(p); + + write(p->thread_fd, "a", 1); +} + +void pulse_poll_deactivate(snd_pulse_t *p) +{ + char buf[10]; + + assert(p); + + /* Drain the pipe */ + while (read(p->main_fd, buf, sizeof(buf)) > 0); +} + +int pulse_poll_descriptors_count(snd_pulse_t *p) +{ + assert(p); + + if (p->main_fd >= 0) + return 1; + else + return 0; +} + +int pulse_poll_descriptors(snd_pulse_t *p, struct pollfd *pfd, unsigned int space) +{ + assert(p); + + assert(space >= 1); + + pfd[0].fd = p->main_fd; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + + return 1; +} + +int pulse_poll_revents(snd_pulse_t *p, struct pollfd *pfd, unsigned int nfds, unsigned short *revents) +{ + assert(p); + + return 1; +} -- cgit