diff options
Diffstat (limited to 'src/audio_out')
-rw-r--r-- | src/audio_out/audio_oss_out.c | 245 |
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; } + |