From 2dd899ae46bcc5019d391bddfab25b66e6348c57 Mon Sep 17 00:00:00 2001 From: Benjamin Klum Date: Wed, 22 Nov 2023 20:44:34 +0100 Subject: [PATCH] Playtime: Decompress app *and* load app library async on start --- main/src/infrastructure/plugin/app.rs | 55 ++++++++----------- .../src/infrastructure/ui/app/app_instance.rs | 10 ++-- playtime-clip-engine | 2 +- 3 files changed, 29 insertions(+), 38 deletions(-) diff --git a/main/src/infrastructure/plugin/app.rs b/main/src/infrastructure/plugin/app.rs index 3bcf01404..4fb4ed100 100644 --- a/main/src/infrastructure/plugin/app.rs +++ b/main/src/infrastructure/plugin/app.rs @@ -126,8 +126,6 @@ pub struct App { message_panel: SharedView, osc_feedback_processor: Rc>, #[cfg(feature = "playtime")] - app_decompression_result: RefCell>>, - #[cfg(feature = "playtime")] app_library: std::cell::OnceCell>, #[cfg(feature = "playtime")] clip_engine_hub: playtime_clip_engine::proto::ClipEngineHub, @@ -288,14 +286,14 @@ impl App { ); // This doesn't yet activate the accelerator (will happen on wake up) let accelerator = RealearnAccelerator::new(shared_main_processors, RealearnSnitch); - // Silently decompress app so it's immediately available when needed (async) + // Silently decompress app and load library in background so it's ready when needed #[cfg(feature = "playtime")] let _ = std::thread::Builder::new() - .name("Decompress Helgobox app".to_string()) + .name("Helgobox app loader".to_string()) .spawn(|| { - let result = decompress_app().map_err(|e| e.to_string()); + let result = decompress_app().and_then(|_| load_app_library()); let _ = Global::task_support().do_later_in_main_thread_asap(|| { - *App::get().app_decompression_result.borrow_mut() = Some(result); + let _ = App::get().app_library.set(result); }); }); // REAPER registers/unregisters actions automatically depending on presence of plug-in @@ -331,8 +329,6 @@ impl App { message_panel: Default::default(), osc_feedback_processor: Rc::new(RefCell::new(osc_feedback_processor)), #[cfg(feature = "playtime")] - app_decompression_result: Default::default(), - #[cfg(feature = "playtime")] app_library: std::cell::OnceCell::new(), #[cfg(feature = "playtime")] clip_engine_hub: playtime_clip_engine::proto::ClipEngineHub::new(), @@ -951,27 +947,14 @@ impl App { } #[cfg(feature = "playtime")] - pub fn get_or_load_app_library( - &self, - ) -> anyhow::Result<&'static crate::infrastructure::ui::AppLibrary> { - let result = match App::get().app_library.get() { - None => { - // Check if decompression was successful - let decompression_result = self.app_decompression_result.borrow(); - match decompression_result.as_ref() { - None => bail!("App is not decompressed yet"), - Some(Err(e)) => bail!("App decompression failed: {e}"), - _ => {} - } - // Load library - App::get() - .app_library - .get_or_init(load_app_library) - .as_ref() - } - Some(l) => l.as_ref(), - }; - result.map_err(|e| anyhow::anyhow!(format!("{e:?}"))) + pub fn get_app_library() -> anyhow::Result<&'static crate::infrastructure::ui::AppLibrary> { + use anyhow::Context; + let app_library = App::get() + .app_library + .get() + .context("App not loaded yet. Please try again later.")? + .as_ref(); + app_library.map_err(|e| anyhow::anyhow!(format!("{e:?}"))) } pub fn has_session(&self, session_id: &str) -> bool { @@ -2041,8 +2024,18 @@ impl RealearnWindowSnitch for RealearnSnitch { #[cfg(feature = "playtime")] fn load_app_library() -> anyhow::Result { + tracing::info!("Loading app library..."); let app_base_dir = App::app_base_dir_path(); - crate::infrastructure::ui::AppLibrary::load(app_base_dir) + let lib = crate::infrastructure::ui::AppLibrary::load(app_base_dir); + match lib.as_ref() { + Ok(_) => { + tracing::info!("App library loaded successfully"); + } + Err(e) => { + tracing::warn!("App library loading failed: {e}"); + } + } + lib } #[cfg(feature = "playtime")] @@ -2065,6 +2058,6 @@ fn decompress_app() -> anyhow::Result<()> { archive .unpack(destination_dir) .context("Couldn't unpack app archive.")?; - tracing::info!("App successfully decompressed"); + tracing::info!("App decompressed successfully"); Ok(()) } diff --git a/main/src/infrastructure/ui/app/app_instance.rs b/main/src/infrastructure/ui/app/app_instance.rs index e90e427b3..7acdcad0e 100644 --- a/main/src/infrastructure/ui/app/app_instance.rs +++ b/main/src/infrastructure/ui/app/app_instance.rs @@ -111,7 +111,7 @@ impl AppInstance for ParentedAppInstance { return Ok(()); } // Fail fast if library not available - App::get().get_or_load_app_library()?; + App::get_app_library()?; // Then open. This actually only opens the SWELL window. The real stuff is done // in the "opened" handler of the SWELL window. self.panel.clone().open(owning_window); @@ -161,7 +161,7 @@ impl AppInstance for StandaloneAppInstance { } fn start_or_show(&mut self, _owning_window: Window) -> Result<()> { - let app_library = App::get().get_or_load_app_library()?; + let app_library = App::get_app_library()?; if let Some(running_state) = &self.running_state { app_library.show_app_instance(None, running_state.common_state.app_handle)?; return Ok(()); @@ -296,7 +296,7 @@ impl AppPanel { fn open_internal(&self, window: Window) -> Result<()> { window.set_text("Playtime"); - let app_library = App::get().get_or_load_app_library()?; + let app_library = App::get_app_library()?; let session_id = extract_session_id(&self.session)?; let app_handle = app_library.start_app_instance(Some(window), session_id)?; let running_state = ParentedAppRunningState { @@ -328,9 +328,7 @@ impl CommonAppRunningState { } pub fn stop(&self, window: Option) -> Result<()> { - App::get() - .get_or_load_app_library()? - .stop_app_instance(window, self.app_handle) + App::get_app_library()?.stop_app_instance(window, self.app_handle) } } diff --git a/playtime-clip-engine b/playtime-clip-engine index 4308ef19f..bb1a73e53 160000 --- a/playtime-clip-engine +++ b/playtime-clip-engine @@ -1 +1 @@ -Subproject commit 4308ef19f6075531b2efdae6b77ef25527bd8961 +Subproject commit bb1a73e53e3293ecf08f6f01a2dcad8cffef37d8