// 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.
///|
/// Native FFI hooks for WASAPI (Windows).
///|
extern "C" fn wasapi_devices_utf8() -> Bytes = "moon_cpal_wasapi_devices_utf8"
///|
extern "C" fn wasapi_default_device_id_utf8(is_input : Int) -> Bytes = "moon_cpal_wasapi_default_device_id_utf8"
///|
#owned(device_id_utf8)
extern "C" fn wasapi_device_name_utf8_len(
device_id_utf8 : Bytes,
device_id_len : Int,
) -> Int = "moon_cpal_wasapi_device_name_utf8_len"
///|
#borrow(out)
#owned(device_id_utf8)
extern "C" fn wasapi_device_name_utf8(
device_id_utf8 : Bytes,
device_id_len : Int,
out : Bytes,
out_len : Int,
) -> Int = "moon_cpal_wasapi_device_name_utf8"
///|
#owned(device_id_utf8)
extern "C" fn wasapi_device_form_factor_u32(
device_id_utf8 : Bytes,
device_id_len : Int,
) -> UInt = "moon_cpal_wasapi_device_form_factor_u32"
///|
#owned(device_id_utf8)
extern "C" fn wasapi_device_property_utf8_len(
device_id_utf8 : Bytes,
device_id_len : Int,
prop_tag : Int,
) -> Int = "moon_cpal_wasapi_device_property_utf8_len"
///|
#borrow(out)
#owned(device_id_utf8)
extern "C" fn wasapi_device_property_utf8(
device_id_utf8 : Bytes,
device_id_len : Int,
prop_tag : Int,
out : Bytes,
out_len : Int,
) -> Int = "moon_cpal_wasapi_device_property_utf8"
///|
#borrow(out)
#owned(device_id_utf8)
extern "C" fn wasapi_default_config_u32(
device_id_utf8 : Bytes,
device_id_len : Int,
is_input : Int,
out : FixedArray[UInt],
out_len : Int,
) -> Int = "moon_cpal_wasapi_default_config_u32"
///|
#owned(device_id_utf8)
extern "C" fn wasapi_device_data_flow_tag(
device_id_utf8 : Bytes,
device_id_len : Int,
) -> Int = "moon_cpal_wasapi_device_data_flow_tag"
///|
#borrow(out)
#owned(device_id_utf8)
extern "C" fn wasapi_default_config_ex_u32(
device_id_utf8 : Bytes,
device_id_len : Int,
is_input : Int,
out : FixedArray[UInt],
out_len : Int,
) -> Int = "moon_cpal_wasapi_default_config_ex_u32"
///|
#borrow(out)
#owned(device_id_utf8)
extern "C" fn wasapi_supported_configs_u32(
device_id_utf8 : Bytes,
device_id_len : Int,
is_input : Int,
out : FixedArray[UInt],
out_len : Int,
) -> Int = "moon_cpal_wasapi_supported_configs_u32"
///|
pub fn devices_utf8() -> Bytes {
wasapi_devices_utf8()
}
///|
pub fn default_device_id_utf8(is_input : Bool) -> String? {
let b = wasapi_default_device_id_utf8(if is_input { 1 } else { 0 })
if b.length() <= 0 {
None
} else {
Some(@core.utf8_bytes_to_string(b, b.length()))
}
}
///|
pub fn device_name_utf8(id : String) -> String? {
if id.length() == 0 {
return None
}
let b1 = @core.string_to_utf8_bytes(id)
let id_len = b1.length()
let n = wasapi_device_name_utf8_len(b1, id_len)
if n <= 0 {
return None
}
let out = Bytes::make(n, (0 : Int).to_byte())
let b2 = @core.string_to_utf8_bytes(id)
let used = wasapi_device_name_utf8(b2, id_len, out, out.length())
if used <= 0 {
return None
}
let need = if used > out.length() { out.length() } else { used }
Some(@core.utf8_bytes_to_string(out, need))
}
///|
pub fn device_form_factor_u32(id : String) -> UInt? {
if id.length() == 0 {
return None
}
let b = @core.string_to_utf8_bytes(id)
let v = wasapi_device_form_factor_u32(b, b.length())
if v == 0xFFFFFFFF {
None
} else {
Some(v)
}
}
///|
pub fn device_property_utf8(id : String, prop_tag : Int) -> String? {
if id.length() == 0 {
return None
}
let b1 = @core.string_to_utf8_bytes(id)
let id_len = b1.length()
let n = wasapi_device_property_utf8_len(b1, id_len, prop_tag)
if n <= 0 {
return None
}
let out = Bytes::make(n, (0 : Int).to_byte())
let b2 = @core.string_to_utf8_bytes(id)
let used = wasapi_device_property_utf8(
b2,
id_len,
prop_tag,
out,
out.length(),
)
if used <= 0 {
return None
}
let need = if used > out.length() { out.length() } else { used }
Some(@core.utf8_bytes_to_string(out, need))
}
///|
pub fn default_config_u32(id : String, is_input : Bool) -> (UInt, UInt, UInt)? {
let b = @core.string_to_utf8_bytes(id)
let out = FixedArray::make(3, (0 : UInt))
let st = wasapi_default_config_u32(
b,
b.length(),
if is_input {
1
} else {
0
},
out,
3,
)
if st < 0 {
None
} else {
Some((out[0], out[1], out[2]))
}
}
///|
pub fn data_flow_tag(id : String) -> Int? {
let b = @core.string_to_utf8_bytes(id)
let st = wasapi_device_data_flow_tag(b, b.length())
if st <= 0 {
None
} else {
Some(st)
}
}
///|
pub fn default_config_ex_u32(
id : String,
is_input : Bool,
) -> (UInt, UInt, UInt, UInt, UInt)? {
let b = @core.string_to_utf8_bytes(id)
let out = FixedArray::make(5, (0 : UInt))
let st = wasapi_default_config_ex_u32(
b,
b.length(),
if is_input {
1
} else {
0
},
out,
5,
)
if st < 0 {
None
} else {
Some((out[0], out[1], out[2], out[3], out[4]))
}
}
///|
pub fn supported_configs_u32(
id : String,
is_input : Bool,
) -> (Int, FixedArray[UInt])? {
// 21 sample rates * 2 formats => 42 entries, each uses 5 u32s.
let out = FixedArray::make(5 * 64, (0 : UInt))
let b = @core.string_to_utf8_bytes(id)
let st = wasapi_supported_configs_u32(
b,
b.length(),
if is_input {
1
} else {
0
},
out,
out.length(),
)
if st < 0 {
None
} else {
Some((st, out))
}
}