SOURCES: mplayer-pulse.patch (NEW) - from official homepage: http:...
glen
glen at pld-linux.org
Mon Dec 4 21:42:21 CET 2006
Author: glen Date: Mon Dec 4 20:42:21 2006 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- from official homepage: http://pulseaudio.org/wiki/PerfectSetup
http://0pointer.de/public/mplayer-pulse.patch
---- Files affected:
SOURCES:
mplayer-pulse.patch (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/mplayer-pulse.patch
diff -u /dev/null SOURCES/mplayer-pulse.patch:1.1
--- /dev/null Mon Dec 4 21:42:21 2006
+++ SOURCES/mplayer-pulse.patch Mon Dec 4 21:42:16 2006
@@ -0,0 +1,1066 @@
+Index: AUTHORS
+===================================================================
+--- AUTHORS (revision 19105)
++++ AUTHORS (working copy)
+@@ -623,7 +623,7 @@
+ * Darwin VCD/SVCD support
+
+ Poettering, Lennart <mzzcynlre at 0pointer.de>
+- * audio driver for the Polypaudio sound server
++ * audio driver for the PulseAudio sound server
+
+ Poirier, Guillaume (poirierg) <poirierg at gmail.com>
+ * French documentation translation and synchronization
+Index: libao2/ao_pulse.c
+===================================================================
+--- libao2/ao_pulse.c (revision 0)
++++ libao2/ao_pulse.c (revision 0)
+@@ -0,0 +1,566 @@
++#include <assert.h>
++#include <string.h>
++#include <stdio.h>
++
++#include <pulse/pulseaudio.h>
++
++#include "config.h"
++#include "libaf/af_format.h"
++#include "mp_msg.h"
++#include "audio_out.h"
++#include "audio_out_internal.h"
++
++#define PULSE_CLIENT_NAME "MPlayer"
++
++/*#define PULSE_DEBUG*/
++
++/** General driver info */
++static ao_info_t info = {
++ "PulseAudio audio output",
++ "pulse",
++ "Lennart Poettering",
++ ""
++};
++
++/** The sink to connect to */
++static char *sink = NULL;
++
++/** PulseAudio playback stream object */
++static struct pa_stream *stream = NULL;
++
++/** PulseAudio connection context */
++static struct pa_context *context = NULL;
++
++/** Main event loop object */
++static struct pa_threaded_mainloop *mainloop = NULL;
++
++/** A temporary variable to store the current volume */
++static pa_cvolume volume;
++static int volume_initialized = 0;
++
++/** Some special libao macro magic */
++LIBAO_EXTERN(pulse)
++
++#define CHECK_DEAD_GOTO(label) do { \
++if (!context || pa_context_get_state(context) != PA_CONTEXT_READY || \
++ !stream || pa_stream_get_state(stream) != PA_STREAM_READY) { \
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \
++ goto label; \
++ } \
++} while(0);
++
++static void context_state_cb(pa_context *c, void *userdata) {
++ assert(c);
++
++ switch (pa_context_get_state(c)) {
++ case PA_CONTEXT_READY:
++ case PA_CONTEXT_TERMINATED:
++ case PA_CONTEXT_FAILED:
++ pa_threaded_mainloop_signal(mainloop, 0);
++ break;
++
++ case PA_CONTEXT_UNCONNECTED:
++ case PA_CONTEXT_CONNECTING:
++ case PA_CONTEXT_AUTHORIZING:
++ case PA_CONTEXT_SETTING_NAME:
++ break;
++ }
++}
++
++static void stream_state_cb(pa_stream *s, void * userdata) {
++ assert(s);
++
++ switch (pa_stream_get_state(s)) {
++
++ case PA_STREAM_READY:
++ case PA_STREAM_FAILED:
++ case PA_STREAM_TERMINATED:
++ pa_threaded_mainloop_signal(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) {
++ assert(s);
++
++ pa_threaded_mainloop_signal(mainloop, 0);
++}
++
++static void stream_latency_update_cb(pa_stream *s, void *userdata) {
++ assert(s);
++
++ pa_threaded_mainloop_signal(mainloop, 0);
++}
++
++static void success_cb(pa_stream *s, int success, void *userdata) {
++ assert(s);
++
++ if (userdata)
++ *(int*) userdata = success;
++ pa_threaded_mainloop_signal(mainloop, 0);
++}
++
++/** libao initialization function, arguments are sampling frequency,
++ * number of channels, sample type and some flags */
++static int init(int rate_hz, int channels, int format, int flags) {
++ struct pa_sample_spec ss;
++ struct pa_channel_map map;
++ char hn[128];
++ char *host = NULL;
++
++ assert(!context);
++ assert(!stream);
++ assert(!mainloop);
++
++ if (ao_subdevice) {
++ int i = strcspn(ao_subdevice, ":");
++ if ((size_t) i >= sizeof(hn))
++ i = sizeof(hn)-1;
++
++ if (i > 0) {
++ strncpy(host = hn, ao_subdevice, i);
++ hn[i] = 0;
++ }
++
++ if (ao_subdevice[i] == ':')
++ sink = ao_subdevice+i+1;
++ }
++
++ ss.channels = channels;
++ ss.rate = rate_hz;
++
++ ao_data.samplerate = rate_hz;
++ ao_data.format = format;
++ ao_data.channels = channels;
++
++ switch (format) {
++ case AF_FORMAT_U8:
++ ss.format = PA_SAMPLE_U8;
++ break;
++ case AF_FORMAT_S16_LE:
++ ss.format = PA_SAMPLE_S16LE;
++ break;
++ case AF_FORMAT_S16_BE:
++ ss.format = PA_SAMPLE_S16BE;
++ break;
++ case AF_FORMAT_FLOAT_LE:
++ ss.format = PA_SAMPLE_FLOAT32LE;
++ break;
++ case AF_FORMAT_FLOAT_BE:
++ ss.format = PA_SAMPLE_FLOAT32BE;
++ break;
++ case AF_FORMAT_MU_LAW:
++ ss.format = PA_SAMPLE_ULAW;
++ break;
++ case AF_FORMAT_A_LAW:
++ ss.format = PA_SAMPLE_ALAW;
++ break;
++ default:
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Unsupported sample spec\n");
++ goto fail;
++ }
++
++ if (!pa_sample_spec_valid(&ss)) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Invalid sample spec\n");
++ goto fail;
++ }
++
++ pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
++ ao_data.bps = pa_bytes_per_second(&ss);
++
++ if (!volume_initialized || ss.channels != volume.channels) {
++ pa_cvolume_reset(&volume, ss.channels);
++ volume_initialized = 1;
++ }
++
++ if (!(mainloop = pa_threaded_mainloop_new())) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to allocate main loop\n");
++ goto fail;
++ }
++
++ if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), PULSE_CLIENT_NAME))) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to allocate context\n");
++ goto fail;
++ }
++
++ pa_context_set_state_callback(context, context_state_cb, NULL);
++
++ if (pa_context_connect(context, host, 0, NULL) < 0) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context)));
++ goto fail;
++ }
++
++ pa_threaded_mainloop_lock(mainloop);
++
++ if (pa_threaded_mainloop_start(mainloop) < 0) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to start main loop\n");
++ goto unlock_and_fail;
++ }
++
++ /* Wait until the context is ready */
++ pa_threaded_mainloop_wait(mainloop);
++
++ if (pa_context_get_state(context) != PA_CONTEXT_READY) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context)));
++ goto unlock_and_fail;
++ }
++
++ if (!(stream = pa_stream_new(context, "audio stream", &ss, &map))) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to create stream: %s\n", pa_strerror(pa_context_errno(context)));
++ goto unlock_and_fail;
++ }
++
++ pa_stream_set_state_callback(stream, stream_state_cb, NULL);
++ pa_stream_set_write_callback(stream, stream_request_cb, NULL);
++ pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL);
++
++ if (pa_stream_connect_playback(stream, sink, NULL, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, &volume, NULL) < 0) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to connect stream: %s\n", pa_strerror(pa_context_errno(context)));
++ goto unlock_and_fail;
++ }
++
++ /* Wait until the stream is ready */
++ pa_threaded_mainloop_wait(mainloop);
++
++ if (pa_stream_get_state(stream) != PA_STREAM_READY) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context)));
++ goto unlock_and_fail;
++ }
++
++ pa_threaded_mainloop_unlock(mainloop);
++
++ return 1;
++
++unlock_and_fail:
++
++ if (mainloop)
++ pa_threaded_mainloop_unlock(mainloop);
++
++fail:
++
++ uninit(1);
++ return 0;
++}
++
++/** Destroy libao driver */
++static void uninit(int immed) {
++#ifdef PULSE_DEBUG
++ fprintf(stderr, "uninit(%i) ***\n", immed);
++#endif
++
++ if (stream) {
++ if (!immed) {
++ pa_operation *o;
++
++ pa_threaded_mainloop_lock(mainloop);
++
++ if ((o = pa_stream_drain(stream, success_cb, NULL))) {
++
++ while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
++ CHECK_DEAD_GOTO(fail);
++ pa_threaded_mainloop_wait(mainloop);
++ }
++
++ fail:
++
++ pa_operation_unref(o);
++ }
++
++ pa_threaded_mainloop_unlock(mainloop);
++ }
++ }
++
++ if (mainloop)
++ pa_threaded_mainloop_stop(mainloop);
++
++ if (stream) {
++ pa_stream_disconnect(stream);
++ pa_stream_unref(stream);
++ stream = NULL;
++ }
++
++ if (context) {
++ pa_context_disconnect(context);
++ pa_context_unref(context);
++ context = NULL;
++ }
++
++ if (mainloop) {
++ pa_threaded_mainloop_free(mainloop);
++ mainloop = NULL;
++ }
++}
++
++/** Play the specified data to the pulseaudio server */
++static int play(void* data, int len, int flags) {
++ int r = -1;
++ pa_operation *o = NULL;
++
++ assert(stream);
++ assert(context);
++
++#ifdef PULSE_DEBUG
++ fprintf(stderr, "playing %lu ***\n", len);
++#endif
++
++ pa_threaded_mainloop_lock(mainloop);
++
++ CHECK_DEAD_GOTO(fail);
++
++ if (len) {
++
++ if (pa_stream_write(stream, data, len, NULL, 0, PA_SEEK_RELATIVE) < 0) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_write() failed: %s\n", pa_strerror(pa_context_errno(context)));
++ goto fail;
++ }
++
++ } else {
++
++ if (!(o = pa_stream_trigger(stream, NULL, NULL))) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_trigger() failed: %s\n", pa_strerror(pa_context_errno(context)));
++ goto fail;
++ }
++
++ /* We don't wait for this operation to complete */
++ }
++
++ r = len;
++
++fail:
++ if (o)
++ pa_operation_unref(o);
++
++ pa_threaded_mainloop_unlock(mainloop);
++
++ return r;
++}
++
++static void cork(int b) {
++ pa_operation *o = NULL;
++ int success = 0;
++
++ assert(stream);
++ assert(context);
++
++#ifdef PULSE_DEBUG
++ fprintf(stderr, "cork(%i) ***\n", b);
++#endif
++
++ pa_threaded_mainloop_lock(mainloop);
++
++ CHECK_DEAD_GOTO(fail);
++
++ if (!(o = pa_stream_cork(stream, b, success_cb, &success))) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_cork() failed: %s\n", pa_strerror(pa_context_errno(context)));
++ goto fail;
++ }
++
++ while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
++ CHECK_DEAD_GOTO(fail);
++ pa_threaded_mainloop_wait(mainloop);
++ }
++
++ if (!success)
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_cork() failed: %s\n", pa_strerror(pa_context_errno(context)));
++
++ pa_operation_unref(o);
++
++fail:
++ pa_threaded_mainloop_unlock(mainloop);
++}
++
++/** Pause the audio stream by corking it on the server */
++static void audio_pause(void) {
++ cork(1);
++ }
++
++/** Resume the audio stream by uncorking it on the server */
++static void audio_resume(void) {
++ cork(0);
++}
++
++/** Reset the audio stream, i.e. flush the playback buffer on the server side */
++static void reset(void) {
++ pa_operation *o = NULL;
++ int success = 0;
++
++ assert(stream);
++ assert(context);
++
++#ifdef PULSE_DEBUG
++ fprintf(stderr, "reset() ***\n");
++#endif
++
++ pa_threaded_mainloop_lock(mainloop);
++
++ CHECK_DEAD_GOTO(fail);
++
++ if (!(o = pa_stream_flush(stream, success_cb, &success))) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_flush() failed: %s\n", pa_strerror(pa_context_errno(context)));
++ goto fail;
++ }
++
++ while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
++ CHECK_DEAD_GOTO(fail);
++ pa_threaded_mainloop_wait(mainloop);
++ }
++
++ if (!success)
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_flush() failed: %s\n", pa_strerror(pa_context_errno(context)));
++
++ pa_operation_unref(o);
++
++fail:
++ pa_threaded_mainloop_unlock(mainloop);
++}
++
++/** Return number of bytes that may be written to the server without blocking */
++static int get_space(void) {
++ size_t l = (size_t) -1;
++
++ pa_threaded_mainloop_lock(mainloop);
++
++ CHECK_DEAD_GOTO(fail);
++
++ l = pa_stream_writable_size(stream);
++
++#ifdef PULSE_DEBUG
++ fprintf(stderr, "\nspace = %lu\n", l);
++#endif
++
++fail:
++
++ pa_threaded_mainloop_unlock(mainloop);
++
++ return l == (size_t) -1 ? -1 : (int) l;
++}
++
++/** Return the current latency in seconds */
++static float get_delay(void) {
++ pa_usec_t latency = (pa_usec_t) -1;
++
++ pa_threaded_mainloop_lock(mainloop);
++
++ for (;;) {
++ CHECK_DEAD_GOTO(fail);
++
++ if (pa_stream_get_latency(stream, &latency, NULL) >= 0)
++ break;
++
++ if (pa_context_errno(context) != PA_ERR_NODATA) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_get_latency() failed: %s\n", pa_strerror(pa_context_errno(context)));
++ goto fail;
++ }
++
++ /* Wait until latency data is available again */
++ pa_threaded_mainloop_wait(mainloop);
++ }
++
++#ifdef PULSE_DEBUG
++ fprintf(stderr, "latency=%0.3f sec\n", (double) latency / 1000000);
++#endif
++
++fail:
++ pa_threaded_mainloop_unlock(mainloop);
++
++ return (latency == (pa_usec_t) -1) ? 0 : ((float) latency / 1000000.0);
++}
++
++/** A callback function that is called when the
++ * pa_context_get_sink_input_info() operation completes. Saves the
++ * volume field of the specified structure to the global variable volume. */
++static void info_func(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) {
++ if (is_last < 0) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to get sink input info: %s\n", pa_strerror(pa_context_errno(context)));
++ return;
++ }
++
++ if (!i)
++ return;
++
++ volume = i->volume;
++ volume_initialized = 1;
++
++ pa_threaded_mainloop_signal(mainloop, 0);
++}
++
++/** Issue special libao controls on the device */
++static int control(int cmd, void *arg) {
++
++ if (!context || !stream)
++ return CONTROL_ERROR;
++
++ switch (cmd) {
++
++ case AOCONTROL_GET_VOLUME: {
++ /* Return the current volume of the playback stream */
++ ao_control_vol_t *vol = (ao_control_vol_t*) arg;
++ pa_operation *o;
++
++ if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_func, NULL))) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_get_sink_input_info() failed: %s\n", pa_strerror(pa_context_errno(context)));
++ return CONTROL_ERROR;
++ }
++
++ while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
++ CHECK_DEAD_GOTO(fail);
++ pa_threaded_mainloop_wait(mainloop);
++ }
++
++ fail:
++ pa_operation_unref(o);
++
++ if (!volume_initialized) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_stream_get_sink_input_info() failed: %s\n", pa_strerror(pa_context_errno(context)));
++ return CONTROL_ERROR;
++ }
++
++ if (volume.channels != 2)
++ vol->left = vol->right = (int) ((pa_cvolume_avg(&volume)*100)/PA_VOLUME_NORM);
++ else {
++ vol->left = (int) (volume.values[0]*100)/PA_VOLUME_NORM;
++ vol->right = (int) (volume.values[1]*100)/PA_VOLUME_NORM;
++ }
++
++ return CONTROL_OK;
++ }
++
++ case AOCONTROL_SET_VOLUME: {
++ /* Set the playback volume of the stream */
++ const ao_control_vol_t *vol = (ao_control_vol_t*) arg;
++ pa_operation *o;
++
++ if (!volume_initialized) {
++ pa_cvolume_reset(&volume, 2);
++ volume_initialized = 1;
++ }
++
++ if (volume.channels != 2)
++ pa_cvolume_set(&volume, volume.channels, ((pa_volume_t) vol->left*PA_VOLUME_NORM)/100);
++ else {
++ volume.values[0] = ((pa_volume_t) vol->left*PA_VOLUME_NORM)/100;
++ volume.values[1] = ((pa_volume_t) vol->right*PA_VOLUME_NORM)/100;
++ }
++
++ if (!(o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL))) {
++ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] pa_context_set_sink_input_volume() failed: %s\n", pa_strerror(pa_context_errno(context)));
++ return CONTROL_ERROR;
++ }
++
++ pa_operation_unref(o);
++
++ /* We don't wait for completion here */
++
++ return CONTROL_OK;
++ }
++
++ default:
++ /* Unknown CONTROL command */
++ return CONTROL_UNKNOWN;
++ }
++}
++
+Index: libao2/ao_polyp.c
+===================================================================
+--- libao2/ao_polyp.c (revision 19105)
++++ libao2/ao_polyp.c (working copy)
+@@ -1,324 +0,0 @@
+-#include <assert.h>
+-#include <string.h>
<<Diff was trimmed, longer than 597 lines>>
More information about the pld-cvs-commit
mailing list