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