use std::ffi::c_char;
use blazen_uniffi::errors::BlazenError as InnerError;
use crate::compute::{BlazenImageGenModel, BlazenSttModel, BlazenTtsModel};
use crate::error::BlazenError;
use crate::string::{cstr_to_opt_string, cstr_to_str};
fn write_error(out_err: *mut *mut BlazenError, err: InnerError) -> i32 {
if !out_err.is_null() {
unsafe {
*out_err = BlazenError::from(err).into_ptr();
}
}
-1
}
fn write_internal_error(out_err: *mut *mut BlazenError, message: &str) -> i32 {
write_error(
out_err,
InnerError::Internal {
message: message.to_owned(),
},
)
}
#[inline]
fn opt_u32_from_i32(v: i32) -> Option<u32> {
if v < 0 {
None
} else {
Some(u32::try_from(v).unwrap_or(0))
}
}
#[inline]
fn opt_f32_from_f32(v: f32) -> Option<f32> {
if v.is_nan() { None } else { Some(v) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tts_model_new_fal(
api_key: *const c_char,
model: *const c_char,
out_model: *mut *mut BlazenTtsModel,
out_err: *mut *mut BlazenError,
) -> i32 {
let Some(api_key) = (unsafe { cstr_to_str(api_key) }) else {
return write_internal_error(
out_err,
"blazen_tts_model_new_fal: api_key must not be null",
);
};
let api_key = api_key.to_owned();
let model = unsafe { cstr_to_opt_string(model) };
match blazen_uniffi::compute::new_fal_tts_model(api_key, model) {
Ok(arc) => {
if !out_model.is_null() {
unsafe {
*out_model = BlazenTtsModel::from(arc).into_ptr();
}
}
0
}
Err(e) => write_error(out_err, e),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_stt_model_new_fal(
api_key: *const c_char,
model: *const c_char,
out_model: *mut *mut BlazenSttModel,
out_err: *mut *mut BlazenError,
) -> i32 {
let Some(api_key) = (unsafe { cstr_to_str(api_key) }) else {
return write_internal_error(
out_err,
"blazen_stt_model_new_fal: api_key must not be null",
);
};
let api_key = api_key.to_owned();
let model = unsafe { cstr_to_opt_string(model) };
match blazen_uniffi::compute::new_fal_stt_model(api_key, model) {
Ok(arc) => {
if !out_model.is_null() {
unsafe {
*out_model = BlazenSttModel::from(arc).into_ptr();
}
}
0
}
Err(e) => write_error(out_err, e),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_image_gen_model_new_fal(
api_key: *const c_char,
model: *const c_char,
out_model: *mut *mut BlazenImageGenModel,
out_err: *mut *mut BlazenError,
) -> i32 {
let Some(api_key) = (unsafe { cstr_to_str(api_key) }) else {
return write_internal_error(
out_err,
"blazen_image_gen_model_new_fal: api_key must not be null",
);
};
let api_key = api_key.to_owned();
let model = unsafe { cstr_to_opt_string(model) };
match blazen_uniffi::compute::new_fal_image_gen_model(api_key, model) {
Ok(arc) => {
if !out_model.is_null() {
unsafe {
*out_model = BlazenImageGenModel::from(arc).into_ptr();
}
}
0
}
Err(e) => write_error(out_err, e),
}
}
#[cfg(feature = "piper")]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tts_model_new_piper(
model_id: *const c_char,
speaker_id: i32,
sample_rate: i32,
out_model: *mut *mut BlazenTtsModel,
out_err: *mut *mut BlazenError,
) -> i32 {
let model_id = unsafe { cstr_to_opt_string(model_id) };
let speaker_id = opt_u32_from_i32(speaker_id);
let sample_rate = opt_u32_from_i32(sample_rate);
match blazen_uniffi::compute::new_piper_tts_model(model_id, speaker_id, sample_rate) {
Ok(arc) => {
if !out_model.is_null() {
unsafe {
*out_model = BlazenTtsModel::from(arc).into_ptr();
}
}
0
}
Err(e) => write_error(out_err, e),
}
}
#[cfg(feature = "whispercpp")]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_stt_model_new_whisper(
model: *const c_char,
device: *const c_char,
language: *const c_char,
out_model: *mut *mut BlazenSttModel,
out_err: *mut *mut BlazenError,
) -> i32 {
let model = unsafe { cstr_to_opt_string(model) };
let device = unsafe { cstr_to_opt_string(device) };
let language = unsafe { cstr_to_opt_string(language) };
match blazen_uniffi::compute::new_whisper_stt_model(model, device, language) {
Ok(arc) => {
if !out_model.is_null() {
unsafe {
*out_model = BlazenSttModel::from(arc).into_ptr();
}
}
0
}
Err(e) => write_error(out_err, e),
}
}
#[cfg(feature = "diffusion")]
#[unsafe(no_mangle)]
#[allow(clippy::too_many_arguments)]
pub unsafe extern "C" fn blazen_image_gen_model_new_diffusion(
model_id: *const c_char,
device: *const c_char,
width: i32,
height: i32,
num_inference_steps: i32,
guidance_scale: f32,
out_model: *mut *mut BlazenImageGenModel,
out_err: *mut *mut BlazenError,
) -> i32 {
let model_id = unsafe { cstr_to_opt_string(model_id) };
let device = unsafe { cstr_to_opt_string(device) };
let width = opt_u32_from_i32(width);
let height = opt_u32_from_i32(height);
let num_inference_steps = opt_u32_from_i32(num_inference_steps);
let guidance_scale = opt_f32_from_f32(guidance_scale);
match blazen_uniffi::compute::new_diffusion_model(
model_id,
device,
width,
height,
num_inference_steps,
guidance_scale,
) {
Ok(arc) => {
if !out_model.is_null() {
unsafe {
*out_model = BlazenImageGenModel::from(arc).into_ptr();
}
}
0
}
Err(e) => write_error(out_err, e),
}
}