// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// Cross-platform host identifiers.
///
/// Ported from upstream `cpal::platform::HostId` (string representation is used for
/// cross-platform matching).
///|
pub suberror HostUnavailable {
HostUnavailable
} derive(Debug, Eq)
///|
pub fn HostUnavailable::to_string(self : HostUnavailable) -> String {
match self {
HostUnavailable => "the requested host is unavailable"
}
}
///|
pub(all) enum HostId {
AAudio
Alsa
Asio
CoreAudio
Custom
Emscripten
Jack
Null
Wasapi
WebAudio
AudioWorklet
} derive(Debug, Eq)
///|
/// Upstream `HostId::name()` returns the variant name (before lowercase display).
pub fn HostId::name(self : HostId) -> String {
match self {
AAudio => "AAudio"
Alsa => "Alsa"
Asio => "Asio"
CoreAudio => "CoreAudio"
Custom => "Custom"
Emscripten => "Emscripten"
Jack => "Jack"
Null => "Null"
Wasapi => "Wasapi"
WebAudio => "WebAudio"
AudioWorklet => "AudioWorklet"
}
}
///|
fn ascii_lower(c : Char) -> Int {
let x = c.to_int()
if 65 <= x && x <= 90 {
x + 32
} else {
x
}
}
///|
fn eq_ignore_ascii_case(a : StringView, b : StringView) -> Bool {
if a.length() != b.length() {
return false
}
let mut i = 0
while i < a.length() {
let ca = a.get_char(i)
let cb = b.get_char(i)
match (ca, cb) {
(Some(x), Some(y)) => if ascii_lower(x) != ascii_lower(y) { return false }
_ => return false
}
i += 1
}
true
}
///|
pub fn HostId::to_string(self : HostId) -> String {
match self {
AAudio => "aaudio"
Alsa => "alsa"
Asio => "asio"
CoreAudio => "coreaudio"
Custom => "custom"
Emscripten => "emscripten"
Jack => "jack"
Null => "null"
Wasapi => "wasapi"
WebAudio => "webaudio"
AudioWorklet => "audioworklet"
}
}
///|
pub fn HostId::from_view(v : StringView) -> HostId? {
if eq_ignore_ascii_case(v, "aaudio") {
Some(AAudio)
} else if eq_ignore_ascii_case(v, "alsa") {
Some(Alsa)
} else if eq_ignore_ascii_case(v, "asio") {
Some(Asio)
} else if eq_ignore_ascii_case(v, "coreaudio") {
Some(CoreAudio)
} else if eq_ignore_ascii_case(v, "custom") {
Some(Custom)
} else if eq_ignore_ascii_case(v, "emscripten") {
Some(Emscripten)
} else if eq_ignore_ascii_case(v, "jack") {
Some(Jack)
} else if eq_ignore_ascii_case(v, "null") {
Some(Null)
} else if eq_ignore_ascii_case(v, "wasapi") {
Some(Wasapi)
} else if eq_ignore_ascii_case(v, "webaudio") {
Some(WebAudio)
} else if eq_ignore_ascii_case(v, "audioworklet") {
Some(AudioWorklet)
} else {
None
}
}
///|
pub fn HostId::from_string(s : String) -> HostId? {
HostId::from_view(s[:])
}
///|
pub fn HostId::parse(s : String) -> HostId raise HostUnavailable {
match HostId::from_string(s) {
Some(id) => id
None => raise HostUnavailable
}
}
///|
pub fn host_unavailable() -> HostUnavailable {
HostUnavailable
}