aboutsummaryrefslogtreecommitdiff
path: root/src/output/sun.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/output/sun.c')
-rw-r--r--src/output/sun.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/src/output/sun.c b/src/output/sun.c
new file mode 100644
index 0000000..75bd7a0
--- /dev/null
+++ b/src/output/sun.c
@@ -0,0 +1,281 @@
+/*
+ sun: audio output for Sun systems
+
+ copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
+ see COPYING and AUTHORS files in distribution or http://mpg123.org
+ initially written by Michael Hipp
+*/
+
+#include "mpg123app.h"
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SUN_AUDIOIO_H
+#include <sun/audioio.h>
+#endif
+
+#ifdef HAVE_SYS_AUDIOIO_H
+#include <sys/audioio.h>
+#endif
+
+#ifdef HAVE_SYS_AUDIO_H
+#include <sys/audio.h>
+#endif
+
+#ifdef HAVE_ASM_AUDIOIO_H
+#include <asm/audioio.h>
+#endif
+
+#include <fcntl.h>
+#include "debug.h"
+
+static void set_format_helper(audio_output_t *ao, audio_info_t *ainfo)
+{
+
+ switch(ao->format) {
+ case -1:
+ case MPG123_ENC_SIGNED_16:
+ default:
+#ifndef AUDIO_ENCODING_LINEAR /* not supported */
+#define AUDIO_ENCODING_LINEAR 3
+#endif
+ ainfo->play.encoding = AUDIO_ENCODING_LINEAR;
+ ainfo->play.precision = 16;
+ break;
+ case MPG123_ENC_UNSIGNED_8:
+#if defined(SOLARIS) || defined(SPARCLINUX)
+ ainfo->play.encoding = AUDIO_ENCODING_LINEAR8;
+ ainfo->play.precision = 8;
+ break;
+#endif
+ case MPG123_ENC_SIGNED_8:
+ error("Linear signed 8 bit not supported!");
+ return;
+ case MPG123_ENC_ULAW_8:
+ ainfo->play.encoding = AUDIO_ENCODING_ULAW;
+ ainfo->play.precision = 8;
+ break;
+ case MPG123_ENC_ALAW_8:
+ ainfo->play.encoding = AUDIO_ENCODING_ALAW;
+ ainfo->play.precision = 8;
+ break;
+ }
+
+}
+
+
+static int reset_parameters_sun(audio_output_t *ao)
+{
+ audio_info_t ainfo;
+
+ AUDIO_INITINFO(&ainfo);
+ if(ao->rate != -1) ainfo.play.sample_rate = ao->rate;
+
+ if(ao->channels >= 0) ainfo.play.channels = ao->channels;
+
+ set_format_helper(ao,&ainfo);
+ if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1) return -1;
+
+ return 0;
+}
+
+static int rate_best_match(audio_output_t *ao)
+{
+ audio_info_t ainfo;
+ AUDIO_INITINFO(&ainfo);
+
+ ainfo.play.sample_rate = ao->rate;
+ if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) < 0) {
+ ao->rate = 0;
+ return 0;
+ }
+ if(ioctl(ao->fn, AUDIO_GETINFO, &ainfo) < 0) {
+ return -1;
+ }
+
+ ao->rate = ainfo.play.sample_rate;
+ return 0;
+}
+
+static int set_rate(audio_output_t *ao)
+{
+ audio_info_t ainfo;
+
+ if(ao->rate != -1) {
+ AUDIO_INITINFO(&ainfo);
+ ainfo.play.sample_rate = ao->rate;
+ if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1) return -1;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int set_channels(audio_output_t *ao)
+{
+ audio_info_t ainfo;
+
+ AUDIO_INITINFO(&ainfo);
+ ainfo.play.channels = ao->channels;
+ if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
+ return -1;
+
+ return 0;
+}
+
+static int set_format(audio_output_t *ao)
+{
+ audio_info_t ainfo;
+
+ AUDIO_INITINFO(&ainfo);
+ set_format_helper(ao,&ainfo);
+ if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
+ return -1;
+
+ return 0;
+}
+
+static int open_sun(audio_output_t *ao)
+{
+ audio_info_t ainfo;
+
+ if(!ao->device) {
+ if(getenv("AUDIODEV")) {
+ ao->device = getenv("AUDIODEV");
+ } else {
+ ao->device = "/dev/audio";
+ }
+ }
+
+ ao->fn = open(ao->device,O_WRONLY);
+ if(ao->fn < 0) return ao->fn;
+
+#if defined(SUNOS) && defined(AUDIO_GETDEV)
+ {
+ int type;
+ if(ioctl(ao->fn, AUDIO_GETDEV, &type) == -1) return -1;
+ if(type == AUDIO_DEV_UNKNOWN || type == AUDIO_DEV_AMD)
+ return -1;
+ }
+#else
+#if defined(SOLARIS) || defined(SPARCLINUX)
+ {
+ struct audio_device ad;
+ if(ioctl(ao->fn, AUDIO_GETDEV, &ad) == -1)
+ return -1;
+ if(!strstr(ad.name,"dbri") && !strstr(ad.name,"CS4231"))
+ warning1("Unknown sound system %s. But we try it.",ad.name);
+ }
+#endif
+#endif
+
+ if(reset_parameters_sun(ao) < 0) return -1;
+
+ AUDIO_INITINFO(&ainfo);
+
+ if(ao->flags > 0)
+ ainfo.play.port = 0;
+ if(ao->flags & AUDIO_OUT_INTERNAL_SPEAKER)
+ ainfo.play.port |= AUDIO_SPEAKER;
+ if(ao->flags & AUDIO_OUT_HEADPHONES)
+ ainfo.play.port |= AUDIO_HEADPHONE;
+ #ifdef AUDIO_LINE_OUT
+ if(ao->flags & AUDIO_OUT_LINE_OUT)
+ ainfo.play.port |= AUDIO_LINE_OUT;
+ #endif
+
+ if(ao->gain != -1)
+ ainfo.play.gain = ao->gain;
+
+ if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
+ return -1;
+
+ return ao->fn;
+}
+
+
+
+
+static int get_formats_sun(audio_output_t *ao)
+{
+ static int tab[][3] = {
+ { AUDIO_ENCODING_ULAW , 8, MPG123_ENC_ULAW_8 } ,
+ { AUDIO_ENCODING_ALAW , 8, MPG123_ENC_ALAW_8 } ,
+ { AUDIO_ENCODING_LINEAR , 16, MPG123_ENC_SIGNED_16 } ,
+#if 0
+#if defined(SOLARIS) || defined(SPARCLINUX)
+ { AUDIO_ENCODING_LINEAR8 , 8, MPG123_ENC_UNSIGNED_8 } ,
+#endif
+#endif
+ };
+
+ audio_info_t ainfo;
+ int i,fmts=0;
+
+ for(i=0;i<sizeof(tab)/sizeof(tab[0]);i++) {
+ AUDIO_INITINFO(&ainfo);
+ ainfo.play.encoding = tab[i][0];
+ ainfo.play.precision = tab[i][1];
+#if 1
+ ainfo.play.sample_rate = ao->rate;
+ ainfo.play.channels = ao->channels;
+#endif
+ if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) >= 0) {
+ fmts |= tab[i][2];
+ }
+ }
+ return fmts;
+}
+
+static int write_sun(audio_output_t *ao,unsigned char *buf,int len)
+{
+ return write(ao->fn,buf,len);
+}
+
+static int close_sun(audio_output_t *ao)
+{
+ close (ao->fn);
+ return 0;
+}
+
+static void flush_sun(audio_output_t *ao)
+{
+ /*ioctl (ao->fn, I_FLUSH, FLUSHRW);*/
+}
+
+
+static int init_sun(audio_output_t* ao)
+{
+ if (ao==NULL) return -1;
+
+ /* Set callbacks */
+ ao->open = open_sun;
+ ao->flush = flush_sun;
+ ao->write = write_sun;
+ ao->get_formats = get_formats_sun;
+ ao->close = close_sun;
+
+ /* Success */
+ return 0;
+}
+
+
+
+
+
+/*
+ Module information data structure
+*/
+mpg123_module_t mpg123_output_module_info = {
+ /* api_version */ MPG123_MODULE_API_VERSION,
+ /* name */ "sun",
+ /* description */ "Audio output for Sun Audio.",
+ /* revision */ "$Rev: 1872 $",
+ /* handle */ NULL,
+
+ /* init_output */ init_sun,
+};
+
+