From 226a58b8ce4f1ac13c81b4b2824b95467dca0336 Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Mon, 15 Sep 2025 21:19:55 -0400 Subject: [PATCH 1/4] Load local auto-splitter on splits path change When the splits path changes and get_global_timer doesn't find an existing timer for that splits path, load the local auto-splitter, if there is one, with the new splits get_global_timer: local auto_splitter load bi-directional update --- src/lib.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d74da5c..b0d7bfa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -493,7 +493,11 @@ impl State { unsafe { debug!("Loading settings."); - let global_timer = get_global_timer(splits_path); + let global_timer = get_global_timer( + splits_path, + #[cfg(feature = "auto-splitting")] + &local_auto_splitter, + ); global_timer .timer .auto_save @@ -506,11 +510,6 @@ impl State { let texture = gs_texture_create(width, height, GS_RGBA, 1, ptr::null_mut(), GS_DYNAMIC); obs_leave_graphics(); - #[cfg(feature = "auto-splitting")] - if let Some(local_auto_splitter) = &local_auto_splitter { - auto_splitter_load(&global_timer, local_auto_splitter.clone()) - } - Self { #[cfg(feature = "auto-splitting")] local_auto_splitter, @@ -1838,23 +1837,62 @@ unsafe extern "C" fn update(data: *mut c_void, settings_obj: *mut obs_data_t) { match &widget.kind { WidgetKind::Title { .. } => {} WidgetKind::Bool { default_value } => { - let value = obs_data_get_bool(settings_obj, data_key.as_ptr()); - if value != *default_value { - map.insert(key.clone(), Value::Bool(value)); + let old_value = state + .auto_splitter_map + .get(&key) + .and_then(|v| v.to_bool()) + .unwrap_or(*default_value); + let asr_value = map + .get(&key) + .and_then(|v| v.to_bool()) + .unwrap_or(*default_value); + if asr_value != old_value { + obs_data_set_bool(settings_obj, data_key.as_ptr(), asr_value); + state + .auto_splitter_map + .insert(key.clone(), Value::Bool(asr_value)); } else { map.remove(key); + let obs_value = obs_data_get_bool(settings_obj, data_key.as_ptr()); + if obs_value != *default_value { + map.insert(key.clone(), Value::Bool(obs_value)); + } else { + map.remove(key); + } } } WidgetKind::Choice { default_option_key, .. } => { - if let Some(value) = + let old_value = state + .auto_splitter_map + .get(&key) + .and_then(|v| v.as_string()) + .unwrap_or(default_option_key); + let asr_value = map + .get(&key) + .and_then(|v| v.as_string()) + .unwrap_or(default_option_key); + if asr_value != old_value { + if let Ok(new_value) = + CString::from_vec_with_nul(format!("{}\0", asr_value).into()) + { + obs_data_set_string( + settings_obj, + data_key.as_ptr(), + new_value.as_ptr(), + ); + } + state + .auto_splitter_map + .insert(key.clone(), Value::String(asr_value.clone())); + } else if let Some(obs_value) = CStr::from_ptr(obs_data_get_string(settings_obj, data_key.as_ptr())) .to_str() .ok() .filter(|v| *v != &**default_option_key) { - map.insert(key.clone(), Value::String(Arc::from(value))); + map.insert(key.clone(), Value::String(Arc::from(obs_value))); } else { map.remove(key); } @@ -1908,10 +1946,17 @@ unsafe extern "C" fn update(data: *mut c_void, settings_obj: *mut obs_data_t) { } fn handle_splits_path_change(state: &mut State, splits_path: PathBuf) { - state.global_timer = get_global_timer(splits_path); + state.global_timer = get_global_timer( + splits_path, + #[cfg(feature = "auto-splitting")] + &state.local_auto_splitter, + ); } -fn get_global_timer(splits_path: PathBuf) -> Arc { +fn get_global_timer( + splits_path: PathBuf, + #[cfg(feature = "auto-splitting")] local_auto_splitter: &Option, +) -> Arc { let mut timers = TIMERS.lock().unwrap(); timers.retain(|timer| timer.strong_count() > 0); if let Some(timer) = timers.iter().find_map(|timer| { @@ -1942,6 +1987,10 @@ fn get_global_timer(splits_path: PathBuf) -> Arc { #[cfg(feature = "auto-splitting")] auto_splitter_is_enabled: AtomicBool::new(false), }); + #[cfg(feature = "auto-splitting")] + if let Some(local_auto_splitter) = local_auto_splitter { + auto_splitter_load(&global_timer, local_auto_splitter.clone()); + } timers.push(Arc::downgrade(&global_timer)); global_timer } From e6a45c309247f4093b6b29259e7bf0a0045d77f5 Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Mon, 15 Sep 2025 21:51:58 -0400 Subject: [PATCH 2/4] livesplit-core: Refragg-2 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73fbcb7..af65d32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1465,7 +1465,7 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "livesplit-auto-splitting" version = "0.1.0" -source = "git+https://github.com/LiveSplit/livesplit-core#7649ba092a0e0723c4dbafe600778ddac78ede4d" +source = "git+https://github.com/AlexKnauth/livesplit-core?branch=Refragg-2#652d2b481a627e5c0d971b6646fc78aacdb650e6" dependencies = [ "anyhow", "arc-swap", @@ -1489,7 +1489,7 @@ dependencies = [ [[package]] name = "livesplit-core" version = "0.13.0" -source = "git+https://github.com/LiveSplit/livesplit-core#7649ba092a0e0723c4dbafe600778ddac78ede4d" +source = "git+https://github.com/AlexKnauth/livesplit-core?branch=Refragg-2#652d2b481a627e5c0d971b6646fc78aacdb650e6" dependencies = [ "arc-swap", "base64-simd", @@ -1525,7 +1525,7 @@ dependencies = [ [[package]] name = "livesplit-hotkey" version = "0.8.0" -source = "git+https://github.com/LiveSplit/livesplit-core#7649ba092a0e0723c4dbafe600778ddac78ede4d" +source = "git+https://github.com/AlexKnauth/livesplit-core?branch=Refragg-2#652d2b481a627e5c0d971b6646fc78aacdb650e6" dependencies = [ "bitflags 2.9.3", "cfg-if", @@ -1542,7 +1542,7 @@ dependencies = [ [[package]] name = "livesplit-title-abbreviations" version = "0.3.0" -source = "git+https://github.com/LiveSplit/livesplit-core#7649ba092a0e0723c4dbafe600778ddac78ede4d" +source = "git+https://github.com/AlexKnauth/livesplit-core?branch=Refragg-2#652d2b481a627e5c0d971b6646fc78aacdb650e6" [[package]] name = "log" diff --git a/Cargo.toml b/Cargo.toml index 4d97112..975a5b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ members = ["obs"] crate-type = ["cdylib"] [dependencies] -livesplit-core = { git = "https://github.com/LiveSplit/livesplit-core", features = [ +livesplit-core = { git = "https://github.com/AlexKnauth/livesplit-core", branch = "Refragg-2", features = [ "software-rendering", "font-loading", ] } From 2ee569680d1da369f41c17ae8ed97c7d41f7d002 Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Mon, 1 Jul 2024 18:11:40 -0400 Subject: [PATCH 3/4] run_auto_splitter_settings_map_store --- src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index b0d7bfa..b1ca005 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1919,6 +1919,13 @@ unsafe extern "C" fn update(data: *mut c_void, settings_obj: *mut obs_data_t) { .set_settings_map_if_unchanged(&original, map.clone()) != Some(false) { + state + .global_timer + .timer + .timer + .write() + .unwrap() + .run_auto_splitter_settings_map_store(map.clone()); state.auto_splitter_map = map; break; } From 018bf332e5a180aff55d9ce606645a1e5e8aad1d Mon Sep 17 00:00:00 2001 From: Alex Knauth Date: Mon, 19 Aug 2024 13:53:18 -0400 Subject: [PATCH 4/4] Update AutoSplitter Settings Map before saving --- src/lib.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index b1ca005..d4949bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -626,6 +626,9 @@ unsafe extern "C" fn reset( return; } + // Update AutoSplitter Settings Map before reset-autosaving + #[cfg(feature = "auto-splitting")] + update_auto_splitter_settings_map(&state.global_timer); drop(state.global_timer.timer.reset(None)); } } @@ -920,6 +923,9 @@ unsafe extern "C" fn save_splits( ) -> bool { unsafe { let state: &mut State = &mut (*data.cast::>()).lock().unwrap(); + // Update AutoSplitter Settings Map before saving + #[cfg(feature = "auto-splitting")] + update_auto_splitter_settings_map(&state.global_timer); state.global_timer.timer.save(); false } @@ -1180,6 +1186,17 @@ fn auto_splitter_load(global_timer: &GlobalTimer, path: PathBuf) { .store(enabled, atomic::Ordering::Relaxed); } +/// Update AutoSplitter Settings Map, from the +/// auto_splitting::Runtime to the Inner Timer Run, +/// to prepare for it to be saved to a splits file +#[cfg(feature = "auto-splitting")] +fn update_auto_splitter_settings_map(global_timer: &GlobalTimer) -> Option<()> { + let m = global_timer.auto_splitter.settings_map()?; + let mut t = global_timer.timer.timer.write().ok()?; + t.run_auto_splitter_settings_map_store(m); + Some(()) +} + #[cfg(feature = "auto-splitting")] unsafe extern "C" fn auto_splitter_activate_clicked( _props: *mut obs_properties_t, @@ -1312,6 +1329,9 @@ unsafe extern "C" fn media_play_pause(data: *mut c_void, pause: bool) { unsafe extern "C" fn media_restart(data: *mut c_void) { unsafe { let state: &mut State = &mut (*data.cast::>()).lock().unwrap(); + // Update AutoSplitter Settings Map before reset-autosaving + #[cfg(feature = "auto-splitting")] + update_auto_splitter_settings_map(&state.global_timer); drop(state.global_timer.timer.reset(None)); drop(state.global_timer.timer.start()); } @@ -1320,6 +1340,9 @@ unsafe extern "C" fn media_restart(data: *mut c_void) { unsafe extern "C" fn media_stop(data: *mut c_void) { unsafe { let state: &mut State = &mut (*data.cast::>()).lock().unwrap(); + // Update AutoSplitter Settings Map before reset-autosaving + #[cfg(feature = "auto-splitting")] + update_auto_splitter_settings_map(&state.global_timer); drop(state.global_timer.timer.reset(None)); } }