libindigo_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5use std::hash::Hash;
6
7include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
8
9#[cfg(test)]
10mod tests {
11    use std::{ffi::{CStr, CString}, ptr};
12
13    use super::*;
14
15    unsafe extern "C" fn my_attach(client: *mut indigo_client) -> indigo_result {
16        let c_msg = std::ffi::CString::new("attached to INDIGO bus...").unwrap();
17        unsafe {
18            indigo_log(c_msg.as_ptr());
19            println!("attach client callback!");
20            // Request property definitions
21            indigo_enumerate_properties(client, &INDIGO_ALL_PROPERTIES as *const _ as *mut indigo_property);
22        }
23        return indigo_result_INDIGO_OK;
24    }
25
26    unsafe extern "C" fn my_define_property(
27        _client: *mut indigo_client,
28        _device: *mut indigo_device,
29        property: *mut indigo_property,
30        message: *const i8) -> indigo_result {
31
32        // let d = CStr::from_bytes_until_nul(&(*device).name.map(|i| i as u8)).unwrap().to_str().unwrap();
33        if property != ptr::null_mut() {
34            // let id = [0 as c_char; 256];
35            // let rust_id = unsafe { CStr::from_ptr(id.as_ptr()) };
36            // let rust_id = rust_id.to_owned();
37            // println!("{:?}", rust_id);
38
39            let ptr = (*property).name.as_ptr();
40            let p = unsafe { CStr::from_ptr(ptr) };
41            let p = p.to_owned();
42            print!("property: {:?}", p);
43        }
44
45        if message != ptr::null() {
46            let m = CStr::from_ptr(message).to_str().unwrap();
47            println!("; message: {m}");
48        } else {
49            println!("; null message");
50        }
51
52        // println!("d: {d}; p: {p}; m: {m}");
53
54        return indigo_result_INDIGO_OK;
55    }
56
57    unsafe extern "C" fn my_update_property(
58        client: *mut indigo_client,
59        device: *mut indigo_device,
60        property: *mut indigo_property,
61        message: *const i8) -> indigo_result {
62
63        println!("update property callback!");
64        // do something useful here ;)
65        return indigo_result_INDIGO_OK;
66    }
67
68    unsafe extern "C" fn  my_detach(
69        client: *mut indigo_client ) -> indigo_result {
70        let c_msg = std::ffi::CString::new("detached from INDIGO bus").unwrap();
71        unsafe { indigo_log(c_msg.as_ptr()) };
72        return indigo_result_INDIGO_OK;
73    }
74
75    fn map_indigo_result(code: u32) -> Result<(),u32> {
76        if code == indigo_result_INDIGO_OK {
77            Ok(())
78        } else {
79            Err(code)
80        }
81    }
82
83    #[test]
84    fn client_test() -> Result<(),u32> {
85        // let name = std::ffi::CString::new("MyClient").unwrap();
86        // let bytes: [i8; name.len() + 1] = name.as_bytes_with_nul().iter().map(|b| *b as i8).collect();
87        // let buf = [0i8;128];
88        // buf[..bytes.len()].copy_from_slice(bytes);
89
90        let name = b"MyClient\0".map(|b| b as i8);
91        let mut buf = [0i8;128];
92        buf[..name.len()].copy_from_slice(&name);
93
94        let mut indigo_client = indigo_client {
95            name: buf,                                      // client name
96            is_remote: false,                               // is this a remote client "no" - this is us
97            client_context: ptr::null_mut(),                // we do not have client specific data
98            last_result: indigo_result_INDIGO_OK,           // result of last bus operation
99                                                            // - we just initialize it with ok
100            version: indigo_version_INDIGO_VERSION_CURRENT, // the client speaks current indigo version
101            enable_blob_mode_records: ptr::null_mut(),      // BLOB mode records -> Set this to NULL
102            attach: Some(my_attach),
103            define_property: Some(my_define_property),
104            update_property: Some(my_update_property),
105            delete_property: None,
106            send_message: None,
107            detach: Some(my_detach)
108        };
109        unsafe {
110            map_indigo_result(indigo_start())?;
111
112            /* We want to see debug messages on the screen */
113            indigo_set_log_level(indigo_log_levels_INDIGO_LOG_DEBUG);
114            map_indigo_result(indigo_attach_client(std::ptr::addr_of_mut!(indigo_client)))?;
115
116            /* We want to connect to a remote indigo host indigosky.local:7624 */
117            let mut server = indigo_server_entry {
118                name: [0i8; 128],
119                host: [0i8; 128],
120                port: 0,
121                connection_id: 0,
122                thread: ptr::null_mut(),
123                thread_started: false,
124                socket: 0,
125                protocol_adapter: ptr::null_mut(),
126                last_error: [0i8; 256],
127                shutdown: false,
128            };
129
130            let server_name = CString::new("indigosky").unwrap();
131            let host = CString::new("localhost").unwrap();
132
133            let mut srv_ptr = ptr::addr_of_mut!(server);
134            let srv_ptr_ptr = ptr::addr_of_mut!(srv_ptr);
135
136            map_indigo_result(indigo_connect_server(server_name.as_ptr(), host.as_ptr(), 7624, srv_ptr_ptr))?;
137
138            /* We can do whatever we want here while we are waiting for
139            the client to complete. For example we can call some GUI
140            framework main loop etc...
141            Instead we will just sleep for 10 seconds.
142            */
143            indigo_usleep(10 * ONE_SECOND_DELAY);
144
145            map_indigo_result(indigo_disconnect_server(srv_ptr))?;
146            map_indigo_result(indigo_detach_client(ptr::addr_of_mut!(indigo_client)))?;
147            map_indigo_result(indigo_stop())
148        }
149    }
150}
151
152impl PartialEq for indigo_client {
153    fn eq(&self, other: &Self) -> bool {
154        self.name == other.name
155    }
156}
157
158impl Hash for indigo_client {
159    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
160        self.name.hash(state);
161    }
162}
163
164impl Eq for indigo_client { }
165
166unsafe impl Sync for indigo_client { }
167unsafe impl Send for indigo_client { }