tauri_plugin_libmpv/
lib.rs

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