disk audio: Implemented "capture" support, cleaned up some things.
--- a/src/audio/SDL_audio.c Sat Aug 06 02:48:00 2016 -0400
+++ b/src/audio/SDL_audio.c Sat Aug 06 03:39:15 2016 -0400
@@ -33,11 +33,6 @@
static SDL_AudioDriver current_audio;
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
* to have a complete list here and saves yet-another block of #ifdefs...
--- a/src/audio/SDL_sysaudio.h Sat Aug 06 02:48:00 2016 -0400
+++ b/src/audio/SDL_sysaudio.h Sat Aug 06 03:39:15 2016 -0400
@@ -26,6 +26,10 @@
#include "SDL_mutex.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 */
typedef struct SDL_AudioDevice SDL_AudioDevice;
#define _THIS SDL_AudioDevice *_this
--- a/src/audio/disk/SDL_diskaudio.c Sat Aug 06 02:48:00 2016 -0400
+++ b/src/audio/disk/SDL_diskaudio.c Sat Aug 06 03:39:15 2016 -0400
@@ -34,42 +34,31 @@
#include "../SDL_audio_c.h"
#include "SDL_diskaudio.h"
+/* !!! FIXME: these should be SDL hints, not environment variables. */
/* environment variables and defaults. */
#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE"
#define DISKDEFAULT_OUTFILE "sdlaudio.raw"
-#define DISKENVR_WRITEDELAY "SDL_DISKAUDIODELAY"
-#define DISKDEFAULT_WRITEDELAY 150
-
-static const char *
-DISKAUD_GetOutputFilename(const char *devname)
-{
- if (devname == NULL) {
- devname = SDL_getenv(DISKENVR_OUTFILE);
- if (devname == NULL) {
- devname = DISKDEFAULT_OUTFILE;
- }
- }
- return devname;
-}
+#define DISKENVR_INFILE "SDL_DISKAUDIOFILEIN"
+#define DISKDEFAULT_INFILE "sdlaudio-in.raw"
+#define DISKENVR_IODELAY "SDL_DISKAUDIODELAY"
+#define DISKDEFAULT_IODELAY 150
/* This function waits until it is possible to write a full sound buffer */
static void
DISKAUD_WaitDevice(_THIS)
{
- SDL_Delay(this->hidden->write_delay);
+ SDL_Delay(this->hidden->io_delay);
}
static void
DISKAUD_PlayDevice(_THIS)
{
- size_t written;
-
- /* Write the audio data */
- written = SDL_RWwrite(this->hidden->output,
- this->hidden->mixbuf, 1, this->hidden->mixlen);
+ const size_t written = SDL_RWwrite(this->hidden->io,
+ this->hidden->mixbuf,
+ 1, this->spec.size);
/* If we couldn't write, assume fatal error for now */
- if (written != this->hidden->mixlen) {
+ if (written != this->spec.size) {
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
@@ -83,22 +72,66 @@
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
DISKAUD_CloseDevice(_THIS)
{
- if (this->hidden->output != NULL) {
- SDL_RWclose(this->hidden->output);
+ if (this->hidden->io != NULL) {
+ SDL_RWclose(this->hidden->io);
}
SDL_free(this->hidden->mixbuf);
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
DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
/* handle != NULL means "user specified the placeholder name on the fake detected device list" */
- const char *fname = DISKAUD_GetOutputFilename(handle ? NULL : devname);
- const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
+ const char *fname = get_filename(iscapture, handle ? NULL : devname);
+ const char *envr = SDL_getenv(DISKENVR_IODELAY);
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc(sizeof(*this->hidden));
@@ -107,27 +140,28 @@
}
SDL_zerop(this->hidden);
- this->hidden->mixlen = this->spec.size;
- this->hidden->write_delay =
- (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
+ this->hidden->io_delay = (envr) ? SDL_atoi(envr) : DISKDEFAULT_IODELAY;
/* Open the audio device */
- this->hidden->output = SDL_RWFromFile(fname, "wb");
- if (this->hidden->output == NULL) {
+ this->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
+ if (this->hidden->io == NULL) {
return -1;
}
/* Allocate mixing buffer */
- this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
- if (this->hidden->mixbuf == NULL) {
- return -1;
+ if (!iscapture) {
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
+ 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
fprintf(stderr,
- "WARNING: You are using the SDL disk writer audio driver!\n"
- " Writing to file [%s].\n", fname);
+ "WARNING: You are using the SDL disk i/o audio driver!\n"
+ " %s file [%s].\n", iscapture ? "Reading from" : "Writing to",
+ fname);
#endif
/* We're ready to rock and roll. :-) */
@@ -137,8 +171,8 @@
static void
DISKAUD_DetectDevices(void)
{
- /* !!! FIXME: stole this literal string from DEFAULT_OUTPUT_DEVNAME in SDL_audio.c */
- SDL_AddAudioDevice(SDL_FALSE, "System audio output device", (void *) 0x1);
+ SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) 0x1);
+ SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) 0x2);
}
static int
@@ -149,10 +183,14 @@
impl->WaitDevice = DISKAUD_WaitDevice;
impl->PlayDevice = DISKAUD_PlayDevice;
impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
+ impl->CaptureFromDevice = DISKAUD_CaptureFromDevice;
+ impl->FlushCapture = DISKAUD_FlushCapture;
+
impl->CloseDevice = DISKAUD_CloseDevice;
impl->DetectDevices = DISKAUD_DetectDevices;
impl->AllowsArbitraryDeviceNames = 1;
+ impl->HasCaptureSupport = SDL_TRUE;
return 1; /* this audio target is available. */
}
--- a/src/audio/disk/SDL_diskaudio.h Sat Aug 06 02:48:00 2016 -0400
+++ b/src/audio/disk/SDL_diskaudio.h Sat Aug 06 03:39:15 2016 -0400
@@ -32,10 +32,9 @@
struct SDL_PrivateAudioData
{
/* The file descriptor for the audio device */
- SDL_RWops *output;
+ SDL_RWops *io;
+ Uint32 io_delay;
Uint8 *mixbuf;
- Uint32 mixlen;
- Uint32 write_delay;
};
#endif /* _SDL_diskaudio_h */