aboutsummaryrefslogtreecommitdiffstats
path: root/src/output/alsa_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/output/alsa_plugin.c')
-rw-r--r--src/output/alsa_plugin.c122
1 files changed, 71 insertions, 51 deletions
diff --git a/src/output/alsa_plugin.c b/src/output/alsa_plugin.c
index 86c70f19d..d90be7815 100644
--- a/src/output/alsa_plugin.c
+++ b/src/output/alsa_plugin.c
@@ -218,6 +218,48 @@ byteswap_bitformat(snd_pcm_format_t fmt)
}
/**
+ * Attempts to configure the specified sample format.
+ */
+static int
+alsa_output_try_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
+ struct audio_format *audio_format,
+ enum sample_format sample_format)
+{
+ snd_pcm_format_t alsa_format = get_bitformat(sample_format);
+ if (alsa_format == SND_PCM_FORMAT_UNKNOWN)
+ return -EINVAL;
+
+ int err = snd_pcm_hw_params_set_format(pcm, hwparams, alsa_format);
+ if (err == 0)
+ audio_format->format = sample_format;
+
+ return err;
+}
+
+/**
+ * Attempts to configure the specified sample format with reversed
+ * host byte order.
+ */
+static int
+alsa_output_try_reverse(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
+ struct audio_format *audio_format,
+ enum sample_format sample_format)
+{
+ snd_pcm_format_t alsa_format =
+ byteswap_bitformat(get_bitformat(sample_format));
+ if (alsa_format == SND_PCM_FORMAT_UNKNOWN)
+ return -EINVAL;
+
+ int err = snd_pcm_hw_params_set_format(pcm, hwparams, alsa_format);
+ if (err == 0) {
+ audio_format->format = sample_format;
+ audio_format->reverse_endian = true;
+ }
+
+ return err;
+}
+
+/**
* Configure a sample format, and probe other formats if that fails.
*/
static int
@@ -234,66 +276,44 @@ alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
}
int err = snd_pcm_hw_params_set_format(pcm, hwparams, bitformat);
- if (err == -EINVAL &&
- byteswap_bitformat(bitformat) != SND_PCM_FORMAT_UNKNOWN) {
- err = snd_pcm_hw_params_set_format(pcm, hwparams,
- byteswap_bitformat(bitformat));
- if (err == 0) {
- g_debug("converting format %s to reverse-endian",
- sample_format_to_string(audio_format->format));
- audio_format->reverse_endian = 1;
- }
- }
+ if (err != -EINVAL)
+ return err;
- if (err == -EINVAL && (audio_format->format == SAMPLE_FORMAT_S24_P32 ||
- audio_format->format == SAMPLE_FORMAT_S16)) {
- /* fall back to 32 bit, let pcm_convert.c do the conversion */
- err = snd_pcm_hw_params_set_format(pcm, hwparams,
- SND_PCM_FORMAT_S32);
- if (err == 0) {
- g_debug("converting format %s to 32 bit\n",
- sample_format_to_string(audio_format->format));
- audio_format->format = SAMPLE_FORMAT_S32;
- }
- }
+ err = alsa_output_try_reverse(pcm, hwparams, audio_format,
+ audio_format->format);
+ if (err != -EINVAL)
+ return err;
- if (err == -EINVAL && (audio_format->format == SAMPLE_FORMAT_S24_P32 ||
- audio_format->format == SAMPLE_FORMAT_S16)) {
+ if (audio_format->format == SAMPLE_FORMAT_S24_P32 ||
+ audio_format->format == SAMPLE_FORMAT_S16) {
/* fall back to 32 bit, let pcm_convert.c do the conversion */
- err = snd_pcm_hw_params_set_format(pcm, hwparams,
- byteswap_bitformat(SND_PCM_FORMAT_S32));
- if (err == 0) {
- g_debug("converting format %s to 32 bit backward-endian\n",
- sample_format_to_string(audio_format->format));
- audio_format->format = SAMPLE_FORMAT_S32;
- audio_format->reverse_endian = 1;
- }
- }
- if (err == -EINVAL && audio_format->format != SAMPLE_FORMAT_S16) {
- /* fall back to 16 bit, let pcm_convert.c do the conversion */
- err = snd_pcm_hw_params_set_format(pcm, hwparams,
- SND_PCM_FORMAT_S16);
- if (err == 0) {
- g_debug("converting format %s to 16 bit\n",
- sample_format_to_string(audio_format->format));
- audio_format->format = SAMPLE_FORMAT_S16;
- }
+ err = alsa_output_try_format(pcm, hwparams, audio_format,
+ SAMPLE_FORMAT_S24_P32);
+ if (err != -EINVAL)
+ return err;
+
+ err = alsa_output_try_reverse(pcm, hwparams, audio_format,
+ SAMPLE_FORMAT_S24_P32);
+ if (err != -EINVAL)
+ return err;
}
- if (err == -EINVAL && audio_format->format != SAMPLE_FORMAT_S16) {
+ if (audio_format->format != SAMPLE_FORMAT_S16) {
/* fall back to 16 bit, let pcm_convert.c do the conversion */
- err = snd_pcm_hw_params_set_format(pcm, hwparams,
- byteswap_bitformat(SND_PCM_FORMAT_S16));
- if (err == 0) {
- g_debug("converting format %s to 16 bit backward-endian\n",
- sample_format_to_string(audio_format->format));
- audio_format->format = SAMPLE_FORMAT_S16;
- audio_format->reverse_endian = 1;
- }
+
+ err = alsa_output_try_format(pcm, hwparams, audio_format,
+ SAMPLE_FORMAT_S16);
+ if (err != -EINVAL)
+ return err;
+
+ err = alsa_output_try_reverse(pcm, hwparams, audio_format,
+ SAMPLE_FORMAT_S16);
+ if (err != -EINVAL)
+ return err;
}
- return err;
+ return -EINVAL;
}
/**