[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