input/alsa: use std::string_view in class SourceSpec

This commit is contained in:
Max Kellermann 2025-01-30 12:51:10 +01:00
parent 7ca8dedb35
commit 459390cd56

@ -17,8 +17,8 @@
#include "event/Call.hxx" #include "event/Call.hxx"
#include "config/Block.hxx" #include "config/Block.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "util/ASCII.hxx" #include "util/StringCompare.hxx"
#include "util/DivideString.hxx" #include "util/StringSplit.hxx"
#include "pcm/AudioParser.hxx" #include "pcm/AudioParser.hxx"
#include "pcm/AudioFormat.hxx" #include "pcm/AudioFormat.hxx"
#include "Log.hxx" #include "Log.hxx"
@ -33,6 +33,8 @@
#include <string.h> #include <string.h>
using std::string_view_literals::operator""sv;
static constexpr Domain alsa_input_domain("alsa"); static constexpr Domain alsa_input_domain("alsa");
static constexpr auto ALSA_URI_PREFIX = "alsa://"; static constexpr auto ALSA_URI_PREFIX = "alsa://";
@ -105,7 +107,7 @@ protected:
} }
private: private:
void OpenDevice(const SourceSpec &spec); void OpenDevice(const AudioFormat &audio_format);
void ConfigureCapture(AudioFormat audio_format); void ConfigureCapture(AudioFormat audio_format);
void Pause() { void Pause() {
@ -122,47 +124,44 @@ private:
class AlsaInputStream::SourceSpec { class AlsaInputStream::SourceSpec {
const char *uri; std::string_view uri;
const char *device_name; std::string_view device_name;
const char *format_string; std::string_view format_string;
AudioFormat audio_format; AudioFormat audio_format;
DivideString components;
public: public:
explicit SourceSpec(const char *_uri) [[nodiscard]]
explicit SourceSpec(std::string_view _uri)
: uri(_uri) : uri(_uri)
, components(uri, '?')
{ {
if (components.IsDefined()) { const auto [a, b] = Split(uri, '?');
device_name = StringAfterPrefixCaseASCII(components.GetFirst(), device_name = StringAfterPrefixIgnoreCase(a, ALSA_URI_PREFIX);
ALSA_URI_PREFIX);
format_string = StringAfterPrefixCaseASCII(components.GetSecond(), if (b.data() != nullptr)
"format="); format_string = StringAfterPrefixIgnoreCase(b, "format="sv);
} else if (global_config.default_format != nullptr)
else {
device_name = StringAfterPrefixCaseASCII(uri, ALSA_URI_PREFIX);
format_string = global_config.default_format; format_string = global_config.default_format;
}
if (IsValidScheme()) { if (IsValidScheme()) {
if (*device_name == 0) if (device_name.empty())
device_name = global_config.default_device; device_name = global_config.default_device;
if (format_string != nullptr) if (format_string.data() != nullptr)
audio_format = ParseAudioFormat(format_string, false); audio_format = ParseAudioFormat(format_string, false);
} }
} }
[[nodiscard]] bool IsValidScheme() const noexcept { [[nodiscard]] bool IsValidScheme() const noexcept {
return device_name != nullptr; return device_name.data() != nullptr;
} }
[[nodiscard]] bool IsValid() const noexcept { [[nodiscard]] bool IsValid() const noexcept {
return (device_name != nullptr) && (format_string != nullptr); return device_name.data() != nullptr && format_string.data() != nullptr;
} }
[[nodiscard]] const char *GetURI() const noexcept { [[nodiscard]] std::string_view GetURI() const noexcept {
return uri; return uri;
} }
[[nodiscard]] const char *GetDeviceName() const noexcept { [[nodiscard]] std::string_view GetDeviceName() const noexcept {
return device_name; return device_name;
} }
[[nodiscard]] const char *GetFormatString() const noexcept { [[nodiscard]] std::string_view GetFormatString() const noexcept {
return format_string; return format_string;
} }
[[nodiscard]] AudioFormat GetAudioFormat() const noexcept { [[nodiscard]] AudioFormat GetAudioFormat() const noexcept {
@ -182,7 +181,7 @@ AlsaInputStream::AlsaInputStream(EventLoop &_loop,
defer_invalidate_sockets(_loop, defer_invalidate_sockets(_loop,
BIND_THIS_METHOD(InvalidateSockets)) BIND_THIS_METHOD(InvalidateSockets))
{ {
OpenDevice(spec); OpenDevice(spec.GetAudioFormat());
SetMimeType(fmt::format("audio/x-mpd-alsa-pcm;format={}", SetMimeType(fmt::format("audio/x-mpd-alsa-pcm;format={}",
spec.GetFormatString())); spec.GetFormatString()));
@ -403,19 +402,19 @@ AlsaInputStream::ConfigureCapture(AudioFormat audio_format)
} }
inline void inline void
AlsaInputStream::OpenDevice(const SourceSpec &spec) AlsaInputStream::OpenDevice(const AudioFormat &audio_format)
{ {
int err; int err;
if ((err = snd_pcm_open(&capture_handle, spec.GetDeviceName(), if ((err = snd_pcm_open(&capture_handle, device.c_str(),
SND_PCM_STREAM_CAPTURE, SND_PCM_STREAM_CAPTURE,
SND_PCM_NONBLOCK | global_config.mode)) < 0) SND_PCM_NONBLOCK | global_config.mode)) < 0)
throw Alsa::MakeError(err, throw Alsa::MakeError(err,
FmtBuffer<256>("Failed to open device {}", FmtBuffer<256>("Failed to open device {}",
spec.GetDeviceName())); device));
try { try {
ConfigureCapture(spec.GetAudioFormat()); ConfigureCapture(audio_format);
} catch (...) { } catch (...) {
snd_pcm_close(capture_handle); snd_pcm_close(capture_handle);
throw; throw;