Blame src/libout123/modules/sndio.c

Packit c32a2d
/*
Packit c32a2d
 *	sndio: sndio audio output
Packit c32a2d
 *
Packit c32a2d
 * Copyright (c) 2008 Christian Weisgerber <naddy@openbsd.org>,
Packit c32a2d
 *                    Alexandre Ratchov <alex@caoua.org>
Packit c32a2d
 *
Packit c32a2d
 * Permission to use, copy, modify, and distribute this software for any
Packit c32a2d
 * purpose with or without fee is hereby granted, provided that the above
Packit c32a2d
 * copyright notice and this permission notice appear in all copies.
Packit c32a2d
 *
Packit c32a2d
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
Packit c32a2d
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
Packit c32a2d
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Packit c32a2d
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Packit c32a2d
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
Packit c32a2d
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Packit c32a2d
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Packit c32a2d
 */
Packit c32a2d
Packit c32a2d
#include "out123_int.h"
Packit c32a2d
Packit c32a2d
#include <sndio.h>
Packit c32a2d
Packit c32a2d
#include "debug.h"
Packit c32a2d
Packit c32a2d
static int open_sndio(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	struct sio_hdl *hdl;
Packit c32a2d
	struct sio_par par;
Packit c32a2d
Packit c32a2d
	hdl = sio_open(ao->device /* NULL is fine */, SIO_PLAY, 0);
Packit c32a2d
	if (hdl == NULL)
Packit c32a2d
		return -1;
Packit c32a2d
Packit c32a2d
	sio_initpar(&par);
Packit c32a2d
	par.rate = ao->rate;
Packit c32a2d
	par.pchan = ao->channels;
Packit c32a2d
	par.le = SIO_LE_NATIVE;
Packit c32a2d
	switch(ao->format) {
Packit c32a2d
	case MPG123_ENC_SIGNED_32:
Packit c32a2d
		par.sig = 1;
Packit c32a2d
		par.bits = 32;
Packit c32a2d
		break;
Packit c32a2d
	case MPG123_ENC_UNSIGNED_32:
Packit c32a2d
		par.sig = 0;
Packit c32a2d
		par.bits = 32;
Packit c32a2d
		break;
Packit c32a2d
	case MPG123_ENC_SIGNED_16:
Packit c32a2d
	case -1: /* query mode */
Packit c32a2d
		par.sig = 1;
Packit c32a2d
		par.bits = 16;
Packit c32a2d
		break;
Packit c32a2d
	case MPG123_ENC_UNSIGNED_16:
Packit c32a2d
		par.sig = 0;
Packit c32a2d
		par.bits = 16;
Packit c32a2d
		break;
Packit c32a2d
	case MPG123_ENC_UNSIGNED_8:
Packit c32a2d
		par.sig = 0;
Packit c32a2d
		par.bits = 8;
Packit c32a2d
		break;
Packit c32a2d
	case MPG123_ENC_SIGNED_8:
Packit c32a2d
		par.sig = 1;
Packit c32a2d
		par.bits = 8;
Packit c32a2d
		break;
Packit c32a2d
	default:
Packit c32a2d
		if (!AOQUIET)
Packit c32a2d
			error1("open_sndio: invalid sample format %d",
Packit c32a2d
			    ao->format);
Packit c32a2d
		sio_close(hdl);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
Packit c32a2d
	if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par) || 
Packit c32a2d
	    !sio_start(hdl)) {
Packit c32a2d
		sio_close(hdl);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
	if ((par.bits != 8 && par.bits != 16 && par.bits != 32) ||
Packit c32a2d
	    par.le != SIO_LE_NATIVE) {
Packit c32a2d
		sio_close(hdl);
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
	ao->rate = par.rate;
Packit c32a2d
	ao->channels = par.pchan;
Packit c32a2d
	switch (par.bits) {
Packit c32a2d
	case 8:
Packit c32a2d
		ao->format = par.sig ? MPG123_ENC_SIGNED_8 :
Packit c32a2d
		    MPG123_ENC_UNSIGNED_8;
Packit c32a2d
		break;
Packit c32a2d
	case 16:
Packit c32a2d
		ao->format = par.sig ? MPG123_ENC_SIGNED_16 :
Packit c32a2d
		    MPG123_ENC_UNSIGNED_16;
Packit c32a2d
		break;
Packit c32a2d
	case 32:
Packit c32a2d
		ao->format = par.sig ? MPG123_ENC_SIGNED_32 :
Packit c32a2d
		    MPG123_ENC_UNSIGNED_32;
Packit c32a2d
		break;
Packit c32a2d
	}
Packit c32a2d
	ao->userptr = hdl;
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int get_formats_sndio(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	return (MPG123_ENC_SIGNED_32|MPG123_ENC_UNSIGNED_32|
Packit c32a2d
	    MPG123_ENC_SIGNED_16|MPG123_ENC_UNSIGNED_16|
Packit c32a2d
	    MPG123_ENC_UNSIGNED_8|MPG123_ENC_SIGNED_8);
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int write_sndio(out123_handle *ao, unsigned char *buf, int len)
Packit c32a2d
{
Packit c32a2d
	struct sio_hdl *hdl = (struct sio_hdl *)ao->userptr;
Packit c32a2d
	int count;
Packit c32a2d
Packit c32a2d
	count = (int)sio_write(hdl, buf, len);
Packit c32a2d
	if (count == 0 && sio_eof(hdl))
Packit c32a2d
		return -1;
Packit c32a2d
	return count;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static void flush_sndio(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	return;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int close_sndio(out123_handle *ao)
Packit c32a2d
{
Packit c32a2d
	struct sio_hdl *hdl = (struct sio_hdl *)ao->userptr;
Packit c32a2d
Packit c32a2d
	sio_close(hdl);
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
static int init_sndio(out123_handle* ao)
Packit c32a2d
{
Packit c32a2d
	if (ao == NULL)
Packit c32a2d
		return -1;
Packit c32a2d
	
Packit c32a2d
	/* Set callbacks */
Packit c32a2d
	ao->open = open_sndio;
Packit c32a2d
	ao->flush = flush_sndio;	/* required */
Packit c32a2d
	ao->write = write_sndio;
Packit c32a2d
	ao->get_formats = get_formats_sndio;
Packit c32a2d
	ao->close = close_sndio;
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
	/* api_version */	MPG123_MODULE_API_VERSION,
Packit c32a2d
	/* name */		"sndio",						
Packit c32a2d
	/* description */	"Output audio using sndio library",
Packit c32a2d
	/* revision */		"$Rev:$",						
Packit c32a2d
	/* handle */		NULL,
Packit c32a2d
	
Packit c32a2d
	/* init_output */	init_sndio,						
Packit c32a2d
};