tauri_plugin_libmpv/
lib.rs1use tauri::{
2 plugin::{Builder, TauriPlugin},
3 Manager, RunEvent, Runtime, WindowEvent,
4};
5
6pub use models::*;
7
8#[cfg(desktop)]
9mod desktop;
10#[cfg(mobile)]
11mod mobile;
12#[cfg(desktop)]
13mod wrapper;
14
15mod commands;
16mod error;
17mod models;
18mod utils;
19
20pub use error::{Error, Result};
21
22#[cfg(desktop)]
23use desktop::Mpv;
24#[cfg(mobile)]
25use mobile::Mpv;
26
27pub trait MpvExt<R: Runtime> {
28 fn mpv(&self) -> &Mpv<R>;
29}
30
31impl<R: Runtime, T: Manager<R>> crate::MpvExt<R> for T {
32 fn mpv(&self) -> &Mpv<R> {
33 self.state::<Mpv<R>>().inner()
34 }
35}
36
37pub fn init<R: Runtime>() -> TauriPlugin<R> {
38 Builder::new("libmpv")
39 .invoke_handler(tauri::generate_handler![
40 commands::init,
41 commands::destroy,
42 commands::command,
43 commands::set_property,
44 commands::get_property,
45 commands::set_video_margin_ratio,
46 ])
47 .setup(|app, api| {
48 unsafe {
49 let locale = std::ffi::CString::new("C").unwrap();
50 libc::setlocale(libc::LC_NUMERIC, locale.as_ptr());
51 }
52
53 #[cfg(mobile)]
54 let mpv = mobile::init(app, api)?;
55 #[cfg(desktop)]
56 let mpv = desktop::init(app, api)?;
57 app.manage(mpv);
58 Ok(())
59 })
60 .on_event(|app_handle, run_event| {
61 if let RunEvent::WindowEvent {
62 label,
63 event: WindowEvent::CloseRequested { api, .. },
64 ..
65 } = run_event
66 {
67 let mpv_state = app_handle.state::<Mpv<R>>();
68
69 let instance_exists = {
70 let instances_lock = match mpv_state.instances.lock() {
71 Ok(guard) => guard,
72 Err(poisoned) => {
73 log::warn!("Mutex for mpv instances was poisoned. Recovering.");
74 poisoned.into_inner()
75 }
76 };
77 instances_lock.contains_key(label)
78 };
79
80 if instance_exists {
81 api.prevent_close();
82
83 let app_handle_clone = app_handle.clone();
84 let window_label = label.to_string();
85
86 tauri::async_runtime::spawn(async move {
87 log::info!(
88 "Close requested for '{}', destroying mpv instance first...",
89 &window_label
90 );
91
92 if let Err(e) = app_handle_clone.mpv().destroy(&window_label) {
93 log::error!(
94 "Failed to destroy mpv for '{}': {}. Still closing.",
95 &window_label,
96 e
97 );
98 }
99
100 if let Some(window) = app_handle_clone.get_webview_window(&window_label) {
101 if let Err(e) = window.close() {
102 log::error!("Failed to close window '{}': {}", &window_label, e);
103 }
104 }
105 });
106 }
107 }
108 })
109 .build()
110}