lib/alsa/Error: a std::system_error category for libasound errors

This commit is contained in:
Max Kellermann
2021-11-04 14:40:02 +01:00
parent 5ff0bbd0f8
commit 5d0941476a
8 changed files with 157 additions and 83 deletions

44
src/lib/alsa/Error.cxx Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright 2021 Max Kellermann <max.kellermann@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Error.hxx"
#include <alsa/error.h>
namespace Alsa {
ErrorCategory error_category;
std::string
ErrorCategory::message(int condition) const
{
return snd_strerror(condition);
}
} // namespace Avahi

53
src/lib/alsa/Error.hxx Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright 2021 Max Kellermann <max.kellermann@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <system_error>
namespace Alsa {
class ErrorCategory final : public std::error_category {
public:
const char *name() const noexcept override {
return "libasound";
}
std::string message(int condition) const override;
};
extern ErrorCategory error_category;
inline std::system_error
MakeError(int error, const char *msg) noexcept
{
return std::system_error(error, error_category, msg);
}
} // namespace Avahi

View File

@@ -18,6 +18,7 @@
*/
#include "HwSetup.hxx"
#include "Error.hxx"
#include "Format.hxx"
#include "util/ByteOrder.hxx"
#include "util/Domain.hxx"
@@ -185,29 +186,27 @@ SetupHw(snd_pcm_t *pcm,
/* configure HW params */
err = snd_pcm_hw_params_any(pcm, hwparams);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_any() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_hw_params_any() failed");
err = snd_pcm_hw_params_set_access(pcm, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_set_access() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_hw_params_set_access() failed");
err = SetupSampleFormat(pcm, hwparams,
audio_format.format, params);
if (err < 0)
throw FormatRuntimeError("Failed to configure format %s: %s",
sample_format_to_string(audio_format.format),
snd_strerror(-err));
throw Alsa::MakeError(err,
fmt::format("Failed to configure format {}",
audio_format.format).c_str());
unsigned int channels = audio_format.channels;
err = snd_pcm_hw_params_set_channels_near(pcm, hwparams,
&channels);
if (err < 0)
throw FormatRuntimeError("Failed to configure %i channels: %s",
(int)audio_format.channels,
snd_strerror(-err));
throw Alsa::MakeError(err,
fmt::format("Failed to configure {} channels",
audio_format.channels).c_str());
audio_format.channels = (int8_t)channels;
@@ -218,9 +217,9 @@ SetupHw(snd_pcm_t *pcm,
err = snd_pcm_hw_params_set_rate_near(pcm, hwparams,
&output_sample_rate, nullptr);
if (err < 0)
throw FormatRuntimeError("Failed to configure sample rate %u Hz: %s",
requested_sample_rate,
snd_strerror(-err));
throw Alsa::MakeError(err,
fmt::format("Failed to configure sample rate {} Hz",
requested_sample_rate).c_str());
if (output_sample_rate == 0)
throw FormatRuntimeError("Failed to configure sample rate %u Hz",
@@ -253,8 +252,7 @@ SetupHw(snd_pcm_t *pcm,
err = snd_pcm_hw_params_set_buffer_time_near(pcm, hwparams,
&buffer_time, nullptr);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_set_buffer_time_near() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_hw_params_set_buffer_time_near() failed");
} else {
err = snd_pcm_hw_params_get_buffer_time(hwparams, &buffer_time,
nullptr);
@@ -275,32 +273,27 @@ SetupHw(snd_pcm_t *pcm,
err = snd_pcm_hw_params_set_period_time_near(pcm, hwparams,
&period_time, nullptr);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_set_period_time_near() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_hw_params_set_period_time_near() failed");
}
err = snd_pcm_hw_params(pcm, hwparams);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_hw_params() failed");
HwResult result;
err = snd_pcm_hw_params_get_format(hwparams, &result.format);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_get_format() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_hw_params_get_format() failed");
err = snd_pcm_hw_params_get_buffer_size(hwparams, &result.buffer_size);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_get_buffer_size() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_hw_params_get_buffer_size() failed");
err = snd_pcm_hw_params_get_period_size(hwparams, &result.period_size,
nullptr);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_get_period_size() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_hw_params_get_period_size() failed");
return result;
}

View File

@@ -18,6 +18,7 @@
*/
#include "NonBlock.hxx"
#include "Error.hxx"
#include "event/MultiSocketMonitor.hxx"
#include "util/RuntimeError.hxx"
@@ -29,8 +30,7 @@ AlsaNonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
if (count == 0)
throw std::runtime_error("snd_pcm_poll_descriptors_count() failed");
else
throw FormatRuntimeError("snd_pcm_poll_descriptors_count() failed: %s",
snd_strerror(-count));
throw Alsa::MakeError(count, "snd_pcm_poll_descriptors_count() failed");
}
struct pollfd *pfds = pfd_buffer.Get(count);
@@ -40,8 +40,7 @@ AlsaNonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
if (count == 0)
throw std::runtime_error("snd_pcm_poll_descriptors() failed");
else
throw FormatRuntimeError("snd_pcm_poll_descriptors() failed: %s",
snd_strerror(-count));
throw Alsa::MakeError(count, "snd_pcm_poll_descriptors() failed");
}
m.ReplaceSocketList(pfds, count);
@@ -71,8 +70,7 @@ AlsaNonBlockPcm::DispatchSockets(MultiSocketMonitor &m,
unsigned short dummy;
int err = snd_pcm_poll_descriptors_revents(pcm, pfds, i - pfds, &dummy);
if (err < 0)
throw FormatRuntimeError("snd_pcm_poll_descriptors_revents() failed: %s",
snd_strerror(-err));
throw Alsa::MakeError(err, "snd_pcm_poll_descriptors_revents() failed");
}
Event::Duration

View File

@@ -14,6 +14,7 @@ conf.set('ENABLE_ALSA', true)
alsa = static_library(
'alsa',
'Version.cxx',
'Error.cxx',
'AllowedFormat.cxx',
'HwSetup.cxx',
'NonBlock.cxx',