From b108b54c6a1358fa69d5dddf58dca08be2758751 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sun, 15 Dec 2024 13:07:28 -0500
Subject: [PATCH] alsa: Bring up to current SDL coding conventions and
standards, other tweaks.
---
src/audio/alsa/SDL_alsa_audio.c | 663 +++++++++++++++-----------------
1 file changed, 300 insertions(+), 363 deletions(-)
diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c
index 730562b5217da..effa180871f77 100644
--- a/src/audio/alsa/SDL_alsa_audio.c
+++ b/src/audio/alsa/SDL_alsa_audio.c
@@ -31,19 +31,18 @@
#define SDL_ALSA_HOTPLUG_THREAD 1
#endif
-// Allow access to a raw mixing buffer
-
-#include <sys/types.h>
-#include <signal.h> // For kill()
-#include <string.h>
-
#include "../SDL_sysaudio.h"
#include "SDL_alsa_audio.h"
-#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
+#ifndef SDL_ALSA_DEBUG
+#define SDL_ALSA_DEBUG 0
#endif
-#define LOGDEBUG(...) SDL_Log("ALSA:" __VA_ARGS__)
+#if SDL_ALSA_DEBUG
+#define LOGDEBUG(...) SDL_Log("ALSA: " __VA_ARGS__)
+#else
+#define LOGDEBUG(...)
+#endif
//TODO: cleanup once the code settled down
@@ -278,33 +277,23 @@ static const ALSA_Device default_recording_handle = {
// All the above may be completely wrong.
static char *get_pcm_str(void *handle)
{
- ALSA_Device *dev;
- size_t pcm_len;
- char *pcm_str;
-
SDL_assert(handle != NULL); // SDL2 used NULL to mean "default" but that's not true in SDL3.
- dev = (ALSA_Device *)handle;
-
+ ALSA_Device *dev = (ALSA_Device *)handle;
+
// If the user does not want to go thru the default PCM or the canonical default, the
// the configuration space being _massive_, give the user the ability to specify
// its own PCMs using environment variables. It will have to fit SDL constraints though.
- if (dev->recording)
- pcm_str = (char*)SDL_getenv("SDL_AUDIO_ALSA_PCM_RECORDING");
- else
- pcm_str = (char*)SDL_getenv("SDL_AUDIO_ALSA_PCM_PLAYBACK");
- if (pcm_str)
- return SDL_strdup(pcm_str);
-
- if (SDL_strlen(dev->id) == 0)
- pcm_str = SDL_strdup("default");
- else {
-#define PCM_STR_FMT "default:CARD=%s"
- pcm_len = (size_t)SDL_snprintf(0, 0, PCM_STR_FMT, dev->id);
-
- pcm_str = SDL_malloc(pcm_len + 1);
- if (pcm_str != NULL)
- SDL_snprintf(pcm_str, pcm_len + 1, PCM_STR_FMT, dev->id);
-#undef PCM_STR_FMT
+ // !!! FIXME: make these into SDL_Hints?
+ const char *env = SDL_getenv(dev->recording ? "SDL_AUDIO_ALSA_PCM_RECORDING" : "SDL_AUDIO_ALSA_PCM_PLAYBACK");
+ if (env) {
+ return SDL_strdup(env);
+ }
+
+ char *pcm_str = NULL;
+ if (SDL_strlen(dev->id) == 0) {
+ pcm_str = SDL_strdup("default");
+ } else {
+ SDL_asprintf(&pcm_str, "default:CARD=%s", dev->id);
}
return pcm_str;
}
@@ -680,16 +669,16 @@ struct ALSA_pcm_cfg_ctx {
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;
- SDL_AudioFormat matched_sdl_format;
- unsigned int chans_n;
- unsigned int target_chans_n;
- unsigned int rate;
- snd_pcm_uframes_t persize; // alsa period size, SDL audio device sample_frames
- snd_pcm_chmap_query_t **chmap_queries;
- unsigned int sdl_chmap[SDL_AUDIO_ALSA__CHMAP_CHANS_N_MAX];
- unsigned int alsa_chmap_installed[SDL_AUDIO_ALSA__CHMAP_CHANS_N_MAX];
+ SDL_AudioFormat matched_sdl_format;
+ unsigned int chans_n;
+ unsigned int target_chans_n;
+ unsigned int rate;
+ snd_pcm_uframes_t persize; // alsa period size, SDL audio device sample_frames
+ snd_pcm_chmap_query_t **chmap_queries;
+ unsigned int sdl_chmap[SDL_AUDIO_ALSA__CHMAP_CHANS_N_MAX];
+ unsigned int alsa_chmap_installed[SDL_AUDIO_ALSA__CHMAP_CHANS_N_MAX];
- unsigned int periods;
+ unsigned int periods;
};
// The following are SDL channel maps with alsa position values, from 0 channels to 8 channels.
// See SDL3/SDL_audio.h
@@ -769,15 +758,18 @@ static enum snd_pcm_chmap_position sdl_channel_maps[SDL_AUDIO_ALSA__SDL_CHMAPS_N
// Helper for the function right below.
static bool has_pos(unsigned int *chmap, unsigned int pos)
{
- unsigned int chan_idx = 0;
- while (true) {
- if (chan_idx == 6)
+ for (unsigned int chan_idx = 0; ; chan_idx++) {
+ if (chan_idx == 6) {
return false;
- if (chmap[chan_idx] == pos)
+ }
+ if (chmap[chan_idx] == pos) {
return true;
- ++chan_idx;
+ }
}
+ SDL_assert(!"Shouldn't hit this code.");
+ return false;
}
+
// XXX: Each time we are going to work on an alsa 6 channels map, we must reduce the set of channel
// maps which is encoded in sdl_channel_maps[6] to a uniq one.
#define HAVE_NONE 0
@@ -787,32 +779,28 @@ static bool has_pos(unsigned int *chmap, unsigned int pos)
static void sdl_6chans_set_rear_or_side_channels_from_alsa_6chans(unsigned int *sdl_6chans,
unsigned int *alsa_6chans)
{
- unsigned int chan_idx;
- unsigned int state;
// For alsa channel maps with 6 channels and with SND_CHMAP_FL,SND_CHMAP_FR,SND_CHMAP_FC,
// SND_CHMAP_LFE, reduce our 6 channels maps to a uniq one.
- if (!has_pos(alsa_6chans, SND_CHMAP_FL)
- || !has_pos(alsa_6chans, SND_CHMAP_FR)
- || !has_pos(alsa_6chans, SND_CHMAP_FC)
- || !has_pos(alsa_6chans, SND_CHMAP_LFE)) {
+ if ( !has_pos(alsa_6chans, SND_CHMAP_FL) ||
+ !has_pos(alsa_6chans, SND_CHMAP_FR) ||
+ !has_pos(alsa_6chans, SND_CHMAP_FC) ||
+ !has_pos(alsa_6chans, SND_CHMAP_LFE)) {
sdl_6chans[4] = SND_CHMAP_UNKNOWN;
sdl_6chans[5] = SND_CHMAP_UNKNOWN;
LOGDEBUG("6channels:unsupported channel map");
return;
}
- chan_idx = 0;
- state = HAVE_NONE;
- while (true) {
- if (chan_idx == 6)
- break;
- if (alsa_6chans[chan_idx] == SND_CHMAP_SL || alsa_6chans[chan_idx] == SND_CHMAP_SR) {
+
+ unsigned int state = HAVE_NONE;
+ for (unsigned int chan_idx = 0; chan_idx < 6; chan_idx++) {
+ if ((alsa_6chans[chan_idx] == SND_CHMAP_SL) || (alsa_6chans[chan_idx] == SND_CHMAP_SR)) {
if (state == HAVE_NONE) {
state = HAVE_SIDE;
} else if (state == HAVE_REAR) {
state = HAVE_BOTH;
break;
}
- } else if (alsa_6chans[chan_idx] == SND_CHMAP_RL || alsa_6chans[chan_idx] == SND_CHMAP_RR) {
+ } else if ((alsa_6chans[chan_idx] == SND_CHMAP_RL) || (alsa_6chans[chan_idx] == SND_CHMAP_RR)) {
if (state == HAVE_NONE) {
state = HAVE_REAR;
} else if (state == HAVE_SIDE) {
@@ -820,9 +808,9 @@ static void sdl_6chans_set_rear_or_side_channels_from_alsa_6chans(unsigned int *
break;
}
}
- ++chan_idx;
}
- if (state == HAVE_BOTH || state == HAVE_NONE) {
+
+ if ((state == HAVE_BOTH) || (state == HAVE_NONE)) {
sdl_6chans[4] = SND_CHMAP_UNKNOWN;
sdl_6chans[5] = SND_CHMAP_UNKNOWN;
LOGDEBUG("6channels:unsupported channel map");
@@ -840,32 +828,27 @@ static void sdl_6chans_set_rear_or_side_channels_from_alsa_6chans(unsigned int *
#undef HAVE_REAR
#undef HAVE_SIDE
#undef HAVE_BOTH
-static void swizzle_map_compute_alsa_subscan(struct ALSA_pcm_cfg_ctx *ctx,
- unsigned int sdl_pos_idx)
+
+static void swizzle_map_compute_alsa_subscan(struct ALSA_pcm_cfg_ctx *ctx, unsigned int sdl_pos_idx)
{
- unsigned int alsa_pos_idx = 0;
- while (true) {
+ for (unsigned int alsa_pos_idx = 0; ; alsa_pos_idx++) {
SDL_assert(alsa_pos_idx != ctx->chans_n); // no 0 channels or not found matching position should happen here (actually enforce playback/recording symmetry).
-
if (ctx->alsa_chmap_installed[alsa_pos_idx] == ctx->sdl_chmap[sdl_pos_idx]) {
LOGDEBUG("swizzle SDL %u <-> alsa %u", sdl_pos_idx,alsa_pos_idx);
ctx->device->hidden->swizzle_map[sdl_pos_idx] = alsa_pos_idx;
return;
}
- ++alsa_pos_idx;
}
}
+
// XXX: this must stay playback/recording symetric.
static void swizzle_map_compute(struct ALSA_pcm_cfg_ctx *ctx)
{
- unsigned int sdl_pos_idx = 0;
- while (true) {
- if (sdl_pos_idx == ctx->chans_n)
- break;
+ for (unsigned int sdl_pos_idx = 0; sdl_pos_idx != ctx->chans_n; sdl_pos_idx++) {
swizzle_map_compute_alsa_subscan(ctx, sdl_pos_idx);
- ++sdl_pos_idx;
}
}
+
#define CHMAP_INSTALLED 0
#define CHANS_N_NEXT 1
#define CHMAP_NOT_FOUND 2
@@ -873,218 +856,185 @@ static void swizzle_map_compute(struct ALSA_pcm_cfg_ctx *ctx)
// namely we can program the channel positions directly from the SDL channel map.
static int alsa_chmap_install(struct ALSA_pcm_cfg_ctx *ctx, unsigned int *chmap)
{
- int status;
- char logdebug_chmap_str[128];
- snd_pcm_chmap_t *chmap_to_install = (snd_pcm_chmap_t*)SDL_stack_alloc(unsigned int,
- 1 + ctx->chans_n);
+ bool isstack;
+ snd_pcm_chmap_t *chmap_to_install = (snd_pcm_chmap_t*)SDL_small_alloc(unsigned int, 1 + ctx->chans_n, &isstack);
+ if (!chmap_to_install) {
+ return -1;
+ }
+
chmap_to_install->channels = ctx->chans_n;
- SDL_memcpy(chmap_to_install->pos, chmap, sizeof(unsigned int) * ctx->chans_n);
+ SDL_memcpy(chmap_to_install->pos, chmap, sizeof (unsigned int) * ctx->chans_n);
+ #if SDL_ALSA_DEBUG
+ char logdebug_chmap_str[128];
ALSA_snd_pcm_chmap_print(chmap_to_install,sizeof(logdebug_chmap_str),logdebug_chmap_str);
LOGDEBUG("channel map to install:%s",logdebug_chmap_str);
+ #endif
- status = ALSA_snd_pcm_set_chmap(ctx->device->hidden->pcm, chmap_to_install);
+ int status = ALSA_snd_pcm_set_chmap(ctx->device->hidden->pcm, chmap_to_install);
if (status < 0) {
- return SDL_SetError("ALSA: failed to install channel map: %s", ALSA_snd_strerror(status));
+ SDL_SetError("ALSA: failed to install channel map: %s", ALSA_snd_strerror(status));
+ return -1;
}
- SDL_memcpy(ctx->alsa_chmap_installed, chmap, ctx->chans_n * sizeof(unsigned int));
+ SDL_memcpy(ctx->alsa_chmap_installed, chmap, ctx->chans_n * sizeof (unsigned int));
+
+ SDL_small_free(chmap_to_install, isstack);
return CHMAP_INSTALLED;
}
+
// We restrict the alsa channel maps because in the unordered matches we do only simple accounting.
// In the end, this will handle mostly alsa channel maps with more than one SND_CHMAP_NA position fillers.
static bool alsa_chmap_has_duplicate_position(struct ALSA_pcm_cfg_ctx *ctx, unsigned int *pos)
{
- unsigned int chan_idx;
-
if (ctx->chans_n < 2) {// we need at least 2 positions
- LOGDEBUG("channel map:no duplicate");
- return false;
+ LOGDEBUG("channel map:no duplicate");
+ return false;
}
- chan_idx = 1;
- while (true) {
- unsigned seen_idx;
- if (chan_idx == ctx->chans_n) {
- LOGDEBUG("channel map:no duplicate");
- return false;
- }
- seen_idx = 0;
- while (true) {
+ for (unsigned int chan_idx = 1; chan_idx != ctx->chans_n; chan_idx++) {
+ for (unsigned int seen_idx = 0; seen_idx != chan_idx; seen_idx++) {
if (pos[seen_idx] == pos[chan_idx]) {
LOGDEBUG("channel map:have duplicate");
return true;
- }
- ++seen_idx;
- if (seen_idx == chan_idx)
- break;
+ }
}
- ++chan_idx;
}
+
+ LOGDEBUG("channel map:no duplicate");
+ return false;
}
+
static int alsa_chmap_cfg_ordered_fixed_or_paired(struct ALSA_pcm_cfg_ctx *ctx)
{
- char logdebug_chmap_str[128];
- snd_pcm_chmap_query_t **chmap_query = ctx->chmap_queries;
- while (true) {
- unsigned int chan_idx;
- unsigned int *alsa_chmap;
-
- if (*chmap_query == NULL)
- break;
- if (((*chmap_query)->map.channels != ctx->chans_n)
- || ((*chmap_query)->type != SND_CHMAP_TYPE_FIXED
- && (*chmap_query)->type != SND_CHMAP_TYPE_PAIRED)) {
- ++chmap_query;
+ for (snd_pcm_chmap_query_t **chmap_query = ctx->chmap_queries; *chmap_query; chmap_query++) {
+ if ( ((*chmap_query)->map.channels != ctx->chans_n) ||
+ (((*chmap_query)->type != SND_CHMAP_TYPE_FIXED) && ((*chmap_query)->type != SND_CHMAP_TYPE_PAIRED)) ) {
continue;
}
+ #if SDL_ALSA_DEBUG
+ char logdebug_chmap_str[128];
ALSA_snd_pcm_chmap_print(&(*chmap_query)->map,sizeof(logdebug_chmap_str),logdebug_chmap_str);
LOGDEBUG("channel map:ordered:fixed|paired:%s",logdebug_chmap_str);
+ #endif
+
+ for (int i = 0; i < ctx->chans_n; i++) {
+ ctx->sdl_chmap[i] = (unsigned int) sdl_channel_maps[ctx->chans_n][i];
+ }
- alsa_chmap = (*chmap_query)->map.pos;
- SDL_memcpy(ctx->sdl_chmap, sdl_channel_maps[ctx->chans_n], ctx->chans_n
- * sizeof(unsigned int));
- if (ctx->chans_n == 6)
+ unsigned int *alsa_chmap = (*chmap_query)->map.pos;
+ if (ctx->chans_n == 6) {
sdl_6chans_set_rear_or_side_channels_from_alsa_6chans(ctx->sdl_chmap, alsa_chmap);
+ }
if (alsa_chmap_has_duplicate_position(ctx, alsa_chmap)) {
- ++chmap_query;
continue;
}
- chan_idx = 0;
- while (true) {
- if (chan_idx == ctx->chans_n)
- return alsa_chmap_install(ctx, alsa_chmap);
- if (ctx->sdl_chmap[chan_idx] != alsa_chmap[chan_idx])
- break; // nope, try next alsa channel map.
- ++chan_idx;
+ for (unsigned int chan_idx = 0; ctx->sdl_chmap[chan_idx] == alsa_chmap[chan_idx]; chan_idx++) {
+ if (chan_idx == ctx->chans_n) {
+ return alsa_chmap_install(ctx, alsa_chmap);
+ }
}
- ++chmap_query;
}
return CHMAP_NOT_FOUND;
}
+
// Here, the alsa channel positions can be programmed in the alsa frame (cf HDMI).
// If the alsa channel map is VAR, we only check we have the unordered set of channel positions we
// are looking for.
static int alsa_chmap_cfg_ordered_var(struct ALSA_pcm_cfg_ctx *ctx)
{
- char logdebug_chmap_str[128];
- snd_pcm_chmap_query_t **chmap_query = ctx->chmap_queries;
- while (true) {
- unsigned int pos_matches_n;
- unsigned int chan_idx;
- unsigned int *alsa_chmap;
-
- if (*chmap_query == NULL)
- break;
- if ((*chmap_query)->map.channels != ctx->chans_n
- || (*chmap_query)->type != SND_CHMAP_TYPE_VAR) {
- ++chmap_query;
+ for (snd_pcm_chmap_query_t **chmap_query = ctx->chmap_queries; *chmap_query; chmap_query++) {
+ if (((*chmap_query)->map.channels != ctx->chans_n) || ((*chmap_query)->type != SND_CHMAP_TYPE_VAR)) {
continue;
}
+ #if SDL_ALSA_DEBUG
+ char logdebug_chmap_str[128];
ALSA_snd_pcm_chmap_print(&(*chmap_query)->map,sizeof(logdebug_chmap_str),logdebug_chmap_str);
LOGDEBUG("channel map:ordered:var:%s",logdebug_chmap_str);
+ #endif
- alsa_chmap = (*chmap_query)->map.pos;
- SDL_memcpy(ctx->sdl_chmap, sdl_channel_maps[ctx->chans_n], ctx->chans_n
- * sizeof(unsigned int));
- if (ctx->chans_n == 6)
+ for (int i = 0; i < ctx->chans_n; i++) {
+ ctx->sdl_chmap[i] = (unsigned int) sdl_channel_maps[ctx->chans_n][i];
+ }
+
+ unsigned int *alsa_chmap = (*chmap_query)->map.pos;
+ if (ctx->chans_n == 6) {
sdl_6chans_set_rear_or_side_channels_from_alsa_6chans(ctx->sdl_chmap, alsa_chmap);
+ }
if (alsa_chmap_has_duplicate_position(ctx, alsa_chmap)) {
- ++chmap_query;
continue;
}
- pos_matches_n = 0;
- chan_idx = 0;
- while (true) {
- unsigned int subscan_chan_idx;
- if (chan_idx == ctx->chans_n)
- break;
- subscan_chan_idx = 0;
- while (true) {
- if (subscan_chan_idx == ctx->chans_n)
- break;
+ unsigned int pos_matches_n = 0;
+ for (unsigned int chan_idx = 0; chan_idx != ctx->chans_n; chan_idx++) {
+ for (unsigned int subscan_chan_idx = 0; subscan_chan_idx != ctx->chans_n; subscan_chan_idx++) {
if (ctx->sdl_chmap[chan_idx] == alsa_chmap[subscan_chan_idx]) {
- ++pos_matches_n;
+ pos_matches_n++;
break;
}
- ++subscan_chan_idx;
}
- ++chan_idx;
}
- if (pos_matches_n == ctx->chans_n)
+
+ if (pos_matches_n == ctx->chans_n) {
return alsa_chmap_install(ctx, ctx->sdl_chmap); // XXX: we program the SDL chmap here
- ++chmap_query;
+ }
}
+
return CHMAP_NOT_FOUND;
}
static int alsa_chmap_cfg_ordered(struct ALSA_pcm_cfg_ctx *ctx)
{
- int status;
-
- status = alsa_chmap_cfg_ordered_fixed_or_paired(ctx);
- if (status != CHMAP_NOT_FOUND)
- return status;
- return alsa_chmap_cfg_ordered_var(ctx);
+ const int status = alsa_chmap_cfg_ordered_fixed_or_paired(ctx);
+ return (status != CHMAP_NOT_FOUND) ? status : alsa_chmap_cfg_ordered_var(ctx);
}
+
// In the unordered case, we are just interested to get the same unordered set of alsa channel
// positions than in the SDL channel map since we will swizzle (no duplicate channel position).
static int alsa_chmap_cfg_unordered(struct ALSA_pcm_cfg_ctx *ctx)
{
- char logdebug_chmap_str[128];
- snd_pcm_chmap_query_t **chmap_query = ctx->chmap_queries;
- while (true) {
- unsigned int pos_matches_n;
- unsigned int chan_idx;
- unsigned int *alsa_chmap;
-
- if (*chmap_query == NULL)
- break;
- if (((*chmap_query)->map.channels != ctx->chans_n)
- || ((*chmap_query)->type != SND_CHMAP_TYPE_FIXED
- && (*chmap_query)->type != SND_CHMAP_TYPE_PAIRED)) {
- ++chmap_query;
+ for (snd_pcm_chmap_query_t **chmap_query = ctx->chmap_queries; *chmap_query; chmap_query++) {
+ if ( ((*chmap_query)->map.channels != ctx->chans_n) ||
+ (((*chmap_query)->type != SND_CHMAP_TYPE_FIXED) && ((*chmap_query)->type != SND_CHMAP_TYPE_PAIRED)) ) {
continue;
}
+ #if SDL_ALSA_DEBUG
+ char logdebug_chmap_str[128];
ALSA_snd_pcm_chmap_print(&(*chmap_query)->map,sizeof(logdebug_chmap_str),logdebug_chmap_str);
LOGDEBUG("channel map:unordered:fixed|paired:%s",logdebug_chmap_str);
+ #endif
- alsa_chmap = (*chmap_query)->map.pos;
- SDL_memcpy(ctx->sdl_chmap, sdl_channel_maps[ctx->chans_n], ctx->chans_n
- * sizeof(unsigned int));
- if (ctx->chans_n == 6)
+ for (int i = 0; i < ctx->chans_n; i++) {
+ ctx->sdl_chmap[i] = (unsigned int) sdl_channel_maps[ctx->chans_n][i];
+ }
+
+ unsigned int *alsa_chmap = (*chmap_query)->map.pos;
+ if (ctx->chans_n == 6) {
sdl_6chans_set_rear_or_side_channels_from_alsa_6chans(ctx->sdl_chmap, alsa_chmap);
+ }
+
if (alsa_chmap_has_duplicate_position(ctx, alsa_chmap)) {
- ++chmap_query;
continue;
}
- pos_matches_n = 0;
- chan_idx = 0;
- while (true) {
- unsigned int subscan_chan_idx;
- if (chan_idx == ctx->chans_n)
- break;
- subscan_chan_idx = 0;
- while (true) {
- if (subscan_chan_idx == ctx->chans_n)
- break;
+ unsigned int pos_matches_n = 0;
+ for (unsigned int chan_idx = 0; chan_idx != ctx->chans_n; chan_idx++) {
+ for (unsigned int subscan_chan_idx = 0; subscan_chan_idx != ctx->chans_n; subscan_chan_idx++) {
if (ctx->sdl_chmap[chan_idx] == alsa_chmap[subscan_chan_idx]) {
- ++pos_matches_n;
+ pos_matches_n++;
break;
}
- ++subscan_chan_idx;
}
- ++chan_idx;
}
- if (pos_matches_n == ctx->chans_n)
+
+ if (pos_matches_n == ctx->chans_n) {
return alsa_chmap_install(ctx, alsa_chmap);
- ++chmap_query;
+ }
}
+
return CHMAP_NOT_FOUND;
}
@@ -1107,14 +1057,14 @@ static int alsa_chmap_cfg(struct ALSA_pcm_cfg_ctx *ctx)
ctx->device->hidden->swizzle_func = no_swizzle;
return status;
}
- if (status != CHMAP_NOT_FOUND)
+ if (status != CHMAP_NOT_FOUND) {
return status; // < 0 error code
+ }
// Fall-thru
//----------------------------------------------------------------------------------------------
status = alsa_chmap_cfg_unordered(ctx); // those we will have to swizzle
if (status == CHMAP_INSTALLED) {
LOGDEBUG("swizzling on");
-
swizzle_map_compute(ctx); // fine grained swizzle configuration
ctx->device->hidden->swizzle_func = swizzle_alsa_channels;
return status;
@@ -1124,8 +1074,8 @@ static int alsa_chmap_cfg(struct ALSA_pcm_cfg_ctx *ctx)
return status; // < 0 error code
}
-#define CHANS_N_SCAN_MODE__EQUAL_OR_ABOVE_REQUESTED_CHANS_N 0 /* target more hardware pressure */
-#define CHANS_N_SCAN_MODE__BELOW_REQUESTED_CHANS_N 1 /* target less hardware pressure */
+#define CHANS_N_SCAN_MODE__EQUAL_OR_ABOVE_REQUESTED_CHANS_N 0 // target more hardware pressure
+#define CHANS_N_SCAN_MODE__BELOW_REQUESTED_CHANS_N 1 // target less hardware pressure
#define CHANS_N_CONFIGURED 0
#define CHANS_N_NOT_CONFIGURED 1
static int ALSA_pcm_cfg_hw_chans_n_scan(struct ALSA_pcm_cfg_ctx *ctx, unsigned int mode)
@@ -1135,22 +1085,18 @@ static int ALSA_pcm_cfg_hw_chans_n_scan(struct ALSA_pcm_cfg_ctx *ctx, unsigned i
target_chans_n--;
}
while (true) {
- int status;
- snd_pcm_format_t alsa_format;
- const SDL_AudioFormat *closefmts;
-
if (mode == CHANS_N_SCAN_MODE__EQUAL_OR_ABOVE_REQUESTED_CHANS_N) {
if (target_chans_n > SDL_AUDIO_ALSA__CHMAP_CHANS_N_MAX) {
return CHANS_N_NOT_CONFIGURED;
}
- } else {/* CHANS_N_SCAN_MODE__BELOW_REQUESTED_CHANS_N */
- if (target_chans_n == 0) {
- return CHANS_N_NOT_CONFIGURED;
- }
+ // else: CHANS_N_SCAN_MODE__BELOW_REQUESTED_CHANS_N
+ } else if (target_chans_n == 0) {
+ return CHANS_N_NOT_CONFIGURED;
}
+
LOGDEBUG("target chans_n is %u\n", target_chans_n);
- status = ALSA_snd_pcm_hw_params_any(ctx->device->hidden->pcm, ctx->hwparams);
+ int status = ALSA_snd_pcm_hw_params_any(ctx->device->hidden->pcm, ctx->hwparams);
if (status < 0) {
SDL_SetError("ALSA: Couldn't get hardware config: %s", ALSA_snd_strerror(status));
return -1;
@@ -1163,8 +1109,8 @@ static int ALSA_pcm_cfg_hw_chans_n_scan(struct ALSA_pcm_cfg_ctx *ctx, unsigned i
return -1;
}
// Try for a closest match on audio format
- alsa_format = 0;
- closefmts = SDL_ClosestAudioFormats(ctx->device->spec.format);
+ snd_pcm_format_t alsa_format = 0;
+ const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(ctx->device->spec.format);
ctx->matched_sdl_format = 0;
while ((ctx->matched_sdl_format = *(closefmts++)) != 0) {
// XXX: we are forcing the same endianness, namely we won't need byte swapping upon
@@ -1265,69 +1211,70 @@ static int ALSA_pcm_cfg_hw_chans_n_scan(struct ALSA_pcm_cfg_ctx *ctx, unsigned i
ALSA_snd_pcm_hw_free(ctx->device->hidden->pcm); // uninstall those hw params
if (mode == CHANS_N_SCAN_MODE__EQUAL_OR_ABOVE_REQUESTED_CHANS_N) {
- ++target_chans_n;
- } else {/* CHANS_N_SCAN_MODE__BELOW_REQUESTED_CHANS_N */
- target_chans_n--;
- }
+ target_chans_n++;
+ } else { // CHANS_N_SCAN_MODE__BELOW_REQUESTED_CHANS_N
+ target_chans_n--;
+ }
}
+
+ SDL_assert(!"Shouldn't reach this code.");
+ return CHANS_N_NOT_CONFIGURED;
}
#undef CHMAP_INSTALLED
#undef CHANS_N_NEXT
#undef CHMAP_NOT_FOUND
-static int ALSA_pcm_cfg_hw(struct ALSA_pcm_cfg_ctx *ctx)
+static bool ALSA_pcm_cfg_hw(struct ALSA_pcm_cfg_ctx *ctx)
{
- int status;
-
LOGDEBUG("target chans_n, equal or above requested chans_n mode\n");
- status = ALSA_pcm_cfg_hw_chans_n_scan(ctx, CHANS_N_SCAN_MODE__EQUAL_OR_ABOVE_REQUESTED_CHANS_N);
- if (status < 0) /* something went too wrong */
- return status;
- if (status == CHANS_N_CONFIGURED)
- return 0;
- /* Here, status == CHANS_N_NOT_CONFIGURED */
+ int status = ALSA_pcm_cfg_hw_chans_n_scan(ctx, CHANS_N_SCAN_MODE__EQUAL_OR_ABOVE_REQUESTED_CHANS_N);
+ if (status < 0) { // something went too wrong
+ return false;
+ } else if (status == CHANS_N_CONFIGURED) {
+ return true;
+ }
+
+ // Here, status == CHANS_N_NOT_CONFIGURED
LOGDEBUG("target chans_n, below requested chans_n mode\n");
status = ALSA_pcm_cfg_hw_chans_n_scan(ctx, CHANS_N_SCAN_MODE__BELOW_REQUESTED_CHANS_N);
- if (status < 0) /* something went too wrong */
- return status;
- if (status == CHANS_N_CONFIGURED)
- return 0;
- /* Here, status == CHANS_N_NOT_CONFIGURED */
- SDL_SetError("ALSA: Coudn't configure targetting any SDL supported channel number");
- return -1;
+ if (status < 0) { // something went too wrong
+ return false;
+ } else if (status == CHANS_N_CONFIGURED) {
+ return true;
+ }
+
+ // Here, status == CHANS_N_NOT_CONFIGURED
+ return SDL_SetError("ALSA: Coudn't configure targetting any SDL supported channel number");
}
#undef CHANS_N_SCAN_MODE__EQUAL_OR_ABOVE_REQUESTED_CHANS_N
#undef CHANS_N_SCAN_MODE__BELOW_REQUESTED_CHANS_N
#undef CHANS_N_CONFIGURED
#undef CHANS_N_NOT_CONFIGURED
-static int ALSA_pcm_cfg_sw(struct ALSA_pcm_cfg_ctx *ctx)
+
+static bool ALSA_pcm_cfg_sw(struct ALSA_pcm_cfg_ctx *ctx)
{
int status;
status = ALSA_snd_pcm_sw_params_current(ctx->device->hidden->pcm, ctx->swparams);
if (status < 0) {
- SDL_SetError("ALSA: Couldn't get software config: %s", ALSA_snd_strerror(status));
- return -1;
+ return SDL_SetError("ALSA: Couldn't get software config: %s", ALSA_snd_strerror(status));
}
- status = ALSA_snd_pcm_sw_params_set_avail_min(ctx->device->hidden->pcm, ctx->swparams,
- ctx->persize); // will become device->sample_frames if the alsa pcm configuration is successful
+
+ status = ALSA_snd_pcm_sw_params_set_avail_min(ctx->device->hidden->pcm, ctx->swparams, ctx->persize); // will become device->sample_frames if the alsa pcm configuration is successful
if (status < 0) {
- SDL_SetError("Couldn't set minimum available samples: %s", ALSA_snd_strerror(status));
- return -1;
+ return SDL_SetError("Couldn't set minimum available samples: %s", ALSA_snd_strerror(status));
}
- status = ALSA_snd_pcm_sw_params_set_start_threshold(ctx->device->hidden->pcm,
- ctx->swparams, 1);
+
+ status = ALSA_snd_pcm_sw_params_set_start_threshold(ctx->device->hidden->pcm, ctx->swparams, 1);
if (status < 0) {
- SDL_SetError("ALSA: Couldn't set start threshold: %s", ALSA_snd_strerror(status));
- return -1;
+ return SDL_SetError("ALSA: Couldn't set start threshold: %s", ALSA_snd_strerror(status));
}
status = ALSA_snd_pcm_sw_params(ctx->device->hidden->pcm, ctx->swparams);
if (status < 0) {
- SDL_SetError("Couldn't set software audio parameters: %s", ALSA_snd_strerror(status));
- return -1;
+ return SDL_SetError("Couldn't set software audio parameters: %s", ALSA_snd_strerror(status));
}
- return 0;
+ return true;
}
@@ -1374,29 +1321,26 @@ static bool ALSA_OpenDevice(SDL_AudioDevice *device)
snd_pcm_hw_params_alloca(&(cfg_ctx.hwparams));
snd_pcm_sw_params_alloca(&(cfg_ctx.swparams));
- status = ALSA_pcm_cfg_hw(&cfg_ctx); // alsa pcm "hardware" part of the pcm
- if (status < 0) {
+ if (!ALSA_pcm_cfg_hw(&cfg_ctx)) { // alsa pcm "hardware" part of the pcm
goto err_close_pcm;
}
+
// from here, we get only the alsa chmap queries in cfg_ctx to explicitely clean, hwparams is
// uninstalled upon pcm closing
// This is useful for debugging
- if (SDL_getenv("SDL_AUDIO_ALSA_DEBUG")) {
- snd_pcm_uframes_t bufsize;
-
- ALSA_snd_pcm_hw_params_get_buffer_size(cfg_ctx.hwparams, &bufsize);
-
- SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
+ #if SDL_ALSA_DEBUG
+ snd_pcm_uframes_t bufsize;
+ ALSA_snd_pcm_hw_params_get_buffer_size(cfg_ctx.hwparams, &bufsize);
+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
"ALSA: period size = %ld, periods = %u, buffer size = %lu",
cfg_ctx.persize, cfg_ctx.periods, bufsize);
- }
+ #endif
-
- status = ALSA_pcm_cfg_sw(&cfg_ctx); // alsa pcm "software" part of the pcm
- if (status < 0) {
+ if (!ALSA_pcm_cfg_sw(&cfg_ctx)) { // alsa pcm "software" part of the pcm
goto err_cleanup_ctx;
}
+
// Now we can update the following parameters in the spec:
cfg_ctx.device->spec.format = cfg_ctx.matched_sdl_format;
cfg_ctx.device->spec.channels = cfg_ctx.chans_n;
@@ -1437,221 +1381,214 @@ static ALSA_Device *hotplug_devices = NULL;
static int hotplug_device_process(snd_ctl_t *ctl, snd_ctl_card_info_t *ctl_card_info, int dev_idx,
snd_pcm_stream_t direction, ALSA_Device **unseen, ALSA_Device **seen)
{
- int r;
- unsigned int subdevs_n;
- unsigned int subdev_idx;
- snd_pcm_info_t *pcm_info;
- bool recording = direction == SND_PCM_STREAM_CAPTURE ? true : false; // used for the unicity of the device
-
- pcm_info = (snd_pcm_info_t*)SDL_stack_alloc(Uint8,ALSA_snd_pcm_info_sizeof());
+ unsigned int subdevs_n = 1; // we have at least one subdevice (substream since the direction is a stream in alsa terminology)
+ unsigned int subdev_idx = 0;
+ const bool recording = direction == SND_PCM_STREAM_CAPTURE ? true : false; // used for the unicity of the device
+ bool isstack;
+ snd_pcm_info_t *pcm_info = (snd_pcm_info_t*)SDL_small_alloc(Uint8, ALSA_snd_pcm_info_sizeof(), &isstack);
SDL_memset(pcm_info, 0, ALSA_snd_pcm_info_sizeof());
- subdev_idx = 0;
- subdevs_n = 1; // we have at least one subdevice (substream since the direction is a stream in alsa te
(Patch may be truncated, please check the link at the top of this post.)