|
|
|
|
@ -10,71 +10,39 @@ |
|
|
|
|
* 16 bit mono output. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H |
|
|
|
|
#include "config.h" |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#include <unistd.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#include <sys/ioctl.h> |
|
|
|
|
#include <sys/audio.h> |
|
|
|
|
#include <fcntl.h> |
|
|
|
|
|
|
|
|
|
#include "common.h" |
|
|
|
|
#include "driver.h" |
|
|
|
|
#include "mixer.h" |
|
|
|
|
#include "sound.h" |
|
|
|
|
|
|
|
|
|
static int audio_fd; |
|
|
|
|
|
|
|
|
|
static int init(struct context_data *); |
|
|
|
|
static int setaudio(struct xmp_options *); |
|
|
|
|
static void bufdump(struct context_data *, void *, int); |
|
|
|
|
static void shutdown(struct context_data *); |
|
|
|
|
|
|
|
|
|
static void dummy() |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Standard sampling rates */ |
|
|
|
|
static int srate[] = { |
|
|
|
|
44100, 32000, 22050, 16000, 11025, 8000, 0 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static char *help[] = { |
|
|
|
|
"gain=val", "Audio output gain (0 to 255)", |
|
|
|
|
"port={s|h|l}", "Audio port (s[peaker], h[eadphones], l[ineout])", |
|
|
|
|
"buffer=val", "Audio buffer size", |
|
|
|
|
NULL |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct sound_driver sound_hpux = { |
|
|
|
|
"hpux", /* driver ID */ |
|
|
|
|
"HP-UX PCM audio", /* driver description */ |
|
|
|
|
help, /* help */ |
|
|
|
|
init, /* init */ |
|
|
|
|
shutdown, /* shutdown */ |
|
|
|
|
dummy, /* starttimer */ |
|
|
|
|
dummy, /* flush */ |
|
|
|
|
bufdump, /* bufdump */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int setaudio(struct xmp_options *o) |
|
|
|
|
static int init(struct options *options) |
|
|
|
|
{ |
|
|
|
|
char **parm = options->driver_parm; |
|
|
|
|
int flags; |
|
|
|
|
int gain = 128; |
|
|
|
|
int bsize = 32 * 1024; |
|
|
|
|
int port = AUDIO_OUT_SPEAKER; |
|
|
|
|
int nch = options->format & XMP_FORMAT_MONO ? 1 : 2; |
|
|
|
|
struct audio_gains agains; |
|
|
|
|
struct audio_describe adescribe; |
|
|
|
|
char *token, **parm; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
parm_init(); |
|
|
|
|
parm_init(parm); |
|
|
|
|
chkparm1("gain", gain = strtoul(token, NULL, 0)); |
|
|
|
|
chkparm1("buffer", bsize = strtoul(token, NULL, 0)); |
|
|
|
|
chkparm1("port", port = (int)*token) |
|
|
|
|
parm_end(); |
|
|
|
|
parm_end(); |
|
|
|
|
|
|
|
|
|
switch (port) { |
|
|
|
|
case 'h': |
|
|
|
|
@ -87,65 +55,63 @@ static int setaudio(struct xmp_options *o) |
|
|
|
|
port = AUDIO_OUT_SPEAKER; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((audio_fd = open("/dev/audio", O_WRONLY)) == -1) |
|
|
|
|
goto err; |
|
|
|
|
|
|
|
|
|
if ((flags = fcntl(audio_fd, F_GETFL, 0)) < 0) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
goto err1; |
|
|
|
|
|
|
|
|
|
flags |= O_NDELAY; |
|
|
|
|
if ((flags = fcntl(audio_fd, F_SETFL, flags)) < 0) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
goto err1; |
|
|
|
|
|
|
|
|
|
if (ioctl(audio_fd, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT) == |
|
|
|
|
-1) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
options->format &= ~XMP_FORMAT_8BIT; |
|
|
|
|
if (ioctl(audio_fd, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT) == -1) |
|
|
|
|
goto err1; |
|
|
|
|
|
|
|
|
|
if (ioctl(audio_fd, AUDIO_SET_CHANNELS, |
|
|
|
|
o->outfmt & XMP_FORMAT_MONO ? 1 : 2) == -1) { |
|
|
|
|
o->outfmt ^= XMP_FORMAT_MONO; |
|
|
|
|
if (ioctl(audio_fd, AUDIO_SET_CHANNELS, nch) == -1) { |
|
|
|
|
options->format ^= XMP_FORMAT_MONO; |
|
|
|
|
nch = options->format & XMP_FORMAT_MONO ? 1 : 2; |
|
|
|
|
|
|
|
|
|
if (ioctl(audio_fd, AUDIO_SET_CHANNELS, |
|
|
|
|
o->outfmt & XMP_FORMAT_MONO ? 1 : 2) == -1) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
if (ioctl(audio_fd, AUDIO_SET_CHANNELS, nch) == -1) { |
|
|
|
|
goto err1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ioctl(audio_fd, AUDIO_SET_OUTPUT, port); |
|
|
|
|
|
|
|
|
|
for (i = 0; ioctl(audio_fd, AUDIO_SET_SAMPLE_RATE, o->freq) == -1; i++) |
|
|
|
|
if ((o->freq = srate[i]) == 0) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
for (i = 0; ; i++) { |
|
|
|
|
if (ioctl(audio_fd, AUDIO_SET_SAMPLE_RATE, options->rate) == 0) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
if ((options->rate = srate[i]) == 0) |
|
|
|
|
goto err1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ioctl(audio_fd, AUDIO_DESCRIBE, &adescribe) == -1) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
goto err1; |
|
|
|
|
|
|
|
|
|
if (ioctl(audio_fd, AUDIO_GET_GAINS, &agains) == -1) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
goto err1; |
|
|
|
|
|
|
|
|
|
agains.transmit_gain = adescribe.min_transmit_gain + |
|
|
|
|
(adescribe.max_transmit_gain - adescribe.min_transmit_gain) * |
|
|
|
|
gain / 256; |
|
|
|
|
|
|
|
|
|
if (ioctl(audio_fd, AUDIO_SET_GAINS, &agains) == -1) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
goto err1; |
|
|
|
|
|
|
|
|
|
ioctl(audio_fd, AUDIO_SET_TXBUFSIZE, bsize); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int init(struct context_data *ctx) |
|
|
|
|
{ |
|
|
|
|
if ((audio_fd = open("/dev/audio", O_WRONLY)) == -1) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
|
|
|
|
|
if (setaudio(ctl) != 0) |
|
|
|
|
return XMP_ERR_DINIT; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
err1: |
|
|
|
|
close(audio_fd); |
|
|
|
|
err: |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
|
|
|
|
|
* timed mods) of audio data to the output device. |
|
|
|
|
*/ |
|
|
|
|
static void bufdump(struct context_data *ctx, void *b, int i) |
|
|
|
|
static void play(void *b, int i) |
|
|
|
|
{ |
|
|
|
|
int j; |
|
|
|
|
|
|
|
|
|
@ -158,7 +124,39 @@ static void bufdump(struct context_data *ctx, void *b, int i) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void shutdown(struct context_data *ctx) |
|
|
|
|
static void deinit() |
|
|
|
|
{ |
|
|
|
|
close(audio_fd); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void flush() |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void onpause() |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void onresume() |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *help[] = { |
|
|
|
|
"gain=val", "Audio output gain (0 to 255)", |
|
|
|
|
"port={s|h|l}", "Audio port (s[peaker], h[eadphones], l[ineout])", |
|
|
|
|
"buffer=val", "Audio buffer size", |
|
|
|
|
NULL |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct sound_driver sound_hpux = { |
|
|
|
|
"hpux", |
|
|
|
|
"HP-UX PCM audio", |
|
|
|
|
help, |
|
|
|
|
init, |
|
|
|
|
deinit, |
|
|
|
|
play, |
|
|
|
|
flush, |
|
|
|
|
onpause, |
|
|
|
|
onresume |
|
|
|
|
}; |