summaryrefslogtreecommitdiff
path: root/libao/src/src/ao_aixs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libao/src/src/ao_aixs.c')
-rw-r--r--libao/src/src/ao_aixs.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/libao/src/src/ao_aixs.c b/libao/src/src/ao_aixs.c
new file mode 100644
index 0000000..d8ba6ed
--- /dev/null
+++ b/libao/src/src/ao_aixs.c
@@ -0,0 +1,256 @@
+/*
+ *
+ * ao_aixs.c AIX (5.1)
+ *
+ * Original Copyright (C) Stefan Tibus - August 2002
+ *
+ * libao is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * libao is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: ao_aixs.c 17718 2010-12-06 20:09:29Z xiphmont $
+
+ ********************************************************************/
+
+#ifdef HAVE_SYS_AUDIO_H
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/audio.h>
+
+#include <ao/ao.h>
+#include <ao/plugin.h>
+
+
+/*
+ * default audio device to be used,
+ * possible options:
+ * /dev/paud0/1 on PCI machines with the Crystal chipset
+ * /dev/baud0/1 on MCA machines with the Crystal chipset
+ * /dev/acpa0/1 on MCA machines with the ACPA
+ */
+#ifndef AO_AIX_DEFAULT_DEV
+#define AO_AIX_DEFAULT_DEV "/dev/baud0/1"
+#define AO_AIX_DEFAULT_DEV2 "/dev/paud0/1"
+#define AO_AIX_DEFAULT_DEV3 "/dev/acpa0/1"
+#endif
+
+
+static char *ao_aixs_options[] = {"dev","id","matrix","verbose","quiet","debug"};
+ao_info ao_aixs_info = {
+ AO_TYPE_LIVE,
+ "AIX audio driver output",
+ "aixs",
+ "Stefan Tibus <sjti@gmx.net>",
+ "Outputs to the AIX audio system.",
+ AO_FMT_NATIVE,
+ 20,
+ ao_aixs_options,
+ sizeof(ao_aixs_options)/sizeof(*ao_aixs_options)
+};
+
+
+typedef struct ao_aixs_internal {
+ char *dev;
+ int id;
+ int fd;
+} ao_aixs_internal;
+
+
+int ao_aixs_test()
+{
+ int fd;
+
+ fd = open(AO_AIX_DEFAULT_DEV, O_WRONLY);
+ if(fd<0)
+ fd = open(AO_AIX_DEFAULT_DEV2, O_WRONLY);
+ if(fd<0)
+ fd = open(AO_AIX_DEFAULT_DEV3, O_WRONLY);
+ if(fd<0)
+ return 0; /* Cannot use this plugin with default parameters */
+
+ close(fd);
+ return 1; /* This plugin works in default mode */
+}
+
+
+ao_info *ao_aixs_driver_info(void)
+{
+ return &ao_aixs_info;
+}
+
+
+int ao_aixs_device_init(ao_device *device)
+{
+ ao_aixs_internal *internal;
+
+ internal = (ao_aixs_internal *) calloc(1,sizeof(ao_aixs_internal));
+
+ if (internal == NULL)
+ return 0; /* Could not initialize device memory */
+
+ device->internal = internal;
+ device->output_matrix_order = AO_OUTPUT_MATRIX_FIXED;
+
+ return 1; /* Memory alloc successful */
+}
+
+int ao_aixs_set_option(ao_device *device, const char *key, const char *value)
+{
+ ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+ if (!strcmp(key, "dev")) {
+ if(internal->dev)
+ free(internal->dev);
+ internal->dev = strdup(value);
+ }
+ if (!strcmp(key, "id")) {
+ internal->id = atoi(value);
+ if(internal->dev)
+ free(internal->dev);
+ internal->dev = NULL;
+ }
+
+ return 1;
+}
+
+
+int ao_aixs_open(ao_device *device, ao_sample_format *format)
+{
+ ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+ audio_init init;
+ audio_control control;
+ audio_change change;
+
+ if(!internal->dev){
+ char buffer[80];
+ int fd;
+
+ sprintf(buffer,"/dev/baud%d/1",id);
+ fd = open(buffer, O_WRONLY);
+ if(fd<0){
+ sprintf(buffer,"/dev/paud%d/1",id);
+ fd = open(buffer, O_WRONLY);
+ }
+ if(fd<0){
+ sprintf(buffer,"/dev/acpa%d/1",id);
+ fd = open(buffer, O_WRONLY);
+ }
+ if(fd<0) return 0;
+ internal->fd = fd;
+ internal->dev = strdup(buffer);
+ }else
+ if ( (internal->fd = open(internal->dev, O_WRONLY)) < 0 )
+ return 0;
+
+ init.srate = format->rate;
+ init.bits_per_sample = format->bits;
+ init.channels = device->output_channels;
+ init.mode = AUDIO_PCM;
+ init.flags = AUDIO_BIG_ENDIAN | AUDIO_TWOS_COMPLEMENT;
+ init.operation = AUDIO_PLAY;
+
+ if (ioctl(internal->fd, AUDIO_INIT, &init) < 0) {
+ close(internal->fd);
+ return 0; /* Unsupported audio format */
+ }
+
+ change.balance = 0x3fff0000;
+ change.volume = 0x3fff0000;
+ change.monitor = AUDIO_IGNORE;
+ change.input = AUDIO_IGNORE;
+ change.output = AUDIO_OUTPUT_1;
+
+ control.ioctl_request = AUDIO_CHANGE;
+ control.position = 0;
+ control.request_info = &change;
+
+ if (ioctl(internal->fd, AUDIO_CONTROL, &control) < 0) {
+ close(internal->fd);
+ return 0;
+ }
+
+ control.ioctl_request = AUDIO_START;
+ control.request_info = NULL;
+
+ if (ioctl(internal->fd, AUDIO_CONTROL, &control) < 0) {
+ close(internal->fd);
+ return 0;
+ }
+
+ device->driver_byte_format = AO_FMT_NATIVE;
+ if(!device->inter_matrix){
+ /* set up matrix such that users are warned about > stereo playback */
+ if(device->output_channels<=2)
+ device->inter_matrix=strdup("L,R");
+ //else no matrix, which results in a warning
+ }
+
+ return 1;
+}
+
+
+int ao_aixs_play(ao_device *device, const char *output_samples,
+ uint_32 num_bytes)
+{
+ ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+ if (write(internal->fd, output_samples, num_bytes) < 0)
+ return 0;
+ else
+ return 1;
+}
+
+
+int ao_aixs_close(ao_device *device)
+{
+ ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+ if(internal->fd)
+ close(internal->fd);
+ internal->fd=-1;
+ return 1;
+}
+
+
+void ao_aixs_device_clear(ao_device *device)
+{
+ ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+ if(internal->dev)
+ free(internal->dev);
+ free(internal);
+ device->internal = NULL;
+}
+
+ao_functions ao_aixs = {
+ ao_aixs_test,
+ ao_aixs_driver_info,
+ ao_aixs_device_init,
+ ao_aixs_set_option,
+ ao_aixs_open,
+ ao_aixs_play,
+ ao_aixs_close,
+ ao_aixs_device_clear
+};
+
+#endif