use std::ffi::CString;
use std::path::Path;
use transcribe_cpp_sys as sys;
use crate::error::{check, Result};
use crate::result::{owned_opt_str, owned_str};
use crate::types::Backend;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum DeviceType {
Cpu,
Gpu,
Igpu,
Accel,
Unknown,
}
impl DeviceType {
fn from_raw(raw: sys::transcribe_device_type) -> Self {
use sys::transcribe_device_type as T;
match raw {
T::TRANSCRIBE_DEVICE_TYPE_CPU => DeviceType::Cpu,
T::TRANSCRIBE_DEVICE_TYPE_GPU => DeviceType::Gpu,
T::TRANSCRIBE_DEVICE_TYPE_IGPU => DeviceType::Igpu,
T::TRANSCRIBE_DEVICE_TYPE_ACCEL => DeviceType::Accel,
_ => DeviceType::Unknown,
}
}
}
#[derive(Debug, Clone)]
pub struct Device {
pub name: String,
pub description: String,
pub kind: String,
pub device_type: DeviceType,
pub device_id: Option<String>,
pub memory_total: u64,
pub memory_free: u64,
pub index: Option<usize>,
pub(crate) handle: sys::transcribe_device_t,
}
unsafe impl Send for Device {}
unsafe impl Sync for Device {}
impl PartialEq for Device {
fn eq(&self, other: &Self) -> bool {
self.handle == other.handle
}
}
impl Eq for Device {}
impl Device {
pub(crate) fn from_raw(
raw: &sys::transcribe_device_info,
handle: sys::transcribe_device_t,
index: Option<usize>,
) -> Device {
Device {
name: owned_str(raw.name),
description: owned_str(raw.description),
kind: owned_str(raw.kind),
device_type: DeviceType::from_raw(raw.device_type),
device_id: owned_opt_str(raw.device_id),
memory_total: raw.memory_total,
memory_free: raw.memory_free,
index,
handle,
}
}
}
pub fn init_backends(dir: impl AsRef<Path>) -> Result<()> {
let dir = dir.as_ref();
let c_dir = CString::new(crate::model::path_bytes(dir)?)?;
let status = unsafe { sys::transcribe_init_backends(c_dir.as_ptr()) };
check(status, "init_backends")
}
pub fn init_backends_default() -> Result<()> {
let status = unsafe { sys::transcribe_init_backends_default() };
check(status, "init_backends_default")
}
pub fn device_count() -> usize {
let n = unsafe { sys::transcribe_device_count() };
n.max(0) as usize
}
pub fn devices() -> Vec<Device> {
let mut out = Vec::with_capacity(device_count());
for i in 0..device_count() as i32 {
let handle = unsafe { sys::transcribe_device_get(i) };
if handle.is_null() {
continue;
}
let mut raw: sys::transcribe_device_info = unsafe { std::mem::zeroed() };
unsafe { sys::transcribe_device_info_init(&mut raw) };
let status = unsafe { sys::transcribe_device_get_info(handle, &mut raw) };
if status == sys::transcribe_status::TRANSCRIBE_OK {
out.push(Device::from_raw(&raw, handle, Some(i as usize)));
}
}
out
}
pub fn backend_available(backend: Backend) -> bool {
unsafe { sys::transcribe_backend_available(backend.to_raw()) }
}