summaryrefslogtreecommitdiff
path: root/src/audio_out
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_out')
-rw-r--r--src/audio_out/audio_oss_out.c245
1 files changed, 138 insertions, 107 deletions
diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c
index 795a2c8d3..8de699765 100644
--- a/src/audio_out/audio_oss_out.c
+++ b/src/audio_out/audio_oss_out.c
@@ -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.2 2001/04/27 10:42:38 f1rmb Exp $
+ * $Id: audio_oss_out.c,v 1.3 2001/04/28 19:47:41 guenter Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -28,6 +28,7 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
+#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
#if defined(__OpenBSD__)
@@ -45,9 +46,7 @@
#include "audio_out.h"
#include "resample.h"
#include "metronom.h"
-#include "libac3/ac3.h"
#include "utils.h"
-#include "metronom.h"
#define AO_OUT_OSS_IFACE_VERSION 1
@@ -59,7 +58,11 @@
#define DSP_TEMPLATE "/dev/dsp%d"
-typedef struct _audio_oss_globals {
+typedef struct oss_functions_s {
+
+ ao_functions_t ao_functions;
+
+ metronom_t *metronom;
char audio_dev[20];
int audio_fd;
@@ -82,16 +85,15 @@ typedef struct _audio_oss_globals {
int audio_started;
-} audio_oss_globals_t;
-
-static audio_oss_globals_t gAudioOSS;
+} oss_functions_t;
/*
* open the audio device for writing to
*/
-static int ao_open(metronom_t *metronom,
+static int ao_open(ao_functions_t *this_gen,
uint32_t bits, uint32_t rate, int mode)
{
+ oss_functions_t *this = (oss_functions_t *) this_gen;
int tmp;
int fsize;
@@ -102,64 +104,64 @@ static int ao_open(metronom_t *metronom,
return -1;
}
- if (gAudioOSS.audio_fd > -1) {
+ if (this->audio_fd > -1) {
- if (rate == gAudioOSS.input_sample_rate)
+ if (rate == this->input_sample_rate)
return 1;
- close (gAudioOSS.audio_fd);
+ close (this->audio_fd);
}
- gAudioOSS.input_sample_rate = rate;
- gAudioOSS.bytes_in_buffer = 0;
- gAudioOSS.last_vpts = 0;
- gAudioOSS.output_rate_correction = 0;
- gAudioOSS.sync_vpts = 0;
- gAudioOSS.sync_bytes_in_buffer = 0;
- gAudioOSS.audio_started = 0;
+ this->input_sample_rate = rate;
+ this->bytes_in_buffer = 0;
+ this->last_vpts = 0;
+ this->output_rate_correction = 0;
+ this->sync_vpts = 0;
+ this->sync_bytes_in_buffer = 0;
+ this->audio_started = 0;
/*
* open audio device
*/
- gAudioOSS.audio_fd=open(gAudioOSS.audio_dev,O_WRONLY|O_NDELAY);
- if(gAudioOSS.audio_fd < 0) {
+ this->audio_fd=open(this->audio_dev,O_WRONLY|O_NDELAY);
+ if(this->audio_fd < 0) {
printf("audio_oss_out: Opening audio device %s: %s\n",
- gAudioOSS.audio_dev, strerror(errno));
+ this->audio_dev, strerror(errno));
return -1;
}
/* We wanted non blocking open but now put it back to normal */
- fcntl(gAudioOSS.audio_fd, F_SETFL, fcntl(gAudioOSS.audio_fd, F_GETFL)&~FNDELAY);
+ fcntl(this->audio_fd, F_SETFL, fcntl(this->audio_fd, F_GETFL)&~FNDELAY);
/*
* configure audio device
*/
tmp = (mode == AO_MODE_STEREO) ? 1 : 0;
- ioctl(gAudioOSS.audio_fd,SNDCTL_DSP_STEREO,&tmp);
+ ioctl(this->audio_fd,SNDCTL_DSP_STEREO,&tmp);
- gAudioOSS.num_channels = tmp+1;
- xprintf (VERBOSE|AUDIO, "audio_oss_out: %d channels\n",gAudioOSS.num_channels);
+ this->num_channels = tmp+1;
+ xprintf (VERBOSE|AUDIO, "audio_oss_out: %d channels\n",this->num_channels);
tmp = bits;
- ioctl(gAudioOSS.audio_fd,SNDCTL_DSP_SAMPLESIZE,&tmp);
+ ioctl(this->audio_fd,SNDCTL_DSP_SAMPLESIZE,&tmp);
- tmp = gAudioOSS.input_sample_rate;
- ioctl(gAudioOSS.audio_fd,SNDCTL_DSP_SPEED, &tmp);
- gAudioOSS.output_sample_rate = tmp;
+ tmp = this->input_sample_rate;
+ ioctl(this->audio_fd,SNDCTL_DSP_SPEED, &tmp);
+ this->output_sample_rate = tmp;
xprintf (VERBOSE|AUDIO, "audio_oss_out: audio rate : %d requested, %d provided by device/sec\n",
- gAudioOSS.input_sample_rate, gAudioOSS.output_sample_rate);
+ this->input_sample_rate, this->output_sample_rate);
- gAudioOSS.sample_rate_factor = (double) gAudioOSS.output_sample_rate / (double) gAudioOSS.input_sample_rate;
- gAudioOSS.audio_step = (uint32_t) 90000 * (uint32_t) 32768
- / gAudioOSS.input_sample_rate;
- gAudioOSS.bytes_per_kpts = gAudioOSS.output_sample_rate * gAudioOSS.num_channels * 2 * 1024 / 90000;
+ 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;
- xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 samples\n", gAudioOSS.audio_step);
+ xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 samples\n", this->audio_step);
- metronom->set_audio_rate(metronom, gAudioOSS.audio_step);
+ this->metronom->set_audio_rate(this->metronom, this->audio_step);
/*
* audio buffer size handling
@@ -177,13 +179,13 @@ static int ao_open(metronom_t *metronom,
xprintf (VERBOSE|AUDIO, "Audio buffer fragment info : %x\n",tmp);
- ioctl(gAudioOSS.audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp);
+ ioctl(this->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp);
return 1;
}
-static uint32_t ao_get_current_vpts (void) {
+static uint32_t ao_get_current_vpts (oss_functions_t *this) {
int pos ;
int32_t diff ;
@@ -191,52 +193,53 @@ static uint32_t ao_get_current_vpts (void) {
count_info info;
- if (gAudioOSS.audio_started) {
- ioctl (gAudioOSS.audio_fd, SNDCTL_DSP_GETOPTR, &info);
+ if (this->audio_started) {
+ ioctl (this->audio_fd, SNDCTL_DSP_GETOPTR, &info);
pos = info.bytes;
} else
pos = 0;
- diff = gAudioOSS.sync_bytes_in_buffer - pos;
+ diff = this->sync_bytes_in_buffer - pos;
- vpts = gAudioOSS.sync_vpts - diff * 1024 / gAudioOSS.bytes_per_kpts;
+ vpts = this->sync_vpts - diff * 1024 / this->bytes_per_kpts;
xprintf (AUDIO|VERBOSE,"audio_oss_out: get_current_vpts pos=%d diff=%d vpts=%d sync_vpts=%d\n",
- pos, diff, vpts, gAudioOSS.sync_vpts);
+ pos, diff, vpts, this->sync_vpts);
return vpts;
}
-static void ao_fill_gap (uint32_t pts_len) {
+static void ao_fill_gap (oss_functions_t *this, uint32_t pts_len) {
- int num_bytes = pts_len * gAudioOSS.bytes_per_kpts / 1024;
+ int num_bytes = pts_len * this->bytes_per_kpts / 1024;
num_bytes = (num_bytes / 4) * 4;
printf ("audio_oss_out: inserting %d 0-bytes to fill a gap of %d pts\n",num_bytes, pts_len);
- gAudioOSS.bytes_in_buffer += num_bytes;
+ this->bytes_in_buffer += num_bytes;
while (num_bytes>0) {
if (num_bytes>8192) {
- write(gAudioOSS.audio_fd, gAudioOSS.zero_space, 8192);
+ write(this->audio_fd, this->zero_space, 8192);
num_bytes -= 8192;
} else {
- write(gAudioOSS.audio_fd, gAudioOSS.zero_space, num_bytes);
+ write(this->audio_fd, this->zero_space, num_bytes);
num_bytes = 0;
}
}
- gAudioOSS.last_vpts += pts_len;
+ this->last_vpts += pts_len;
}
-static void ao_write_audio_data(metronom_t *metronom,
+static void ao_write_audio_data(ao_functions_t *this_gen,
int16_t* output_samples, uint32_t num_samples,
uint32_t pts_)
{
+ oss_functions_t *this = (oss_functions_t *) this_gen;
uint32_t vpts,
audio_vpts,
master_vpts;
@@ -245,30 +248,30 @@ static void ao_write_audio_data(metronom_t *metronom,
uint16_t sample_buffer[8192];
- if (gAudioOSS.audio_fd<0)
+ if (this->audio_fd<0)
return;
- vpts = metronom->got_audio_samples (metronom, pts_, num_samples);
+ vpts = this->metronom->got_audio_samples (this->metronom, pts_, num_samples);
xprintf (VERBOSE|AUDIO, "audio_oss_out: got %d samples, vpts=%d, last_vpts=%d\n",
- num_samples, vpts, gAudioOSS.last_vpts);
+ num_samples, vpts, this->last_vpts);
/*
* check if these samples "fit" in the audio output buffer
* or do we have an audio "gap" here?
*/
- gap = vpts - gAudioOSS.last_vpts ;
+ gap = vpts - this->last_vpts ;
/*
printf ("audio_oss_out: gap = %d - %d + %d = %d\n",
- vpts, gAudioOSS.last_vpts, diff, gap);
+ vpts, this->last_vpts, diff, gap);
*/
bDropPackage = 0;
if (gap>GAP_TOLERANCE) {
- ao_fill_gap (gap);
+ ao_fill_gap (this, gap);
} else if (gap<-GAP_TOLERANCE) {
bDropPackage = 1;
}
@@ -277,8 +280,8 @@ static void ao_write_audio_data(metronom_t *metronom,
* sync on master clock
*/
- audio_vpts = ao_get_current_vpts () ;
- master_vpts = metronom->get_current_time (metronom);
+ audio_vpts = ao_get_current_vpts (this) ;
+ master_vpts = this->metronom->get_current_time (this->metronom);
diff = audio_vpts - master_vpts;
xprintf (AUDIO|VERBOSE, "audio_oss_out: syncing on master clock: audio_vpts=%d master_vpts=%d\n",
@@ -301,14 +304,14 @@ static void ao_write_audio_data(metronom_t *metronom,
}
} else if (abs(diff)>1000) {
- gAudioOSS.output_rate_correction = diff/10 ;
+ this->output_rate_correction = diff/10 ;
- printf ("audio_oss_out: diff = %d => rate correction : %d\n", diff, gAudioOSS.output_rate_correction);
+ printf ("audio_oss_out: diff = %d => rate correction : %d\n", diff, this->output_rate_correction);
- if ( gAudioOSS.output_rate_correction < -500)
- gAudioOSS.output_rate_correction = -500;
- else if ( gAudioOSS.output_rate_correction > 500)
- gAudioOSS.output_rate_correction = 500;
+ if ( this->output_rate_correction < -500)
+ this->output_rate_correction = -500;
+ else if ( this->output_rate_correction > 500)
+ this->output_rate_correction = 500;
}
*/
@@ -319,7 +322,7 @@ static void ao_write_audio_data(metronom_t *metronom,
if (abs(diff)>MAX_MASTER_CLOCK_DIV) {
printf ("master clock adjust time %d -> %d (diff: %d)\n", master_vpts, audio_vpts, diff);
- metronom->adjust_clock (metronom, audio_vpts);
+ this->metronom->adjust_clock (this->metronom, audio_vpts);
}
@@ -328,13 +331,13 @@ static void ao_write_audio_data(metronom_t *metronom,
*/
if (!bDropPackage) {
- int num_output_samples = num_samples * (gAudioOSS.output_sample_rate + gAudioOSS.output_rate_correction) / gAudioOSS.input_sample_rate;
+ int num_output_samples = num_samples * (this->output_sample_rate + this->output_rate_correction) / this->input_sample_rate;
audio_out_resample_stereo (output_samples, num_samples,
sample_buffer, num_output_samples);
- write(gAudioOSS.audio_fd, sample_buffer, num_output_samples * 2 * gAudioOSS.num_channels);
+ write(this->audio_fd, sample_buffer, num_output_samples * 2 * this->num_channels);
xprintf (AUDIO|VERBOSE, "audio_oss_out :audio package written\n");
@@ -342,64 +345,69 @@ static void ao_write_audio_data(metronom_t *metronom,
* remember vpts
*/
- gAudioOSS.sync_vpts = vpts;
- gAudioOSS.sync_bytes_in_buffer = gAudioOSS.bytes_in_buffer;
+ this->sync_vpts = vpts;
+ this->sync_bytes_in_buffer = this->bytes_in_buffer;
/*
* step values
*/
- gAudioOSS.bytes_in_buffer += num_output_samples * 2 * gAudioOSS.num_channels;
- gAudioOSS.audio_started = 1;
+ this->bytes_in_buffer += num_output_samples * 2 * this->num_channels;
+ this->audio_started = 1;
} else {
printf ("audio_oss_out: audio package (vpts = %d) dropped\n", vpts);
- gAudioOSS.sync_vpts = vpts;
+ this->sync_vpts = vpts;
}
- gAudioOSS.last_vpts = vpts + num_samples * 90000 / gAudioOSS.input_sample_rate ;
+ this->last_vpts = vpts + num_samples * 90000 / this->input_sample_rate ;
}
-static void ao_close(void)
+static void ao_close(ao_functions_t *this_gen)
{
- close(gAudioOSS.audio_fd);
- gAudioOSS.audio_fd = -1;
+ oss_functions_t *this = (oss_functions_t *) this_gen;
+ close(this->audio_fd);
+ this->audio_fd = -1;
}
-static int ao_is_mode_supported (int mode) {
- return ((mode == AO_MODE_STEREO) || (mode == AO_MODE_MONO));
+static uint32_t ao_get_supported_modes (ao_functions_t *this) {
+ return AO_MODE_STEREO | AO_MODE_MONO;
}
-static char *ao_get_ident(void) {
- return "OSS";
+static void ao_connect (ao_functions_t *this_gen, metronom_t *metronom) {
+ oss_functions_t *this = (oss_functions_t *) this_gen;
+
+ this->metronom = metronom;
}
-static ao_functions_t audio_ossout = {
- AO_OUT_OSS_IFACE_VERSION,
- ao_is_mode_supported,
- ao_open,
- ao_write_audio_data,
- ao_close,
- ao_get_ident
-};
+static void ao_exit(ao_functions_t *this_gen)
+{
+ oss_functions_t *this = (oss_functions_t *) this_gen;
+
+ if (this->audio_fd != -1)
+ close(this->audio_fd);
+ free (this->zero_space);
+ free (this);
+}
-ao_functions_t *init_audio_out_plugin (int iface, config_values_t *config) {
- int caps;
- char devname[] = "/dev/dsp\0\0\0";
- int best_rate;
- int rate ;
- int devnum;
- int audio_fd;
+ao_functions_t *init_audio_out_plugin (config_values_t *config) {
+ oss_functions_t *this;
+ int caps;
+ char devname[] = "/dev/dsp\0\0\0";
+ int best_rate;
+ int rate ;
+ int devnum;
+ int audio_fd;
- /* FIXME: add iface check */
+ this = (oss_functions_t *) malloc (sizeof (oss_functions_t));
/*
* find best device driver/channel
*/
- xprintf (VERBOSE|AUDIO, "Opening audio device...");
+ xprintf (VERBOSE|AUDIO, "audio_oss_out: Opening audio device...");
devnum = 0;
best_rate = 0;
while (devnum<16) {
@@ -412,7 +420,7 @@ ao_functions_t *init_audio_out_plugin (int iface, config_values_t *config) {
rate = 48000;
ioctl(audio_fd,SNDCTL_DSP_SPEED, &rate);
if (rate>best_rate) {
- strncpy (gAudioOSS.audio_dev, devname, 19);
+ strncpy (this->audio_dev, devname, 19);
best_rate = rate;
}
@@ -427,37 +435,60 @@ ao_functions_t *init_audio_out_plugin (int iface, config_values_t *config) {
* open that device
*/
- audio_fd=open(gAudioOSS.audio_dev, O_WRONLY|O_NDELAY);
+ audio_fd=open(this->audio_dev, O_WRONLY|O_NDELAY);
if(audio_fd < 0)
{
- xprintf(VERBOSE|AUDIO, "%s: Opening audio device %s\n",
- strerror(errno), gAudioOSS.audio_dev);
+ xprintf(VERBOSE|AUDIO, "audio_oss_out: %s: Opening audio device %s\n",
+ strerror(errno), this->audio_dev);
+ free (this);
return NULL;
} else
- xprintf (VERBOSE|AUDIO, " %s\n", gAudioOSS.audio_dev);
+ xprintf (VERBOSE|AUDIO, " %s\n", this->audio_dev);
ioctl (audio_fd, SNDCTL_DSP_GETCAPS, &caps);
if ((caps & DSP_CAP_REALTIME) > 0) {
- xprintf (VERBOSE|AUDIO, "audio_out : realtime check: passed :-)\n");
+ xprintf (VERBOSE|AUDIO, "audio_oss_out : realtime check: passed :-)\n");
} else {
- xprintf (VERBOSE|AUDIO, "audio_out : realtime check: *FAILED* :-(((((\n\n");
+ xprintf (VERBOSE|AUDIO, "audio_oss_out : realtime check: *FAILED* :-(((((\n\n");
}
+ /*
if ((caps & DSP_CAP_TRIGGER) > 0) {
xprintf (VERBOSE|AUDIO, "audio_out : trigger check : passed :-)\n");
} else {
xprintf (VERBOSE|AUDIO, "audio_out : trigger check : *FAILED* :-(((((\n");
}
+ */
close (audio_fd);
- gAudioOSS.output_sample_rate = 0;
+ this->output_sample_rate = 0;
+
+ this->zero_space = malloc (8192);
+ memset (this->zero_space, 0, 8192);
+
+ this->ao_functions.get_supported_modes = ao_get_supported_modes;
+ 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;
- gAudioOSS.zero_space = xmalloc (8192);
+ return &this->ao_functions;
+}
+
+static ao_info_t ao_info_oss = {
+ AUDIO_OUT_IFACE_VERSION,
+ "oss",
+ "xine audio output plugin using oss-compliant audio devices/drivers",
+ 5
+};
- return &audio_ossout;
+ao_info_t *get_audio_out_plugin_info() {
+ return &ao_info_oss;
}
+