|
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 |
};
|