mirror of
https://github.com/Ryujinx/SDL.git
synced 2024-12-24 17:55:38 +00:00
alsa: Implemented audio capture support!
This commit is contained in:
parent
754efd43f4
commit
41e8f9ede4
|
@ -29,6 +29,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "SDL_assert.h"
|
||||||
#include "SDL_timer.h"
|
#include "SDL_timer.h"
|
||||||
#include "SDL_audio.h"
|
#include "SDL_audio.h"
|
||||||
#include "../SDL_audiomem.h"
|
#include "../SDL_audiomem.h"
|
||||||
|
@ -44,6 +45,8 @@ static int (*ALSA_snd_pcm_open)
|
||||||
static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm);
|
static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm);
|
||||||
static snd_pcm_sframes_t (*ALSA_snd_pcm_writei)
|
static snd_pcm_sframes_t (*ALSA_snd_pcm_writei)
|
||||||
(snd_pcm_t *, const void *, snd_pcm_uframes_t);
|
(snd_pcm_t *, const void *, snd_pcm_uframes_t);
|
||||||
|
static snd_pcm_sframes_t (*ALSA_snd_pcm_readi)
|
||||||
|
(snd_pcm_t *, void *, snd_pcm_uframes_t);
|
||||||
static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
|
static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
|
||||||
static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
|
static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
|
||||||
static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
|
static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
|
||||||
|
@ -85,6 +88,7 @@ static int (*ALSA_snd_pcm_nonblock) (snd_pcm_t *, int);
|
||||||
static int (*ALSA_snd_pcm_wait)(snd_pcm_t *, int);
|
static int (*ALSA_snd_pcm_wait)(snd_pcm_t *, int);
|
||||||
static int (*ALSA_snd_pcm_sw_params_set_avail_min)
|
static int (*ALSA_snd_pcm_sw_params_set_avail_min)
|
||||||
(snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
|
(snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
|
||||||
|
static int (*ALSA_snd_pcm_reset)(snd_pcm_t *);
|
||||||
static int (*ALSA_snd_device_name_hint) (int, const char *, void ***);
|
static int (*ALSA_snd_device_name_hint) (int, const char *, void ***);
|
||||||
static char* (*ALSA_snd_device_name_get_hint) (const void *, const char *);
|
static char* (*ALSA_snd_device_name_get_hint) (const void *, const char *);
|
||||||
static int (*ALSA_snd_device_name_free_hint) (void **);
|
static int (*ALSA_snd_device_name_free_hint) (void **);
|
||||||
|
@ -121,6 +125,7 @@ load_alsa_syms(void)
|
||||||
SDL_ALSA_SYM(snd_pcm_open);
|
SDL_ALSA_SYM(snd_pcm_open);
|
||||||
SDL_ALSA_SYM(snd_pcm_close);
|
SDL_ALSA_SYM(snd_pcm_close);
|
||||||
SDL_ALSA_SYM(snd_pcm_writei);
|
SDL_ALSA_SYM(snd_pcm_writei);
|
||||||
|
SDL_ALSA_SYM(snd_pcm_readi);
|
||||||
SDL_ALSA_SYM(snd_pcm_recover);
|
SDL_ALSA_SYM(snd_pcm_recover);
|
||||||
SDL_ALSA_SYM(snd_pcm_prepare);
|
SDL_ALSA_SYM(snd_pcm_prepare);
|
||||||
SDL_ALSA_SYM(snd_pcm_drain);
|
SDL_ALSA_SYM(snd_pcm_drain);
|
||||||
|
@ -147,6 +152,7 @@ load_alsa_syms(void)
|
||||||
SDL_ALSA_SYM(snd_pcm_nonblock);
|
SDL_ALSA_SYM(snd_pcm_nonblock);
|
||||||
SDL_ALSA_SYM(snd_pcm_wait);
|
SDL_ALSA_SYM(snd_pcm_wait);
|
||||||
SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
|
SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
|
||||||
|
SDL_ALSA_SYM(snd_pcm_reset);
|
||||||
SDL_ALSA_SYM(snd_device_name_hint);
|
SDL_ALSA_SYM(snd_device_name_hint);
|
||||||
SDL_ALSA_SYM(snd_device_name_get_hint);
|
SDL_ALSA_SYM(snd_device_name_get_hint);
|
||||||
SDL_ALSA_SYM(snd_device_name_free_hint);
|
SDL_ALSA_SYM(snd_device_name_free_hint);
|
||||||
|
@ -342,6 +348,57 @@ ALSA_GetDeviceBuf(_THIS)
|
||||||
return (this->hidden->mixbuf);
|
return (this->hidden->mixbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ALSA_CaptureFromDevice(_THIS, void *buffer, int buflen)
|
||||||
|
{
|
||||||
|
Uint8 *sample_buf = (Uint8 *) buffer;
|
||||||
|
const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
|
||||||
|
this->spec.channels;
|
||||||
|
const int total_frames = buflen / frame_size;
|
||||||
|
snd_pcm_uframes_t frames_left = total_frames;
|
||||||
|
|
||||||
|
SDL_assert((buflen % frame_size) == 0);
|
||||||
|
|
||||||
|
while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) {
|
||||||
|
/* !!! FIXME: This works, but needs more testing before going live */
|
||||||
|
/* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */
|
||||||
|
int status = ALSA_snd_pcm_readi(this->hidden->pcm_handle,
|
||||||
|
sample_buf, frames_left);
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
/*printf("ALSA: capture error %d\n", status);*/
|
||||||
|
if (status == -EAGAIN) {
|
||||||
|
/* Apparently snd_pcm_recover() doesn't handle this case -
|
||||||
|
does it assume snd_pcm_wait() above? */
|
||||||
|
SDL_Delay(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
|
||||||
|
if (status < 0) {
|
||||||
|
/* Hmm, not much we can do - abort */
|
||||||
|
fprintf(stderr, "ALSA read failed (unrecoverable): %s\n",
|
||||||
|
ALSA_snd_strerror(status));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*printf("ALSA: captured %d bytes\n", status * frame_size);*/
|
||||||
|
sample_buf += status * frame_size;
|
||||||
|
frames_left -= status;
|
||||||
|
}
|
||||||
|
|
||||||
|
swizzle_alsa_channels(this, buffer, total_frames - frames_left);
|
||||||
|
|
||||||
|
return (total_frames - frames_left) * frame_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ALSA_FlushCapture(_THIS)
|
||||||
|
{
|
||||||
|
ALSA_snd_pcm_reset(this->hidden->pcm_handle);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ALSA_CloseDevice(_THIS)
|
ALSA_CloseDevice(_THIS)
|
||||||
{
|
{
|
||||||
|
@ -494,7 +551,8 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
/* Name of device should depend on # channels in spec */
|
/* Name of device should depend on # channels in spec */
|
||||||
status = ALSA_snd_pcm_open(&pcm_handle,
|
status = ALSA_snd_pcm_open(&pcm_handle,
|
||||||
get_audio_device(handle, this->spec.channels),
|
get_audio_device(handle, this->spec.channels),
|
||||||
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
|
||||||
|
SND_PCM_NONBLOCK);
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
ALSA_CloseDevice(this);
|
ALSA_CloseDevice(this);
|
||||||
|
@ -757,6 +815,10 @@ ALSA_Init(SDL_AudioDriverImpl * impl)
|
||||||
impl->CloseDevice = ALSA_CloseDevice;
|
impl->CloseDevice = ALSA_CloseDevice;
|
||||||
impl->Deinitialize = ALSA_Deinitialize;
|
impl->Deinitialize = ALSA_Deinitialize;
|
||||||
impl->FreeDeviceHandle = ALSA_FreeDeviceHandle;
|
impl->FreeDeviceHandle = ALSA_FreeDeviceHandle;
|
||||||
|
impl->CaptureFromDevice = ALSA_CaptureFromDevice;
|
||||||
|
impl->FlushCapture = ALSA_FlushCapture;
|
||||||
|
|
||||||
|
impl->HasCaptureSupport = SDL_TRUE;
|
||||||
|
|
||||||
return 1; /* this audio target is available. */
|
return 1; /* this audio target is available. */
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue