1 use libc::c_void; 2 3 use crate::enums::{ChannelData, FileTypes, MessageType, Status}; 4 use crate::rtaudio::{CsAudioDevice, RtAudioParams}; 5 6 use csound_sys as raw; 7 8 /// Struct containing the relevant info of files are opened by csound. 9 #[derive(Debug, Clone)] 10 pub struct FileInfo { 11 /// pathname of the file; either full or relative to current dir 12 pub name: Option<String>, 13 /// Enum equivalent code for the file type code from the enum CSOUND_FILETYPES 14 pub file_type: FileTypes, 15 /// true if Csound is writing the file, false if reading 16 pub is_writing: bool, 17 /// true if it is a temporary file that Csound will delete; false if not 18 pub is_temp: bool, 19 } 20 21 #[doc(hidden)] 22 #[derive(Default)] 23 pub struct Callbacks<'a> { 24 pub message_cb: Option<Box<dyn FnMut(MessageType, &str) + 'a>>, 25 pub devlist_cb: Option<Box<dyn FnMut(CsAudioDevice) + 'a>>, 26 pub play_open_cb: Option<Box<dyn FnMut(&RtAudioParams) -> Status + 'a>>, 27 pub rec_open_cb: Option<Box<dyn FnMut(&RtAudioParams) -> Status + 'a>>, 28 pub rt_play_cb: Option<Box<dyn FnMut(&[f64]) + 'a>>, 29 pub rt_rec_cb: Option<Box<dyn FnMut(&mut [f64]) -> usize + 'a>>, 30 pub sense_event_cb: Option<Box<dyn FnMut() + 'a>>, 31 pub keyboard_cb: Option<Box<dyn FnMut() -> char + 'a>>, // TODO this callback doesn't work at the 32 //csound side 33 pub rt_close_cb: Option<Box<dyn FnMut() + 'a>>, 34 pub cscore_cb: Option<Box<dyn FnMut() + 'a>>, 35 pub input_channel_cb: Option<Box<dyn FnMut(&str) -> ChannelData + 'a>>, 36 pub output_channel_cb: Option<Box<dyn FnMut(&str, ChannelData) + 'a>>, 37 pub file_open_cb: Option<Box<dyn FnMut(&FileInfo) + 'a>>, 38 pub midi_in_open_cb: Option<Box<dyn FnMut(&str) + 'a>>, 39 pub midi_out_open_cb: Option<Box<dyn FnMut(&str) + 'a>>, 40 pub midi_read_cb: Option<Box<dyn FnMut(&mut [u8]) -> usize + 'a>>, 41 pub midi_write_cb: Option<Box<dyn FnMut(&[u8]) -> usize + 'a>>, 42 pub midi_in_close_cb: Option<Box<dyn FnMut() + 'a>>, 43 pub midi_out_close_cb: Option<Box<dyn FnMut() + 'a>>, 44 pub yield_cb: Option<Box<dyn FnMut() -> bool + 'a>>, 45 } 46 47 impl<'a> Callbacks<'a> { set_message_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(MessageType, &str) + 'a,48 pub(crate) unsafe fn set_message_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 49 where 50 F: FnMut(MessageType, &str) + 'a, 51 { 52 self.message_cb = Some(Box::new(cb)); 53 raw::csoundSetMessageStringCallback(csound, Trampoline::message_string_cb) 54 } 55 set_devlist_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(CsAudioDevice) + 'a,56 pub(crate) unsafe fn set_devlist_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 57 where 58 F: FnMut(CsAudioDevice) + 'a, 59 { 60 self.devlist_cb = Some(Box::new(cb)); 61 raw::csoundSetAudioDeviceListCallback(csound, Some(Trampoline::audioDeviceListCallback)); 62 } 63 set_play_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&RtAudioParams) -> Status + 'a,64 pub(crate) unsafe fn set_play_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 65 where 66 F: FnMut(&RtAudioParams) -> Status + 'a, 67 { 68 self.play_open_cb = Some(Box::new(cb)); 69 raw::csoundSetPlayopenCallback(csound, Some(Trampoline::playOpenCallback)); 70 } 71 set_rec_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&RtAudioParams) -> Status + 'a,72 pub(crate) unsafe fn set_rec_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 73 where 74 F: FnMut(&RtAudioParams) -> Status + 'a, 75 { 76 self.play_open_cb = Some(Box::new(cb)); 77 raw::csoundSetRecopenCallback(csound, Some(Trampoline::recOpenCallback)); 78 } 79 set_rt_play_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&[f64]) + 'a,80 pub(crate) unsafe fn set_rt_play_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 81 where 82 F: FnMut(&[f64]) + 'a, 83 { 84 self.rt_play_cb = Some(Box::new(cb)); 85 csound_sys::csoundSetRtplayCallback(csound, Some(Trampoline::rtplayCallback)); 86 } 87 set_rt_rec_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&mut [f64]) -> usize + 'a,88 pub(crate) unsafe fn set_rt_rec_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 89 where 90 F: FnMut(&mut [f64]) -> usize + 'a, 91 { 92 self.rt_rec_cb = Some(Box::new(cb)); 93 csound_sys::csoundSetRtrecordCallback(csound, Some(Trampoline::rtrecordCallback)); 94 } 95 set_rt_close_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut() + 'a,96 pub(crate) unsafe fn set_rt_close_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 97 where 98 F: FnMut() + 'a, 99 { 100 self.rt_close_cb = Some(Box::new(cb)); 101 csound_sys::csoundSetRtcloseCallback(csound, Some(Trampoline::rtcloseCallback)); 102 } 103 set_sense_event_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut() + 'a,104 pub(crate) unsafe fn set_sense_event_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 105 where 106 F: FnMut() + 'a, 107 { 108 self.sense_event_cb = Some(Box::new(cb)); 109 csound_sys::csoundRegisterSenseEventCallback( 110 csound, 111 Some(Trampoline::senseEventCallback), 112 ::std::ptr::null_mut() as *mut c_void, 113 ); 114 } 115 116 /*pub(crate) unsafe fn set_cscore_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 117 where 118 F: FnMut() + 'a, 119 { 120 self.cscore_cb = Some(Box::new(cb)); 121 csound_sys::csoundSetCscoreCallback( 122 csound, 123 Some(Trampoline::scoreCallback), 124 ); 125 }*/ 126 set_input_channel_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&str) -> ChannelData + 'a,127 pub(crate) unsafe fn set_input_channel_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 128 where 129 F: FnMut(&str) -> ChannelData + 'a, 130 { 131 self.input_channel_cb = Some(Box::new(cb)); 132 csound_sys::csoundSetInputChannelCallback(csound, Some(Trampoline::inputChannelCallback)); 133 } 134 set_output_channel_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&str, ChannelData) + 'a,135 pub(crate) unsafe fn set_output_channel_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 136 where 137 F: FnMut(&str, ChannelData) + 'a, 138 { 139 self.output_channel_cb = Some(Box::new(cb)); 140 csound_sys::csoundSetOutputChannelCallback(csound, Some(Trampoline::outputChannelCallback)); 141 } 142 set_file_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&FileInfo) + 'a,143 pub(crate) unsafe fn set_file_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 144 where 145 F: FnMut(&FileInfo) + 'a, 146 { 147 self.file_open_cb = Some(Box::new(cb)); 148 csound_sys::csoundSetFileOpenCallback(csound, Some(Trampoline::fileOpenCallback)); 149 } 150 set_midi_in_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&str) + 'a,151 pub(crate) unsafe fn set_midi_in_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 152 where 153 F: FnMut(&str) + 'a, 154 { 155 self.midi_in_open_cb = Some(Box::new(cb)); 156 csound_sys::csoundSetExternalMidiInOpenCallback( 157 csound, 158 Some(Trampoline::midiInOpenCallback), 159 ); 160 } 161 set_midi_out_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&str) + 'a,162 pub(crate) unsafe fn set_midi_out_open_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 163 where 164 F: FnMut(&str) + 'a, 165 { 166 self.midi_out_open_cb = Some(Box::new(cb)); 167 csound_sys::csoundSetExternalMidiOutOpenCallback( 168 csound, 169 Some(Trampoline::midiOutOpenCallback), 170 ); 171 } 172 set_midi_read_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&mut [u8]) -> usize + 'a,173 pub(crate) unsafe fn set_midi_read_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 174 where 175 F: FnMut(&mut [u8]) -> usize + 'a, 176 { 177 self.midi_read_cb = Some(Box::new(cb)); 178 csound_sys::csoundSetExternalMidiReadCallback(csound, Some(Trampoline::midiReadCallback)); 179 } 180 set_midi_write_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut(&[u8]) -> usize + 'a,181 pub(crate) unsafe fn set_midi_write_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 182 where 183 F: FnMut(&[u8]) -> usize + 'a, 184 { 185 self.midi_write_cb = Some(Box::new(cb)); 186 csound_sys::csoundSetExternalMidiWriteCallback(csound, Some(Trampoline::midiWriteCallback)); 187 } 188 set_midi_in_close_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut() + 'a,189 pub(crate) unsafe fn set_midi_in_close_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 190 where 191 F: FnMut() + 'a, 192 { 193 self.midi_in_close_cb = Some(Box::new(cb)); 194 csound_sys::csoundSetExternalMidiInCloseCallback( 195 csound, 196 Some(Trampoline::midiInCloseCallback), 197 ); 198 } 199 set_midi_out_close_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut() + 'a,200 pub(crate) unsafe fn set_midi_out_close_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 201 where 202 F: FnMut() + 'a, 203 { 204 self.midi_out_close_cb = Some(Box::new(cb)); 205 csound_sys::csoundSetExternalMidiOutCloseCallback( 206 csound, 207 Some(Trampoline::midiOutCloseCallback), 208 ); 209 } 210 set_yield_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) where F: FnMut() -> bool + 'a,211 pub(crate) unsafe fn set_yield_cb<F>(&'a mut self, csound: *mut raw::CSOUND, cb: F) 212 where 213 F: FnMut() -> bool + 'a, 214 { 215 self.yield_cb = Some(Box::new(cb)); 216 csound_sys::csoundSetYieldCallback(csound, Some(Trampoline::yieldCallback)); 217 } 218 } 219 220 pub mod Trampoline { 221 222 use csound_sys as raw; 223 use va_list::VaList; 224 225 use super::*; 226 use crate::csound::CallbackHandler; 227 use crate::rtaudio::{CsAudioDevice, RtAudioParams}; 228 use libc::{c_char, c_int, c_uchar, c_void, memcpy}; 229 use std::ffi::{CStr, CString}; 230 use std::panic::{self, AssertUnwindSafe}; 231 use std::slice; 232 ptr_to_string(ptr: *const c_char) -> Option<String>233 pub fn ptr_to_string(ptr: *const c_char) -> Option<String> { 234 if !ptr.is_null() { 235 let result = match unsafe { CStr::from_ptr(ptr) }.to_str().ok() { 236 Some(str_slice) => Some(str_slice.to_owned()), 237 None => None, 238 }; 239 return result; 240 } 241 None 242 } 243 convert_str_to_c<T>(string: T) -> Result<CString, &'static str> where T: AsRef<str>,244 pub fn convert_str_to_c<T>(string: T) -> Result<CString, &'static str> 245 where 246 T: AsRef<str>, 247 { 248 let string = string.as_ref(); 249 if string.is_empty() { 250 return Err("Failed to convert empty string to C"); 251 } 252 CString::new(string).map_err(|_| "Failed converting rust string to CString") 253 } 254 catch<T, F: FnOnce() -> T>(f: F) -> Option<T>255 fn catch<T, F: FnOnce() -> T>(f: F) -> Option<T> { 256 match panic::catch_unwind(AssertUnwindSafe(f)) { 257 Ok(ret) => Some(ret), 258 Err(_) => { 259 std::process::exit(-1); 260 } 261 } 262 } 263 default_message_callback( _csound: *mut raw::CSOUND, _attr: c_int, _format: *const c_char, _args: VaList, )264 pub extern "C" fn default_message_callback( 265 _csound: *mut raw::CSOUND, 266 _attr: c_int, 267 _format: *const c_char, 268 _args: VaList, 269 ) { 270 } 271 message_string_cb( csound: *mut raw::CSOUND, attr: c_int, message: *const c_char, )272 pub extern "C" fn message_string_cb( 273 csound: *mut raw::CSOUND, 274 attr: c_int, 275 message: *const c_char, 276 ) { 277 catch(|| unsafe { 278 let info = CStr::from_ptr(message); 279 if let Ok(s) = info.to_str() { 280 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 281 .callbacks 282 .message_cb 283 .as_mut() 284 { 285 fun(MessageType::from(attr as u32), s); 286 } 287 } 288 }); 289 } 290 291 /****** Event callbacks functions *******************************************************************/ 292 senseEventCallback(csound: *mut raw::CSOUND, _userData: *mut c_void)293 pub extern "C" fn senseEventCallback(csound: *mut raw::CSOUND, _userData: *mut c_void) { 294 catch(|| unsafe { 295 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 296 .callbacks 297 .sense_event_cb 298 .as_mut() 299 { 300 fun(); 301 } 302 }); 303 } 304 305 /****** real time audio callbacks functions *******************************************************************/ 306 playOpenCallback( csound: *mut raw::CSOUND, dev: *const raw::csRtAudioParams, ) -> c_int307 pub extern "C" fn playOpenCallback( 308 csound: *mut raw::CSOUND, 309 dev: *const raw::csRtAudioParams, 310 ) -> c_int { 311 catch(|| unsafe { 312 let rtParams = RtAudioParams { 313 devName: ptr_to_string((*dev).devName), 314 devNum: (*dev).devNum as u32, 315 bufSamp_SW: (*dev).bufSamp_SW as u32, 316 bufSamp_HW: (*dev).bufSamp_HW as u32, 317 nChannels: (*dev).nChannels as u32, 318 sampleFormat: (*dev).sampleFormat as u32, 319 sampleRate: (*dev).sampleRate as f32, 320 }; 321 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 322 .callbacks 323 .play_open_cb 324 .as_mut() 325 { 326 return fun(&rtParams).to_i32() as c_int; 327 } 328 0 329 }) 330 .unwrap() 331 } 332 recOpenCallback( csound: *mut raw::CSOUND, dev: *const raw::csRtAudioParams, ) -> c_int333 pub extern "C" fn recOpenCallback( 334 csound: *mut raw::CSOUND, 335 dev: *const raw::csRtAudioParams, 336 ) -> c_int { 337 catch(|| unsafe { 338 let rtParams = RtAudioParams { 339 devName: ptr_to_string((*dev).devName), 340 devNum: (*dev).devNum as u32, 341 bufSamp_SW: (*dev).bufSamp_SW as u32, 342 bufSamp_HW: (*dev).bufSamp_HW as u32, 343 nChannels: (*dev).nChannels as u32, 344 sampleFormat: (*dev).sampleFormat as u32, 345 sampleRate: (*dev).sampleRate as f32, 346 }; 347 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 348 .callbacks 349 .rec_open_cb 350 .as_mut() 351 { 352 return fun(&rtParams).to_i32() as c_int; 353 } 354 -1 355 }) 356 .unwrap() 357 } 358 rtcloseCallback(csound: *mut raw::CSOUND)359 pub extern "C" fn rtcloseCallback(csound: *mut raw::CSOUND) { 360 catch(|| unsafe { 361 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 362 .callbacks 363 .rt_close_cb 364 .as_mut() 365 { 366 fun(); 367 } 368 }); 369 } 370 rtplayCallback(csound: *mut raw::CSOUND, outBuf: *const f64, nbytes: c_int)371 pub extern "C" fn rtplayCallback(csound: *mut raw::CSOUND, outBuf: *const f64, nbytes: c_int) { 372 catch(|| unsafe { 373 let out = slice::from_raw_parts(outBuf, nbytes as usize); 374 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 375 .callbacks 376 .rt_play_cb 377 .as_mut() 378 { 379 fun(&out); 380 } 381 }); 382 } 383 rtrecordCallback( csound: *mut raw::CSOUND, outBuf: *mut f64, nbytes: c_int, ) -> c_int384 pub extern "C" fn rtrecordCallback( 385 csound: *mut raw::CSOUND, 386 outBuf: *mut f64, 387 nbytes: c_int, 388 ) -> c_int { 389 catch(|| unsafe { 390 let mut buff = slice::from_raw_parts_mut(outBuf, nbytes as usize); 391 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 392 .callbacks 393 .rt_rec_cb 394 .as_mut() 395 { 396 return fun(&mut buff) as c_int; 397 } 398 -1 399 }) 400 .unwrap() 401 } 402 audioDeviceListCallback( csound: *mut raw::CSOUND, dev: *mut raw::CS_AUDIODEVICE, isOutput: c_int, ) -> c_int403 pub extern "C" fn audioDeviceListCallback( 404 csound: *mut raw::CSOUND, 405 dev: *mut raw::CS_AUDIODEVICE, 406 isOutput: c_int, 407 ) -> c_int { 408 catch(|| unsafe { 409 let audioDevice = CsAudioDevice { 410 device_name: ptr_to_string((*dev).device_name.as_ptr()), 411 device_id: ptr_to_string((*dev).device_id.as_ptr()), 412 rt_module: ptr_to_string((*dev).rt_module.as_ptr()), 413 max_nchnls: (*dev).max_nchnls as u32, 414 isOutput: isOutput as u32, 415 }; 416 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 417 .callbacks 418 .devlist_cb 419 .as_mut() 420 { 421 fun(audioDevice); 422 } 423 0 424 }) 425 .unwrap() 426 } 427 428 /*pub extern "C" fn keyboard_callback( 429 userData: *mut c_void, 430 p: *mut c_void, 431 _type_: c_uint, 432 ) -> c_int { 433 unsafe { 434 match (*(userData as *mut CallbackHandler)) 435 .callbacks 436 .keyboard_cb() { 437 '\0' => {} 438 value => { 439 *(p as *mut c_int) = value as c_int; 440 } 441 } 442 0 443 } 444 }*/ 445 446 /********* General Input/Output callbacks ********************************************************************/ fileOpenCallback( csound: *mut raw::CSOUND, filePath: *const c_char, fileType: c_int, operation: c_int, isTemp: c_int, )447 pub extern "C" fn fileOpenCallback( 448 csound: *mut raw::CSOUND, 449 filePath: *const c_char, 450 fileType: c_int, 451 operation: c_int, 452 isTemp: c_int, 453 ) { 454 catch(|| unsafe { 455 let name = ptr_to_string(filePath); 456 let file_info = FileInfo { 457 name, 458 file_type: FileTypes::from(fileType as u8), 459 is_writing: operation != 0, 460 is_temp: isTemp != 0, 461 }; 462 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 463 .callbacks 464 .file_open_cb 465 .as_mut() 466 { 467 fun(&file_info); 468 } 469 }); 470 } 471 472 /* Score Handling callbacks ********************************************************* */ 473 474 // Sets an pub external callback for Cscore processing. Pass NULL to reset to the internal cscore() function (which does nothing). 475 // This callback is retained after a csoundReset() call. 476 /*pub extern "C" fn scoreCallback(csound: *mut raw::CSOUND) { 477 catch(|| unsafe { 478 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 479 .callbacks 480 .cscore_cb 481 .as_mut() 482 { 483 fun(); 484 } 485 }); 486 }*/ 487 488 /* Channels and events callbacks **************************************************** */ 489 inputChannelCallback( csound: *mut raw::CSOUND, channelName: *const c_char, channelValuePtr: *mut c_void, _channelType: *const c_void, )490 pub extern "C" fn inputChannelCallback( 491 csound: *mut raw::CSOUND, 492 channelName: *const c_char, 493 channelValuePtr: *mut c_void, 494 _channelType: *const c_void, 495 ) { 496 catch(|| unsafe { 497 let name = (CStr::from_ptr(channelName)).to_str(); 498 if name.is_err() { 499 return; 500 } 501 let name = name.unwrap(); 502 let result = if let Some(fun) = (*(raw::csoundGetHostData(csound) 503 as *mut CallbackHandler)) 504 .callbacks 505 .input_channel_cb 506 .as_mut() 507 { 508 fun(name) 509 } else { 510 return; 511 }; 512 513 match result { 514 ChannelData::CS_CONTROL_CHANNEL(data) => { 515 *(channelValuePtr as *mut f64) = data; 516 } 517 518 ChannelData::CS_STRING_CHANNEL(s) => { 519 let len = s.len(); 520 let c_str = CString::new(s); 521 if raw::csoundGetChannelDatasize(csound, channelName) as usize <= len { 522 if let Ok(ptr) = c_str { 523 memcpy(channelValuePtr, ptr.as_ptr() as *mut c_void, len); 524 } 525 } 526 } 527 528 _ => {} 529 } 530 }); 531 } 532 outputChannelCallback( csound: *mut raw::CSOUND, channelName: *const c_char, channelValuePtr: *mut c_void, _channelType: *const c_void, )533 pub extern "C" fn outputChannelCallback( 534 csound: *mut raw::CSOUND, 535 channelName: *const c_char, 536 channelValuePtr: *mut c_void, 537 _channelType: *const c_void, 538 ) { 539 catch(|| unsafe { 540 let name = (CStr::from_ptr(channelName)).to_str(); 541 if name.is_err() { 542 return; 543 } 544 let name = name.unwrap(); 545 let mut ptr = ::std::ptr::null_mut(); 546 let ptr: *mut *mut f64 = &mut ptr as *mut *mut _; 547 let channel_type = raw::csoundGetChannelPtr(csound, ptr, channelName, 0) as u32; 548 let channel_type = channel_type & raw::CSOUND_CHANNEL_TYPE_MASK as u32; 549 550 let fun = if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 551 .callbacks 552 .output_channel_cb 553 .as_mut() 554 { 555 fun 556 } else { 557 return; 558 }; 559 560 match channel_type { 561 raw::CSOUND_CONTROL_CHANNEL => { 562 let value = *(channelValuePtr as *mut f64); 563 let data = ChannelData::CS_CONTROL_CHANNEL(value); 564 fun(name, data); 565 } 566 567 raw::CSOUND_STRING_CHANNEL => { 568 let data = ChannelData::CS_STRING_CHANNEL( 569 ptr_to_string(channelValuePtr as *const c_char) 570 .unwrap_or_else(|| "".to_owned()), 571 ); 572 fun(name, data); 573 } 574 575 _ => {} 576 } 577 }); 578 } 579 580 /****** MIDI I/O callbacks functions *******************************************************************/ 581 582 // Sets callback for opening real time MIDI input. midiInOpenCallback( csound: *mut raw::CSOUND, _userData: *mut *mut c_void, devName: *const c_char, ) -> c_int583 pub extern "C" fn midiInOpenCallback( 584 csound: *mut raw::CSOUND, 585 _userData: *mut *mut c_void, 586 devName: *const c_char, 587 ) -> c_int { 588 catch(|| unsafe { 589 let name = match CStr::from_ptr(devName).to_str() { 590 Ok(s) => s, 591 _ => return raw::CSOUND_ERROR, 592 }; 593 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 594 .callbacks 595 .midi_in_open_cb 596 .as_mut() 597 { 598 fun(&name); 599 } 600 raw::CSOUND_SUCCESS 601 }) 602 .unwrap() 603 } 604 605 // Sets callback for opening real time MIDI output. midiOutOpenCallback( csound: *mut raw::CSOUND, _userData: *mut *mut c_void, devName: *const c_char, ) -> c_int606 pub extern "C" fn midiOutOpenCallback( 607 csound: *mut raw::CSOUND, 608 _userData: *mut *mut c_void, 609 devName: *const c_char, 610 ) -> c_int { 611 catch(|| unsafe { 612 let name = match CStr::from_ptr(devName).to_str() { 613 Ok(s) => s, 614 _ => return raw::CSOUND_ERROR, 615 }; 616 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 617 .callbacks 618 .midi_out_open_cb 619 .as_mut() 620 { 621 fun(&name); 622 } 623 raw::CSOUND_SUCCESS 624 }) 625 .unwrap() 626 } 627 628 // Sets callback for reading from real time MIDI input. midiReadCallback( csound: *mut raw::CSOUND, _userData: *mut c_void, buf: *mut c_uchar, nbytes: c_int, ) -> c_int629 pub extern "C" fn midiReadCallback( 630 csound: *mut raw::CSOUND, 631 _userData: *mut c_void, 632 buf: *mut c_uchar, 633 nbytes: c_int, 634 ) -> c_int { 635 catch(|| unsafe { 636 let mut out = slice::from_raw_parts_mut(buf, nbytes as usize); 637 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 638 .callbacks 639 .midi_read_cb 640 .as_mut() 641 { 642 return fun(&mut out) as c_int; 643 } 644 -1 645 }) 646 .unwrap() 647 } 648 649 // Sets callback for writing to real time MIDI output. 650 #[allow(dead_code)] midiWriteCallback( csound: *mut raw::CSOUND, _userData: *mut c_void, buf: *const u8, nbytes: c_int, ) -> c_int651 pub extern "C" fn midiWriteCallback( 652 csound: *mut raw::CSOUND, 653 _userData: *mut c_void, 654 buf: *const u8, 655 nbytes: c_int, 656 ) -> c_int { 657 catch(|| unsafe { 658 let buffer = slice::from_raw_parts(buf, nbytes as usize); 659 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 660 .callbacks 661 .midi_write_cb 662 .as_mut() 663 { 664 return fun(&buffer) as c_int; 665 } 666 -1 667 }) 668 .unwrap() 669 } 670 671 //Sets callback for closing real time MIDI input. midiInCloseCallback( csound: *mut raw::CSOUND, _userData: *mut c_void, ) -> c_int672 pub extern "C" fn midiInCloseCallback( 673 csound: *mut raw::CSOUND, 674 _userData: *mut c_void, 675 ) -> c_int { 676 catch(|| unsafe { 677 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 678 .callbacks 679 .midi_in_close_cb 680 .as_mut() 681 { 682 fun(); 683 } 684 raw::CSOUND_SUCCESS 685 }) 686 .unwrap() 687 } 688 689 // Sets callback for closing real time MIDI output. midiOutCloseCallback( csound: *mut raw::CSOUND, _userData: *mut c_void, ) -> c_int690 pub extern "C" fn midiOutCloseCallback( 691 csound: *mut raw::CSOUND, 692 _userData: *mut c_void, 693 ) -> c_int { 694 catch(|| unsafe { 695 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 696 .callbacks 697 .midi_out_close_cb 698 .as_mut() 699 { 700 fun(); 701 } 702 raw::CSOUND_SUCCESS 703 }) 704 .unwrap() 705 } 706 yieldCallback(csound: *mut raw::CSOUND) -> c_int707 pub extern "C" fn yieldCallback(csound: *mut raw::CSOUND) -> c_int { 708 catch(|| unsafe { 709 if let Some(fun) = (*(raw::csoundGetHostData(csound) as *mut CallbackHandler)) 710 .callbacks 711 .yield_cb 712 .as_mut() 713 { 714 return fun() as c_int; 715 } 716 0 717 }) 718 .unwrap() 719 } 720 } 721 722 //Sets callback for converting MIDI error codes to strings. 723 /*pub extern fn pub externalMidiErrorStringCallback (midi_error_code : c_int) -> *const c_char { 724 unsafe{ 725 } 726 }*/ 727