[vlc-commits] PulseAudio: add helper library to share the mainloop
Rémi Denis-Courmont
git at videolan.org
Mon Jul 18 21:39:52 CEST 2011
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Jul 18 21:32:16 2011 +0300| [8ed55bbf8dd519cb93297eddc78e533e7041e19d] | committer: Rémi Denis-Courmont
PulseAudio: add helper library to share the mainloop
With only one PulseAudio plugin, this is not very useful currently.
In principles, it enables sharing the mainloop across plugins.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8ed55bbf8dd519cb93297eddc78e533e7041e19d
---
include/vlc_pulse.h | 41 ++++++++++
src/Makefile.am | 11 +++
src/pulse/mainloop.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 266 insertions(+), 0 deletions(-)
diff --git a/include/vlc_pulse.h b/include/vlc_pulse.h
new file mode 100644
index 0000000..48e2ce8
--- /dev/null
+++ b/include/vlc_pulse.h
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * vlcpulse.h : PulseAudio support library for LibVLC plugins
+ *****************************************************************************
+ * Copyright (C) 2011 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLCPULSE_H
+# define VLCPULSE_H 1
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+VLC_API void vlc_pa_lock (void);
+VLC_API void vlc_pa_unlock (void);
+VLC_API void vlc_pa_signal (int);
+VLC_API void vlc_pa_wait (void);
+
+VLC_API pa_context *vlc_pa_connect (vlc_object_t *obj);
+VLC_API void vlc_pa_disconnect (vlc_object_t *obj, pa_context *ctx);
+
+VLC_API void vlc_pa_error (vlc_object_t *, const char *msg, pa_context *);
+#define vlc_pa_error(o, m, c) vlc_pa_error(VLC_OBJECT(o), m, c)
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 14e2175..110a04c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -528,6 +528,17 @@ SOURCES_libvlc_control = \
control/media_discoverer.c
###############################################################################
+# libvlc pulse
+###############################################################################
+
+pkglib_LTLIBRARIES = libvlcpulse.la
+
+libvlcpulse_la_SOURCES = pulse/mainloop.c ../include/vlc_pulse.h
+libvlcpulse_la_CPPFLAGS = $(PULSE_CFLAGS)
+libvlcpulse_la_LIBADD = $(PULSE_LIBS) libvlccore.la
+libvlcpulse_la_LDFLAGS = -export-symbols-regex ^vlc_pa_ -no-undefined
+
+###############################################################################
# GIT revision
###############################################################################
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
new file mode 100644
index 0000000..df0c851
--- /dev/null
+++ b/src/pulse/mainloop.c
@@ -0,0 +1,214 @@
+/*****************************************************************************
+ * vlcpulse.c : PulseAudio support library for LibVLC plugins
+ *****************************************************************************
+ * Copyright (C) 2008 the VideoLAN team
+ * Copyright (C) 2009-2011 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#define MODULE_STRING "vlcpulse"
+#include <vlc_common.h>
+#include <pulse/pulseaudio.h>
+
+#include <vlc_pulse.h>
+#include <assert.h>
+
+#undef vlc_pa_error
+void vlc_pa_error (vlc_object_t *obj, const char *msg, pa_context *ctx)
+{
+ msg_Err (obj, "%s: %s", msg, pa_strerror (pa_context_errno (ctx)));
+}
+
+static pa_threaded_mainloop *vlc_pa_mainloop;
+static unsigned refs = 0;
+static vlc_mutex_t lock = VLC_STATIC_MUTEX;
+
+/**
+ * Creates and references the VLC PulseAudio threaded main loop.
+ * @return the mainloop or NULL on failure
+ */
+static pa_threaded_mainloop *vlc_pa_mainloop_init (void)
+{
+ pa_threaded_mainloop *mainloop;
+
+ vlc_mutex_lock (&lock);
+ if (refs == 0)
+ {
+ mainloop = pa_threaded_mainloop_new ();
+ if (unlikely(mainloop == NULL))
+ goto out;
+
+ if (pa_threaded_mainloop_start (mainloop) < 0)
+ {
+ pa_threaded_mainloop_free (mainloop);
+ goto out;
+ }
+ vlc_pa_mainloop = mainloop;
+ }
+ else
+ {
+ if (unlikely(refs < UINT_MAX))
+ {
+ mainloop = NULL;
+ goto out;
+ }
+ mainloop = vlc_pa_mainloop;
+ }
+
+ assert (mainloop != NULL);
+ refs++;
+out:
+ vlc_mutex_unlock (&lock);
+ return mainloop;
+}
+
+/**
+ * Releases a reference to the VLC PulseAudio main loop.
+ */
+static void vlc_pa_mainloop_deinit (pa_threaded_mainloop *mainloop)
+{
+ vlc_mutex_lock (&lock);
+ assert (refs > 0);
+ assert (mainloop == vlc_pa_mainloop);
+
+ if (--refs > 0)
+ mainloop = NULL;
+ vlc_mutex_unlock (&lock);
+
+ if (mainloop != NULL)
+ {
+ pa_threaded_mainloop_stop (mainloop);
+ pa_threaded_mainloop_free (mainloop);
+ }
+}
+
+/**
+ * Acquires the main loop lock.
+ */
+void vlc_pa_lock (void)
+{
+ pa_threaded_mainloop_lock (vlc_pa_mainloop);
+}
+
+/**
+ * Releases the main loop lock.
+ */
+void vlc_pa_unlock (void)
+{
+ pa_threaded_mainloop_unlock (vlc_pa_mainloop);
+}
+
+/**
+ * Signals the main loop.
+ */
+void vlc_pa_signal (int do_wait)
+{
+ pa_threaded_mainloop_signal (vlc_pa_mainloop, do_wait);
+}
+
+/**
+ * Waits for the main loop to be signaled.
+ */
+void vlc_pa_wait (void)
+{
+ pa_threaded_mainloop_wait (vlc_pa_mainloop);
+}
+
+
+static void context_state_cb (pa_context *ctx, void *userdata)
+{
+ pa_threaded_mainloop *mainloop = userdata;
+
+ switch (pa_context_get_state(ctx))
+ {
+ case PA_CONTEXT_READY:
+ case PA_CONTEXT_FAILED:
+ case PA_CONTEXT_TERMINATED:
+ pa_threaded_mainloop_signal(mainloop, 0);
+ default:
+ break;
+ }
+}
+
+static bool context_wait (pa_threaded_mainloop *mainloop, pa_context *ctx)
+{
+ pa_context_state_t state;
+
+ while ((state = pa_context_get_state (ctx)) != PA_CONTEXT_READY)
+ {
+ if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
+ return -1;
+ pa_threaded_mainloop_wait (mainloop);
+ }
+ return 0;
+}
+
+/**
+ * Initializes the PulseAudio main loop and connects to the PulseAudio server.
+ * @return a PulseAudio context on success, or NULL on error
+ */
+pa_context *vlc_pa_connect (vlc_object_t *obj)
+{
+ pa_threaded_mainloop *mainloop = vlc_pa_mainloop_init ();
+ if (unlikely(mainloop == NULL))
+ return NULL;
+
+ char *ua = var_InheritString (obj, "user-agent");
+ pa_context *ctx;
+
+ pa_threaded_mainloop_lock (mainloop);
+
+ ctx = pa_context_new (pa_threaded_mainloop_get_api (mainloop), ua);
+ free (ua);
+ if (unlikely(ctx == NULL))
+ goto fail;
+
+ pa_context_set_state_callback (ctx, context_state_cb, mainloop);
+ if (pa_context_connect (ctx, NULL, 0, NULL) < 0
+ || context_wait (mainloop, ctx))
+ {
+ vlc_pa_error (obj, "PulseAudio server connection failure", ctx);
+ pa_context_unref (ctx);
+ goto fail;
+ }
+
+ pa_threaded_mainloop_unlock (mainloop);
+ return ctx;
+
+fail:
+ pa_threaded_mainloop_unlock (mainloop);
+ vlc_pa_mainloop_deinit (mainloop);
+ return NULL;
+}
+
+/**
+ * Closes a connection to PulseAudio.
+ */
+void vlc_pa_disconnect (vlc_object_t *obj, pa_context *ctx)
+{
+ pa_threaded_mainloop *mainloop = vlc_pa_mainloop;
+
+ pa_threaded_mainloop_lock (mainloop);
+ pa_context_unref (ctx);
+ pa_threaded_mainloop_unlock (mainloop);
+
+ vlc_pa_mainloop_deinit (mainloop);
+ (void) obj;
+}
More information about the vlc-commits
mailing list