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