[MPlayer-dev-eng] [PATCH] polypaudio audio driver
Lennart Poettering
mzzcynlre at 0pointer.de
Sun Oct 31 23:25:03 CET 2004
On Sat, 30.10.04 10:41, Sascha Sommer (saschasommer at freenet.de) wrote:
> > > (http://0pointer.de/lennart/projects/polypaudio/).
> > >
> > > Please merge it!
[..]
> Sorry, something is still missing.
> Can you please read DOCS/tech/code-documentation.txt and add comments
> to the driver?
Here we are: a new, updated patch including doxygen compatible
comments is attached.
Please apply!
Thank you,
Lennart
--
name { Lennart Poettering } loc { Hamburg - Germany }
mail { mzft (at) 0pointer (dot) de } gpg { 1A015CC4 }
www { http://0pointer.de/lennart/ } icq# { 11060553 }
-------------- next part --------------
--- mplayer-cvs.orig/configure 2004-10-31 22:48:19.000000000 +0100
+++ mplayer-cvs/configure 2004-10-31 22:48:11.000000000 +0100
@@ -261,6 +261,7 @@
--disable-ossaudio disable OSS sound support [autodetect]
--disable-arts disable aRts sound support [autodetect]
--disable-esd disable esd sound support [autodetect]
+ --disable-polyp disable Polypaudio sound support [autodetect]
--disable-jack disable JACK sound support [autodetect]
--disable-nas disable NAS sound support [autodetect]
--disable-sgiaudio disable SGI sound support [autodetect]
@@ -1287,6 +1288,7 @@
_ossaudio=auto
_arts=auto
_esd=auto
+_polyp=auto
_jack=auto
_liblzo=auto
_mad=auto
@@ -1464,6 +1466,8 @@
--disable-arts) _arts=no ;;
--enable-esd) _esd=yes ;;
--disable-esd) _esd=no ;;
+ --enable-polyp) _polyp=yes ;;
+ --disable-polyp) _polyp=no ;;
--enable-jack) _jack=yes ;;
--disable-jack) _jack=no ;;
--enable-mad) _mad=yes ;;
@@ -4393,6 +4397,34 @@
_noaomodules="esd $_noaomodules"
fi
+echocheck "Polyp"
+if test "$_polyp" = auto ; then
+ _polyp=no
+ if ( pkg-config --exists 'polyplib >= 0.6 polyplib-error >= 0.6 polyplib-mainloop >= 0.6' ) >> "$TMPLOG" 2>&1 ; then
+
+cat > $TMPC << EOF
+#include <polyp/polyplib.h>
+#include <polyp/mainloop.h>
+#include <polyp/polyplib-error.h>
+int main(void) { return 0; }
+EOF
+cc_check `pkg-config --libs --cflags polyplib polyplib-error polyplib-mainloop` && ( "$TMPO" >> "$TMPLOG" 2>&1 ) && _polyp=yes
+
+ fi
+fi
+echores "$_polyp"
+
+if test "$_polyp" = yes ; then
+ _def_polyp='#define USE_POLYP 1'
+ _aosrc="$_aosrc ao_polyp.c"
+ _aomodules="polyp $_aomodules"
+ _ld_polyp=`pkg-config --libs polyplib polyplib-error polyplib-mainloop`
+ _inc_polyp=`pkg-config --cflags polyplib polyplib-error polyplib-mainloop`
+else
+ _def_polyp='#undef USE_POLYP'
+ _noaomodules="polyp $_noaomodules"
+fi
+
echocheck "JACK"
if test "$_jack" = auto ; then
@@ -6483,6 +6515,8 @@
ARTS_INC = $_inc_arts
ESD_LIB = $_ld_esd
ESD_INC = $_inc_esd
+POLYP_LIB = $_ld_polyp
+POLYP_INC = $_inc_polyp
JACK_LIB = $_ld_jack
JACK_INC = $_inc_jack
SGIAUDIO_LIB = $_ld_sgiaudio
@@ -6910,6 +6944,7 @@
$_def_arts
$_def_esd
$_def_esd_latency
+$_def_polyp
$_def_jack
$_def_sys_asoundlib_h
$_def_alsa_asoundlib_h
--- mplayer-cvs.orig/Makefile 2004-10-31 22:48:18.000000000 +0100
+++ mplayer-cvs/Makefile 2004-10-28 16:07:57.000000000 +0200
@@ -31,7 +31,7 @@
OBJS_MPLAYER = $(SRCS_MPLAYER:.c=.o)
VO_LIBS = $(AA_LIB) $(X_LIB) $(SDL_LIB) $(GGI_LIB) $(MP1E_LIB) $(MLIB_LIB) $(SVGA_LIB) $(DIRECTFB_LIB) $(CACA_LIB)
-AO_LIBS = $(ARTS_LIB) $(ESD_LIB) $(JACK_LIB) $(NAS_LIB) $(SGIAUDIO_LIB)
+AO_LIBS = $(ARTS_LIB) $(ESD_LIB) $(JACK_LIB) $(NAS_LIB) $(SGIAUDIO_LIB) $(POLYP_LIB)
CODEC_LIBS = $(AV_LIB) $(FAME_LIB) $(MAD_LIB) $(VORBIS_LIB) $(THEORA_LIB) $(FAAD_LIB) $(LIBLZO_LIB) $(DECORE_LIB) $(XVID_LIB) $(DTS_LIB) $(PNG_LIB) $(Z_LIB) $(JPEG_LIB) $(ALSA_LIB) $(XMMS_LIB) $(X264_LIB)
COMMON_LIBS = libmpcodecs/libmpcodecs.a $(W32_LIB) $(DS_LIB) libaf/libaf.a libmpdemux/libmpdemux.a input/libinput.a postproc/libswscale.a osdep/libosdep.a $(DVDREAD_LIB) $(CODEC_LIBS) $(FREETYPE_LIB) $(TERMCAP_LIB) $(CDPARANOIA_LIB) $(MPLAYER_NETWORK_LIB) $(WIN32_LIB) $(GIF_LIB) $(MACOSX_FRAMEWORKS) $(SMBSUPPORT_LIB) $(FRIBIDI_LIB) $(FONTCONFIG_LIB) $(ENCA_LIB)
--- mplayer-cvs.orig/libao2/Makefile 2004-06-25 20:11:13.000000000 +0200
+++ mplayer-cvs/libao2/Makefile 2004-10-28 01:52:42.000000000 +0200
@@ -6,7 +6,7 @@
OBJS=$(SRCS:.c=.o)
-CFLAGS = $(OPTFLAGS) -I. -I.. $(ARTS_INC) $(ESD_INC) $(JACK_INC) $(SDL_INC) $(X11_INC) $(EXTRA_INC) $(DXR2_INC) $(DVB_INC)
+CFLAGS = $(OPTFLAGS) -I. -I.. $(ARTS_INC) $(ESD_INC) $(JACK_INC) $(SDL_INC) $(X11_INC) $(EXTRA_INC) $(DXR2_INC) $(DVB_INC) $(POLYP_INC)
.SUFFIXES: .c .o
--- mplayer-cvs.orig/libao2/ao_polyp.c 1970-01-01 01:00:00.000000000 +0100
+++ mplayer-cvs/libao2/ao_polyp.c 2004-10-31 23:19:52.000000000 +0100
@@ -0,0 +1,325 @@
+#include <assert.h>
+
+#include "../config.h"
+
+#include <polyp/polyplib.h>
+#include <polyp/polyplib-error.h>
+#include <polyp/mainloop.h>
+
+#include "audio_out.h"
+#include "audio_out_internal.h"
+#include "afmt.h"
+#include "../config.h"
+#include "../mp_msg.h"
+
+#define POLYP_CLIENT_NAME "MPlayer"
+
+/** General driver info */
+static ao_info_t info = {
+ "Polypaudio audio output",
+ "polyp",
+ "Lennart Poettering",
+ ""
+};
+
+/** The sink to connect to */
+static char *sink = NULL;
+
+/** Polypaudio playback stream object */
+static struct pa_stream *stream = NULL;
+
+/** Polypaudio connection context */
+static struct pa_context *context = NULL;
+
+/** Main event loop object */
+static struct pa_mainloop *mainloop = NULL;
+
+/** Some special libao macro magic */
+LIBAO_EXTERN(polyp)
+
+/** Wait until no further actions are pending on the connection context */
+static void wait_for_completion(void) {
+ assert(context && mainloop);
+
+ while (pa_context_is_pending(context))
+ pa_mainloop_iterate(mainloop, 1, NULL);
+}
+
+/** Make sure that the connection context doesn't starve to death */
+static void keep_alive(void) {
+ assert(context && mainloop);
+
+ while (pa_mainloop_iterate(mainloop, 0, NULL) > 0);
+}
+
+/** Wait until the specified operation completes */
+static void wait_for_operation(struct pa_operation *o) {
+ assert(o && context && mainloop);
+
+ while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
+ pa_mainloop_iterate(mainloop, 1, NULL);
+
+ pa_operation_unref(o);
+}
+
+/** 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_buffer_attr a;
+ char hn[128];
+ char *host = NULL;
+
+ assert(!context && !stream && !mainloop);
+
+ if (ao_subdevice) {
+ int i = strcspn(ao_subdevice, ":");
+ if (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;
+ }
+
+ mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] -%s-%s-\n", host, sink);
+
+
+ ss.channels = channels;
+ ss.rate = rate_hz;
+
+ switch (format) {
+ case AFMT_U8:
+ ss.format = PA_SAMPLE_U8;
+ break;
+ case AFMT_S16_LE:
+ ss.format = PA_SAMPLE_S16LE;
+ break;
+ case AFMT_S16_BE:
+ ss.format = PA_SAMPLE_S16BE;
+ break;
+ case AFMT_FLOAT:
+ ss.format = PA_SAMPLE_FLOAT32;
+ break;
+ default:
+ mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Unsupported sample spec\n");
+ goto fail;
+ }
+
+
+ if (!pa_sample_spec_valid(&ss)) {
+ mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Invalid sample spec\n");
+ goto fail;
+ }
+
+
+ mainloop = pa_mainloop_new();
+ assert(mainloop);
+
+ context = pa_context_new(pa_mainloop_get_api(mainloop), POLYP_CLIENT_NAME);
+ assert(context);
+
+ pa_context_connect(context, host, 1, NULL);
+
+ wait_for_completion();
+
+ if (pa_context_get_state(context) != PA_CONTEXT_READY) {
+ mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context)));
+ goto fail;
+ }
+
+ stream = pa_stream_new(context, "audio stream", &ss);
+ assert(stream);
+
+ a.maxlength = pa_bytes_per_second(&ss)*1;
+ a.tlength = a.maxlength*9/10;
+ a.prebuf = a.tlength/2;
+ a.minreq = a.tlength/10;
+
+ pa_stream_connect_playback(stream, sink, &a, PA_STREAM_INTERPOLATE_LATENCY, PA_VOLUME_NORM);
+
+ wait_for_completion();
+
+ if (pa_stream_get_state(stream) != PA_STREAM_READY) {
+ mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context)));
+ goto fail;
+ }
+
+ return 1;
+
+fail:
+ uninit(1);
+ return 0;
+}
+
+/** Destroy libao driver */
+static void uninit(int immed) {
+ if (stream) {
+ if (!immed && pa_stream_get_state(stream) == PA_STREAM_READY)
+ wait_for_operation(pa_stream_drain(stream, NULL, NULL));
+
+ pa_stream_unref(stream);
+ stream = NULL;
+ }
+
+ if (context) {
+ pa_context_unref(context);
+ context = NULL;
+ }
+
+ if (mainloop) {
+ pa_mainloop_free(mainloop);
+ mainloop = NULL;
+ }
+}
+
+/** Play the specified data to the polypaudio server */
+static int play(void* data, int len, int flags) {
+ assert(stream && context);
+
+ if (pa_stream_get_state(stream) != PA_STREAM_READY)
+ return -1;
+
+ if (!len)
+ wait_for_operation(pa_stream_trigger(stream, NULL, NULL));
+ else
+ pa_stream_write(stream, data, len, NULL, 0);
+
+ wait_for_completion();
+
+ if (pa_stream_get_state(stream) != PA_STREAM_READY)
+ return -1;
+
+ return len;
+}
+
+/** Pause the audio stream by corking it on the server */
+static void audio_pause() {
+ assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY);
+ wait_for_operation(pa_stream_cork(stream, 1, NULL, NULL));
+}
+
+/** Resume the audio stream by uncorking it on the server */
+static void audio_resume() {
+ assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY);
+ wait_for_operation(pa_stream_cork(stream, 0, NULL, NULL));
+}
+
+/** Reset the audio stream, i.e. flush the playback buffer on the server side */
+static void reset() {
+ assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY);
+ wait_for_operation(pa_stream_flush(stream, NULL, NULL));
+}
+
+/** Return number of bytes that may be written to the server without blocking */
+static int get_space(void) {
+ uint32_t l;
+ assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY);
+
+ keep_alive();
+
+ l = pa_stream_writable_size(stream);
+
+ return l;
+}
+
+/* A temporary latency variable */
+/* static pa_usec_t latency = 0; */
+
+/* static void latency_func(struct pa_stream *s, const struct pa_latency_info *l, void *userdata) { */
+/* int negative = 0; */
+
+/* if (!l) { */
+/* mp_msg(MSGT_AO, MSGL_ERR, "AO: [polyp] Invalid sample spec: %s\n", pa_strerror(pa_context_errno(context))); */
+/* return; */
+/* } */
+
+/* latency = pa_stream_get_latency(s, l, &negative); */
+
+/* /\* Nor really required *\/ */
+/* if (negative) */
+/* latency = 0; */
+/* } */
+
+/** Return the current latency in seconds */
+static float get_delay(void) {
+ assert(stream && context && pa_stream_get_state(stream) == PA_STREAM_READY);
+ pa_usec_t latency;
+
+ /* latency = 0; */
+/* wait_for_operation(pa_stream_get_latency(stream, latency_func, NULL)); */
+ /* pa_operation_unref(pa_stream_get_latency(stream, latency_func, NULL)); */
+
+ latency = pa_stream_get_interpolated_latency(stream, NULL);
+
+ return (float) latency/1000000;
+}
+
+/** A temporary variable to store the current volume */
+static pa_volume_t volume = PA_VOLUME_NORM;
+
+/** 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: [polyp] Failed to get sink input info: %s\n", pa_strerror(pa_context_errno(context)));
+ return;
+ }
+
+ if (!i)
+ return;
+
+ volume = i->volume;
+}
+
+/** Issue special libao controls on the device */
+static int control(int cmd, void *arg) {
+
+ if (!context || !stream)
+ return CONTROL_ERROR;
+
+ switch (cmd) {
+
+ case AOCONTROL_SET_DEVICE:
+ /* Change the playback device */
+ sink = (char*)arg;
+ return CONTROL_OK;
+
+ case AOCONTROL_GET_DEVICE:
+ /* Return the playback device */
+ *(char**)arg = sink;
+ return CONTROL_OK;
+
+ case AOCONTROL_GET_VOLUME: {
+ /* Return the current volume of the playback stream */
+ ao_control_vol_t *vol = (ao_control_vol_t*) arg;
+
+ volume = PA_VOLUME_NORM;
+ wait_for_operation(pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_func, NULL));
+ vol->left = vol->right = (int) (pa_volume_to_user(volume)*100);
+ 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;
+ int v = vol->left;
+ if (vol->right > v)
+ v = vol->left;
+
+ wait_for_operation(pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), pa_volume_from_user((double)v/100), NULL, NULL));
+
+ return CONTROL_OK;
+ }
+
+ default:
+ /* Unknown CONTROL command */
+ return CONTROL_UNKNOWN;
+ }
+}
+
--- mplayer-cvs.orig/libao2/audio_out.c 2004-10-13 18:22:57.000000000 +0200
+++ mplayer-cvs/libao2/audio_out.c 2004-10-28 01:52:42.000000000 +0200
@@ -25,6 +25,9 @@
#ifdef USE_ESD
extern ao_functions_t audio_out_esd;
#endif
+#ifdef USE_POLYP
+extern ao_functions_t audio_out_polyp;
+#endif
#ifdef USE_JACK
extern ao_functions_t audio_out_jack;
#endif
@@ -103,6 +106,9 @@
#ifdef USE_ESD
&audio_out_esd,
#endif
+#ifdef USE_POLYP
+ &audio_out_polyp,
+#endif
#ifdef USE_JACK
&audio_out_jack,
#endif
--- mplayer-cvs.orig/AUTHORS 2004-10-31 22:48:18.000000000 +0100
+++ mplayer-cvs/AUTHORS 2004-10-31 22:48:10.000000000 +0100
@@ -726,6 +726,8 @@
Zubimendi, Andoni <andoni at lpsat.net>.
* Spanish documentation translation
+Poettering, Lennart <mzzcynlre at 0pointer.de>
+ * Audio driver for the Polypaudio sound server
________________
The codecs, libs
More information about the MPlayer-dev-eng
mailing list