diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-06-24 07:17:37 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-06-24 07:17:37 +0000 |
commit | c91eb356a10124ed87c89e1e0a3caf3b5e1f86bc (patch) | |
tree | d85924d9f15c4f9ced1db9903ee8d81cfee6c7fd | |
parent | 9d3c2abaa8e7a6f9edea6166203e4deea257ccb1 (diff) | |
download | xine-lib-c91eb356a10124ed87c89e1e0a3caf3b5e1f86bc.tar.gz xine-lib-c91eb356a10124ed87c89e1e0a3caf3b5e1f86bc.tar.bz2 |
added arts audio support contributed by Philip Stadermann
CVS patchset: 226
CVS date: 2001/06/24 07:17:37
-rw-r--r-- | AUTHORS | 3 | ||||
-rw-r--r-- | acconfig.h | 6 | ||||
-rw-r--r-- | configure.in | 15 | ||||
-rwxr-xr-x | cvscompile.sh | 2 | ||||
-rw-r--r-- | m4/Makefile.am | 2 | ||||
-rw-r--r-- | src/audio_out/Makefile.am | 16 | ||||
-rw-r--r-- | src/audio_out/audio_arts_out.c | 434 | ||||
-rw-r--r-- | src/audio_out/audio_arts_out.h | 27 | ||||
-rw-r--r-- | src/audio_out/audio_oss_out.c | 6 |
9 files changed, 498 insertions, 13 deletions
@@ -95,6 +95,9 @@ Contributions Juergen Keil <jk@tools.de> solaris port and other bugfixes + Philip Stadermann <pstadermann@gmx.de> + arts audio server support + (let us know if we've forgotten anyone) diff --git a/acconfig.h b/acconfig.h index 7e747e199..6d8b3ca26 100644 --- a/acconfig.h +++ b/acconfig.h @@ -58,3 +58,9 @@ /* Define this if you have kernel statistics available via kstat interface */ #undef HAVE_KSTAT + +/* Define this if you have ARTS (libartsc) installed */ +#undef HAVE_ARTS + +/* Define this if you have ARTS (libartsc) installed */ +#undef HAVE_ARTS diff --git a/configure.in b/configure.in index f7d954181..6f0ac380a 100644 --- a/configure.in +++ b/configure.in @@ -238,6 +238,13 @@ AM_PATH_ESD(0.2.8, AC_MSG_RESULT(*** All of ESD dependent parts will be disabled ***)) AM_CONDITIONAL(HAVE_ESD, test x"$no_esd" != "xyes") +dnl +dnl ARTS support +dnl +AM_PATH_ARTS(0.9.5, + AC_DEFINE(HAVE_ARTS), + AC_MSG_RESULT(*** All of ARTS dependent parts will be disabled ***)) +AM_CONDITIONAL(HAVE_ARTS, test x"$no_arts" != "xyes") dnl dnl SUN style audio interface @@ -289,8 +296,8 @@ enable_w32dll="no" case $host in i386-*-freebsd*) GLOBAL_CFLAGS="$GLOBAL_CFLAGS -pipe -fomit-frame-pointer -malign-functions=4 -malign-loops=4 -malign-jumps=4 -malign-functions=4 $m_wm $m_psb -fexpensive-optimizations $f_si $f_nsa -ffast-math -funroll-loops -finline-functions" - GLOBAL_CFLAGS="$GLOBAL_CFLAGS $CFLAGS $COMMON_CFLAGS $ALSA_CFLAGS $ESD_CFLAGS" - DEBUG_CFLAGS="$X_CFLAGS $DEBUG_CFLAGS $CFLAGS $COMMON_CFLAGS $ALSA_CFLAGS $ESD_CFLAGS -DDEBUG" + GLOBAL_CFLAGS="$GLOBAL_CFLAGS $CFLAGS $COMMON_CFLAGS $ALSA_CFLAGS $ESD_CFLAGS $ARTS_CFLAGS" + DEBUG_CFLAGS="$X_CFLAGS $DEBUG_CFLAGS $CFLAGS $COMMON_CFLAGS $ALSA_CFLAGS $ESD_CFLAGS $ARTS_CFLAGS -DDEBUG" AC_DEFINE(__i386__) AC_DEFINE([ARCH_X86],,[x86 architecture]) @@ -386,8 +393,8 @@ case $host in *) echo "$host is not currently supported by xine"; exit 1;; esac - GLOBAL_CFLAGS="$GLOBAL_CFLAGS $COMMON_CFLAGS $ALSA_CFLAGS $ESD_CFLAGS" - DEBUG_CFLAGS="$DEBUG_CFLAGS $COMMON_CFLAGS $ALSA_CFLAGS $ESD_CFLAGS -g -DDEBUG" + GLOBAL_CFLAGS="$GLOBAL_CFLAGS $COMMON_CFLAGS $ALSA_CFLAGS $ESD_CFLAGS $ARTS_CFLAGS" + DEBUG_CFLAGS="$DEBUG_CFLAGS $COMMON_CFLAGS $ALSA_CFLAGS $ESD_CFLAGS $ARTS_CFLAGS -g -DDEBUG" ;; esac diff --git a/cvscompile.sh b/cvscompile.sh index a19d28097..ebbdc4be5 100755 --- a/cvscompile.sh +++ b/cvscompile.sh @@ -1,7 +1,7 @@ #!/bin/sh # Run this to generate all the initial Makefiles, etc. -m4_files="_xine.m4 alsa.m4 esd.m4 aa.m4" +m4_files="_xine.m4 alsa.m4 arts.m4 esd.m4 aa.m4" if test -d m4; then rm -f acinclude.m4 for m4f in $m4_files; do diff --git a/m4/Makefile.am b/m4/Makefile.am index 90630dcee..4b1db639e 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -6,7 +6,7 @@ m4datadir = @ACLOCAL_DIR@ m4data_DATA = xine.m4 endif -EXTRA_DIST = _xine.m4 alsa.m4 esd.m4 xine.m4 aa.m4 +EXTRA_DIST = _xine.m4 alsa.m4 arts.m4 esd.m4 xine.m4 aa.m4 debug: diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am index aac9ec194..ce40db822 100644 --- a/src/audio_out/Makefile.am +++ b/src/audio_out/Makefile.am @@ -1,6 +1,6 @@ -CFLAGS = @GLOBAL_CFLAGS@ -DXINE_COMPILE $(ALSA_CFLAGS) $(ESD_CFLAGS) +CFLAGS = @GLOBAL_CFLAGS@ -DXINE_COMPILE $(ALSA_CFLAGS) $(ESD_CFLAGS) $(ARTS_CFLAGS) -EXTRA_DIST = audio_alsa_out.c audio_alsa05_out.c audio_esd_out.c audio_sun_out.c +EXTRA_DIST = audio_alsa_out.c audio_alsa05_out.c audio_esd_out.c audio_sun_out.c audio_arts_out.c LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic @@ -26,6 +26,10 @@ if HAVE_SUNAUDIO sun_module = xineplug_ao_out_sun.la endif +if HAVE_ARTS +arts_module = xineplug_ao_out_arts.la +endif + ## # IMPORTANT: # --------- @@ -33,7 +37,7 @@ endif # scheme "xineplug_ao_out_" # #lib_LTLIBRARIES = $(oss_module) $(alsa_module) $(sun_module) $(esd_module) -lib_LTLIBRARIES = $(oss_module) $(alsa_module) $(sun_module) #$(esd_module) +lib_LTLIBRARIES = $(oss_module) $(alsa_module) $(sun_module) $(arts_module) #$(esd_module) xineplug_ao_out_oss_la_SOURCES = audio_oss_out.c resample.c xineplug_ao_out_oss_la_LDFLAGS = -avoid-version -module @@ -50,8 +54,12 @@ xineplug_ao_out_alsa_la_LDFLAGS = -avoid-version -module xineplug_ao_out_sun_la_SOURCES = audio_sun_out.c resample.c xineplug_ao_out_sun_la_LDFLAGS = -avoid-version -module +xineplug_ao_out_arts_la_SOURCES = audio_arts_out.c resample.c +xineplug_ao_out_arts_la_LIBADD = $(ARTS_LIBS) +xineplug_ao_out_arts_la_LDFLAGS = -avoid-version -module + noinst_HEADERS = audio_oss_out.h audio_alsa_out.h audio_esd_out.h \ - audio_sun_out.h resample.h + audio_sun_out.h audio_arts_out.h resample.h debug: diff --git a/src/audio_out/audio_arts_out.c b/src/audio_out/audio_arts_out.c new file mode 100644 index 000000000..bb51b16e5 --- /dev/null +++ b/src/audio_out/audio_arts_out.c @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2000, 2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: audio_arts_out.c,v 1.1 2001/06/24 07:17:37 guenter Exp $ + */ + +/* required for swab() */ +#define _XOPEN_SOURCE 500 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <math.h> +#include <unistd.h> +#include <inttypes.h> +#include <artsc.h> + +#include "xine_internal.h" +#include "monitor.h" +#include "audio_out.h" +#include "resample.h" +#include "metronom.h" +#include "utils.h" + +#define AO_OUT_ARTS_IFACE_VERSION 1 + +#define AUDIO_NUM_FRAGMENTS 15 +#define AUDIO_FRAGMENT_SIZE 8192 + +/*#define GAP_TOLERANCE 5000 */ +#define GAP_TOLERANCE 15000 +#define MAX_GAP 90000 + +typedef struct arts_functions_s { + + ao_functions_t ao_functions; + + metronom_t *metronom; + + arts_stream_t audio_stream; + int capabilities; + int mode; + + int32_t output_sample_rate, input_sample_rate; + double sample_rate_factor; + uint32_t num_channels; + + uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */ + + int audio_step; /* pts per 32 768 samples (sample = #bytes/2) */ + int32_t bytes_per_kpts; /* bytes per 1024/90000 sec */ + + int16_t *zero_space; + + int audio_started; + uint32_t last_audio_vpts; + + uint32_t latency; + +} arts_functions_t; + +/* + * open the audio device for writing to + */ +static int ao_open(ao_functions_t *this_gen, + uint32_t bits, uint32_t rate, int mode) +{ + arts_functions_t *this = (arts_functions_t *) this_gen; + + printf ("audio_arts_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode); + + if ( (mode & this->capabilities) == 0 ) { + printf ("audio_arts_out: unsupported mode %08x\n", mode); + return -1; + } + + if (this->audio_stream) { + + if ( (mode == this->mode) && (rate == this->input_sample_rate) ) + return 1; + + arts_close_stream(this->audio_stream); + } + + this->mode = mode; + this->input_sample_rate = rate; + this->bytes_in_buffer = 0; + this->audio_started = 0; + this->last_audio_vpts = 0; + + this->output_sample_rate = rate; + + switch (mode) { + case AO_CAP_MODE_MONO: + this->num_channels = 1; + break; + case AO_CAP_MODE_STEREO: + this->num_channels = 2; + break; + } + printf ("audio_arts_out: %d channels output\n",this->num_channels); + + /* XXX: Handle errors */ + arts_init(); + + this->audio_stream=arts_play_stream(this->output_sample_rate, bits, this->num_channels, "xine"); + + this->sample_rate_factor = (double) this->output_sample_rate / (double) this->input_sample_rate; + this->audio_step = (uint32_t) 90000 * (uint32_t) 32768 + / this->input_sample_rate; + this->bytes_per_kpts = this->output_sample_rate * this->num_channels * 2 * 1024 / 90000; + + printf ("audio_out : audio_step %d pts per 32768 samples\n", this->audio_step); + + this->latency = arts_stream_get (this->audio_stream, ARTS_P_TOTAL_LATENCY); + + printf ("audio_out : latency %d ms\n", this->latency); + + this->metronom->set_audio_rate(this->metronom, this->audio_step); + + return 1; +} + +static void ao_fill_gap (arts_functions_t *this, uint32_t pts_len) { + + int num_bytes; + + if (pts_len > MAX_GAP) + pts_len = MAX_GAP; + + num_bytes= pts_len * this->bytes_per_kpts / 1024; + num_bytes = (num_bytes / (2*this->num_channels)) * (2*this->num_channels); + if(this->mode == AO_CAP_MODE_AC3) return; + printf ("audio_arts_out: inserting %d 0-bytes to fill a gap of %d pts\n",num_bytes, pts_len); + + this->bytes_in_buffer += num_bytes; + + while (num_bytes>0) { + if (num_bytes>8192) { + arts_write(this->audio_stream, this->zero_space, 8192); + num_bytes -= 8192; + } else { + arts_write(this->audio_stream, this->zero_space, num_bytes); + num_bytes = 0; + } + } +} + +static int ao_write_audio_data(ao_functions_t *this_gen, + int16_t* output_samples, uint32_t num_samples, + uint32_t pts_) +{ + + arts_functions_t *this = (arts_functions_t *) this_gen; + uint32_t vpts, buffer_vpts; + int32_t gap; + int bDropPackage; + uint16_t sample_buffer[10000]; +/* count_info info; */ +/* int pos; */ + + if (this->audio_stream<0) + return 1; + + xprintf (VERBOSE|AUDIO, "audio_arts_out: got %d samples, vpts=%d\n", + num_samples, vpts); + + vpts = this->metronom->got_audio_samples (this->metronom, pts_, num_samples); + + if (vpts<this->last_audio_vpts) { + /* reject this */ + + return 1; + } + + this->last_audio_vpts = vpts; + + /* + * where, in the timeline is the "end" of the audio buffer at the moment? + */ + + buffer_vpts = this->metronom->get_current_time (this->metronom); + + buffer_vpts += this->latency * 90; + +/* + if (this->audio_started) { + ioctl (this->audio_fd, SNDCTL_DSP_GETOPTR, &info); + pos = info.bytes; + } else + + pos = 0; +*/ + +// if (pos>this->bytes_in_buffer) /* buffer ran dry */ +// this->bytes_in_buffer = pos; + +// buffer_vpts += (this->bytes_in_buffer - pos) * 1024 / this->bytes_per_kpts; + + + /* + printf ("audio_arts_out: got audio package vpts = %d, buffer_vpts = %d\n", + vpts, buffer_vpts); + */ + + /* + * calculate gap: + */ + + + gap = vpts - buffer_vpts; + + + bDropPackage = 0; + + + if (gap>GAP_TOLERANCE) { + ao_fill_gap (this, gap); + + /* keep xine responsive */ + + if (gap>MAX_GAP) + return 0; + + } else if (gap<-GAP_TOLERANCE) { + bDropPackage = 1; + } + + + /* + * resample and output samples + */ + if(this->mode == AO_CAP_MODE_AC3) bDropPackage=0; + + if (!bDropPackage) { + int num_output_samples = num_samples * (this->output_sample_rate) / this->input_sample_rate; + + switch (this->mode) { + case AO_CAP_MODE_MONO: + audio_out_resample_mono (output_samples, num_samples, + sample_buffer, num_output_samples); + arts_write(this->audio_stream, sample_buffer, num_output_samples * 2); + break; + case AO_CAP_MODE_STEREO: + audio_out_resample_stereo (output_samples, num_samples, + sample_buffer, num_output_samples); + arts_write(this->audio_stream, sample_buffer, num_output_samples * 4); + break; + case AO_CAP_MODE_4CHANNEL: + audio_out_resample_4channel (output_samples, num_samples, + sample_buffer, num_output_samples); + arts_write(this->audio_stream, sample_buffer, num_output_samples * 8); + break; + case AO_CAP_MODE_5CHANNEL: + audio_out_resample_5channel (output_samples, num_samples, + sample_buffer, num_output_samples); + arts_write(this->audio_stream, sample_buffer, num_output_samples * 10); + break; + case AO_CAP_MODE_AC3: + num_output_samples = num_samples+8; + sample_buffer[0] = 0xf872; //spdif syncword + sample_buffer[1] = 0x4e1f; // ............. + sample_buffer[2] = 0x0001; // AC3 data + sample_buffer[3] = num_samples * 8; +// sample_buffer[4] = 0x0b77; // AC3 syncwork already in output_samples + + // ac3 seems to be swabbed data + swab(output_samples,sample_buffer+4, num_samples ); + arts_write(this->audio_stream, sample_buffer, num_output_samples); + arts_write(this->audio_stream, this->zero_space, 6144-num_output_samples); + num_output_samples=num_output_samples/4; + break; + } + + xprintf (AUDIO|VERBOSE, "audio_arts_out :audio package written\n"); + + /* + * step values + */ + + this->bytes_in_buffer += num_output_samples * 2 * this->num_channels; + this->audio_started = 1; + } else { + printf ("audio_arts_out: audio package (vpts = %d) dropped\n", vpts); + } + + return 1; +} + + +static void ao_close(ao_functions_t *this_gen) +{ + arts_functions_t *this = (arts_functions_t *) this_gen; + arts_close_stream(this->audio_stream); + arts_free(); + this->audio_stream = NULL; +} + +static uint32_t ao_get_capabilities (ao_functions_t *this_gen) { + arts_functions_t *this = (arts_functions_t *) this_gen; + return this->capabilities; +} + +static void ao_connect (ao_functions_t *this_gen, metronom_t *metronom) { + arts_functions_t *this = (arts_functions_t *) this_gen; + + this->metronom = metronom; +} + +static void ao_exit(ao_functions_t *this_gen) +{ + arts_functions_t *this = (arts_functions_t *) this_gen; + + if (this->audio_stream) { + arts_close_stream(this->audio_stream); + arts_free(); + } + + free (this->zero_space); + free (this); +} + +/* + * + */ +static int ao_get_property (ao_functions_t *this, int property) { + + /* FIXME: implement some properties + switch(property) { + case AO_PROP_MIXER_VOL: + break; + case AO_PROP_PCM_VOL: + break; + case AO_PROP_MUTE_VOL: + break; + } + */ + return 0; +} + +/* + * + */ +static int ao_set_property (ao_functions_t *this, int property, int value) { + + /* FIXME: Implement property support. + switch(property) { + case AO_PROP_MIXER_VOL: + break; + case AO_PROP_PCM_VOL: + break; + case AO_PROP_MUTE_VOL: + break; + } + */ + + return ~value; +} + +ao_functions_t *init_audio_out_plugin (config_values_t *config) { + + arts_functions_t *this; + int rc; + + this = (arts_functions_t *) malloc (sizeof (arts_functions_t)); + + rc = arts_init(); + if(rc < 0) { + fprintf(stderr,"audio_arts_out: arts_init failed: %s\n",arts_error_text(rc)); + return NULL; + } + arts_free(); + + /* + * set capabilities + */ + this->capabilities = 0; + printf ("audio_arts_out : supported modes are "); + this->capabilities |= AO_CAP_MODE_MONO; + printf ("mono "); + this->capabilities |= AO_CAP_MODE_STEREO; + printf ("stereo "); + printf ("\n"); + + this->output_sample_rate = 0; + + this->zero_space = malloc (8192); + memset (this->zero_space, 0, 8192); + + this->ao_functions.get_capabilities = ao_get_capabilities; + this->ao_functions.get_property = ao_get_property; + this->ao_functions.set_property = ao_set_property; + this->ao_functions.connect = ao_connect; + this->ao_functions.open = ao_open; + this->ao_functions.write_audio_data = ao_write_audio_data; + this->ao_functions.close = ao_close; + this->ao_functions.exit = ao_exit; + + return &this->ao_functions; +} + +static ao_info_t ao_info_arts = { + AUDIO_OUT_IFACE_VERSION, + "arts", + "xine audio output plugin using arts-compliant audio devices/drivers", + 5 +}; + +ao_info_t *get_audio_out_plugin_info() { + return &ao_info_arts; +} + diff --git a/src/audio_out/audio_arts_out.h b/src/audio_out/audio_arts_out.h new file mode 100644 index 000000000..7c119e579 --- /dev/null +++ b/src/audio_out/audio_arts_out.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2000 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: audio_arts_out.h,v 1.1 2001/06/24 07:17:37 guenter Exp $ + */ +#ifndef _AUDIO_ARTS_OUT_H_ +#define _AUDIO_ARTS_OUT_H_ 1 + +ao_functions_t *audio_artsout_init(void); + +#endif diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c index 4d214923f..bb8104f1d 100644 --- a/src/audio_out/audio_oss_out.c +++ b/src/audio_out/audio_oss_out.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 the xine project + * Copyright (C) 2000, 2001 the xine project * * This file is part of xine, a unix video player. * @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: audio_oss_out.c,v 1.17 2001/06/24 03:36:30 guenter Exp $ + * $Id: audio_oss_out.c,v 1.18 2001/06/24 07:17:37 guenter Exp $ */ /* required for swab() */ @@ -280,7 +280,7 @@ static int ao_write_audio_data(ao_functions_t *this_gen, int pos; if (this->audio_fd<0) - return; + return 1; vpts = this->metronom->got_audio_samples (this->metronom, pts_, num_samples); |