]> git.sesse.net Git - vlc/blobdiff - modules/audio_output/pulse.c
pulse: fix a memory leak.
[vlc] / modules / audio_output / pulse.c
index 8ef3e4cccfbffa824373714f3a1210be506336c4..4a239640a6ce841c201f26baaf706ef38878b4f4 100644 (file)
 #include <vlc_cpu.h>
 
 #include <pulse/pulseaudio.h>
+#ifdef X_DISPLAY_MISSING
+# error Xlib required due to PulseAudio bug 799!
+#endif
+#include <vlc_xlib.h>
 
 #include <assert.h>
 
@@ -59,8 +63,6 @@ struct aout_sys_t
     mtime_t start_date;
 };
 
-#define    PULSE_CLIENT_NAME N_("VLC media player")
-
 #if 0
 #define PULSE_DEBUG( ...) \
     msg_Dbg( p_aout, __VA_ARGS__ )
@@ -101,10 +103,8 @@ vlc_module_begin ()
     set_capability( "audio output", 160 )
     set_category( CAT_AUDIO )
     set_subcategory( SUBCAT_AUDIO_AOUT )
-    add_shortcut( "pulseaudio" )
-    add_shortcut( "pa" )
+    add_shortcut( "pulseaudio", "pa" )
     set_callbacks( Open, Close )
-    linked_with_a_crap_library_which_uses_atexit()
 vlc_module_end ()
 
 /*****************************************************************************
@@ -118,6 +118,10 @@ static int Open ( vlc_object_t *p_this )
     const struct pa_buffer_attr *buffer_attr;
     struct pa_buffer_attr a;
     struct pa_channel_map map;
+    char * p_client_name;
+
+    if( !vlc_xlib_init( p_this ) )
+        return VLC_EGENERIC;
 
     /* Allocate structures */
     p_aout->output.p_sys = p_sys = calloc( 1, sizeof( aout_sys_t ) );
@@ -204,7 +208,15 @@ static int Open ( vlc_object_t *p_this )
         goto fail;
     }
 
-    if (!(p_sys->context = pa_context_new(pa_threaded_mainloop_get_api(p_sys->mainloop), _( PULSE_CLIENT_NAME )))) {
+    if ((p_client_name = var_InheritString(p_aout, "user-agent")) == NULL) {
+        msg_Err(p_aout, "No user-agent string available.");
+        goto fail;
+    }
+
+    p_sys->context = pa_context_new(pa_threaded_mainloop_get_api(p_sys->mainloop), p_client_name);
+    free(p_client_name);
+    if(!p_sys->context)
+    {
         msg_Err(p_aout, "Failed to allocate context");
         goto fail;
     }
@@ -309,21 +321,15 @@ static void Play( aout_instance_t * p_aout )
 {
     struct aout_sys_t * p_sys = (struct aout_sys_t *) p_aout->output.p_sys;
 
-    pa_operation *o;
-
     if(!p_sys->started){
         msg_Dbg(p_aout, "Pulse stream started");
+        pa_threaded_mainloop_lock(p_sys->mainloop);
         p_sys->start_date =
             aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
         p_sys->started = 1;
 
-        pa_threaded_mainloop_lock(p_sys->mainloop);
-        if((o = pa_stream_flush(p_sys->stream, success_cb, p_aout))){
-            pa_operation_unref(o);
-        }
-        pa_threaded_mainloop_unlock(p_sys->mainloop);
-
         pa_threaded_mainloop_signal(p_sys->mainloop, 0);
+        pa_threaded_mainloop_unlock(p_sys->mainloop);
     }
 }
 
@@ -338,26 +344,21 @@ static void Close ( vlc_object_t *p_this )
     msg_Dbg(p_aout, "Pulse Close");
 
     if(p_sys->stream){
-        pa_operation *o;
         pa_threaded_mainloop_lock(p_sys->mainloop);
         pa_stream_set_write_callback(p_sys->stream, NULL, NULL);
 
-/* I didn't find any explanation why we need to do pa_stream_drain on close
- * as we don't really care if we lose 20ms buffer in this point anyway?
- * And disabling this speeds up closing pulseaudio quite a lot (atleast for me).
- */
-#if 0
-        if((o = pa_stream_drain(p_sys->stream, success_cb, p_aout))){
-            while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
-                CHECK_DEAD_GOTO(fail);
-                pa_threaded_mainloop_wait(p_sys->mainloop);
-            }
+        pa_operation *o;
 
-        fail:
+        o = pa_stream_flush(p_sys->stream, success_cb, p_aout);
+        while( pa_operation_get_state(o) == PA_OPERATION_RUNNING )
+            pa_threaded_mainloop_wait(p_sys->mainloop);
+        pa_operation_unref(o);
+
+        o = pa_stream_drain(p_sys->stream, success_cb, p_aout);
+        while( pa_operation_get_state(o) == PA_OPERATION_RUNNING )
+            pa_threaded_mainloop_wait(p_sys->mainloop);
+        pa_operation_unref(o);
 
-            pa_operation_unref(o);
-        }
-#endif
         pa_threaded_mainloop_unlock(p_sys->mainloop);
     }
     uninit(p_aout);