use std::ffi::CString;
use std::sync::Mutex;
use once_cell::sync::Lazy;
extern crate libc;
extern "C" {
fn executeAppleScript(script: *const libc::c_char) -> *const libc::c_char;
fn compileAppleScript(script_source: *const libc::c_char) -> *mut libc::c_void;
fn executeCompiledAppleScript(
compiled_script: *mut libc::c_void,
parameters: *const libc::c_char,
) -> *const libc::c_char;
fn sendAppleEvent(
compiled_script: *mut libc::c_void,
event_code: *const libc::c_char,
parameters: *const libc::c_char,
) -> *const libc::c_char;
}
static APPLE_SCRIPT_EXECUTOR: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
pub fn run_apple_script(script: &str) -> String {
let _lock = APPLE_SCRIPT_EXECUTOR.lock().unwrap();
let c_script = CString::new(script).expect("CString::new failed");
unsafe {
let result = executeAppleScript(c_script.as_ptr());
std::ffi::CStr::from_ptr(result)
.to_string_lossy()
.into_owned()
}
}
pub fn compile_script(script: &str) -> *mut libc::c_void {
let c_script = CString::new(script).unwrap();
unsafe { compileAppleScript(c_script.as_ptr()) }
}
pub fn execute_script(compiled_script: *mut libc::c_void, parameters: &str) -> Option<String> {
let c_parameters = CString::new(parameters).unwrap();
unsafe {
let result = executeCompiledAppleScript(compiled_script, c_parameters.as_ptr());
if result.is_null() {
None
} else {
Some(
std::ffi::CStr::from_ptr(result)
.to_string_lossy()
.into_owned(),
)
}
}
}
pub fn send_apple_event(
compiled_script: *mut libc::c_void,
event_code: &str,
parameters: &str,
) -> Option<String> {
let c_parameters = CString::new(parameters).unwrap();
let c_event_code = CString::new(event_code).unwrap();
unsafe {
let result = sendAppleEvent(
compiled_script,
c_event_code.as_ptr(),
c_parameters.as_ptr(),
);
if result.is_null() {
None
} else {
Some(
std::ffi::CStr::from_ptr(result)
.to_string_lossy()
.into_owned(),
)
}
}
}