summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2001-08-25 08:19:58 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2001-08-25 08:19:58 +0000
commitefd3876c95acfc8973139bfe0f2ec8f4236d872d (patch)
tree60940a9ec15f56f77cf0db148aac91eb5316a479
parent408dcaecfed16ceb4f9da7ec3691adeb9407e1d2 (diff)
downloadxine-lib-efd3876c95acfc8973139bfe0f2ec8f4236d872d.tar.gz
xine-lib-efd3876c95acfc8973139bfe0f2ec8f4236d872d.tar.bz2
adapted alsa05 plugin to new audio architecture (untested)
CVS patchset: 486 CVS date: 2001/08/25 08:19:58
-rw-r--r--src/audio_out/Makefile.am15
-rw-r--r--src/audio_out/audio_alsa05_out.c422
2 files changed, 111 insertions, 326 deletions
diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am
index a13d56df0..e8818b6ca 100644
--- a/src/audio_out/Makefile.am
+++ b/src/audio_out/Makefile.am
@@ -17,9 +17,9 @@ endif
# on the alsa project side
#
if HAVE_ALSA
-#if HAVE_ALSA05
-#alsa05_module = xineplug_ao_out_alsa05.la
-#endif
+if HAVE_ALSA05
+alsa05_module = xineplug_ao_out_alsa05.la
+endif
if HAVE_ALSA09
alsa_module = xineplug_ao_out_alsa.la
endif
@@ -50,16 +50,17 @@ endif
#lib_LTLIBRARIES = $(oss_module) $(alsa05_module) $(alsa_module) $(sun_module) \
# $(arts_module) $(esd_module)
-lib_LTLIBRARIES = $(oss_module) $(alsa_module) $(esd_module) $(sun_module) $(arts_module)
+lib_LTLIBRARIES = $(oss_module) $(alsa_module) $(esd_module) $(sun_module) $(arts_module) \
+ $(alsa05_module)
## $(irixal_module)
xineplug_ao_out_oss_la_SOURCES = audio_oss_out.c
xineplug_ao_out_oss_la_LDFLAGS = -avoid-version -module
-#xineplug_ao_out_alsa05_la_SOURCES = audio_alsa05_out.c resample.c
-#xineplug_ao_out_alsa05_la_LIBADD = $(ALSA_LIBS)
-#xineplug_ao_out_alsa05_la_LDFLAGS = -avoid-version -module
+xineplug_ao_out_alsa05_la_SOURCES = audio_alsa05_out.c resample.c
+xineplug_ao_out_alsa05_la_LIBADD = $(ALSA_LIBS)
+xineplug_ao_out_alsa05_la_LDFLAGS = -avoid-version -module
xineplug_ao_out_alsa_la_SOURCES = audio_alsa_out.c
xineplug_ao_out_alsa_la_LIBADD = $(ALSA_LIBS)
diff --git a/src/audio_out/audio_alsa05_out.c b/src/audio_out/audio_alsa05_out.c
index d07cc65d9..79c547414 100644
--- a/src/audio_out/audio_alsa05_out.c
+++ b/src/audio_out/audio_alsa05_out.c
@@ -24,7 +24,7 @@
* for the SPDIF AC3 sync part
* (c) 2000 Andy Lo A Foe <andy@alsaplayer.org>
*
- * $Id: audio_alsa05_out.c,v 1.7 2001/08/25 04:33:33 guenter Exp $
+ * $Id: audio_alsa05_out.c,v 1.8 2001/08/25 08:19:58 guenter Exp $
*/
/* required for swab() */
@@ -50,11 +50,11 @@
#include "resample.h"
#include "utils.h"
+#define AO_ALSA_IFACE_VERSION 2
+
#define AUDIO_NUM_FRAGMENTS 6
#define AUDIO_FRAGMENT_SIZE 1536
-#define ZERO_BUF_SIZE 15360 /* has to be a multiplier of 3 and 5 (??)*/
-
#define GAP_TOLERANCE 5000
#define MAX_GAP 90000
@@ -62,58 +62,40 @@
extern uint32_t xine_debug;
-typedef struct _audio_alsa_globals {
-
- ao_functions_t ao_functions;
-
- snd_pcm_t *front_handle;
+typedef struct alsa_driver_s {
- int32_t output_sample_rate, input_sample_rate;
- uint32_t num_channels;
+ ao_driver_t ao_driver;
- uint32_t bytes_in_buffer; /* number of bytes written to audio hardware */
- uint32_t last_vpts; /* vpts at which last written package ends */
+ snd_pcm_t *front_handle;
- uint32_t sync_vpts; /* this syncpoint is used as a starting point */
- uint32_t sync_bytes_in_buffer; /* for vpts <-> samplecount assoc */
+ int32_t output_sample_rate, input_sample_rate;
+ uint32_t num_channels;
- int audio_step; /* pts per 32 768 samples (sample = #bytes/2) */
- int32_t bytes_per_kpts; /* bytes per 1024/90000 sec */
+ uint32_t bytes_in_buffer; /* number of bytes written to audio hardware */
+ uint32_t bytes_per_frame;
- uint32_t last_audio_vpts;
+ int pcm_default_card;
+ int pcm_default_device;
- int16_t *zero_space;
+ int direction;
+ int mode;
+ int start_mode;
+ int stop_mode;
+ int format;
+ int rate;
+ int voices;
+ int interleave;
+ int frag_size;
+ int frag_count;
+ int pcm_len;
+ int ao_mode;
- int do_resample; /* resampling if output and input sample rate are different */
- int audio_started;
- int pcm_default_card;
- int pcm_default_device;
+ int capabilities;
- int direction;
- int mode;
- int start_mode;
- int stop_mode;
- int format;
- int rate;
- int voices;
- int interleave;
- int frag_size;
- int frag_count;
- int pcm_len;
- int ao_mode;
- metronom_t *metronom;
- int capabilities;
- uint16_t *sample_buffer;
+} alsa_driver_t;
-} audio_alsa_globals_t;
-
-
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
-static void alsa_set_frag(audio_alsa_globals_t *this, int fragment_size, int fragment_count) {
+static void alsa_set_frag(alsa_driver_t *this, int fragment_size, int fragment_count) {
snd_pcm_channel_params_t params;
snd_pcm_channel_setup_t setup;
snd_pcm_format_t format;
@@ -173,11 +155,11 @@ static void alsa_set_frag(audio_alsa_globals_t *this, int fragment_size, int fra
*/
}
-/* ------------------------------------------------------------------------- */
/*
* open the audio device for writing to
*/
-static int ao_open(ao_functions_t *this_gen,uint32_t bits, uint32_t rate, int ao_mode) {
+static int ao_alsa_open(ao_driver_t *this_gen,uint32_t bits, uint32_t rate, int ao_mode) {
+
int channels;
int subdevice = 0;
int direction = SND_PCM_OPEN_PLAYBACK;
@@ -187,7 +169,7 @@ static int ao_open(ao_functions_t *this_gen,uint32_t bits, uint32_t rate, int ao
snd_pcm_channel_info_t pcm_chan_info;
int err;
int mode;
- audio_alsa_globals_t *this = (audio_alsa_globals_t *) this_gen;
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
switch (ao_mode) {
@@ -215,19 +197,14 @@ static int ao_open(ao_functions_t *this_gen,uint32_t bits, uint32_t rate, int ao
if(this->front_handle != NULL) {
if(rate == this->input_sample_rate)
- return 1;
+ return this->output_sample_rate;
snd_pcm_close(this->front_handle);
}
this->input_sample_rate = rate;
this->bytes_in_buffer = 0;
- this->last_vpts = 0;
- this->sync_vpts = 0;
- this->sync_bytes_in_buffer = 0;
- this->audio_started = 0;
this->direction = SND_PCM_CHANNEL_PLAYBACK;
- this->last_audio_vpts = 0;
if (ao_mode == AO_CAP_MODE_AC3) {
this->pcm_default_device = 2;
@@ -290,7 +267,8 @@ static int ao_open(ao_functions_t *this_gen,uint32_t bits, uint32_t rate, int ao
pcm_format.rate = this->rate = rate;
pcm_format.interleave = this->interleave = 1;
- this->num_channels = channels;
+ this->num_channels = channels;
+ this->bytes_per_frame = (bits*this->num_channels)/8;
xprintf (VERBOSE|AUDIO, "audio channels = %d ao_mode = %d\n",
this->num_channels,ao_mode);
@@ -300,28 +278,6 @@ static int ao_open(ao_functions_t *this_gen,uint32_t bits, uint32_t rate, int ao
else
this->output_sample_rate = this->input_sample_rate;
- // is there a need to resample?
- if ((this->input_sample_rate) != (this->output_sample_rate)) {
- this->do_resample=1;
- printf("audio_alsa05_out: resampling from %d to %d.\n",
- this->input_sample_rate,this->output_sample_rate);
- }
- else
- this->do_resample=0;
-
- 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;
-
-
- xprintf (VERBOSE|AUDIO, "%d input samples/sec %d output samples/sec\n",
- rate, this->output_sample_rate);
- xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 samples\n",
- this->audio_step);
-
- this->metronom->set_audio_rate (this->metronom,this->audio_step);
memcpy(&pcm_chan_params.format, &pcm_format, sizeof(snd_pcm_format_t));
@@ -374,212 +330,89 @@ static int ao_open(ao_functions_t *this_gen,uint32_t bits, uint32_t rate, int ao
this->bytes_in_buffer = 0;
- return 1;
+ return this->output_sample_rate;
}
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
-static void ao_fill_gap (audio_alsa_globals_t *this, uint32_t pts_len) {
- int num_bytes;
+static int ao_alsa_num_channels(ao_driver_t *this_gen) {
- if (pts_len > MAX_GAP)
- pts_len = MAX_GAP;
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
+ return this->num_channels;
- num_bytes = pts_len * this->bytes_per_kpts / 1024;
- num_bytes = (num_bytes / (2*this->num_channels)) * (2*this->num_channels);
-
- this->bytes_in_buffer += num_bytes;
-
- printf ("audio_alsa05_out: inserting %d 0-bytes to fill a gap of %d pts\n",
- num_bytes, pts_len);
-
- while (num_bytes>0) {
- if (num_bytes> ZERO_BUF_SIZE) {
- snd_pcm_write(this->front_handle, this->zero_space,
- ZERO_BUF_SIZE);
- num_bytes -= ZERO_BUF_SIZE;
- } else {
- snd_pcm_write(this->front_handle, this->zero_space, num_bytes);
- num_bytes = 0;
- }
- }
}
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
-static uint32_t ao_get_current_pos (audio_alsa_globals_t *this) {
- uint32_t pos;
- snd_pcm_channel_status_t pcm_stat;
- int err;
-
-
- if (this->audio_started) {
- memset(&pcm_stat, 0, sizeof(snd_pcm_channel_status_t));
- pcm_stat.channel = SND_PCM_CHANNEL_PLAYBACK;
- if((err = snd_pcm_channel_status(this->front_handle,
- &pcm_stat)) < 0) {
- //Hide error report
- perr("snd_pcm_channel_status() failed: %s\n", snd_strerror(err));
- return 0;
- }
- pos = pcm_stat.scount;
- }
- else {
- pos = this->bytes_in_buffer;
- }
+static int ao_alsa_bytes_per_frame(ao_driver_t *this_gen) {
- return pos;
-}
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
+ return this->bytes_per_frame;
+}
+static int ao_alsa_get_gap_tolerance (ao_driver_t *this_gen) {
+ return GAP_TOLERANCE;
+}
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
-static int ao_write_audio_data(ao_functions_t *this_gen,
- int16_t* output_samples,
- uint32_t num_samples, uint32_t pts_) {
- uint32_t vpts, buffer_vpts;
- int32_t gap;
- int bDropPackage;
- uint32_t pos;
- audio_alsa_globals_t *this = (audio_alsa_globals_t *) this_gen;
+static int ao_alsa_delay(ao_driver_t *this_gen) {
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
+ int bytes_left;
+ snd_pcm_channel_status_t pcm_stat;
+ int err;
- xprintf(VERBOSE|AUDIO, "Audio : play %d samples at pts %d pos %d \n",
- num_samples, pts_, this->bytes_in_buffer);
+
+ memset(&pcm_stat, 0, sizeof(snd_pcm_channel_status_t));
+ pcm_stat.channel = SND_PCM_CHANNEL_PLAYBACK;
+ if((err = snd_pcm_channel_status(this->front_handle,
+ &pcm_stat)) < 0) {
+ /* Hide error report */
+ perr("snd_pcm_channel_status() failed: %s\n", snd_strerror(err));
+ return 0;
+ }
- if (this->front_handle == NULL) // no output device
- return 1;
-
- // what's the last delivered sample?
- vpts = this->metronom->got_audio_samples (this->metronom,pts_, num_samples);
+ /* calc delay */
- if (vpts<this->last_audio_vpts) {
- /* reject this */
+ bytes_left = this->bytes_in_buffer - pcm_stat.scount;
- return 1;
+ if (bytes_left<=0) { /* buffer ran dry */
+ bytes_left = 0;
+ this->bytes_in_buffer = pcm_stat.scount;
}
- this->last_audio_vpts = vpts;
- bDropPackage = 0;
-
- // get the sample that should be played NOW
- buffer_vpts = this->metronom->get_current_time (this->metronom);
-
- if (this->audio_started) {
- pos = ao_get_current_pos (this);
- }
- else pos=0;
-
+ return bytes_left / this->bytes_per_frame;
+}
- if (pos>this->bytes_in_buffer) { /* buffer ran dry */
- printf("Buffer ran dry.\n");
- this->bytes_in_buffer = pos;
- }
- buffer_vpts += (this->bytes_in_buffer - pos) * 1024 / this->bytes_per_kpts;
- // alternative to this command:
- // vpts = vpts - (this->bytes_in_buffer - pos) * 1024 / this->bytes_per_kpts;
-
- gap = vpts - buffer_vpts;
+static int ao_alsa_write (ao_driver_t *this_gen,
+ int16_t* frame_buffer, uint32_t num_frames) {
- // activate this for debugging output
- /*
- printf("pos: %d -- buffer_vpts: %d -- vpts: %d -- gap: %d -- bib: %d\n"
- ,pos,buffer_vpts, vpts, gap,this->bytes_in_buffer);
- */
- xprintf (VERBOSE|AUDIO, "audio_alsa05_out: got %d samples, vpts=%d, "
- "last_vpts=%d\n", num_samples, vpts, this->last_vpts);
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
- if (gap > GAP_TOLERANCE) {
+ this->bytes_in_buffer += num_frames * this->bytes_per_frame;
- ao_fill_gap (this, gap);
-
- /* keep xine responsive */
-
- if (gap>MAX_GAP)
- return 0;
- }
- else if (gap < -GAP_TOLERANCE) {
- bDropPackage = 1;
- }
-
- if (!bDropPackage) {
- int num_output_samples = num_samples * (this->output_sample_rate) / this->input_sample_rate;
-
- if (!this->do_resample) {
- snd_pcm_write(this->front_handle, output_samples,
- num_output_samples * this->num_channels * 2);
- } else
- switch (this->ao_mode) {
- case AO_CAP_MODE_MONO:
- audio_out_resample_mono (output_samples, num_samples,
- this->sample_buffer, num_output_samples);
- snd_pcm_write(this->front_handle, output_samples, num_output_samples * 2);
- break;
- case AO_CAP_MODE_STEREO:
- audio_out_resample_stereo (output_samples, num_samples,
- this->sample_buffer, num_output_samples);
- snd_pcm_write(this->front_handle, this->sample_buffer, num_output_samples * 4);
- break;
- case AO_CAP_MODE_AC3:
- // I hope this works. I cannot test because I don't have a SPDIF out
- num_output_samples = num_samples+8;
- this->sample_buffer[0] = 0xf872; //spdif syncword
- this->sample_buffer[1] = 0x4e1f; // .............
- this->sample_buffer[2] = 0x0001; // AC3 data
- this->sample_buffer[3] = num_samples * 8;
- // this->sample_buffer[4] = 0x0b77; // AC3 syncwork already in output_samples
-
- // ac3 seems to be swabbed data
- swab(output_samples,this->sample_buffer+4, num_samples );
- snd_pcm_write(this->front_handle, output_samples, num_output_samples);
- snd_pcm_write(this->front_handle, output_samples, 6144-num_output_samples);
- num_output_samples=num_output_samples/4;
- break;
- }
-
- // step values
- this->bytes_in_buffer += num_output_samples * this->num_channels * 2;
- this->audio_started = 1;
- }
+ snd_pcm_write(this->front_handle, frame_buffer,
+ num_frames * this->bytes_per_frame);
return 1;
}
-
-
-
-
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
-static void ao_close(ao_functions_t *this_gen) {
+static void ao_alsa_close(ao_driver_t *this_gen) {
int err;
- audio_alsa_globals_t *this = (audio_alsa_globals_t *) this_gen;
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
if(this->front_handle) {
if((err = snd_pcm_playback_flush(this->front_handle)) < 0) {
perr("snd_pcm_channel_flush() failed: %s\n", snd_strerror(err));
}
- if((err = snd_pcm_close(this->front_handle)) < 0) {
- perr("snd_pcm_close() failed: %s\n", snd_strerror(err));
- }
-
- this->front_handle = NULL;
+ if((err = snd_pcm_close(this->front_handle)) < 0) {
+ perr("snd_pcm_close() failed: %s\n", snd_strerror(err));
+ }
+
+ this->front_handle = NULL;
}
}
-static int ao_get_property (ao_functions_t *this_gen, int property) {
- // audio_alsa_globals_t *this = (audio_alsa_globals_t *) this_gen;
+static int ao_alsa_get_property (ao_driver_t *this_gen, int property) {
+ /* alsa_driver_t *this = (alsa_driver_t *) this_gen; */
/* FIXME: implement some properties
switch(property) {
@@ -594,11 +427,8 @@ static int ao_get_property (ao_functions_t *this_gen, int property) {
return 0;
}
-/*
- *
- */
-static int ao_set_property (ao_functions_t *this_gen, int property, int value) {
- // audio_alsa_globals_t *this = (audio_alsa_globals_t *) this_gen;
+static int ao_alsa_set_property (ao_driver_t *this_gen, int property, int value) {
+ /* alsa_driver_t *this = (alsa_driver_t *) this_gen; */
/* FIXME: Implement property support.
switch(property) {
@@ -614,52 +444,19 @@ static int ao_set_property (ao_functions_t *this_gen, int property, int value) {
return ~value;
}
-static void ao_connect (ao_functions_t *this_gen, metronom_t *metronom) {
- audio_alsa_globals_t *this = (audio_alsa_globals_t *) this_gen;
- this->metronom = metronom;
-}
-
-static uint32_t ao_get_capabilities (ao_functions_t *this_gen) {
- audio_alsa_globals_t *this = (audio_alsa_globals_t *) this_gen;
+static uint32_t ao_alsa_get_capabilities (ao_driver_t *this_gen) {
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
return this->capabilities;
}
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
-static int ao_is_mode_supported (int mode) {
-
- switch (mode) {
-
- case AO_CAP_MODE_STEREO:
- case AO_CAP_MODE_AC3:
- /*case AO_MODE_MONO: FIXME */
- return 1;
-
- }
-
- return 0;
-}
-
-static void ao_exit(ao_functions_t *this_gen)
-{
- audio_alsa_globals_t *this = (audio_alsa_globals_t *) this_gen;
- free(this->sample_buffer);
- free(this->zero_space);
+static void ao_alsa_exit(ao_driver_t *this_gen) {
+ /* alsa_driver_t *this = (alsa_driver_t *) this_gen; */
}
-
-
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
-
static ao_info_t ao_info_alsa = {
- AUDIO_OUT_IFACE_VERSION,
+ AO_ALSA_IFACE_VERSION,
"alsa05",
"xine audio output plugin using alsa-compliant audio devices/drivers",
10
@@ -669,20 +466,11 @@ ao_info_t *get_audio_out_plugin_info() {
return &ao_info_alsa;
}
-
-
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
static void sighandler(int signum) {
}
-/* ------------------------------------------------------------------------- */
-/*
- *
- */
-ao_functions_t *init_audio_out_plugin(config_values_t *config) {
- audio_alsa_globals_t *this;
+
+ao_driver_t *init_audio_out_plugin(config_values_t *config) {
+ alsa_driver_t *this;
int best_rate;
int devnum;
int err;
@@ -694,7 +482,7 @@ ao_functions_t *init_audio_out_plugin(config_values_t *config) {
snd_pcm_channel_info_t pcm_chan_info;
struct sigaction action;
- this = (audio_alsa_globals_t *) malloc (sizeof (audio_alsa_globals_t));
+ this = (alsa_driver_t *) malloc (sizeof (alsa_driver_t));
/* Check if, at least, one card is installed */
if((devnum = snd_cards()) == 0) {
@@ -744,22 +532,18 @@ ao_functions_t *init_audio_out_plugin(config_values_t *config) {
this->capabilities |= AO_CAP_MODE_AC3;
+ this->ao_driver.get_capabilities = ao_alsa_get_capabilities;
+ this->ao_driver.get_property = ao_alsa_get_property;
+ this->ao_driver.set_property = ao_alsa_set_property;
+ this->ao_driver.open = ao_alsa_open;
+ this->ao_driver.num_channels = ao_alsa_num_channels;
+ this->ao_driver.bytes_per_frame = ao_alsa_bytes_per_frame;
+ this->ao_driver.delay = ao_alsa_delay;
+ this->ao_driver.write = ao_alsa_write;
+ this->ao_driver.close = ao_alsa_close;
+ this->ao_driver.exit = ao_alsa_exit;
+ this->ao_driver.get_gap_tolerance = ao_alsa_get_gap_tolerance;
- 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;
-
-
-
- this->sample_buffer = malloc (40000);
- memset (this->sample_buffer, 0, 40000);
- this->zero_space = malloc (ZERO_BUF_SIZE);
- memset (this->zero_space, 0, ZERO_BUF_SIZE);
action.sa_handler = sighandler;
sigemptyset(&(action.sa_mask));
@@ -846,5 +630,5 @@ ao_functions_t *init_audio_out_plugin(config_values_t *config) {
snd_pcm_close (this->front_handle);
this->front_handle = NULL;
- return &this->ao_functions;
+ return &this->ao_driver;
}