From b30c37eb7996749b5106261fc18729cc7ae5f273 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 26 Oct 2017 09:30:37 +0200 Subject: [PATCH] output/alsa: move functions to lib/alsa/Format.hxx --- Makefile.am | 1 + src/lib/alsa/Format.hxx | 132 ++++++++++++++++++++++++ src/output/plugins/AlsaOutputPlugin.cxx | 100 +----------------- 3 files changed, 134 insertions(+), 99 deletions(-) create mode 100644 src/lib/alsa/Format.hxx diff --git a/Makefile.am b/Makefile.am index c9e5a82f5..635802241 100644 --- a/Makefile.am +++ b/Makefile.am @@ -258,6 +258,7 @@ UPNP_SOURCES = \ ALSA_SOURCES = \ src/lib/alsa/Version.cxx src/lib/alsa/Version.hxx \ + src/lib/alsa/Format.hxx \ src/lib/alsa/PeriodBuffer.hxx \ src/lib/alsa/NonBlock.cxx src/lib/alsa/NonBlock.hxx diff --git a/src/lib/alsa/Format.hxx b/src/lib/alsa/Format.hxx new file mode 100644 index 000000000..0fa79e69f --- /dev/null +++ b/src/lib/alsa/Format.hxx @@ -0,0 +1,132 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ALSA_FORMAT_HXX +#define MPD_ALSA_FORMAT_HXX + +#include "check.h" +#include "pcm/SampleFormat.hxx" +#include "Compiler.h" + +#include + +#include + +/** + * Convert MPD's #SampleFormat enum to libasound's snd_pcm_format_t + * enum. Returns SND_PCM_FORMAT_UNKNOWN if there is no according ALSA + * PCM format. + */ +gcc_const +inline snd_pcm_format_t +ToAlsaPcmFormat(SampleFormat sample_format) noexcept +{ + switch (sample_format) { + case SampleFormat::UNDEFINED: + return SND_PCM_FORMAT_UNKNOWN; + + case SampleFormat::DSD: +#ifdef HAVE_ALSA_DSD + return SND_PCM_FORMAT_DSD_U8; +#else + return SND_PCM_FORMAT_UNKNOWN; +#endif + + case SampleFormat::S8: + return SND_PCM_FORMAT_S8; + + case SampleFormat::S16: + return SND_PCM_FORMAT_S16; + + case SampleFormat::S24_P32: + return SND_PCM_FORMAT_S24; + + case SampleFormat::S32: + return SND_PCM_FORMAT_S32; + + case SampleFormat::FLOAT: + return SND_PCM_FORMAT_FLOAT; + } + + assert(false); + gcc_unreachable(); +} + +/** + * Determine the byte-swapped PCM format. Returns + * SND_PCM_FORMAT_UNKNOWN if the format cannot be byte-swapped. + */ +gcc_const +inline snd_pcm_format_t +ByteSwapAlsaPcmFormat(snd_pcm_format_t fmt) noexcept +{ + switch (fmt) { + case SND_PCM_FORMAT_S16_LE: return SND_PCM_FORMAT_S16_BE; + case SND_PCM_FORMAT_S24_LE: return SND_PCM_FORMAT_S24_BE; + case SND_PCM_FORMAT_S32_LE: return SND_PCM_FORMAT_S32_BE; + case SND_PCM_FORMAT_S16_BE: return SND_PCM_FORMAT_S16_LE; + case SND_PCM_FORMAT_S24_BE: return SND_PCM_FORMAT_S24_LE; + + case SND_PCM_FORMAT_S24_3BE: + return SND_PCM_FORMAT_S24_3LE; + + case SND_PCM_FORMAT_S24_3LE: + return SND_PCM_FORMAT_S24_3BE; + + case SND_PCM_FORMAT_S32_BE: return SND_PCM_FORMAT_S32_LE; + +#ifdef HAVE_ALSA_DSD_U32 + case SND_PCM_FORMAT_DSD_U16_LE: + return SND_PCM_FORMAT_DSD_U16_BE; + + case SND_PCM_FORMAT_DSD_U16_BE: + return SND_PCM_FORMAT_DSD_U16_LE; + + case SND_PCM_FORMAT_DSD_U32_LE: + return SND_PCM_FORMAT_DSD_U32_BE; + + case SND_PCM_FORMAT_DSD_U32_BE: + return SND_PCM_FORMAT_DSD_U32_LE; +#endif + + default: return SND_PCM_FORMAT_UNKNOWN; + } +} + +/** + * Check if there is a "packed" version of the give PCM format. + * Returns SND_PCM_FORMAT_UNKNOWN if not. + */ +gcc_const +inline snd_pcm_format_t +PackAlsaPcmFormat(snd_pcm_format_t fmt) noexcept +{ + switch (fmt) { + case SND_PCM_FORMAT_S24_LE: + return SND_PCM_FORMAT_S24_3LE; + + case SND_PCM_FORMAT_S24_BE: + return SND_PCM_FORMAT_S24_3BE; + + default: + return SND_PCM_FORMAT_UNKNOWN; + } +} + +#endif diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index 893f46a39..ad9bf7599 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "AlsaOutputPlugin.hxx" +#include "lib/alsa/Format.hxx" #include "lib/alsa/NonBlock.hxx" #include "lib/alsa/PeriodBuffer.hxx" #include "lib/alsa/Version.hxx" @@ -366,105 +367,6 @@ alsa_test_default_device() return true; } -/** - * Convert MPD's #SampleFormat enum to libasound's snd_pcm_format_t - * enum. Returns SND_PCM_FORMAT_UNKNOWN if there is no according ALSA - * PCM format. - */ -gcc_const -static snd_pcm_format_t -ToAlsaPcmFormat(SampleFormat sample_format) noexcept -{ - switch (sample_format) { - case SampleFormat::UNDEFINED: - return SND_PCM_FORMAT_UNKNOWN; - - case SampleFormat::DSD: -#ifdef HAVE_ALSA_DSD - return SND_PCM_FORMAT_DSD_U8; -#else - return SND_PCM_FORMAT_UNKNOWN; -#endif - - case SampleFormat::S8: - return SND_PCM_FORMAT_S8; - - case SampleFormat::S16: - return SND_PCM_FORMAT_S16; - - case SampleFormat::S24_P32: - return SND_PCM_FORMAT_S24; - - case SampleFormat::S32: - return SND_PCM_FORMAT_S32; - - case SampleFormat::FLOAT: - return SND_PCM_FORMAT_FLOAT; - } - - assert(false); - gcc_unreachable(); -} - -/** - * Determine the byte-swapped PCM format. Returns - * SND_PCM_FORMAT_UNKNOWN if the format cannot be byte-swapped. - */ -static snd_pcm_format_t -ByteSwapAlsaPcmFormat(snd_pcm_format_t fmt) noexcept -{ - switch (fmt) { - case SND_PCM_FORMAT_S16_LE: return SND_PCM_FORMAT_S16_BE; - case SND_PCM_FORMAT_S24_LE: return SND_PCM_FORMAT_S24_BE; - case SND_PCM_FORMAT_S32_LE: return SND_PCM_FORMAT_S32_BE; - case SND_PCM_FORMAT_S16_BE: return SND_PCM_FORMAT_S16_LE; - case SND_PCM_FORMAT_S24_BE: return SND_PCM_FORMAT_S24_LE; - - case SND_PCM_FORMAT_S24_3BE: - return SND_PCM_FORMAT_S24_3LE; - - case SND_PCM_FORMAT_S24_3LE: - return SND_PCM_FORMAT_S24_3BE; - - case SND_PCM_FORMAT_S32_BE: return SND_PCM_FORMAT_S32_LE; - -#ifdef HAVE_ALSA_DSD_U32 - case SND_PCM_FORMAT_DSD_U16_LE: - return SND_PCM_FORMAT_DSD_U16_BE; - - case SND_PCM_FORMAT_DSD_U16_BE: - return SND_PCM_FORMAT_DSD_U16_LE; - - case SND_PCM_FORMAT_DSD_U32_LE: - return SND_PCM_FORMAT_DSD_U32_BE; - - case SND_PCM_FORMAT_DSD_U32_BE: - return SND_PCM_FORMAT_DSD_U32_LE; -#endif - - default: return SND_PCM_FORMAT_UNKNOWN; - } -} - -/** - * Check if there is a "packed" version of the give PCM format. - * Returns SND_PCM_FORMAT_UNKNOWN if not. - */ -static snd_pcm_format_t -PackAlsaPcmFormat(snd_pcm_format_t fmt) -{ - switch (fmt) { - case SND_PCM_FORMAT_S24_LE: - return SND_PCM_FORMAT_S24_3LE; - - case SND_PCM_FORMAT_S24_BE: - return SND_PCM_FORMAT_S24_3BE; - - default: - return SND_PCM_FORMAT_UNKNOWN; - } -} - /** * Attempts to configure the specified sample format. On failure, * fall back to the packed version.