summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Caujolle-Bert <f1rmb@users.sourceforge.net>2001-10-01 23:04:57 +0000
committerDaniel Caujolle-Bert <f1rmb@users.sourceforge.net>2001-10-01 23:04:57 +0000
commitc48149133f36b24fb87924209a950681be0727c7 (patch)
tree18a1126eeaecf6a6310fb9d74e91a531b2c62f40 /src
parent9d7e1140adde62d0959af667474a54470d98968a (diff)
downloadxine-lib-c48149133f36b24fb87924209a950681be0727c7.tar.gz
xine-lib-c48149133f36b24fb87924209a950681be0727c7.tar.bz2
Add simple mixer control in xine-engine/ao plugins. Fixed some missings
in audio_decoder. xine-ui warn at compile time due of a #warning i added, i will remove it pretty soon. CVS patchset: 715 CVS date: 2001/10/01 23:04:57
Diffstat (limited to 'src')
-rw-r--r--src/audio_out/audio_alsa_out.c315
-rw-r--r--src/audio_out/audio_oss_out.c220
-rw-r--r--src/xine-engine/audio_decoder.c6
-rw-r--r--src/xine-engine/audio_out.c19
-rw-r--r--src/xine-engine/audio_out.h10
-rw-r--r--src/xine-engine/xine.c25
6 files changed, 546 insertions, 49 deletions
diff --git a/src/audio_out/audio_alsa_out.c b/src/audio_out/audio_alsa_out.c
index e887b277d..0ec7de759 100644
--- a/src/audio_out/audio_alsa_out.c
+++ b/src/audio_out/audio_alsa_out.c
@@ -26,7 +26,7 @@
* (c) 2001 James Courtier-Dutton <James@superbug.demon.co.uk>
*
*
- * $Id: audio_alsa_out.c,v 1.28 2001/09/14 20:44:01 jcdutton Exp $
+ * $Id: audio_alsa_out.c,v 1.29 2001/10/01 23:04:57 f1rmb Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -40,7 +40,8 @@
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
-#include <sys/asoundlib.h>
+#include <alloca.h>
+#include <alsa/asoundlib.h>
#include <sys/ioctl.h>
#include <inttypes.h>
@@ -75,11 +76,18 @@
#define AO_OUT_ALSA_IFACE_VERSION 2
-#define GAP_TOLERANCE 5000
+#define GAP_TOLERANCE 5000
+
+#define MIXER_MASK_LEFT (1 << 0)
+#define MIXER_MASK_RIGHT (1 << 1)
+#define MIXER_MASK_STEREO (MIXER_MASK_LEFT|MIXER_MASK_RIGHT)
typedef struct alsa_driver_s {
ao_driver_t ao_driver;
+
+ config_values_t *config;
+
char audio_default_device[20];
char audio_front_device[20];
char audio_surround40_device[20];
@@ -97,9 +105,46 @@ typedef struct alsa_driver_s {
uint32_t bytes_per_frame;
uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */
+ struct {
+ char *name;
+ snd_mixer_t *handle;
+ snd_mixer_elem_t *elem;
+ long min;
+ long max;
+ long left_vol;
+ long right_vol;
+ int mute;
+ } mixer;
+
} alsa_driver_t;
- static snd_output_t *jcd_out;
+static snd_output_t *jcd_out;
+
+static int ao_alsa_get_percent_from_volume(long val, long min, long max)
+{
+ int range = max - min;
+ int tmp;
+
+ if (range == 0)
+ return 0;
+ val -= min;
+ tmp = rint((double)val / (double)range * 100);
+ return tmp;
+}
+
+static long ao_alsa_get_volume_from_percent(int val, long min, long max)
+{
+ int range = max - min;
+ long tmp;
+
+ if (range == 0)
+ return 0;
+ val -= min;
+ tmp = (long) ((range * val) / 100);
+ return tmp;
+}
+
+
/*
* open the audio device for writing to
*/
@@ -402,44 +447,283 @@ static uint32_t ao_alsa_get_capabilities (ao_driver_t *this_gen) {
static void ao_alsa_exit(ao_driver_t *this_gen)
{
alsa_driver_t *this = (alsa_driver_t *) this_gen;
+
+ config_values_t *config = this->config;
+
+ config->set_int (config, "mixer_volume",
+ (((ao_alsa_get_percent_from_volume(this->mixer.left_vol,
+ this->mixer.min, this->mixer.max)) +
+ (ao_alsa_get_percent_from_volume(this->mixer.right_vol,
+ this->mixer.min, this->mixer.max))) /2));
+ config->save(config);
+
if (this->audio_fd) snd_pcm_close(this->audio_fd);
free (this);
}
-static int ao_alsa_get_property (ao_driver_t *this, int property) {
+static int ao_alsa_get_property (ao_driver_t *this_gen, int property) {
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
+ int err;
- /* FIXME: implement some properties
switch(property) {
case AO_PROP_MIXER_VOL:
- break;
case AO_PROP_PCM_VOL:
+ if(this->mixer.elem) {
+ if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT,
+ &this->mixer.left_vol)) < 0) {
+ printf("snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
+ goto __done;
+ }
+
+ if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT,
+ &this->mixer.right_vol)) < 0) {
+ printf("snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
+ goto __done;
+ }
+
+ __done:
+ return (((ao_alsa_get_percent_from_volume(this->mixer.left_vol,
+ this->mixer.min, this->mixer.max)) +
+ (ao_alsa_get_percent_from_volume(this->mixer.right_vol,
+ this->mixer.min, this->mixer.max))) /2);
+ }
break;
+
case AO_PROP_MUTE_VOL:
+ return (this->mixer.mute) ? 1 : 0;
break;
}
- */
+
return 0;
}
/*
*
*/
-static int ao_alsa_set_property (ao_driver_t *this, int property, int value) {
+static int ao_alsa_set_property (ao_driver_t *this_gen, int property, int value) {
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
+ int err;
- /* FIXME: Implement property support.
switch(property) {
case AO_PROP_MIXER_VOL:
- break;
case AO_PROP_PCM_VOL:
+ if(this->mixer.elem) {
+
+ this->mixer.left_vol = this->mixer.right_vol = ao_alsa_get_volume_from_percent(value, this->mixer.min, this->mixer.max);
+
+ if((err = snd_mixer_selem_set_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT,
+ this->mixer.left_vol)) < 0) {
+ printf("snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
+ return ~value;
+ }
+
+ if((err = snd_mixer_selem_set_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT,
+ this->mixer.right_vol)) < 0) {
+ printf("snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
+ return ~value;
+ }
+
+ return value;
+ }
break;
+
case AO_PROP_MUTE_VOL:
+ if(this->mixer.elem) {
+ int sw;
+ int old_mute = this->mixer.mute;
+
+ this->mixer.mute = (value) ? MIXER_MASK_STEREO : 0;
+
+ if ((this->mixer.mute != old_mute)
+ && snd_mixer_selem_has_playback_switch(this->mixer.elem)) {
+ if (snd_mixer_selem_has_playback_switch_joined(this->mixer.elem)) {
+ snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw);
+ snd_mixer_selem_set_playback_switch_all(this->mixer.elem, !sw);
+ } else {
+ if (this->mixer.mute & MIXER_MASK_LEFT) {
+ snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw);
+ snd_mixer_selem_set_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, !sw);
+ }
+ if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN &&
+ (this->mixer.mute & MIXER_MASK_RIGHT)) {
+ snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &sw);
+ snd_mixer_selem_set_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, !sw);
+ }
+ }
+ }
+
+ return value;
+ }
+
+ return ~value;
break;
}
- */
return ~value;
}
+static void ao_alsa_mixer_init(ao_driver_t *this_gen) {
+ alsa_driver_t *this = (alsa_driver_t *) this_gen;
+ config_values_t *config = this->config;
+ snd_ctl_card_info_t *hw_info;
+ snd_ctl_t *ctl_handle;
+ int err;
+ void *mixer_sid;
+ snd_mixer_elem_t *elem;
+ int mixer_n_selems = 0;
+ snd_mixer_selem_id_t *sid;
+ int loop = 0;
+ int found;
+ int sw;
+
+ snd_ctl_card_info_alloca(&hw_info);
+
+ if ((err = snd_ctl_open (&ctl_handle, this->audio_default_device, 0)) < 0) {
+ printf("snd_ctl_open(): %s\n", snd_strerror(err));
+ return;
+ }
+
+ if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0) {
+ printf("snd_ctl_card_info(): %s\n", snd_strerror(err));
+ snd_ctl_close(ctl_handle);
+ return;
+ }
+
+ snd_ctl_close (ctl_handle);
+
+ /*
+ * Open mixer device
+ */
+ if ((err = snd_mixer_open (&this->mixer.handle, 0)) < 0) {
+ printf("snd_mixer_open(): %s\n", snd_strerror(err));
+ return;
+ }
+
+ if ((err = snd_mixer_attach (this->mixer.handle, this->audio_default_device)) < 0) {
+ printf("snd_mixer_attach(): %s\n", snd_strerror(err));
+ snd_mixer_close(this->mixer.handle);
+ return;
+ }
+
+ if ((err = snd_mixer_selem_register (this->mixer.handle, NULL, NULL)) < 0) {
+ printf("snd_mixer_selem_register(): %s\n", snd_strerror(err));
+ snd_mixer_close(this->mixer.handle);
+ return;
+ }
+
+ // snd_mixer_set_callback (mixer_handle, mixer_event);
+
+ if ((err = snd_mixer_load (this->mixer.handle)) < 0) {
+ printf("snd_mixer_load(): %s\n", snd_strerror(err));
+ snd_mixer_close(this->mixer.handle);
+ return;
+ }
+
+ mixer_sid = alloca(snd_mixer_selem_id_sizeof() * snd_mixer_get_count(this->mixer.handle));
+ if (mixer_sid == NULL) {
+ printf("alloca() failed: %s\n", strerror(errno));
+ snd_mixer_close(this->mixer.handle);
+ return;
+ }
+
+ __again:
+
+ found = 0;
+ mixer_n_selems = 0;
+ for (elem = snd_mixer_first_elem(this->mixer.handle); elem; elem = snd_mixer_elem_next(elem)) {
+ sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_n_selems);
+
+ if (!snd_mixer_selem_is_active(elem))
+ continue;
+
+ snd_mixer_selem_get_id(elem, sid);
+ mixer_n_selems++;
+
+ if(!strcmp((snd_mixer_selem_get_name(elem)), this->mixer.name)) {
+
+ // printf("found %s\n", snd_mixer_selem_get_name(elem));
+
+ this->mixer.elem = elem;
+
+ snd_mixer_selem_get_playback_volume_range(this->mixer.elem,
+ &this->mixer.min, &this->mixer.max);
+ if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT,
+ &this->mixer.left_vol)) < 0) {
+ printf("snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
+ snd_mixer_close(this->mixer.handle);
+ return;
+ }
+
+ if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT,
+ &this->mixer.right_vol)) < 0) {
+ printf("snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
+ snd_mixer_close(this->mixer.handle);
+ return;
+ }
+
+ /* Channels mute */
+ this->mixer.mute = 0;
+ if(snd_mixer_selem_has_playback_switch(this->mixer.elem)) {
+
+ if (snd_mixer_selem_has_playback_switch_joined(this->mixer.elem)) {
+ snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw);
+ if(!sw)
+ this->mixer.mute = MIXER_MASK_STEREO;
+ }
+ else {
+ if (this->mixer.mute & MIXER_MASK_LEFT) {
+ snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &sw);
+ if(!sw)
+ this->mixer.mute |= MIXER_MASK_LEFT;
+ }
+ if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN &&
+ (this->mixer.mute & MIXER_MASK_RIGHT)) {
+ snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &sw);
+ if(!sw)
+ this->mixer.mute |= MIXER_MASK_RIGHT;
+ }
+ }
+
+ this->capabilities |= AO_CAP_MUTE_VOL;
+ }
+
+ found++;
+
+ goto __mixer_found;
+ }
+ }
+
+ if(loop)
+ goto __mixer_found; /* Yes, untrue but... ;-) */
+
+ if(!strcmp(this->mixer.name, "PCM")) {
+ config->set_str(config, "mixer_name", "Master");
+ loop++;
+ }
+ else {
+ config->set_str(config, "mixer_name", "PCM");
+ }
+
+ config->save(config);
+
+ this->mixer.name = config->lookup_str(config, "mixer_name", "PCM");
+
+ goto __again;
+
+ __mixer_found:
+
+ /*
+ * Ugly: yes[*] no[ ]
+ */
+ if(found) {
+ if(!strcmp(this->mixer.name, "Master"))
+ this->capabilities |= AO_CAP_MIXER_VOL;
+ else
+ this->capabilities |= AO_CAP_PCM_VOL;
+ }
+
+}
+
ao_driver_t *init_audio_out_plugin (config_values_t *config) {
alsa_driver_t *this;
@@ -514,7 +798,12 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) {
this->capabilities |= AO_CAP_MODE_AC5;
}
printf("audio_alsa_out: Capabilities 0x%X\n",this->capabilities);
-
+
+ this->config = config;
+
+ this->mixer.name = config->lookup_str(config, "mixer_name", "PCM");
+ ao_alsa_mixer_init(&this->ao_driver);
+
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;
diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c
index b176cfb14..cdf1dcf44 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.40 2001/09/30 23:12:05 heikos Exp $
+ * $Id: audio_oss_out.c,v 1.41 2001/10/01 23:04:57 f1rmb Exp $
*
* 20-8-2001 First implementation of Audio sync and Audio driver separation.
* Copyright (C) 2001 James Courtier-Dutton James@superbug.demon.co.uk
@@ -100,21 +100,31 @@ static int use_getodelay = 0;
typedef struct oss_driver_s {
- ao_driver_t ao_driver;
- char audio_dev[20];
- int audio_fd;
- int capabilities;
- int mode;
-
- int32_t output_sample_rate, input_sample_rate;
- uint32_t num_channels;
- uint32_t bits_per_sample;
- uint32_t bytes_per_frame;
- uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */
+ ao_driver_t ao_driver;
+ char audio_dev[20];
+ int audio_fd;
+ int capabilities;
+ int mode;
+
+ config_values_t *config;
+
+ int32_t output_sample_rate, input_sample_rate;
+ uint32_t num_channels;
+ uint32_t bits_per_sample;
+ uint32_t bytes_per_frame;
+ uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */
- int audio_started;
- int audio_has_realtime; /* OSS driver supports real-time */
- int static_delay; /* estimated delay for non-realtime drivers */
+ int audio_started;
+ int audio_has_realtime; /* OSS driver supports real-time */
+ int static_delay; /* estimated delay for non-realtime drivers */
+
+ struct {
+ char *name;
+ int prop;
+ int volume;
+ int mute;
+ } mixer;
+
} oss_driver_t;
/*
@@ -368,6 +378,10 @@ static uint32_t ao_oss_get_capabilities (ao_driver_t *this_gen) {
static void ao_oss_exit(ao_driver_t *this_gen)
{
oss_driver_t *this = (oss_driver_t *) this_gen;
+ config_values_t *config = this->config;
+
+ config->set_int (config, "mixer_volume", this->mixer.volume);
+ config->save(config);
if (this->audio_fd != -1)
close(this->audio_fd);
@@ -375,41 +389,128 @@ static void ao_oss_exit(ao_driver_t *this_gen)
free (this);
}
-/*
- *
- */
static int ao_oss_get_property (ao_driver_t *this_gen, int property) {
- oss_driver_t *this = (oss_driver_t *) this;
+ oss_driver_t *this = (oss_driver_t *) this_gen;
+ int mixer_fd;
+ int audio_devs;
- /* FIXME: implement some properties
switch(property) {
- case AO_PROP_MIXER_VOL:
- break;
case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+ mixer_fd = open(this->mixer.name, O_RDONLY);
+ if(mixer_fd != -1) {
+ int cmd = 0;
+ int v;
+
+ ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &audio_devs);
+
+ if(audio_devs & SOUND_MASK_PCM)
+ cmd = SOUND_MIXER_READ_PCM;
+ else if(audio_devs & SOUND_MASK_VOLUME)
+ cmd = SOUND_MIXER_READ_VOLUME;
+ else {
+ close(mixer_fd);
+ return 0;
+ }
+ ioctl(mixer_fd, cmd, &v);
+ this->mixer.volume = (((v & 0xFF00) >> 8) + (v & 0x00FF)) / 2;
+ close(mixer_fd);
+ }
+ else
+ printf("%s(): open() %s failed: %s\n",
+ __FUNCTION__, this->mixer.name, strerror(errno));
+
+ return this->mixer.volume;
break;
+
case AO_PROP_MUTE_VOL:
+ return this->mixer.mute;
break;
}
- */
+
return 0;
}
-/*
- *
- */
static int ao_oss_set_property (ao_driver_t *this_gen, int property, int value) {
- oss_driver_t *this = (oss_driver_t *) this;
+ oss_driver_t *this = (oss_driver_t *) this_gen;
+ int mixer_fd;
+ int audio_devs;
- /* FIXME: Implement property support.
switch(property) {
- case AO_PROP_MIXER_VOL:
- break;
case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+ if(!this->mixer.mute) {
+
+ mixer_fd = open(this->mixer.name, O_RDONLY);
+
+ if(mixer_fd != -1) {
+ int cmd = 0;
+ int v;
+
+ ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &audio_devs);
+
+ if(audio_devs & SOUND_MASK_PCM)
+ cmd = SOUND_MIXER_WRITE_PCM;
+ else if(audio_devs & SOUND_MASK_VOLUME)
+ cmd = SOUND_MIXER_WRITE_VOLUME;
+ else {
+ close(mixer_fd);
+ return ~value;
+ }
+ v = (value << 8) | value;
+ ioctl(mixer_fd, cmd, &v);
+ close(mixer_fd);
+
+ if(!this->mixer.mute)
+ this->mixer.volume = value;
+
+ }
+ else
+ printf("%s(): open() %s failed: %s\n",
+ __FUNCTION__, this->mixer.name, strerror(errno));
+ }
+ else
+ this->mixer.volume = value;
+
+ return this->mixer.volume;
break;
+
case AO_PROP_MUTE_VOL:
+ this->mixer.mute = (value) ? 1 : 0;
+
+ if(this->mixer.mute) {
+
+ mixer_fd = open(this->mixer.name, O_RDONLY);
+
+ if(mixer_fd != -1) {
+ int cmd = 0;
+ int v = 0;
+
+ ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &audio_devs);
+
+ if(audio_devs & SOUND_MASK_PCM)
+ cmd = SOUND_MIXER_WRITE_PCM;
+ else if(audio_devs & SOUND_MASK_VOLUME)
+ cmd = SOUND_MIXER_WRITE_VOLUME;
+ else {
+ close(mixer_fd);
+ return ~value;
+ }
+
+ ioctl(mixer_fd, cmd, &v);
+ close(mixer_fd);
+
+ }
+ else
+ printf("%s(): open() %s failed: %s\n",
+ __FUNCTION__, this->mixer.name, strerror(errno));
+ }
+ else
+ (void) ao_oss_set_property(&this->ao_driver, this->mixer.prop, this->mixer.volume);
+
+ return value;
break;
}
- */
return ~value;
}
@@ -428,7 +529,7 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) {
int devnum;
int audio_fd;
int num_channels, status, arg;
-
+
this = (oss_driver_t *) malloc (sizeof (oss_driver_t));
/*
@@ -574,7 +675,61 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) {
}
printf ("\n");
+
+ /*
+ * Mixer initialisation.
+ */
+ __again:
+ this->mixer.name = config->lookup_str(config, "mixer_name", "/dev/mixer");
+ {
+ int mixer_fd;
+ int audio_devs;
+
+ mixer_fd = open(this->mixer.name, O_RDONLY);
+
+ if(mixer_fd != -1) {
+ ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &audio_devs);
+
+ if(audio_devs & SOUND_MASK_PCM) {
+ this->capabilities |= AO_CAP_PCM_VOL;
+ this->mixer.prop = AO_PROP_PCM_VOL;
+ }
+ else if(audio_devs & SOUND_MASK_VOLUME) {
+ this->capabilities |= AO_CAP_MIXER_VOL;
+ this->mixer.prop = AO_PROP_MIXER_VOL;
+ }
+
+ /*
+ * This is obsolete in Linux kernel OSS
+ * implementation, so this will certainly doesn't work.
+ * So we just simulate the mute stuff
+ */
+ /*
+ if(audio_devs & SOUND_MASK_MUTE)
+ this->capabilities |= AO_CAP_MUTE_VOL;
+ */
+ this->capabilities |= AO_CAP_MUTE_VOL;
+
+ }
+ else {
+ if(strcmp(this->mixer.name, "/dev/mixer")) {
+ config->set_str(config, "mixer_name", "/dev/mixer");
+ config->save(config);
+ goto __again;
+ }
+ else
+ printf("%s(): open() %s failed: %s\n",
+ __FUNCTION__, this->mixer.name, strerror(errno));
+ }
+
+ this->mixer.mute = 0;
+ this->mixer.volume = ao_oss_get_property (&this->ao_driver, this->mixer.prop);
+ this->mixer.volume = config->lookup_int (config, "mixer_volume", 50);
+
+ (void) ao_oss_set_property(&this->ao_driver, this->mixer.prop, this->mixer.volume);
+
+ }
close (audio_fd);
this->output_sample_rate = 0;
@@ -582,6 +737,7 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) {
this->static_delay = config->lookup_int (config, "oss_static_delay", 1000);
+ this->config = config;
this->ao_driver.get_capabilities = ao_oss_get_capabilities;
this->ao_driver.get_property = ao_oss_get_property;
this->ao_driver.set_property = ao_oss_set_property;
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index 2b5320dd6..f6995c439 100644
--- a/src/xine-engine/audio_decoder.c
+++ b/src/xine-engine/audio_decoder.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_decoder.c,v 1.41 2001/09/25 23:27:02 guenter Exp $
+ * $Id: audio_decoder.c,v 1.42 2001/10/01 23:04:57 f1rmb Exp $
*
*
* functions that implement audio decoding
@@ -300,5 +300,9 @@ void audio_decoder_shutdown (xine_t *this) {
pthread_join (this->audio_thread, &p);
}
+
+ if(this->audio_out)
+ this->audio_out->exit (this->audio_out);
+
}
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index 20fd26876..27fb336b2 100644
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -17,7 +17,7 @@
* along with self program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_out.c,v 1.17 2001/09/12 22:00:51 joachim_koenig Exp $
+ * $Id: audio_out.c,v 1.18 2001/10/01 23:04:57 f1rmb Exp $
*
* 22-8-2001 James imported some useful AC3 sections from the previous alsa driver.
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -406,12 +406,26 @@ static void ao_close(ao_instance_t *this)
this->driver->close(this->driver);
}
+static void ao_exit(ao_instance_t *this) {
+ this->driver->exit(this->driver);
+}
+
static uint32_t ao_get_capabilities (ao_instance_t *this) {
uint32_t result;
result=this->driver->get_capabilities(this->driver);
return result;
}
+static int ao_get_property (ao_instance_t *this, int property) {
+
+ return(this->driver->get_property(this->driver, property));
+}
+
+static int ao_set_property (ao_instance_t *this, int property, int value) {
+
+ return(this->driver->set_property(this->driver, property, value));
+}
+
ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom,
config_values_t *config) {
@@ -425,7 +439,10 @@ ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom,
this->open = ao_open;
this->write = ao_write;
this->close = ao_close;
+ this->exit = ao_exit;
this->get_capabilities = ao_get_capabilities;
+ this->get_property = ao_get_property;
+ this->set_property = ao_set_property;
this->audio_loop_running = 0;
this->frame_buffer = xmalloc (40000);
this->zero_space = xmalloc (ZERO_BUF_SIZE * 2 * 6);
diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h
index d23db13f5..501eac29a 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.17 2001/09/14 20:44:01 jcdutton Exp $
+ * $Id: audio_out.h,v 1.18 2001/10/01 23:04:57 f1rmb Exp $
*/
#ifndef HAVE_AUDIO_OUT_H
#define HAVE_AUDIO_OUT_H
@@ -126,6 +126,14 @@ typedef struct ao_instance_s ao_instance_t;
struct ao_instance_s {
uint32_t (*get_capabilities) (ao_instance_t *this); /* for constants see below */
+ /*
+ * Get/Set audio property
+ *
+ * See AO_PROP_* bellow
+ */
+ int (*get_property) (ao_instance_t *this, int property);
+ int (*set_property) (ao_instance_t *this, int property, int value);
+
/* open audio driver for audio output
* return value: 0:failure, >0:output sample rate
*/
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 837a3180d..6d6721be8 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.60 2001/09/10 13:36:56 jkeil Exp $
+ * $Id: xine.c,v 1.61 2001/10/01 23:04:57 f1rmb Exp $
*
* top-level xine functions
*
@@ -621,4 +621,27 @@ int xine_get_stream_length (xine_t *this) {
return 0;
}
+int xine_get_audio_capabilities(xine_t *this) {
+
+ if(this->audio_out)
+ return (this->audio_out->get_capabilities(this->audio_out));
+
+ return AO_CAP_NOCAP;
+}
+
+int xine_get_audio_property(xine_t *this, int property) {
+
+ if(this->audio_out)
+ return(this->audio_out->get_property(this->audio_out, property));
+
+ return 0;
+}
+
+int xine_set_audio_property(xine_t *this, int property, int value) {
+
+ if(this->audio_out)
+ return(this->audio_out->set_property(this->audio_out, property, value));
+
+ return ~value;
+}