Blame src/libout123/modules/sgi.c

Packit c32a2d
/*
Packit c32a2d
	sgi: audio output on SGI boxen
Packit c32a2d
Packit c32a2d
	copyright ?-2013 by the mpg123 project - free software under the terms of the LGPL 2.1
Packit c32a2d
	see COPYING and AUTHORS files in distribution or http://mpg123.org
Packit c32a2d
	initially written (as it seems) by Thomas Woerner
Packit c32a2d
*/
Packit c32a2d
Packit c32a2d
#include "out123_int.h"
Packit c32a2d
#include <fcntl.h>
Packit c32a2d
#include <dmedia/audio.h>
Packit c32a2d
#include "errno.h"
Packit c32a2d
#include "debug.h"
Packit c32a2d
Packit c32a2d
static int set_rate(out123_handle *ao, ALconfig config)
Packit c32a2d
{
Packit c32a2d
	int dev = alGetDevice(config);
Packit c32a2d
	ALpv params[1];
Packit c32a2d
Packit c32a2d
	/* Make sure the device is OK */
Packit c32a2d
	if(dev < 0)
Packit c32a2d
	{
Packit c32a2d
		error1("set_rate: %s", alGetErrorString(oserror()));
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
	if(ao->rate > 0)
Packit c32a2d
	{
Packit c32a2d
		params[0].param = AL_RATE;
Packit c32a2d
		params[0].value.ll = alDoubleToFixed((double)ao->rate);
Packit c32a2d
		if(alSetParams(dev, params, 1) < 0)
Packit c32a2d
		{
Packit c32a2d
			error1("set_rate: %s", alGetErrorString(oserror()));
Packit c32a2d
			return -1;
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static int set_channels(out123_handle *ao, ALconfig config)
Packit c32a2d
{
Packit c32a2d
	int ret;
Packit c32a2d
Packit c32a2d
	if(ao->channels == 2)
Packit c32a2d
	ret = alSetChannels(config, AL_STEREO);
Packit c32a2d
	else
Packit c32a2d
	ret = alSetChannels(config, AL_MONO);
Packit c32a2d
Packit c32a2d
	if(ret < 0)
Packit c32a2d
	{
Packit c32a2d
		error1("set_channels : %s", alGetErrorString(oserror()));
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int set_format(out123_handle *ao, ALconfig config)
Packit c32a2d
{
Packit c32a2d
	if(ao->format == MPG123_ENC_FLOAT_32)
Packit c32a2d
	{
Packit c32a2d
		if(alSetSampFmt(config, AL_SAMPFMT_FLOAT) < 0)
Packit c32a2d
		{
Packit c32a2d
			error1("SetSampFmt: %s", alGetErrorString(oserror()));
Packit c32a2d
			return -1;
Packit c32a2d
		}
Packit c32a2d
	} else
Packit c32a2d
	{
Packit c32a2d
		if(alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) < 0)
Packit c32a2d
		{
Packit c32a2d
			error1("SetSampFmt: %s", alGetErrorString(oserror()));
Packit c32a2d
			return -1;
Packit c32a2d
		}
Packit c32a2d
		if(alSetWidth(config, AL_SAMPLE_16) < 0)
Packit c32a2d
		{
Packit c32a2d
			error1("SetWidth: %s", alGetErrorString(oserror()));
Packit c32a2d
			return -1;
Packit c32a2d
		}
Packit c32a2d
	}
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static int open_sgi(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	int current_dev;
Packit c32a2d
	ALport port = NULL;
Packit c32a2d
	ALconfig config = alNewConfig();
Packit c32a2d
Packit c32a2d
	ao->userptr = NULL;
Packit c32a2d
Packit c32a2d
	/* Test for correct completion */
Packit c32a2d
	if(config == 0)
Packit c32a2d
	{
Packit c32a2d
		error1("open_sgi: %s", alGetErrorString(oserror()));
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Setup output device to specified device name. If there is no device name
Packit c32a2d
	specified in ao structure, use the default for output */
Packit c32a2d
	if((ao->device) != NULL)
Packit c32a2d
	{
Packit c32a2d
		current_dev = alGetResourceByName(AL_SYSTEM, ao->device, AL_OUTPUT_DEVICE_TYPE);
Packit c32a2d
Packit c32a2d
		debug2("Dev: %s %i", ao->device, current_dev);
Packit c32a2d
Packit c32a2d
		if(!current_dev)
Packit c32a2d
		{
Packit c32a2d
			int i, numOut;
Packit c32a2d
			char devname[32];
Packit c32a2d
			ALpv pv[1];
Packit c32a2d
			ALvalue *alvalues;
Packit c32a2d
Packit c32a2d
			error2("Invalid audio resource: %s (%s)", ao->device, alGetErrorString(oserror()));
Packit c32a2d
Packit c32a2d
			if((numOut= alQueryValues(AL_SYSTEM,AL_DEFAULT_OUTPUT,0,0,0,0))>=0)
Packit c32a2d
			fprintf(stderr, "There are %d output devices on this system.\n", numOut);
Packit c32a2d
			else
Packit c32a2d
			{
Packit c32a2d
				fprintf(stderr, "Can't find output devices. alQueryValues failed: %s\n", alGetErrorString(oserror()));
Packit c32a2d
				goto open_sgi_bad;
Packit c32a2d
			}
Packit c32a2d
Packit c32a2d
			alvalues = malloc(sizeof(ALvalue) * numOut);
Packit c32a2d
			i = alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, alvalues, numOut, pv, 0);
Packit c32a2d
			if(i == -1)
Packit c32a2d
			error1("alQueryValues: %s", alGetErrorString(oserror()));
Packit c32a2d
			else
Packit c32a2d
			{
Packit c32a2d
				for(i=0; i < numOut; i++)
Packit c32a2d
				{
Packit c32a2d
					pv[0].param = AL_NAME;
Packit c32a2d
					pv[0].value.ptr = devname;
Packit c32a2d
					pv[0].sizeIn = 32;
Packit c32a2d
					alGetParams(alvalues[i].i, pv, 1);
Packit c32a2d
Packit c32a2d
					fprintf(stderr, "%i: %s\n", i, devname);
Packit c32a2d
				}
Packit c32a2d
			}
Packit c32a2d
			free(alvalues);
Packit c32a2d
Packit c32a2d
			goto open_sgi_bad;
Packit c32a2d
		}
Packit c32a2d
Packit c32a2d
		if(alSetDevice(config, current_dev) < 0)
Packit c32a2d
		{
Packit c32a2d
			error1("open: alSetDevice : %s",alGetErrorString(oserror()));
Packit c32a2d
			goto open_sgi_bad;
Packit c32a2d
		}
Packit c32a2d
	} else
Packit c32a2d
	current_dev = AL_DEFAULT_OUTPUT;
Packit c32a2d
Packit c32a2d
	/* Set the device */
Packit c32a2d
	if(alSetDevice(config, current_dev) < 0)
Packit c32a2d
	{
Packit c32a2d
		error1("open_sgi: %s", alGetErrorString(oserror()));
Packit c32a2d
		goto open_sgi_bad;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	/* Set port parameters */
Packit c32a2d
Packit c32a2d
	if(alSetQueueSize(config, 131069) < 0)
Packit c32a2d
	{
Packit c32a2d
		error1("open_sgi: setting audio buffer failed: %s", alGetErrorString(oserror()));
Packit c32a2d
		goto open_sgi_bad;
Packit c32a2d
	}
Packit c32a2d
	
Packit c32a2d
	if(   set_format(ao, config) < 0
Packit c32a2d
	   || set_rate(ao, config) < 0
Packit c32a2d
	   || set_channels(ao, config) < 0 )
Packit c32a2d
	goto open_sgi_bad;
Packit c32a2d
	
Packit c32a2d
	/* Open the audio port */
Packit c32a2d
	port = alOpenPort("mpg123-VSC", "w", config);
Packit c32a2d
	if(port == NULL)
Packit c32a2d
	{
Packit c32a2d
		error1("Unable to open audio channel: %s", alGetErrorString(oserror()));
Packit c32a2d
		goto open_sgi_bad;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	ao->userptr = (void*)port;
Packit c32a2d
Packit c32a2d
	alFreeConfig(config);
Packit c32a2d
	return 1;
Packit c32a2d
Packit c32a2d
open_sgi_bad:
Packit c32a2d
	/* clean up and return error */
Packit c32a2d
	alFreeConfig(config);
Packit c32a2d
	return -1;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static int get_formats_sgi(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	return MPG123_ENC_SIGNED_16|MPG123_ENC_FLOAT_32;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static int write_sgi(out123_handle *ao, unsigned char *buf, int len)
Packit c32a2d
{
Packit c32a2d
	int length = len;
Packit c32a2d
Packit c32a2d
	if(!ao || !ao->userptr) return -1;
Packit c32a2d
Packit c32a2d
	ALport port = (ALport)ao->userptr;
Packit c32a2d
Packit c32a2d
	if(ao->channels == 2) length >>= 2;
Packit c32a2d
	else length >>= 1;
Packit c32a2d
Packit c32a2d
	if(ao->format == MPG123_ENC_FLOAT_32) length >>=1;
Packit c32a2d
Packit c32a2d
	/* Not much error checking ... */
Packit c32a2d
	alWriteFrames(port, buf, length);
Packit c32a2d
Packit c32a2d
	return len;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
Packit c32a2d
static int close_sgi(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	if(!ao || !ao->userptr) return -1;
Packit c32a2d
Packit c32a2d
	ALport port = (ALport)ao->userptr;
Packit c32a2d
Packit c32a2d
	if(port)
Packit c32a2d
	{
Packit c32a2d
		/* play all remaining samples */
Packit c32a2d
		while(alGetFilled(port) > 0) sginap(1);
Packit c32a2d
Packit c32a2d
		alClosePort(port);
Packit c32a2d
		ao->userptr=NULL;
Packit c32a2d
	}
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void flush_sgi(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	ALport port = (ALport)ao->userptr;
Packit c32a2d
Packit c32a2d
	if(port) alDiscardFrames(port, alGetFilled(port));
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int init_sgi(out123_handle* ao)
Packit c32a2d
{
Packit c32a2d
	if(ao == NULL) return -1;
Packit c32a2d
Packit c32a2d
	/* Set callbacks */
Packit c32a2d
	ao->open = open_sgi;
Packit c32a2d
	ao->flush = flush_sgi;
Packit c32a2d
	ao->write = write_sgi;
Packit c32a2d
	ao->get_formats = get_formats_sgi;
Packit c32a2d
	ao->close = close_sgi;
Packit c32a2d
Packit c32a2d
	/* Success */
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/*
Packit c32a2d
	Module information data structure
Packit c32a2d
*/
Packit c32a2d
mpg123_module_t mpg123_output_module_info =
Packit c32a2d
{
Packit c32a2d
	/* api_version */	MPG123_MODULE_API_VERSION,
Packit c32a2d
	/* name */			"sgi",
Packit c32a2d
	/* description */	"Audio output for SGI.",
Packit c32a2d
	/* revision */		"$Rev:$",
Packit c32a2d
	/* handle */		NULL,
Packit c32a2d
Packit c32a2d
	/* init_output */	init_sgi,
Packit c32a2d
};