@@ -48,6 +48,19 @@ impl ResponseBuffer {
4848 }
4949}
5050
51+ /// Request buffer with binary payload for `execute_command_with_binary`.
52+ ///
53+ /// Used for audio streaming — carries both JSON params and raw PCM bytes.
54+ #[ repr( C ) ]
55+ struct StreamingRequestBuffer {
56+ command : * const i8 ,
57+ command_length : i32 ,
58+ data : * const i8 ,
59+ data_length : i32 ,
60+ binary_data : * const u8 ,
61+ binary_data_length : i32 ,
62+ }
63+
5164/// Signature for `execute_command`.
5265type ExecuteCommandFn = unsafe extern "C" fn ( * const RequestBuffer , * mut ResponseBuffer ) ;
5366
@@ -63,6 +76,10 @@ type ExecuteCommandWithCallbackFn = unsafe extern "C" fn(
6376 * mut std:: ffi:: c_void ,
6477) ;
6578
79+ /// Signature for `execute_command_with_binary`.
80+ type ExecuteCommandWithBinaryFn =
81+ unsafe extern "C" fn ( * const StreamingRequestBuffer , * mut ResponseBuffer ) ;
82+
6683// ── Library name helpers ─────────────────────────────────────────────────────
6784
6885#[ cfg( target_os = "windows" ) ]
@@ -237,6 +254,8 @@ pub(crate) struct CoreInterop {
237254 CallbackFn ,
238255 * mut std:: ffi:: c_void ,
239256 ) ,
257+ execute_command_with_binary :
258+ Option < unsafe extern "C" fn ( * const StreamingRequestBuffer , * mut ResponseBuffer ) > ,
240259}
241260
242261impl std:: fmt:: Debug for CoreInterop {
@@ -307,12 +326,22 @@ impl CoreInterop {
307326 * sym
308327 } ;
309328
329+ // SAFETY: Same as above — symbol must match `ExecuteCommandWithBinaryFn`.
330+ // Optional: older native cores may not export this symbol (used for audio streaming).
331+ let execute_command_with_binary: Option < ExecuteCommandWithBinaryFn > = unsafe {
332+ library
333+ . get :: < ExecuteCommandWithBinaryFn > ( b"execute_command_with_binary\0 " )
334+ . ok ( )
335+ . map ( |sym| * sym)
336+ } ;
337+
310338 Ok ( Self {
311339 _library : library,
312340 #[ cfg( target_os = "windows" ) ]
313341 _dependency_libs,
314342 execute_command,
315343 execute_command_with_callback,
344+ execute_command_with_binary,
316345 } )
317346 }
318347
@@ -354,6 +383,61 @@ impl CoreInterop {
354383 Self :: process_response ( response)
355384 }
356385
386+ /// Execute a command with an additional binary payload.
387+ ///
388+ /// Used for audio streaming — `binary_data` carries raw PCM bytes
389+ /// alongside the JSON parameters.
390+ pub fn execute_command_with_binary (
391+ & self ,
392+ command : & str ,
393+ params : Option < & Value > ,
394+ binary_data : & [ u8 ] ,
395+ ) -> Result < String > {
396+ let native_fn = self . execute_command_with_binary . ok_or_else ( || {
397+ FoundryLocalError :: CommandExecution {
398+ reason : "execute_command_with_binary is not supported by this native core \
399+ (symbol not found)"
400+ . into ( ) ,
401+ }
402+ } ) ?;
403+
404+ let cmd = CString :: new ( command) . map_err ( |e| FoundryLocalError :: CommandExecution {
405+ reason : format ! ( "Invalid command string: {e}" ) ,
406+ } ) ?;
407+
408+ let data_json = match params {
409+ Some ( v) => serde_json:: to_string ( v) ?,
410+ None => String :: new ( ) ,
411+ } ;
412+ let data_cstr =
413+ CString :: new ( data_json. as_str ( ) ) . map_err ( |e| FoundryLocalError :: CommandExecution {
414+ reason : format ! ( "Invalid data string: {e}" ) ,
415+ } ) ?;
416+
417+ let request = StreamingRequestBuffer {
418+ command : cmd. as_ptr ( ) ,
419+ command_length : cmd. as_bytes ( ) . len ( ) as i32 ,
420+ data : data_cstr. as_ptr ( ) ,
421+ data_length : data_cstr. as_bytes ( ) . len ( ) as i32 ,
422+ binary_data : if binary_data. is_empty ( ) {
423+ std:: ptr:: null ( )
424+ } else {
425+ binary_data. as_ptr ( )
426+ } ,
427+ binary_data_length : binary_data. len ( ) as i32 ,
428+ } ;
429+
430+ let mut response = ResponseBuffer :: new ( ) ;
431+
432+ // SAFETY: `request` fields point into `cmd`, `data_cstr`, and
433+ // `binary_data` which are all alive for the duration of this call.
434+ unsafe {
435+ ( native_fn) ( & request, & mut response) ;
436+ }
437+
438+ Self :: process_response ( response)
439+ }
440+
357441 /// Execute a command that streams results back via `callback`.
358442 ///
359443 /// Each chunk delivered by the native library is decoded as UTF-8 and
0 commit comments