diff -u vlc-0.8.6.release.d/debian/rules vlc-0.8.6.release.d/debian/rules --- vlc-0.8.6.release.d/debian/rules +++ vlc-0.8.6.release.d/debian/rules @@ -27,6 +27,7 @@ --enable-ggi \ --enable-sdl \ --enable-esd \ + --enable-pulse \ --disable-qt \ --enable-mad \ --enable-arts \ @@ -253,6 +254,7 @@ ln -s vlc debian/vlc-nox/usr/share/doc/vlc-nox ln -s libvlc0 debian/libvlc0-dev/usr/share/doc/libvlc0-dev ln -s vlc debian/vlc-plugin-esd/usr/share/doc/vlc-plugin-esd + ln -s vlc debian/vlc-plugin-pulse/usr/share/doc/vlc-plugin-pulse ln -s vlc debian/vlc-plugin-sdl/usr/share/doc/vlc-plugin-sdl ln -s vlc debian/vlc-plugin-ggi/usr/share/doc/vlc-plugin-ggi ln -s vlc debian/vlc-plugin-arts/usr/share/doc/vlc-plugin-arts diff -u vlc-0.8.6.release.d/debian/changelog vlc-0.8.6.release.d/debian/changelog --- vlc-0.8.6.release.d/debian/changelog +++ vlc-0.8.6.release.d/debian/changelog @@ -1,3 +1,16 @@ +vlc (0.8.6.release.d-0ubuntu7) hardy; urgency=low + + * Add new package with pulse output plugin (LP: #196417) + - debian/patches/030_pulse.diff: + + patch from upstream trunk to support pulseaudio output + - debian/rules: + + enable pulseaudio + - debian/control: + + add dependencies to libpulse-dev + + new package description + + -- Martin Hamrle Tue, 11 Mar 2008 23:09:49 +0100 + vlc (0.8.6.release.d-0ubuntu6) hardy; urgency=low [ Andrew Starr-Bochicchio (andrewsomething) ] diff -u vlc-0.8.6.release.d/debian/control vlc-0.8.6.release.d/debian/control --- vlc-0.8.6.release.d/debian/control +++ vlc-0.8.6.release.d/debian/control @@ -3,7 +3,7 @@ Priority: optional Maintainer: Ubuntu MOTU Developers XSBC-Original-Maintainer: Sam Hocevar (Debian packages) -Build-Depends: debhelper (>= 4.0), dh-buildinfo, quilt, nasm, yasm [amd64], gettext, linux-libc-dev, libxul-dev, xlibmesa-gl-dev, liba52-0.7.4-dev, libaa1-dev, libarts1-dev (>= 1.4.2-1), libasound2-dev (>= 0.9.0beta10a), libaudiofile-dev, libavahi-client-dev, libavcodec-dev (>= 0.cvs20060823-1), libavformat-dev (>= 0.cvs20060823-1), libcdio-dev, libdvbpsi4-dev, libdvdnav-dev, libdvdread-dev (>= 0.9.5), libdts-dev, libesd0-dev, libflac-dev (>= 1.1.2-3), libfreetype6-dev, libfribidi-dev, libggi2-dev, libglib2.0-0, libglide2-dev [i386], libgnutls-dev (>= 1.2.8), libhal-dev (>= 0.5.5.1-3), libid3tag0-dev, libidl0, libimlib2-dev, liblircclient-dev, liblivemedia-dev (>= 2006.03.17), libmad0-dev, libmatroska-dev (>= 0.8.0), libmodplug-dev, libmpcdec-dev, libmpeg2-4-dev, libncurses5-dev, libogg-dev, libpostproc-dev (>= 0.cvs20060823-1), libpng12-dev, libsdl1.2-dev (>= 1.2.7+1.2.8cvs20041007-5.3), libsmbclient-dev, libsvga1-dev [i386], libsysfs-dev, libtar-dev, libtheora-dev, libvcdinfo-dev, libvorbis-dev, libwxgtk2.6-dev, libx11-dev, libxext-dev, libxml2-dev, libxt-dev, libxv-dev, zlib1g-dev, libavc1394-dev, libraw1394-dev, libdc1394-13-dev, libxosd-dev, libspeex-dev, libsdl-image1.2-dev, libgtk2.0-dev, libnotify-dev, libdirectfb-dev, subversion, libcaca-dev, libjack-dev +Build-Depends: debhelper (>= 4.0), dh-buildinfo, quilt, nasm, yasm [amd64], gettext, libtool, automake, cvs, linux-libc-dev, libxul-dev, xlibmesa-gl-dev, liba52-0.7.4-dev, libaa1-dev, libarts1-dev (>= 1.4.2-1), libasound2-dev (>= 0.9.0beta10a), libaudiofile-dev, libavahi-client-dev, libavcodec-dev (>= 0.cvs20060823-1), libavformat-dev (>= 0.cvs20060823-1), libcdio-dev, libdvbpsi4-dev, libdvdnav-dev, libdvdread-dev (>= 0.9.5), libdts-dev, libesd0-dev, libflac-dev (>= 1.1.2-3), libfreetype6-dev, libfribidi-dev, libggi2-dev, libglib2.0-0, libglide2-dev [i386], libgnutls-dev (>= 1.2.8), libhal-dev (>= 0.5.5.1-3), libid3tag0-dev, libidl0, libimlib2-dev, liblircclient-dev, liblivemedia-dev (>= 2006.03.17), libmad0-dev, libmatroska-dev (>= 0.8.0), libmodplug-dev, libmpcdec-dev, libmpeg2-4-dev, libncurses5-dev, libogg-dev, libpostproc-dev (>= 0.cvs20060823-1), libpng12-dev, libsdl1.2-dev (>= 1.2.7+1.2.8cvs20041007-5.3), libsmbclient-dev, libsvga1-dev [i386], libsysfs-dev, libtar-dev, libtheora-dev, libvcdinfo-dev, libvorbis-dev, libwxgtk2.6-dev, libx11-dev, libxext-dev, libxml2-dev, libxt-dev, libxv-dev, zlib1g-dev, libavc1394-dev, libraw1394-dev, libdc1394-13-dev, libxosd-dev, libspeex-dev, libsdl-image1.2-dev, libgtk2.0-dev, libnotify-dev, libdirectfb-dev, subversion, libcaca-dev, libjack-dev, libpulse-dev (>= 0.9.8) Standards-Version: 3.7.2 XS-Vcs-Svn: svn://svn.videolan.org/pkg-multimedia/unstable/vlc/ @@ -29,9 +29,9 @@ for broadcasting purposes or for movie format transformations. Support for most output methods is provided by this package, but features can be added by installing additional audio plugins (vlc-plugin-esd, vlc-plugin-sdl, - vlc-plugin-arts) or video plugins (vlc-plugin-sdl, vlc-plugin-ggi, - vlc-plugin-glide, vlc-plugin-svgalib). There is also a web browser plugin - in the mozilla-plugin-vlc package. + vlc-plugin-arts, vlc-plugin-pulse) or video plugins (vlc-plugin-sdl, + vlc-plugin-ggi, vlc-plugin-glide, vlc-plugin-svgalib). There is also a web + browser plugin in the mozilla-plugin-vlc package. Package: vlc-nox Section: net @@ -53,9 +53,9 @@ for broadcasting purposes or for movie format transformations. Support for most output methods is provided by this package, but features can be added by installing additional audio plugins (vlc-plugin-esd, vlc-plugin-sdl, - vlc-plugin-arts) or video plugins (vlc-plugin-sdl, vlc-plugin-ggi, - vlc-plugin-glide, vlc-plugin-svgalib). There is also a web browser plugin - in the mozilla-plugin-vlc package. + vlc-plugin-arts, vlc-plugin-pulse) or video plugins (vlc-plugin-sdl, + vlc-plugin-ggi, vlc-plugin-glide, vlc-plugin-svgalib). There is also a web + browser plugin in the mozilla-plugin-vlc package. . This package contains a version of VLC that does not require X and that is thus suitable for headless servers. @@ -100,6 +100,20 @@ DivX, MOV, WMV, QuickTime, mp3, Ogg/Vorbis files, DVDs, VCDs, and multimedia streams from various network sources. +Package: vlc-plugin-pulse +Architecture: any +Depends: vlc-nox, ${shlibs:Depends}, ${misc:Depends} +Conflicts: vlc-pulse (<< 0.5.0) +Replaces: vlc-pulse (<< 0.5.0) +Description: Pulseaudio audio output plugin for VLC + This plugin adds support for the Pulseaudio to the VLC + media player. To activate it, use the `--aout pulse' flag or select the + `pulse' audio output plugin from the preferences menu. + . + VLC is the VideoLAN project's media player. It plays MPEG, MPEG2, MPEG4, + DivX, MOV, WMV, QuickTime, mp3, Ogg/Vorbis files, DVDs, VCDs, and multimedia + streams from various network sources. + Package: vlc-plugin-alsa Architecture: all Depends: vlc diff -u vlc-0.8.6.release.d/debian/patches/series vlc-0.8.6.release.d/debian/patches/series --- vlc-0.8.6.release.d/debian/patches/series +++ vlc-0.8.6.release.d/debian/patches/series @@ -8,2 +8,3 @@ 021_CVE-2008-0984.diff +030_pulse.diff 022_no_cpu_consumption.diff only in patch2: unchanged: --- vlc-0.8.6.release.d.orig/debian/vlc-plugin-pulse.dirs +++ vlc-0.8.6.release.d/debian/vlc-plugin-pulse.dirs @@ -0,0 +1,2 @@ +usr/lib/vlc/audio_output +usr/share/doc only in patch2: unchanged: --- vlc-0.8.6.release.d.orig/debian/vlc-plugin-pulse.install +++ vlc-0.8.6.release.d/debian/vlc-plugin-pulse.install @@ -0,0 +1 @@ +usr/lib/vlc/audio_output/libpulse_plugin.so only in patch2: unchanged: --- vlc-0.8.6.release.d.orig/debian/patches/030_pulse.diff +++ vlc-0.8.6.release.d/debian/patches/030_pulse.diff @@ -0,0 +1,521 @@ +Index: vlc-0.8.6.release.d/THANKS +=================================================================== +--- vlc-0.8.6.release.d.orig/THANKS 2008-03-01 09:54:28.000000000 +0100 ++++ vlc-0.8.6.release.d/THANKS 2008-03-01 09:56:07.000000000 +0100 +@@ -144,6 +144,7 @@ + Rudolf Cornelissen - BeOS fixes + Scott Caudle - Visualization, WX + improvements ++Martin Hamrle - PulseAudio output module + Sebastien Chaumat - YOPY port tests + Simon Damkjær Andersen - playmode icons and the entire Fullscreen Panel design for the OS GUI (v0.8.6) + Steve Lhomme - MSVC fixes and Matroska enhancements +Index: vlc-0.8.6.release.d/configure.ac +=================================================================== +--- vlc-0.8.6.release.d.orig/configure.ac 2008-03-01 09:53:14.000000000 +0100 ++++ vlc-0.8.6.release.d/configure.ac 2008-03-01 09:59:54.000000000 +0100 +@@ -4765,6 +4765,20 @@ + fi]) + + dnl ++dnl Pulseaudio module ++dnl ++AC_ARG_ENABLE(pulse, ++ [ --enable-pulse Pulseaudio support (default enabled)]) ++ if test "${enable_pulse}" != "no" ++ then ++ PKG_CHECK_MODULES(PULSE, libpulse >= 0.9.8, ++ [ VLC_ADD_PLUGINS([pulse]) ++ VLC_ADD_CFLAGS([pulse],[${PULSE_CFLAGS}]) ++ VLC_ADD_LDFLAGS([pulse],[${PULSE_LIBS}])]:, ++ [AC_MSG_WARN(pulsaudio library not found)]) ++ fi ++ ++dnl + dnl MacOS X module + dnl + ORIGCFLAGS=$CFLAGS +Index: vlc-0.8.6.release.d/modules/audio_output/Modules.am +=================================================================== +--- vlc-0.8.6.release.d.orig/modules/audio_output/Modules.am 2008-03-01 09:54:06.000000000 +0100 ++++ vlc-0.8.6.release.d/modules/audio_output/Modules.am 2008-03-01 09:56:07.000000000 +0100 +@@ -10,3 +10,4 @@ + SOURCES_portaudio = portaudio.c + SOURCES_auhal = auhal.c + SOURCES_jack = jack.c ++SOURCES_pulse = pulse.c +Index: vlc-0.8.6.release.d/modules/audio_output/pulse.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ vlc-0.8.6.release.d/modules/audio_output/pulse.c 2008-03-01 09:57:10.000000000 +0100 +@@ -0,0 +1,470 @@ ++/***************************************************************************** ++ * pulse.c : Pulseaudio output plugin for vlc ++ ***************************************************************************** ++ * Copyright (C) 2008 the VideoLAN team ++ * ++ * Authors: Martin Hamrle ++ * ++ * 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. ++ *****************************************************************************/ ++ ++/***************************************************************************** ++ * Preamble ++ *****************************************************************************/ ++#ifdef HAVE_CONFIG_H ++# include "config.h" ++#endif ++ ++#include ++ ++#include ++#include "aout_internal.h" ++ ++#include ++ ++/***************************************************************************** ++ * aout_sys_t: Pulseaudio output method descriptor ++ ***************************************************************************** ++ * This structure is part of the audio output thread descriptor. ++ * It describes the specific properties of an audio device. ++ *****************************************************************************/ ++struct aout_sys_t ++{ ++ /** PulseAudio playback stream object */ ++ struct pa_stream *stream; ++ ++ /** PulseAudio connection context */ ++ struct pa_context *context; ++ ++ /** Main event loop object */ ++ struct pa_threaded_mainloop *mainloop; ++ ++ int started; ++ size_t buffer_size; ++ mtime_t start_date; ++}; ++ ++#define PULSE_CLIENT_NAME N_("VLC media player") ++ ++#if 0 ++#define PULSE_DEBUG( ...) \ ++ msg_Dbg( p_aout, __VA_ARGS__ ) ++#else ++#define PULSE_DEBUG( ...) \ ++ (void) 0 ++#endif ++ ++ ++#define CHECK_DEAD_GOTO(label) do { \ ++if (!p_sys->context || pa_context_get_state(p_sys->context) != PA_CONTEXT_READY || \ ++ !p_sys->stream || pa_stream_get_state(p_sys->stream) != PA_STREAM_READY) { \ ++ msg_Err(p_aout, "Connection died: %s", p_sys->context ? pa_strerror(pa_context_errno(p_sys->context)) : "NULL"); \ ++ goto label; \ ++ } \ ++} while(0); ++/***************************************************************************** ++ * Local prototypes ++ *****************************************************************************/ ++static int Open ( vlc_object_t * ); ++static void Close ( vlc_object_t * ); ++static void Play ( aout_instance_t * ); ++ ++static void context_state_cb(pa_context *c, void *userdata); ++static void stream_state_cb(pa_stream *s, void * userdata); ++static void stream_request_cb(pa_stream *s, size_t length, void *userdata); ++static void stream_latency_update_cb(pa_stream *s, void *userdata); ++static void success_cb(pa_stream *s, int sucess, void *userdata); ++static void uninit(aout_instance_t *p_aout); ++/***************************************************************************** ++ * Module descriptor ++ *****************************************************************************/ ++vlc_module_begin(); ++ set_shortname( "Pulse Audio" ); ++ set_description( _("Pulseaudio audio output") ); ++ set_capability( "audio output", 200 ); ++ set_category( CAT_AUDIO ); ++ set_subcategory( SUBCAT_AUDIO_AOUT ); ++ add_shortcut( "pulseaudio" ); ++ add_shortcut( "pa" ); ++ set_callbacks( Open, Close ); ++vlc_module_end(); ++ ++/***************************************************************************** ++ * Open: open the audio device ++ *****************************************************************************/ ++static int Open ( vlc_object_t *p_this ) ++{ ++ aout_instance_t *p_aout = (aout_instance_t *)p_this; ++ struct aout_sys_t * p_sys; ++ struct pa_sample_spec ss; ++ const struct pa_buffer_attr *buffer_attr; ++ struct pa_buffer_attr a; ++ struct pa_channel_map map; ++ ++ /* Allocate structures */ ++ p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) ); ++ if( p_sys == NULL ) ++ { ++ msg_Err( p_aout, "out of memory" ); ++ return VLC_ENOMEM; ++ } ++ p_sys->started = 0; ++ p_sys->stream = NULL; ++ p_sys->mainloop = NULL; ++ p_sys->context = NULL; ++ ++ PULSE_DEBUG( "Pulse start initialization"); ++ ++ ss.rate = p_aout->output.output.i_rate; ++ ss.channels = 2; ++ ++ ss.format = PA_SAMPLE_S16LE; ++ p_aout->output.output.i_physical_channels = ++ AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; ++ p_aout->output.output.i_format = AOUT_FMT_S16_NE; ++ ++ if (!pa_sample_spec_valid(&ss)) { ++ msg_Err(p_aout,"Invalid sample spec"); ++ goto fail; ++ } ++ ++ a.maxlength = pa_bytes_per_second(&ss)/4/pa_frame_size(&ss); ++ a.tlength = a.maxlength*9/10; ++ a.prebuf = a.tlength/2; ++ a.minreq = a.tlength/10; ++ ++ a.maxlength *= pa_frame_size(&ss); ++ a.tlength *= pa_frame_size(&ss); ++ a.prebuf *= pa_frame_size(&ss); ++ a.minreq *= pa_frame_size(&ss); ++ ++ p_sys->buffer_size = a.minreq; ++ ++ pa_channel_map_init_stereo(&map); ++ ++ ++ if (!(p_sys->mainloop = pa_threaded_mainloop_new())) { ++ msg_Err(p_aout, "Failed to allocate main loop"); ++ goto fail; ++ } ++ ++ if (!(p_sys->context = pa_context_new(pa_threaded_mainloop_get_api(p_sys->mainloop), _( PULSE_CLIENT_NAME )))) { ++ msg_Err(p_aout, "Failed to allocate context"); ++ goto fail; ++ } ++ ++ pa_context_set_state_callback(p_sys->context, context_state_cb, p_aout); ++ ++ PULSE_DEBUG( "Pulse before context connect"); ++ ++ if (pa_context_connect(p_sys->context, NULL, 0, NULL) < 0) { ++ msg_Err(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); ++ goto fail; ++ } ++ ++ PULSE_DEBUG( "Pulse after context connect"); ++ ++ pa_threaded_mainloop_lock(p_sys->mainloop); ++ ++ if (pa_threaded_mainloop_start(p_sys->mainloop) < 0) { ++ msg_Err(p_aout, "Failed to start main loop"); ++ goto unlock_and_fail; ++ } ++ ++ msg_Dbg(p_aout, "Pulse mainloop started"); ++ ++ /* Wait until the context is ready */ ++ pa_threaded_mainloop_wait(p_sys->mainloop); ++ ++ if (pa_context_get_state(p_sys->context) != PA_CONTEXT_READY) { ++ msg_Err(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); ++ goto unlock_and_fail; ++ } ++ ++ if (!(p_sys->stream = pa_stream_new(p_sys->context, "audio stream", &ss, &map))) { ++ msg_Err(p_aout, "Failed to create stream: %s", pa_strerror(pa_context_errno(p_sys->context))); ++ goto unlock_and_fail; ++ } ++ ++ PULSE_DEBUG( "Pulse after new stream"); ++ ++ pa_stream_set_state_callback(p_sys->stream, stream_state_cb, p_aout); ++ pa_stream_set_write_callback(p_sys->stream, stream_request_cb, p_aout); ++ pa_stream_set_latency_update_callback(p_sys->stream, stream_latency_update_cb, p_aout); ++ ++ if (pa_stream_connect_playback(p_sys->stream, NULL, &a, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { ++ msg_Err(p_aout, "Failed to connect stream: %s", pa_strerror(pa_context_errno(p_sys->context))); ++ goto unlock_and_fail; ++ } ++ ++ PULSE_DEBUG("Pulse stream connect"); ++ ++ /* Wait until the stream is ready */ ++ pa_threaded_mainloop_wait(p_sys->mainloop); ++ ++ msg_Dbg(p_aout,"Pulse stream connected"); ++ ++ if (pa_stream_get_state(p_sys->stream) != PA_STREAM_READY) { ++ msg_Err(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); ++ goto unlock_and_fail; ++ } ++ ++ ++ PULSE_DEBUG("Pulse after stream get status"); ++ ++ pa_threaded_mainloop_unlock(p_sys->mainloop); ++ ++ buffer_attr = pa_stream_get_buffer_attr(p_sys->stream); ++ p_aout->output.i_nb_samples = buffer_attr->minreq / pa_frame_size(&ss); ++ p_aout->output.pf_play = Play; ++ aout_VolumeSoftInit(p_aout); ++ msg_Dbg(p_aout, "Pulse initialized successfully"); ++ { ++ char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; ++ ++ msg_Dbg(p_aout, "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u", buffer_attr->maxlength, buffer_attr->tlength, buffer_attr->prebuf, buffer_attr->minreq); ++ msg_Dbg(p_aout, "Using sample spec '%s', channel map '%s'.", ++ pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(p_sys->stream)), ++ pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(p_sys->stream))); ++ ++ msg_Dbg(p_aout, "Connected to device %s (%u, %ssuspended).", ++ pa_stream_get_device_name(p_sys->stream), ++ pa_stream_get_device_index(p_sys->stream), ++ pa_stream_is_suspended(p_sys->stream) ? "" : "not "); ++ } ++ ++ return VLC_SUCCESS; ++ ++unlock_and_fail: ++ msg_Dbg(p_aout, "Pulse initialization unlock and fail"); ++ ++ if (p_sys->mainloop) ++ pa_threaded_mainloop_unlock(p_sys->mainloop); ++fail: ++ msg_Err(p_aout, "Pulse initialization failed"); ++ uninit(p_aout); ++ return VLC_EGENERIC; ++} ++ ++/***************************************************************************** ++ * Play: play a sound samples buffer ++ *****************************************************************************/ ++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"); ++ 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); ++ } ++} ++ ++/***************************************************************************** ++ * Close: close the audio device ++ *****************************************************************************/ ++static void Close ( vlc_object_t *p_this ) ++{ ++ aout_instance_t *p_aout = (aout_instance_t *)p_this; ++ struct aout_sys_t * p_sys = p_aout->output.p_sys; ++ ++ 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); ++ ++ 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); ++ } ++ ++ fail: ++ ++ pa_operation_unref(o); ++ } ++ ++ pa_threaded_mainloop_unlock(p_sys->mainloop); ++ } ++ uninit(p_aout); ++} ++ ++static void uninit(aout_instance_t *p_aout){ ++ struct aout_sys_t * p_sys = p_aout->output.p_sys; ++ ++ if (p_sys->mainloop) ++ pa_threaded_mainloop_stop(p_sys->mainloop); ++ ++ if (p_sys->stream) { ++ pa_stream_disconnect(p_sys->stream); ++ pa_stream_unref(p_sys->stream); ++ p_sys->stream = NULL; ++ } ++ ++ if (p_sys->context) { ++ pa_context_disconnect(p_sys->context); ++ pa_context_unref(p_sys->context); ++ p_sys->context = NULL; ++ } ++ ++ if (p_sys->mainloop) { ++ pa_threaded_mainloop_free(p_sys->mainloop); ++ p_sys->mainloop = NULL; ++ } ++ ++ free(p_sys); ++ p_aout->output.p_sys = NULL; ++} ++ ++static void context_state_cb(pa_context *c, void *userdata) { ++ aout_instance_t *p_aout = (aout_instance_t *)userdata; ++ struct aout_sys_t * p_sys = (struct aout_sys_t *) p_aout->output.p_sys; ++ ++ assert(c); ++ ++ PULSE_DEBUG( "Pulse context state changed"); ++ ++ switch (pa_context_get_state(c)) { ++ case PA_CONTEXT_READY: ++ case PA_CONTEXT_TERMINATED: ++ case PA_CONTEXT_FAILED: ++ PULSE_DEBUG( "Pulse context state changed signal"); ++ pa_threaded_mainloop_signal(p_sys->mainloop, 0); ++ break; ++ ++ case PA_CONTEXT_UNCONNECTED: ++ case PA_CONTEXT_CONNECTING: ++ case PA_CONTEXT_AUTHORIZING: ++ case PA_CONTEXT_SETTING_NAME: ++ PULSE_DEBUG( "Pulse context state changed no signal"); ++ break; ++ } ++} ++ ++static void stream_state_cb(pa_stream *s, void * userdata) { ++ aout_instance_t *p_aout = (aout_instance_t *)userdata; ++ struct aout_sys_t * p_sys = (struct aout_sys_t *) p_aout->output.p_sys; ++ ++ assert(s); ++ ++ PULSE_DEBUG( "Pulse stream state changed"); ++ ++ switch (pa_stream_get_state(s)) { ++ ++ case PA_STREAM_READY: ++ case PA_STREAM_FAILED: ++ case PA_STREAM_TERMINATED: ++ pa_threaded_mainloop_signal(p_sys->mainloop, 0); ++ break; ++ ++ case PA_STREAM_UNCONNECTED: ++ case PA_STREAM_CREATING: ++ break; ++ } ++} ++ ++static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { ++ aout_instance_t *p_aout = (aout_instance_t *)userdata; ++ struct aout_sys_t * p_sys = (struct aout_sys_t *) p_aout->output.p_sys; ++ mtime_t next_date; ++ ++ assert(s); ++ assert(p_sys); ++ ++ size_t buffer_size = p_sys->buffer_size; ++ ++ PULSE_DEBUG( "Pulse stream request %d", length); ++ ++ do{ ++ aout_buffer_t * p_buffer = NULL; ++ if(p_sys->started){ ++ pa_usec_t latency; ++ int negative; ++ if(pa_stream_get_latency(p_sys->stream, &latency, &negative)<0){ ++ if (pa_context_errno(p_sys->context) != PA_ERR_NODATA) { ++ msg_Err(p_aout, "pa_stream_get_latency() failed: %s", pa_strerror(pa_context_errno(p_sys->context))); ++ } ++ latency = 0; ++ ++ } ++ PULSE_DEBUG( "Pulse stream request latency="I64Fd"", latency); ++ next_date = mdate() + latency; ++ ++ ++ if(p_sys->start_date < next_date + AOUT_PTS_TOLERANCE ){ ++ /* ++ vlc_mutex_lock( &p_aout->output_fifo_lock ); ++ p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo ); ++ vlc_mutex_unlock( &p_aout->output_fifo_lock ); ++ */ ++ p_buffer = aout_OutputNextBuffer( p_aout, next_date, 0); ++ } ++ } ++ ++ if ( p_buffer != NULL ) ++ { ++ PULSE_DEBUG( "Pulse stream request write buffer %d", p_buffer->i_nb_bytes); ++ pa_stream_write(p_sys->stream, p_buffer->p_buffer, p_buffer->i_nb_bytes, NULL, 0, PA_SEEK_RELATIVE); ++ length -= p_buffer->i_nb_bytes; ++ aout_BufferFree( p_buffer ); ++ } ++ else ++ { ++ PULSE_DEBUG( "Pulse stream request write zeroes"); ++ void *data = pa_xmalloc(buffer_size); ++ bzero(data, buffer_size); ++ pa_stream_write(p_sys->stream, data, buffer_size, pa_xfree, 0, PA_SEEK_RELATIVE); ++ length -= buffer_size; ++ } ++ }while(length > buffer_size); ++ ++ pa_threaded_mainloop_signal(p_sys->mainloop, 0); ++} ++ ++static void stream_latency_update_cb(pa_stream *s, void *userdata) { ++ aout_instance_t *p_aout = (aout_instance_t *)userdata; ++ struct aout_sys_t * p_sys = (struct aout_sys_t *) p_aout->output.p_sys; ++ ++ assert(s); ++ ++ PULSE_DEBUG( "Pulse stream latency update"); ++ ++ pa_threaded_mainloop_signal(p_sys->mainloop, 0); ++} ++ ++static void success_cb(pa_stream *s, int sucess, void *userdata) ++{ ++ aout_instance_t *p_aout = (aout_instance_t *)userdata; ++ struct aout_sys_t * p_sys = (struct aout_sys_t *) p_aout->output.p_sys; ++ ++ assert(s); ++ ++ pa_threaded_mainloop_signal(p_sys->mainloop, 0); ++} ++ ++#undef PULSE_DEBUG