From 12d67b2b0a4fd1a0bbaea2eb2bb5e5969fef0a54 Mon Sep 17 00:00:00 2001 From: Guenter Bartsch Date: Sat, 28 Apr 2001 19:47:41 +0000 Subject: bugfix in video_out_xv, sorted out audio output plugin handling/code CVS patchset: 39 CVS date: 2001/04/28 19:47:41 --- src/audio_out/audio_oss_out.c | 245 +++++++++++++++++++++++------------------ src/libac3/decode.c | 16 +-- src/video_out/video_out_xv.c | 4 +- src/xine-engine/audio_out.h | 94 ++++++++-------- src/xine-engine/load_plugins.c | 118 ++++++++++++++++---- src/xine-engine/video_out.h | 15 +-- src/xine-engine/xine.c | 5 +- 7 files changed, 304 insertions(+), 193 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 #include #include +#include #include #include #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; } + diff --git a/src/libac3/decode.c b/src/libac3/decode.c index fd004f3fe..5d1fd68b3 100644 --- a/src/libac3/decode.c +++ b/src/libac3/decode.c @@ -76,7 +76,7 @@ static int16_t s16_samples[2 * 6 * 256] __attribute__ ((aligned(16))); /* output buffer for spdiv output */ static int16_t s16_samples_out[4 * 6 * 256] __attribute__ ((aligned(16))); -static ao_functions_t ac3_output; +static ao_functions_t *ac3_output; // downmix stuff static float cmixlev_lut[4] = { 0.707, 0.595, 0.500, 0.707 }; @@ -168,7 +168,7 @@ void inline decode_mute (void) void ac3_init(ac3_config_t *config ,ao_functions_t *foo) { memcpy(&ac3_config,config,sizeof(ac3_config_t)); - ac3_output = *foo; + ac3_output = foo; imdct_init (); /* downmix_init (); */ @@ -286,18 +286,18 @@ size_t ac3_decode_data (metronom_t *metronom, } if (!is_output_initialized) { - ac3_output.open (metronom, 16, syncinfo.sampling_rate, - (ac3_config.flags & AO_MODE_AC3) ? AO_MODE_AC3 : AO_MODE_STEREO); + ac3_output->open (ac3_output, 16, syncinfo.sampling_rate, + (ac3_config.flags & AO_MODE_AC3) ? AO_MODE_AC3 : AO_MODE_STEREO); is_output_initialized = 1; } if ((ac3_config.flags & AO_MODE_AC3) == 0) { - ac3_output.write_audio_data(metronom, - s16_samples, 256*6, pts_); + ac3_output->write_audio_data(ac3_output, + s16_samples, 256*6, pts_); } else { - ac3_output.write_audio_data(metronom, - s16_samples_out, 6 * 256, pts_); + ac3_output->write_audio_data(ac3_output, + s16_samples_out, 6 * 256, pts_); } pts_ = 0; diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 529b6c9a7..b32908e16 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.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: video_out_xv.c,v 1.5 2001/04/27 23:51:52 guenter Exp $ + * $Id: video_out_xv.c,v 1.6 2001/04/28 19:47:42 guenter Exp $ * * video_out_xv.c, X11 video extension interface for xine * @@ -468,8 +468,10 @@ static void xv_setup_window (xv_driver_t *this) { XFree(wm_hint); } + /* FIXME wm_delete_window = XInternAtom(this->display, "WM_DELETE_WINDOW", False); XSetWMProtocols(this->display, this->window, &wm_delete_window, 1); + */ /* Map window. */ diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h index 9b332e72d..98bbc4683 100644 --- a/src/xine-engine/audio_out.h +++ b/src/xine-engine/audio_out.h @@ -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_out.h,v 1.2 2001/04/27 10:42:38 f1rmb Exp $ + * $Id: audio_out.h,v 1.3 2001/04/28 19:47:42 guenter Exp $ */ #ifndef HAVE_AUDIO_OUT_H #define HAVE_AUDIO_OUT_H @@ -30,90 +30,96 @@ #endif -#define AUDIO_OUT_PLUGIN_IFACE_VERSION 1 +#define AUDIO_OUT_IFACE_VERSION 1 /* * audio output modes Used as Bitfield in AC3 decoder */ #define AO_MODE_AC3 1 -#define AO_MODE_MONO 2 /* 1 sample == 2 bytes */ -#define AO_MODE_STEREO 4 /* 1 sample == 4 bytes */ -#define AO_MODE_4CHANNEL 8 /* 1 sample == 8 bytes */ -#define AO_MODE_5CHANNEL 16 /* 1 sample == 10 bytes */ +#define AO_MODE_AC5 2 +#define AO_MODE_MONO 4 /* 1 sample == 2 bytes */ +#define AO_MODE_STEREO 8 /* 1 sample == 4 bytes */ +#define AO_MODE_4CHANNEL 16 /* 1 sample == 8 bytes */ +#define AO_MODE_5CHANNEL 32 /* 1 sample == 10 bytes */ -typedef struct ao_functions_s -{ +/* + * ao_functions_s contains the functions every audio output + * driver plugin has to implement. + */ + +typedef struct ao_functions_s ao_functions_t; + +struct ao_functions_s { /* - * plugin interface version, lower versions _may_ be supported + * find out what output modes are supported by this plugin + * (constants for the bit vector to return see above) */ - int interface_version; + uint32_t (*get_supported_modes) (ao_functions_t *this); /* - * find out if desired output mode is supported by - * this driver + * connect this driver to the xine engine */ - - int (*is_mode_supported) (int mode); + void (*connect) (ao_functions_t *this, metronom_t *metronom); /* - * init device - buffer will be flushed(!) + * open the driver and make it ready to receive audio data + * buffers may be flushed(!) + * * return value: <=0 : failure, 1 : ok */ - int (*open)(metronom_t *metronom, uint32_t bits, uint32_t rate, int mode); + int (*open)(ao_functions_t *this, uint32_t bits, uint32_t rate, int mode); /* * write audio data to output buffer - may block * audio driver must sync sample playback with metronom */ - void (*write_audio_data)(metronom_t *metronom, + void (*write_audio_data)(ao_functions_t *this, int16_t* audio_data, uint32_t num_samples, uint32_t pts); /* - * close the audio driver + * this is called when the decoder no longer uses the audio + * output driver - the driver should get ready to get opened() again */ - void (*close)(void); + void (*close)(ao_functions_t *this); /* - * return human readable identifier for this plugin + * shut down this audio output driver plugin and + * free all resources allocated */ - char* (*get_identifier) (void); - -} ao_functions_t; + void (*exit) (ao_functions_t *this); -/* - * available drivers: - */ +} ; -#define AO_DRIVER_UNSET -1 -#define AO_DRIVER_NULL 0 -#define AO_DRIVER_OSS 1 -#if defined(HAVE_ALSA) -# define AO_DRIVER_ALSA 2 -# if defined(HAVE_ESD) -# define AO_DRIVER_ESD 3 -# endif -#else /* no ALSA */ -# if defined(HAVE_ESD) -# define AO_DRIVER_ESD 2 -# endif -#endif /* - * find right device driver, init it + * to build a dynamic audio output plugin, + * you have to implement these functions: + * + * + * ao_functions_t *init_audio_out_plugin (config_values_t *config) + * + * init this plugin, check if device is available + * + * ao_info_t *get_audio_out_plugin_info () + * + * peek at some (static) information about the plugin without initializing it + * */ -//ao_functions_t *ao_init(char *driver_name) ; - -ao_functions_t *init_audio_out_plugin(int iface, config_values_t *cfg); +typedef struct ao_info_s { -char *ao_get_available_drivers (); + int interface_version; + char *id; + char *description; + int priority; +} ao_info_t ; #endif diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index fde565b03..7e35e4f6b 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.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: load_plugins.c,v 1.11 2001/04/27 23:51:52 guenter Exp $ + * $Id: load_plugins.c,v 1.12 2001/04/28 19:47:42 guenter Exp $ * * * Load input/demux/audio_out/video_out/codec plugins @@ -458,8 +458,77 @@ vo_driver_t *xine_load_video_output_plugin(config_values_t *config, return NULL; } -ao_functions_t *xine_load_audio_output_plugin(config_values_t *config, - char *id) { +char **xine_list_audio_output_plugins() { + + char **plugin_ids; + int num_plugins = 0; + DIR *dir; + + plugin_ids = xmalloc (50 * sizeof (char *)); + plugin_ids[0] = NULL; + + dir = opendir (XINE_PLUGINDIR); + + if (dir) { + struct dirent *dir_entry; + + while ((dir_entry = readdir (dir)) != NULL) { + char str[1024]; + void *plugin; + int nLen = strlen (dir_entry->d_name); + + if ((strncasecmp(dir_entry->d_name, + XINE_AUDIO_OUT_PLUGIN_PREFIXNAME, + XINE_AUDIO_OUT_PLUGIN_PREFIXNAME_LENGTH) == 0) && + ((dir_entry->d_name[nLen-3]=='.') + && (dir_entry->d_name[nLen-2]=='s') + && (dir_entry->d_name[nLen-1]=='o'))) { + + sprintf (str, "%s/%s", XINE_PLUGINDIR, dir_entry->d_name); + + /* + * now, see if we can open this plugin, + * and get it's id + */ + + if(!(plugin = dlopen (str, RTLD_LAZY))) { + + /* printf("load_plugins: cannot load plugin %s (%s)\n", + str, dlerror()); */ + + } else { + + ao_info_t* (*getinfo) (); + ao_info_t *ao_info; + + if ((getinfo = dlsym(plugin, "get_audio_out_plugin_info")) != NULL) { + ao_info = getinfo(); + + if ( ao_info->interface_version == AUDIO_OUT_IFACE_VERSION) { + + /* FIXME: sort the list by ao_info->priority */ + + plugin_ids[num_plugins] = ao_info->id; + num_plugins++; + plugin_ids[num_plugins] = NULL; + } + } else { + + printf("load_plugins: %s seems to be an invalid plugin (lacks get_audio_out_plugin_info() function)\n", str); + + } + } + } + } + } else { + perror ("load_plugins: get_available_audio_output_plugins - cannot access plugin dir:"); + } + + return plugin_ids; +} + +ao_functions_t *xine_load_audio_output_plugin(config_values_t *config, char *id) { + DIR *dir; ao_functions_t *aod = NULL; @@ -486,23 +555,30 @@ ao_functions_t *xine_load_audio_output_plugin(config_values_t *config, sprintf (str, "%s/%s", XINE_PLUGINDIR, pEntry->d_name); if(!(plugin = dlopen (str, RTLD_LAZY))) { - fprintf(stderr, "%s(%d): %s doesn't seem to be installed (%s)\n", - __FILE__, __LINE__, str, dlerror()); - exit(1); - } - else { - void *(*initplug) (int, config_values_t *); + printf("load_plugins: audio output plugin %s failed to link: %s\n", + str, dlerror()); + return NULL; + } else { + void *(*initplug) (config_values_t *); + ao_info_t* (*getinfo) (); + ao_info_t *ao_info; + + if ((getinfo = dlsym(plugin, "get_audio_out_plugin_info")) != NULL) { + ao_info = getinfo(); - if((initplug = dlsym(plugin, "init_audio_out_plugin")) != NULL) { - - aod = (ao_functions_t *) initplug(AUDIO_OUT_PLUGIN_IFACE_VERSION, - config); - - printf("audio output plugin found : %s(ID: %s, iface: %d)\n", - str, aod->get_identifier(), aod->interface_version); + if (!strcmp(id, ao_info->id)) { - if(!strcasecmp(id, aod->get_identifier())) { - return aod; + if((initplug = dlsym(plugin, "init_audio_out_plugin")) != NULL) { + + aod = (ao_functions_t *) initplug(config); + + if (aod) + printf("load_plugins: audio output plugin %s sucessfully loaded.\n", str); + else + printf("load_plugins: audio output plugin %s: init_audio_out_plugin failed.\n", str); + + return aod; + } } } } @@ -512,9 +588,3 @@ ao_functions_t *xine_load_audio_output_plugin(config_values_t *config, return NULL; } -char **xine_list_audio_output_plugins() { - - printf ("load_plugins: FIXME: list_audio_output_plugins not implemented yet\n"); - - return NULL; -} diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 864132660..6998a7c26 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -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: video_out.h,v 1.3 2001/04/27 23:51:52 guenter Exp $ + * $Id: video_out.h,v 1.4 2001/04/28 19:47:42 guenter Exp $ * * * xine version of video_out.h @@ -205,7 +205,7 @@ struct vo_instance_s { #define VO_CAP_COLORKEY 0x00000100 /* driver can set COLORKEY value */ /* - * vo_driver_s contains the function every display driver + * vo_driver_s contains the functions every display driver * has to implement. The vo_new_instance function (see below) * should then be used to construct a vo_instance using this * driver. Some of the function pointers will be copied @@ -266,25 +266,26 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) ; * you have to implement these functions: * * - * init_video_out_plugin init and set up driver so it is fully operational + * vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual); + * + * init and set up driver so it is fully operational * * parameters: config - config object pointer * visual - driver specific info (e.g. Display*) * * return value: video_driver_t* in case of success, - * NULL on failure (e.g. wrong interface version, wrong visual type...) + * NULL on failure (e.g. wrong interface version, + * wrong visual type...) * - * vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual); * * - * get_video_out_plugin_info + * vo_info_t *get_video_out_plugin_info (); * * peek at some (static) information about the plugin without initializing it * * parameters: none * * return value: vo_info_t* : some information about the plugin - * vo_info_t *get_video_out_plugin_info (); */ typedef struct vo_info_s { diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 70f9bf8f2..32b40a33a 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.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: xine.c,v 1.7 2001/04/24 21:10:42 guenter Exp $ + * $Id: xine.c,v 1.8 2001/04/28 19:47:42 guenter Exp $ * * top-level xine functions * @@ -96,7 +96,7 @@ void xine_stop (xine_t *this) { this->spu_fifo->clear(this->spu_fifo); if (this->audio_out) - this->audio_out->close (); + this->audio_out->close (this->audio_out); this->metronom->reset(this->metronom); this->metronom->stop_clock (this->metronom); @@ -438,6 +438,7 @@ xine_t *xine_init (vo_driver_t *vo, video_decoder_init (this); this->audio_out = ao; + this->audio_out->connect (this->audio_out, this->metronom); audio_decoder_init (this); /* -- cgit v1.2.3