Merge pull request #4268 from Kingtous/feat/plugins
feat: callbacks and flutter msg bridge
This commit is contained in:
		
						commit
						ec394e11ac
					
				| @ -44,19 +44,20 @@ pub const HW_STRIDE_ALIGN: usize = 0; // recommended by av_frame_get_buffer | |||||||
| pub mod record; | pub mod record; | ||||||
| mod vpx; | mod vpx; | ||||||
| 
 | 
 | ||||||
|  | #[repr(usize)] | ||||||
| #[derive(Copy, Clone)] | #[derive(Copy, Clone)] | ||||||
| pub enum ImageFormat { | pub enum ImageFormat { | ||||||
|     Raw, |     Raw, | ||||||
|     ABGR, |     ABGR, | ||||||
|     ARGB, |     ARGB, | ||||||
| } | } | ||||||
| 
 | #[repr(C)] | ||||||
| pub struct ImageRgb { | pub struct ImageRgb { | ||||||
|     pub raw: Vec<u8>, |     pub raw: Vec<u8>, | ||||||
|     pub w: usize, |     pub w: usize, | ||||||
|     pub h: usize, |     pub h: usize, | ||||||
|     fmt: ImageFormat, |     pub fmt: ImageFormat, | ||||||
|     stride: usize, |     pub stride: usize, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ImageRgb { | impl ImageRgb { | ||||||
|  | |||||||
| @ -691,7 +691,7 @@ pub fn session_add( | |||||||
|     switch_uuid: &str, |     switch_uuid: &str, | ||||||
|     force_relay: bool, |     force_relay: bool, | ||||||
|     password: String, |     password: String, | ||||||
| ) -> ResultType<()> { | ) -> ResultType<Session<FlutterHandler>> { | ||||||
|     let session_id = get_session_id(id.to_owned()); |     let session_id = get_session_id(id.to_owned()); | ||||||
|     LocalConfig::set_remote_id(&session_id); |     LocalConfig::set_remote_id(&session_id); | ||||||
| 
 | 
 | ||||||
| @ -725,11 +725,11 @@ pub fn session_add( | |||||||
|         .unwrap() |         .unwrap() | ||||||
|         .initialize(session_id, conn_type, switch_uuid, force_relay); |         .initialize(session_id, conn_type, switch_uuid, force_relay); | ||||||
| 
 | 
 | ||||||
|     if let Some(same_id_session) = SESSIONS.write().unwrap().insert(id.to_owned(), session) { |     if let Some(same_id_session) = SESSIONS.write().unwrap().insert(id.to_owned(), session.clone()) { | ||||||
|         same_id_session.close(); |         same_id_session.close(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Ok(()) |     Ok(session) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// start a session with the given id.
 | /// start a session with the given id.
 | ||||||
|  | |||||||
| @ -1405,6 +1405,13 @@ pub fn plugin_event(_id: String, _peer: String, _event: Vec<u8>) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub fn plugin_register_event_stream(id: String, event2ui: StreamSink<EventToUI>) { | ||||||
|  |     #[cfg(feature = "plugin_framework")] | ||||||
|  |     { | ||||||
|  |         crate::plugin::native_handlers::session::session_register_event_stream(id, event2ui); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[inline] | #[inline] | ||||||
| pub fn plugin_get_session_option( | pub fn plugin_get_session_option( | ||||||
|     _id: String, |     _id: String, | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ pub mod ipc; | |||||||
| mod plog; | mod plog; | ||||||
| mod plugins; | mod plugins; | ||||||
| pub mod native; | pub mod native; | ||||||
| mod native_handlers; | pub mod native_handlers; | ||||||
| 
 | 
 | ||||||
| pub use plugins::{ | pub use plugins::{ | ||||||
|     handle_client_event, handle_listen_event, handle_server_event, handle_ui_event, load_plugin, |     handle_client_event, handle_listen_event, handle_server_event, handle_ui_event, load_plugin, | ||||||
|  | |||||||
| @ -1,17 +1,36 @@ | |||||||
| use std::sync::{atomic::AtomicU64, Arc, RwLock}; | use std::{ | ||||||
| 
 |     collections::HashMap, | ||||||
| use crate::{ |     ffi::{c_char, c_void}, | ||||||
|     call_if_method, define_method_prefix, flutter::FlutterHandler, return_if_not_method, |     ptr::addr_of_mut, | ||||||
|     ui_session_interface::Session, |     sync::{Arc, RwLock}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | use flutter_rust_bridge::StreamSink; | ||||||
|  | 
 | ||||||
|  | use crate::{ | ||||||
|  |     define_method_prefix, | ||||||
|  |     flutter::{FlutterHandler}, | ||||||
|  |     ui_session_interface::Session, plugin::MSG_TO_UI_TYPE_PLUGIN_EVENT, flutter_ffi::EventToUI, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const MSG_TO_UI_TYPE_SESSION_CREATED: &str = "session_created"; | ||||||
|  | 
 | ||||||
| use super::PluginNativeHandler; | use super::PluginNativeHandler; | ||||||
| 
 | 
 | ||||||
|  | pub type OnSessionRgbaCallback = unsafe extern "C" fn( | ||||||
|  |     *const c_char, // Session ID
 | ||||||
|  |     *mut c_void,   // raw data
 | ||||||
|  |     *mut usize,    // width
 | ||||||
|  |     *mut usize,    // height,
 | ||||||
|  |     *mut usize,    // stride,
 | ||||||
|  |     *mut scrap::ImageFormat,    // ImageFormat
 | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| #[derive(Default)] | #[derive(Default)] | ||||||
| /// Session related handler for librustdesk core.
 | /// Session related handler for librustdesk core.
 | ||||||
| pub struct PluginNativeSessionHandler { | pub struct PluginNativeSessionHandler { | ||||||
|     sessions: Arc<RwLock<Vec<Session<FlutterHandler>>>>, |     sessions: Arc<RwLock<Vec<Session<FlutterHandler>>>>, | ||||||
|     id: AtomicU64, |     cbs: Arc<RwLock<HashMap<String, OnSessionRgbaCallback>>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| lazy_static::lazy_static! { | lazy_static::lazy_static! { | ||||||
| @ -28,26 +47,31 @@ impl PluginNativeHandler for PluginNativeSessionHandler { | |||||||
|     ) -> Option<super::NR> { |     ) -> Option<super::NR> { | ||||||
|         match method { |         match method { | ||||||
|             "create_session" => { |             "create_session" => { | ||||||
|  |                 if let Some(id) = data.get("id") { | ||||||
|  |                     if let Some(id) = id.as_str() { | ||||||
|                         return Some(super::NR { |                         return Some(super::NR { | ||||||
|                             return_type: 1, |                             return_type: 1, | ||||||
|                     data: SESSION_HANDLER.create_session() as _, |                             data: SESSION_HANDLER.create_session(id.to_string()).as_ptr() as _, | ||||||
|                         }); |                         }); | ||||||
|                     } |                     } | ||||||
|             "add_session_hook" => { |                 } | ||||||
|  |             } | ||||||
|  |             "start_session" => { | ||||||
|                 if let Some(id) = data.get("id") { |                 if let Some(id) = data.get("id") { | ||||||
|                     if let Some(id) = id.as_u64() { |                     if let Some(id) = id.as_str() { | ||||||
|                         SESSION_HANDLER.add_session_hook(id); |                         let sessions = SESSION_HANDLER.sessions.read().unwrap(); | ||||||
|                         return Some(super::NR { |                         for session in sessions.iter() { | ||||||
|                             return_type: 0, |                             if session.id == id { | ||||||
|                             data: std::ptr::null(), |                                 crate::ui_session_interface::io_loop(session.clone()); | ||||||
|                         }); |                             } | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             "remove_session_hook" => { |             "remove_session_hook" => { | ||||||
|                 if let Some(id) = data.get("id") { |                 if let Some(id) = data.get("id") { | ||||||
|                     if let Some(id) = id.as_u64() { |                     if let Some(id) = id.as_str() { | ||||||
|                         SESSION_HANDLER.remove_session_hook(id); |                         SESSION_HANDLER.remove_session_hook(id.to_string()); | ||||||
|                         return Some(super::NR { |                         return Some(super::NR { | ||||||
|                             return_type: 0, |                             return_type: 0, | ||||||
|                             data: std::ptr::null(), |                             data: std::ptr::null(), | ||||||
| @ -57,8 +81,8 @@ impl PluginNativeHandler for PluginNativeSessionHandler { | |||||||
|             } |             } | ||||||
|             "remove_session" => { |             "remove_session" => { | ||||||
|                 if let Some(id) = data.get("id") { |                 if let Some(id) = data.get("id") { | ||||||
|                     if let Some(id) = id.as_u64() { |                     if let Some(id) = id.as_str() { | ||||||
|                         SESSION_HANDLER.remove_session(id); |                         SESSION_HANDLER.remove_session(id.to_owned()); | ||||||
|                         return Some(super::NR { |                         return Some(super::NR { | ||||||
|                             return_type: 0, |                             return_type: 0, | ||||||
|                             data: std::ptr::null(), |                             data: std::ptr::null(), | ||||||
| @ -76,38 +100,61 @@ impl PluginNativeHandler for PluginNativeSessionHandler { | |||||||
|         method: &str, |         method: &str, | ||||||
|         data: &serde_json::Map<String, serde_json::Value>, |         data: &serde_json::Map<String, serde_json::Value>, | ||||||
|         raw: *const std::ffi::c_void, |         raw: *const std::ffi::c_void, | ||||||
|         raw_len: usize, |         _raw_len: usize, | ||||||
|     ) -> Option<super::NR> { |     ) -> Option<super::NR> { | ||||||
|  |         match method { | ||||||
|  |             "add_session_hook" => { | ||||||
|  |                 if let Some(id) = data.get("id") { | ||||||
|  |                     if let Some(id) = id.as_str() { | ||||||
|  |                         let cb: OnSessionRgbaCallback = unsafe { std::mem::transmute(raw) }; | ||||||
|  |                         SESSION_HANDLER.add_session_hook(id.to_string(), cb); | ||||||
|  |                         return Some(super::NR { | ||||||
|  |                             return_type: 0, | ||||||
|  |                             data: std::ptr::null(), | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             _ => {} | ||||||
|  |         } | ||||||
|         None |         None | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PluginNativeSessionHandler { | impl PluginNativeSessionHandler { | ||||||
|     fn create_session(&self) -> u64 { |     fn create_session(&self, session_id: String) -> String { | ||||||
|  |         let session = | ||||||
|  |             crate::flutter::session_add(&session_id, false, false, "", false, "".to_owned()); | ||||||
|  |         if let Ok(session) = session { | ||||||
|             let mut sessions = self.sessions.write().unwrap(); |             let mut sessions = self.sessions.write().unwrap(); | ||||||
|         let unique_id = self.id.fetch_add(1, std::sync::atomic::Ordering::SeqCst); |  | ||||||
|         let mut session: Session<FlutterHandler> = Session::default(); |  | ||||||
|         session.id = self.get_hook_key(unique_id); |  | ||||||
|             sessions.push(session); |             sessions.push(session); | ||||||
|         return unique_id; |             // push a event to notify flutter to bind a event stream for this session.
 | ||||||
|  |             let mut m = HashMap::new(); | ||||||
|  |             m.insert("name", MSG_TO_UI_TYPE_SESSION_CREATED); | ||||||
|  |             m.insert("session_id", &session_id); | ||||||
|  |             crate::flutter::push_global_event(crate::flutter::APP_TYPE_DESKTOP_REMOTE, serde_json::to_string(&m).unwrap_or("".to_string())); | ||||||
|  |             return session_id; | ||||||
|  |         } else { | ||||||
|  |             return "".to_string(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn add_session_hook(&self, session_id: u64) { |     fn add_session_hook(&self, session_id: String, cb: OnSessionRgbaCallback) { | ||||||
|         let sessions = self.sessions.read().unwrap(); |         let sessions = self.sessions.read().unwrap(); | ||||||
|         let session_id = self.get_hook_key(session_id); |  | ||||||
|         for session in sessions.iter() { |         for session in sessions.iter() { | ||||||
|             if session.id == session_id { |             if session.id == session_id { | ||||||
|  |                 self.cbs.write().unwrap().insert(session_id.to_owned(), cb); | ||||||
|                 session.ui_handler.add_session_hook( |                 session.ui_handler.add_session_hook( | ||||||
|                     session_id.to_owned(), |                     session_id, | ||||||
|                     crate::flutter::SessionHook::OnSessionRgba(session_rgba_cb), |                     crate::flutter::SessionHook::OnSessionRgba(session_rgba_cb), | ||||||
|                 ); |                 ); | ||||||
|  |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn remove_session_hook(&self, session_id: u64) { |     fn remove_session_hook(&self, session_id: String) { | ||||||
|         let sessions = self.sessions.read().unwrap(); |         let sessions = self.sessions.read().unwrap(); | ||||||
|         let session_id = self.get_hook_key(session_id); |  | ||||||
|         for session in sessions.iter() { |         for session in sessions.iter() { | ||||||
|             if session.id == session_id { |             if session.id == session_id { | ||||||
|                 session.ui_handler.remove_session_hook(&session_id); |                 session.ui_handler.remove_session_hook(&session_id); | ||||||
| @ -115,27 +162,55 @@ impl PluginNativeSessionHandler { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn remove_session(&self, session_id: u64) { |     fn remove_session(&self, session_id: String) { | ||||||
|  |         let _ = self.cbs.write().unwrap().remove(&session_id); | ||||||
|         let mut sessions = self.sessions.write().unwrap(); |         let mut sessions = self.sessions.write().unwrap(); | ||||||
|         let session_id = self.get_hook_key(session_id); |  | ||||||
|         for i in 0..sessions.len() { |         for i in 0..sessions.len() { | ||||||
|             if sessions[i].id == session_id { |             if sessions[i].id == session_id { | ||||||
|  |                 sessions[i].close_event_stream(); | ||||||
|  |                 sessions[i].close(); | ||||||
|                 sessions.remove(i); |                 sessions.remove(i); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn get_hook_key(&self, id: u64) -> String { |  | ||||||
|         format!("{}_{}", self.method_prefix(), id) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // The callback function for rgba data
 |     // The callback function for rgba data
 | ||||||
|     fn session_rgba_cb(&self, key: String, rgb: &mut scrap::ImageRgb) { |     fn session_rgba_cb(&self, session_id: String, rgb: &mut scrap::ImageRgb) { | ||||||
|         todo!() |         let cbs = self.cbs.read().unwrap(); | ||||||
|  |         if let Some(cb) = cbs.get(&session_id) { | ||||||
|  |             unsafe { | ||||||
|  |                 cb( | ||||||
|  |                     session_id.as_ptr() as _, | ||||||
|  |                     rgb.raw.as_mut_ptr() as _, | ||||||
|  |                     addr_of_mut!(rgb.w), | ||||||
|  |                     addr_of_mut!(rgb.h), | ||||||
|  |                     addr_of_mut!(rgb.stride), | ||||||
|  |                     addr_of_mut!(rgb.fmt), | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[inline] | ||||||
|  |     // The callback function for rgba data
 | ||||||
|  |     fn session_register_event_stream(&self, session_id: String, stream: StreamSink<EventToUI>) { | ||||||
|  |         let sessions = self.sessions.read().unwrap(); | ||||||
|  |         for session in sessions.iter() { | ||||||
|  |             if session.id == session_id { | ||||||
|  |                 *session.event_stream.write().unwrap() = Some(stream); | ||||||
|  |                 break; | ||||||
|  |             }            
 | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn session_rgba_cb(key: String, rgb: &mut scrap::ImageRgb) { | #[inline] | ||||||
|     SESSION_HANDLER.session_rgba_cb(key, rgb); | fn session_rgba_cb(id: String, rgb: &mut scrap::ImageRgb) { | ||||||
|  |     SESSION_HANDLER.session_rgba_cb(id, rgb); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[inline] | ||||||
|  | pub fn session_register_event_stream(id: String, stream: StreamSink<EventToUI>) { | ||||||
|  |     SESSION_HANDLER.session_register_event_stream(id, stream); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user