Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 147630 Details for
Bug 215342
Add pulseaudio output modules to media-video/vlc
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
pulse audio output module patch from upstream
pulse.patch (text/plain), 16.82 KB, created by
R Bar-On
on 2008-03-29 15:51:28 UTC
(
hide
)
Description:
pulse audio output module patch from upstream
Filename:
MIME Type:
Creator:
R Bar-On
Created:
2008-03-29 15:51:28 UTC
Size:
16.82 KB
patch
obsolete
>Index: configure.ac >=================================================================== >--- configure.ac (revision 25086) >+++ configure.ac (working copy) >@@ -4646,6 +4646,24 @@ > fi]) > > dnl >+dnl Pulseaudio module >+dnl >+AC_ARG_ENABLE(pulse, >+ [ --enable-pulse Pulseaudio support (default disabled)], >+ [ >+ if test "x$enable_pulse" != "xno"; then >+ PKG_CHECK_MODULES([PULSEAUDIO], [libpulse], [ >+ VLC_ADD_PLUGINS([pulse]) >+ VLC_ADD_CFLAGS([pulse],[`pkg-config --cflags libpulse`]) >+ VLC_ADD_LIBS([pulse],[`pkg-config --libs libpulse`]) >+ ], [ >+ AS_IF([test "${enable_pulse}" = "yes"],[ >+ AC_MSG_WARN( libpulse not found) >+ ]) >+ ]) >+ fi]) >+ >+dnl > dnl Portaudio module > dnl > AC_ARG_ENABLE(portaudio, >Index: modules/audio_output/Modules.am >=================================================================== >--- modules/audio_output/Modules.am (revision 25086) >+++ modules/audio_output/Modules.am (working copy) >@@ -10,3 +10,4 @@ > SOURCES_portaudio = portaudio.c > SOURCES_auhal = auhal.c > SOURCES_jack = jack.c >+SOURCES_pulse = pulse.c >Index: modules/audio_output/pulse.c >=================================================================== >--- modules/audio_output/pulse.c (revision 0) >+++ modules/audio_output/pulse.c (revision 0) >@@ -0,0 +1,455 @@ >+/***************************************************************************** >+ * pulse.c : Pulseaudio output plugin for vlc >+ ***************************************************************************** >+ * Copyright (C) 2000-2002 the VideoLAN team >+ * >+ * Authors: Martin Hamrle <hamrle@post.cz> >+ * >+ * 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 <vlc/vlc.h> >+#include <vlc_aout.h> >+ >+#include <pulse/pulseaudio.h> >+ >+/***************************************************************************** >+ * 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 "vlc" >+ >+#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\n", 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 success, void *userdata); >+static void uninit(aout_instance_t *p_aout); >+/***************************************************************************** >+ * Module descriptor >+ *****************************************************************************/ >+vlc_module_begin(); >+ set_shortname( "pulse" ); >+ set_description( _("Pulseaudio audio output") ); >+ set_capability( "audio output", 40 ); >+ set_category( CAT_AUDIO ); >+ set_subcategory( SUBCAT_AUDIO_AOUT ); >+ add_shortcut( "pulse" ); >+ 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; >+ >+ msg_Dbg(p_aout, "Pulse start initialization\n"); >+ >+ 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\n"); >+ 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\n"); >+ 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\n"); >+ goto fail; >+ } >+ >+ pa_context_set_state_callback(p_sys->context, context_state_cb, p_aout); >+ >+ msg_Dbg(p_aout, "Pulse before context connect\n"); >+ >+ if (pa_context_connect(p_sys->context, NULL, 0, NULL) < 0) { >+ msg_Err(p_aout, "Failed to connect to server: %s\n", pa_strerror(pa_context_errno(p_sys->context))); >+ goto fail; >+ } >+ >+ msg_Dbg(p_aout, "Pulse after context connect\n"); >+ >+ 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\n"); >+ goto unlock_and_fail; >+ } >+ >+ msg_Dbg(p_aout, "Pulse mainloop started\n"); >+ >+ /* 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\n", 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\n", pa_strerror(pa_context_errno(p_sys->context))); >+ goto unlock_and_fail; >+ } >+ >+ msg_Dbg(p_aout, "Pulse after new stream\n"); >+ >+ 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\n", pa_strerror(pa_context_errno(p_sys->context))); >+ goto unlock_and_fail; >+ } >+ >+ msg_Dbg(p_aout, "Pulse stream connect\n"); >+ >+ /* Wait until the stream is ready */ >+ pa_threaded_mainloop_wait(p_sys->mainloop); >+ >+ msg_Dbg(p_aout, "Pulse stream connected\n"); >+ >+ if (pa_stream_get_state(p_sys->stream) != PA_STREAM_READY) { >+ msg_Err(p_aout, "Failed to connect to server: %s\n", pa_strerror(pa_context_errno(p_sys->context))); >+ goto unlock_and_fail; >+ } >+ >+ >+ msg_Dbg(p_aout, "Pulse after stream get status\n"); >+ >+ 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; >+ msg_Dbg(p_aout, "Pulse initialized successfully\n"); >+ { >+ 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\n", buffer_attr->maxlength, buffer_attr->tlength, buffer_attr->prebuf, buffer_attr->minreq); >+ msg_Dbg(p_aout, "Using sample spec '%s', channel map '%s'.\n", >+ 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).\n", >+ 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\n"); >+ >+ if (p_sys->mainloop) >+ pa_threaded_mainloop_unlock(p_sys->mainloop); >+fail: >+ msg_Err(p_aout, "Pulse initialization failed\n"); >+ 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\n"); >+ 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\n"); >+ >+ 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); >+ >+ msg_Dbg(p_aout, "Pulse context state changed\n"); >+ >+ switch (pa_context_get_state(c)) { >+ case PA_CONTEXT_READY: >+ case PA_CONTEXT_TERMINATED: >+ case PA_CONTEXT_FAILED: >+ msg_Dbg(p_aout, "Pulse context state changed signal\n"); >+ 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: >+ msg_Dbg(p_aout, "Pulse context state changed no signal\n"); >+ 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); >+ >+ msg_Dbg(p_aout, "Pulse stream state changed\n"); >+ >+ 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; >+ >+ msg_Dbg(p_aout, "Pulse stream request %d\n", 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\n", pa_strerror(pa_context_errno(p_sys->context))); >+ } >+ latency = 0; >+ >+ } >+ msg_Dbg(p_aout, "Pulse stream request latency="I64Fd"\n", 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 ) >+ { >+ msg_Dbg(p_aout, "Pulse stream request write buffer %d\n", 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 >+ { >+ msg_Dbg(p_aout, "Pulse stream request write zeroes\n"); >+ 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); >+ >+ msg_Dbg(p_aout, "Pulse stream latency update\n"); >+ >+ pa_threaded_mainloop_signal(p_sys->mainloop, 0); >+} >+ >+static void success_cb(pa_stream *s, int success, 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); >+} >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 215342
: 147630 |
147631