disk audio: Implemented "capture" support, cleaned up some things.
parent
a15b974044
commit
978df1ad74
|
@ -33,11 +33,6 @@
|
||||||
static SDL_AudioDriver current_audio;
|
static SDL_AudioDriver current_audio;
|
||||||
static SDL_AudioDevice *open_devices[16];
|
static SDL_AudioDevice *open_devices[16];
|
||||||
|
|
||||||
/* !!! FIXME: These are wordy and unlocalized... */
|
|
||||||
#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
|
|
||||||
#define DEFAULT_INPUT_DEVNAME "System audio capture device"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not all of these will be compiled and linked in, but it's convenient
|
* Not all of these will be compiled and linked in, but it's convenient
|
||||||
* to have a complete list here and saves yet-another block of #ifdefs...
|
* to have a complete list here and saves yet-another block of #ifdefs...
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
#include "SDL_mutex.h"
|
#include "SDL_mutex.h"
|
||||||
#include "SDL_thread.h"
|
#include "SDL_thread.h"
|
||||||
|
|
||||||
|
/* !!! FIXME: These are wordy and unlocalized... */
|
||||||
|
#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
|
||||||
|
#define DEFAULT_INPUT_DEVNAME "System audio capture device"
|
||||||
|
|
||||||
/* The SDL audio driver */
|
/* The SDL audio driver */
|
||||||
typedef struct SDL_AudioDevice SDL_AudioDevice;
|
typedef struct SDL_AudioDevice SDL_AudioDevice;
|
||||||
#define _THIS SDL_AudioDevice *_this
|
#define _THIS SDL_AudioDevice *_this
|
||||||
|
|
|
@ -34,42 +34,31 @@
|
||||||
#include "../SDL_audio_c.h"
|
#include "../SDL_audio_c.h"
|
||||||
#include "SDL_diskaudio.h"
|
#include "SDL_diskaudio.h"
|
||||||
|
|
||||||
|
/* !!! FIXME: these should be SDL hints, not environment variables. */
|
||||||
/* environment variables and defaults. */
|
/* environment variables and defaults. */
|
||||||
#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE"
|
#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE"
|
||||||
#define DISKDEFAULT_OUTFILE "sdlaudio.raw"
|
#define DISKDEFAULT_OUTFILE "sdlaudio.raw"
|
||||||
#define DISKENVR_WRITEDELAY "SDL_DISKAUDIODELAY"
|
#define DISKENVR_INFILE "SDL_DISKAUDIOFILEIN"
|
||||||
#define DISKDEFAULT_WRITEDELAY 150
|
#define DISKDEFAULT_INFILE "sdlaudio-in.raw"
|
||||||
|
#define DISKENVR_IODELAY "SDL_DISKAUDIODELAY"
|
||||||
static const char *
|
#define DISKDEFAULT_IODELAY 150
|
||||||
DISKAUD_GetOutputFilename(const char *devname)
|
|
||||||
{
|
|
||||||
if (devname == NULL) {
|
|
||||||
devname = SDL_getenv(DISKENVR_OUTFILE);
|
|
||||||
if (devname == NULL) {
|
|
||||||
devname = DISKDEFAULT_OUTFILE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return devname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function waits until it is possible to write a full sound buffer */
|
/* This function waits until it is possible to write a full sound buffer */
|
||||||
static void
|
static void
|
||||||
DISKAUD_WaitDevice(_THIS)
|
DISKAUD_WaitDevice(_THIS)
|
||||||
{
|
{
|
||||||
SDL_Delay(this->hidden->write_delay);
|
SDL_Delay(this->hidden->io_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DISKAUD_PlayDevice(_THIS)
|
DISKAUD_PlayDevice(_THIS)
|
||||||
{
|
{
|
||||||
size_t written;
|
const size_t written = SDL_RWwrite(this->hidden->io,
|
||||||
|
this->hidden->mixbuf,
|
||||||
/* Write the audio data */
|
1, this->spec.size);
|
||||||
written = SDL_RWwrite(this->hidden->output,
|
|
||||||
this->hidden->mixbuf, 1, this->hidden->mixlen);
|
|
||||||
|
|
||||||
/* If we couldn't write, assume fatal error for now */
|
/* If we couldn't write, assume fatal error for now */
|
||||||
if (written != this->hidden->mixlen) {
|
if (written != this->spec.size) {
|
||||||
SDL_OpenedAudioDeviceDisconnected(this);
|
SDL_OpenedAudioDeviceDisconnected(this);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_AUDIO
|
#ifdef DEBUG_AUDIO
|
||||||
|
@ -83,22 +72,66 @@ DISKAUD_GetDeviceBuf(_THIS)
|
||||||
return (this->hidden->mixbuf);
|
return (this->hidden->mixbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
DISKAUD_CaptureFromDevice(_THIS, void *buffer, int buflen)
|
||||||
|
{
|
||||||
|
struct SDL_PrivateAudioData *h = this->hidden;
|
||||||
|
const int origbuflen = buflen;
|
||||||
|
|
||||||
|
SDL_Delay(h->io_delay);
|
||||||
|
|
||||||
|
if (h->io) {
|
||||||
|
const size_t br = SDL_RWread(h->io, buffer, 1, buflen);
|
||||||
|
buflen -= (int) br;
|
||||||
|
buffer = ((Uint8 *) buffer) + br;
|
||||||
|
if (buflen > 0) { /* EOF (or error, but whatever). */
|
||||||
|
SDL_RWclose(h->io);
|
||||||
|
h->io = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we ran out of file, just write silence. */
|
||||||
|
SDL_memset(buffer, this->spec.silence, buflen);
|
||||||
|
|
||||||
|
return origbuflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DISKAUD_FlushCapture(_THIS)
|
||||||
|
{
|
||||||
|
/* no op...we don't advance the file pointer or anything. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DISKAUD_CloseDevice(_THIS)
|
DISKAUD_CloseDevice(_THIS)
|
||||||
{
|
{
|
||||||
if (this->hidden->output != NULL) {
|
if (this->hidden->io != NULL) {
|
||||||
SDL_RWclose(this->hidden->output);
|
SDL_RWclose(this->hidden->io);
|
||||||
}
|
}
|
||||||
SDL_free(this->hidden->mixbuf);
|
SDL_free(this->hidden->mixbuf);
|
||||||
SDL_free(this->hidden);
|
SDL_free(this->hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_filename(const int iscapture, const char *devname)
|
||||||
|
{
|
||||||
|
if (devname == NULL) {
|
||||||
|
devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE);
|
||||||
|
if (devname == NULL) {
|
||||||
|
devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return devname;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
{
|
{
|
||||||
/* handle != NULL means "user specified the placeholder name on the fake detected device list" */
|
/* handle != NULL means "user specified the placeholder name on the fake detected device list" */
|
||||||
const char *fname = DISKAUD_GetOutputFilename(handle ? NULL : devname);
|
const char *fname = get_filename(iscapture, handle ? NULL : devname);
|
||||||
const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
|
const char *envr = SDL_getenv(DISKENVR_IODELAY);
|
||||||
|
|
||||||
this->hidden = (struct SDL_PrivateAudioData *)
|
this->hidden = (struct SDL_PrivateAudioData *)
|
||||||
SDL_malloc(sizeof(*this->hidden));
|
SDL_malloc(sizeof(*this->hidden));
|
||||||
|
@ -107,27 +140,28 @@ DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
}
|
}
|
||||||
SDL_zerop(this->hidden);
|
SDL_zerop(this->hidden);
|
||||||
|
|
||||||
this->hidden->mixlen = this->spec.size;
|
this->hidden->io_delay = (envr) ? SDL_atoi(envr) : DISKDEFAULT_IODELAY;
|
||||||
this->hidden->write_delay =
|
|
||||||
(envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
|
|
||||||
|
|
||||||
/* Open the audio device */
|
/* Open the audio device */
|
||||||
this->hidden->output = SDL_RWFromFile(fname, "wb");
|
this->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
|
||||||
if (this->hidden->output == NULL) {
|
if (this->hidden->io == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate mixing buffer */
|
/* Allocate mixing buffer */
|
||||||
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
|
if (!iscapture) {
|
||||||
if (this->hidden->mixbuf == NULL) {
|
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
|
||||||
return -1;
|
if (this->hidden->mixbuf == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||||
}
|
}
|
||||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
|
||||||
|
|
||||||
#if HAVE_STDIO_H
|
#if HAVE_STDIO_H
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"WARNING: You are using the SDL disk writer audio driver!\n"
|
"WARNING: You are using the SDL disk i/o audio driver!\n"
|
||||||
" Writing to file [%s].\n", fname);
|
" %s file [%s].\n", iscapture ? "Reading from" : "Writing to",
|
||||||
|
fname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We're ready to rock and roll. :-) */
|
/* We're ready to rock and roll. :-) */
|
||||||
|
@ -137,8 +171,8 @@ DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
static void
|
static void
|
||||||
DISKAUD_DetectDevices(void)
|
DISKAUD_DetectDevices(void)
|
||||||
{
|
{
|
||||||
/* !!! FIXME: stole this literal string from DEFAULT_OUTPUT_DEVNAME in SDL_audio.c */
|
SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) 0x1);
|
||||||
SDL_AddAudioDevice(SDL_FALSE, "System audio output device", (void *) 0x1);
|
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) 0x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -149,10 +183,14 @@ DISKAUD_Init(SDL_AudioDriverImpl * impl)
|
||||||
impl->WaitDevice = DISKAUD_WaitDevice;
|
impl->WaitDevice = DISKAUD_WaitDevice;
|
||||||
impl->PlayDevice = DISKAUD_PlayDevice;
|
impl->PlayDevice = DISKAUD_PlayDevice;
|
||||||
impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
|
impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
|
||||||
|
impl->CaptureFromDevice = DISKAUD_CaptureFromDevice;
|
||||||
|
impl->FlushCapture = DISKAUD_FlushCapture;
|
||||||
|
|
||||||
impl->CloseDevice = DISKAUD_CloseDevice;
|
impl->CloseDevice = DISKAUD_CloseDevice;
|
||||||
impl->DetectDevices = DISKAUD_DetectDevices;
|
impl->DetectDevices = DISKAUD_DetectDevices;
|
||||||
|
|
||||||
impl->AllowsArbitraryDeviceNames = 1;
|
impl->AllowsArbitraryDeviceNames = 1;
|
||||||
|
impl->HasCaptureSupport = SDL_TRUE;
|
||||||
|
|
||||||
return 1; /* this audio target is available. */
|
return 1; /* this audio target is available. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,9 @@
|
||||||
struct SDL_PrivateAudioData
|
struct SDL_PrivateAudioData
|
||||||
{
|
{
|
||||||
/* The file descriptor for the audio device */
|
/* The file descriptor for the audio device */
|
||||||
SDL_RWops *output;
|
SDL_RWops *io;
|
||||||
|
Uint32 io_delay;
|
||||||
Uint8 *mixbuf;
|
Uint8 *mixbuf;
|
||||||
Uint32 mixlen;
|
|
||||||
Uint32 write_delay;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _SDL_diskaudio_h */
|
#endif /* _SDL_diskaudio_h */
|
||||||
|
|
Loading…
Reference in New Issue