streamkit_plugin_sdk_native/
types.rs

1// SPDX-FileCopyrightText: © 2025 StreamKit Contributors
2//
3// SPDX-License-Identifier: MPL-2.0
4
5//! C ABI types for native plugins
6//!
7//! These types define the stable binary interface between the host and native plugins.
8//! The layout of these structs must remain stable across versions.
9
10use std::os::raw::{c_char, c_void};
11
12/// API version number. Plugins and host check compatibility via this field.
13pub const NATIVE_PLUGIN_API_VERSION: u32 = 2;
14
15/// Opaque handle to a plugin instance
16pub type CPluginHandle = *mut c_void;
17
18/// Log level for plugin logging
19#[repr(C)]
20#[derive(Debug, Copy, Clone, PartialEq, Eq)]
21pub enum CLogLevel {
22    Trace = 0,
23    Debug = 1,
24    Info = 2,
25    Warn = 3,
26    Error = 4,
27}
28
29/// Callback function type for plugin logging
30/// Parameters: (level, target, message, user_data)
31/// - level: The log level
32/// - target: Module path (e.g., "kokoro_plugin_native::kokoro_node")
33/// - message: The log message
34/// - user_data: Opaque pointer passed by host
35pub type CLogCallback = extern "C" fn(CLogLevel, *const c_char, *const c_char, *mut c_void);
36
37/// Result type for C ABI functions
38#[repr(C)]
39#[derive(Debug, Copy, Clone)]
40pub struct CResult {
41    pub success: bool,
42    /// Optional null-terminated error message.
43    ///
44    /// # Ownership
45    ///
46    /// This pointer is **borrowed** and must not be freed by the caller.
47    /// Callers should copy it immediately if they need to keep it.
48    pub error_message: *const c_char,
49}
50
51impl CResult {
52    pub const fn success() -> Self {
53        Self { success: true, error_message: std::ptr::null() }
54    }
55
56    pub const fn error(msg: *const c_char) -> Self {
57        Self { success: false, error_message: msg }
58    }
59}
60
61/// Audio sample format
62#[repr(C)]
63#[derive(Debug, Copy, Clone, PartialEq, Eq)]
64pub enum CSampleFormat {
65    F32 = 0,
66    S16Le = 1,
67}
68
69/// Audio format specification
70#[repr(C)]
71#[derive(Debug, Copy, Clone)]
72pub struct CAudioFormat {
73    pub sample_rate: u32,
74    pub channels: u16,
75    pub sample_format: CSampleFormat,
76}
77
78/// Packet type discriminant
79#[repr(C)]
80#[derive(Debug, Copy, Clone, PartialEq, Eq)]
81pub enum CPacketType {
82    RawAudio = 0,
83    OpusAudio = 1,
84    Text = 2,
85    Transcription = 3,
86    Custom = 4,
87    Binary = 5,
88    Any = 6,
89    Passthrough = 7,
90}
91
92/// Encoding for Custom packets.
93#[repr(C)]
94#[derive(Debug, Copy, Clone, PartialEq, Eq)]
95pub enum CCustomEncoding {
96    Json = 0,
97}
98
99/// Optional timing and sequencing metadata for packets.
100#[repr(C)]
101#[derive(Debug, Copy, Clone, Default)]
102pub struct CPacketMetadata {
103    pub timestamp_us: u64,
104    pub has_timestamp_us: bool,
105    pub duration_us: u64,
106    pub has_duration_us: bool,
107    pub sequence: u64,
108    pub has_sequence: bool,
109}
110
111/// Custom packet payload passed across the C ABI boundary.
112///
113/// `data_json` points to UTF-8 encoded JSON (not null-terminated).
114#[repr(C)]
115pub struct CCustomPacket {
116    pub type_id: *const c_char,
117    pub encoding: CCustomEncoding,
118    pub data_json: *const u8,
119    pub data_len: usize,
120    /// Optional metadata pointer (may be null).
121    pub metadata: *const CPacketMetadata,
122}
123
124/// Full packet type with optional format information
125/// For RawAudio, includes the audio format details
126#[repr(C)]
127#[derive(Debug, Copy, Clone)]
128pub struct CPacketTypeInfo {
129    pub type_discriminant: CPacketType,
130    /// For RawAudio: pointer to CAudioFormat, otherwise null
131    pub audio_format: *const CAudioFormat,
132    /// For Custom: pointer to a null-terminated type id string, otherwise null
133    pub custom_type_id: *const c_char,
134}
135
136/// Audio frame data (for RawAudio packets)
137#[repr(C)]
138pub struct CAudioFrame {
139    pub sample_rate: u32,
140    pub channels: u16,
141    pub samples: *const f32,
142    pub sample_count: usize,
143}
144
145/// Generic packet container
146/// The data field interpretation depends on packet_type
147#[repr(C)]
148pub struct CPacket {
149    pub packet_type: CPacketType,
150    pub data: *const c_void,
151    pub len: usize,
152}
153
154/// Input pin definition
155#[repr(C)]
156pub struct CInputPin {
157    pub name: *const c_char,
158    /// Array of accepted packet types with format info
159    pub accepts_types: *const CPacketTypeInfo,
160    pub accepts_types_count: usize,
161}
162
163/// Output pin definition
164#[repr(C)]
165pub struct COutputPin {
166    pub name: *const c_char,
167    pub produces_type: CPacketTypeInfo,
168}
169
170/// Node metadata returned by plugin
171#[repr(C)]
172pub struct CNodeMetadata {
173    pub kind: *const c_char,
174    /// Optional description of the node (null-terminated string, can be null)
175    pub description: *const c_char,
176    pub inputs: *const CInputPin,
177    pub inputs_count: usize,
178    pub outputs: *const COutputPin,
179    pub outputs_count: usize,
180    /// JSON schema for parameters (null-terminated string)
181    pub param_schema: *const c_char,
182    /// Array of category strings
183    pub categories: *const *const c_char,
184    pub categories_count: usize,
185}
186
187/// Callback function type for sending output packets
188/// Parameters: (pin_name, packet, user_data) -> CResult
189pub type COutputCallback = extern "C" fn(*const c_char, *const CPacket, *mut c_void) -> CResult;
190
191/// Callback function type for emitting telemetry events to the host.
192///
193/// Parameters:
194/// - `event_type`: null-terminated UTF-8 string (e.g., "vad.speech_start")
195/// - `data_json`: UTF-8 JSON bytes (not null-terminated)
196/// - `data_len`: length of `data_json`
197/// - `metadata`: optional packet-style metadata (may be null)
198/// - `user_data`: opaque pointer provided by the host
199pub type CTelemetryCallback = Option<
200    extern "C" fn(*const c_char, *const u8, usize, *const CPacketMetadata, *mut c_void) -> CResult,
201>;
202
203/// The main plugin API structure
204/// Plugins export a function that returns a pointer to this struct
205#[repr(C)]
206pub struct CNativePluginAPI {
207    /// API version for compatibility checking
208    pub version: u32,
209
210    /// Get metadata about the node type
211    /// Returns: Pointer to CNodeMetadata (must remain valid for plugin lifetime)
212    pub get_metadata: extern "C" fn() -> *const CNodeMetadata,
213
214    /// Create a new plugin instance
215    /// params: JSON string with initialization parameters (nullable)
216    /// log_callback: Callback for plugin to send log messages to host
217    /// log_user_data: Opaque pointer to pass to log callback
218    /// Returns: Opaque handle to the instance, or null on error
219    pub create_instance: extern "C" fn(*const c_char, CLogCallback, *mut c_void) -> CPluginHandle,
220
221    /// Process an incoming packet
222    /// handle: Plugin instance handle
223    /// input_pin: Name of the input pin
224    /// packet: The packet to process
225    /// output_callback: Callback to send output packets
226    /// callback_data: User data to pass to output callback
227    /// telemetry_callback: Callback to emit telemetry events
228    /// telemetry_user_data: User data to pass to telemetry callback
229    pub process_packet: extern "C" fn(
230        CPluginHandle,
231        *const c_char,
232        *const CPacket,
233        COutputCallback,
234        *mut c_void,
235        CTelemetryCallback,
236        *mut c_void,
237    ) -> CResult,
238
239    /// Update runtime parameters
240    /// handle: Plugin instance handle
241    /// params: JSON string with new parameters (nullable)
242    pub update_params: extern "C" fn(CPluginHandle, *const c_char) -> CResult,
243
244    /// Flush any buffered data (called when input stream ends)
245    /// handle: Plugin instance handle
246    /// output_callback: Callback to send output packets
247    /// callback_data: User data to pass to output callback
248    /// telemetry_callback: Callback to emit telemetry events
249    /// telemetry_user_data: User data to pass to telemetry callback
250    pub flush: extern "C" fn(
251        CPluginHandle,
252        COutputCallback,
253        *mut c_void,
254        CTelemetryCallback,
255        *mut c_void,
256    ) -> CResult,
257
258    /// Destroy a plugin instance
259    /// handle: Plugin instance handle
260    pub destroy_instance: extern "C" fn(CPluginHandle),
261}
262
263/// Symbol name that plugins must export
264pub const PLUGIN_API_SYMBOL: &[u8] = b"streamkit_native_plugin_api\0";