|
Packit |
c32a2d |
/*
|
|
Packit |
c32a2d |
mint: audio output for MINT
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
copyright ?-2006 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 by Petr Stehlik
|
|
Packit |
c32a2d |
*/
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
#include "out123_int.h"
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/* derived from LINUX, VOXWARE and SUN for MiNT Audio Device by Petr Stehlik */
|
|
Packit |
c32a2d |
#include <fcntl.h>
|
|
Packit |
c32a2d |
#include <ioctl.h>
|
|
Packit |
c32a2d |
#include <audios.h>
|
|
Packit |
c32a2d |
#include "debug.h"
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/* Globals */
|
|
Packit |
c32a2d |
extern int outburst;
|
|
Packit |
c32a2d |
int real_rate_printed = 0;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int rate_best_match(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
int ret,dsp_rate;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
if(!ai || ao->fn < 0 || ao->rate < 0)
|
|
Packit |
c32a2d |
return -1;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
dsp_rate = ao->rate;
|
|
Packit |
c32a2d |
ret = ioctl(ao->fn,AIOCSSPEED, (void *)dsp_rate);
|
|
Packit |
c32a2d |
ret = ioctl(ao->fn,AIOCGSPEED,&dsp_rate);
|
|
Packit |
c32a2d |
if(ret < 0) return ret;
|
|
Packit |
c32a2d |
ao->rate = dsp_rate;
|
|
Packit |
c32a2d |
return 0;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int set_rate(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
int dsp_rate = ao->rate;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
if(ao->rate >= 0) {
|
|
Packit |
c32a2d |
int ret, real_rate;
|
|
Packit |
c32a2d |
ret = ioctl(ao->fn, AIOCSSPEED, (void *)dsp_rate);
|
|
Packit |
c32a2d |
if (ret >= 0 && !real_rate_printed) {
|
|
Packit |
c32a2d |
ioctl(ao->fn,AIOCGSPEED,&real_rate);
|
|
Packit |
c32a2d |
if (real_rate != dsp_rate) {
|
|
Packit |
c32a2d |
fprintf(stderr, "Replay rate: %d Hz\n", real_rate);
|
|
Packit |
c32a2d |
real_rate_printed = 1;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
return ret;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
return 0;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int set_channels(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
int chan = ao->channels;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
if(ao->channels < 1) return 0;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
return ioctl(ao->fn, AIOCSCHAN, (void *)chan);
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int set_format(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
int fmts;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
if(ao->format == -1)
|
|
Packit |
c32a2d |
return 0;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
switch(ao->format) {
|
|
Packit |
c32a2d |
case MPG123_ENC_SIGNED_16:
|
|
Packit |
c32a2d |
default:
|
|
Packit |
c32a2d |
fmts = AFMT_S16;
|
|
Packit |
c32a2d |
break;
|
|
Packit |
c32a2d |
case MPG123_ENC_UNSIGNED_8:
|
|
Packit |
c32a2d |
fmts = AFMT_U8;
|
|
Packit |
c32a2d |
break;
|
|
Packit |
c32a2d |
case MPG123_ENC_SIGNED_8:
|
|
Packit |
c32a2d |
fmts = AFMT_S8;
|
|
Packit |
c32a2d |
break;
|
|
Packit |
c32a2d |
case MPG123_ENC_ULAW_8:
|
|
Packit |
c32a2d |
fmts = AFMT_ULAW;
|
|
Packit |
c32a2d |
break;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
return ioctl(ao->fn, AIOCSFMT, (void *)fmts);
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int reset_parameters(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
int ret;
|
|
Packit |
c32a2d |
ret = ioctl(ao->fn,AIOCRESET,NULL);
|
|
Packit |
c32a2d |
if(ret >= 0) ret = set_format(ai);
|
|
Packit |
c32a2d |
if(ret >= 0) ret = set_channels(ai);
|
|
Packit |
c32a2d |
if(ret >= 0) ret = set_rate(ai);
|
|
Packit |
c32a2d |
return ret;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int open_mint(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
const char *dev = ao->device;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
if(!ai) return -1;
|
|
Packit |
c32a2d |
if(!dev)
|
|
Packit |
c32a2d |
dev = "/dev/audio";
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
ao->fn = open(dev,O_WRONLY);
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
if(ao->fn < 0)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
error1("Can't open %s!",dev);
|
|
Packit |
c32a2d |
return -1;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
ioctl(ao->fn, AIOCGBLKSIZE, &outburst);
|
|
Packit |
c32a2d |
if(outburst > MAXOUTBURST)
|
|
Packit |
c32a2d |
outburst = MAXOUTBURST;
|
|
Packit |
c32a2d |
if(audio_reset_parameters(ai) < 0) {
|
|
Packit |
c32a2d |
close(ao->fn);
|
|
Packit |
c32a2d |
return -1;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
return ao->fn;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int get_formats_mint(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
int ret = 0;
|
|
Packit |
c32a2d |
int fmts;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
if(ioctl(ao->fn,AIOCGFMTS,&fmts) < 0)
|
|
Packit |
c32a2d |
return -1;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
if(fmts & AFMT_ULAW)
|
|
Packit |
c32a2d |
ret |= MPG123_ENC_ULAW_8;
|
|
Packit |
c32a2d |
if(fmts & AFMT_S16)
|
|
Packit |
c32a2d |
ret |= MPG123_ENC_SIGNED_16;
|
|
Packit |
c32a2d |
if(fmts & AFMT_U8)
|
|
Packit |
c32a2d |
ret |= MPG123_ENC_UNSIGNED_8;
|
|
Packit |
c32a2d |
if(fmts & AFMT_S8)
|
|
Packit |
c32a2d |
ret |= MPG123_ENC_SIGNED_8;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
return ret;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int write_mint(out123_handle *ao,unsigned char *buf,int len)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
return write(ao->fn,buf,len);
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int close_mint(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
close (ao->fn);
|
|
Packit |
c32a2d |
return 0;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static void flush_mint(out123_handle *ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
static int init_mint(out123_handle* ao)
|
|
Packit |
c32a2d |
{
|
|
Packit |
c32a2d |
if (ao==NULL) return -1;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/* Set callbacks */
|
|
Packit |
c32a2d |
ao->open = open_mint;
|
|
Packit |
c32a2d |
ao->flush = flush_mint;
|
|
Packit |
c32a2d |
ao->write = write_mint;
|
|
Packit |
c32a2d |
ao->get_formats = get_formats_mint;
|
|
Packit |
c32a2d |
ao->close = close_mint;
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/* Success */
|
|
Packit |
c32a2d |
return 0;
|
|
Packit |
c32a2d |
}
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|
|
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 */ "mint",
|
|
Packit |
c32a2d |
/* description */ "Audio output for MINT.",
|
|
Packit |
c32a2d |
/* revision */ "$Rev:$",
|
|
Packit |
c32a2d |
/* handle */ NULL,
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
/* init_output */ init_mint,
|
|
Packit |
c32a2d |
};
|
|
Packit |
c32a2d |
|
|
Packit |
c32a2d |
|