feat: SIGUSR2 handling for toggles (#354)
* feat: SIGUSR2 handling for toggles * run format --------- Co-authored-by: CJ Pais <cj@cjpais.com>
This commit is contained in:
parent
97f3018be0
commit
9c4b1e1f5c
5 changed files with 95 additions and 9 deletions
11
src-tauri/Cargo.lock
generated
11
src-tauri/Cargo.lock
generated
|
|
@ -2349,6 +2349,7 @@ dependencies = [
|
||||||
"rustfft",
|
"rustfft",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"signal-hook",
|
||||||
"strsim",
|
"strsim",
|
||||||
"tar",
|
"tar",
|
||||||
"tauri",
|
"tauri",
|
||||||
|
|
@ -5560,6 +5561,16 @@ version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook"
|
||||||
|
version = "0.3.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"signal-hook-registry",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.6"
|
version = "1.4.6"
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,10 @@ tauri-build = { version = "2", features = [] }
|
||||||
[dependencies]
|
[dependencies]
|
||||||
once_cell = "1"
|
once_cell = "1"
|
||||||
tauri = { version = "2.9.1", features = [
|
tauri = { version = "2.9.1", features = [
|
||||||
"protocol-asset",
|
"protocol-asset",
|
||||||
"macos-private-api",
|
"macos-private-api",
|
||||||
"tray-icon",
|
"tray-icon",
|
||||||
'image-png',
|
'image-png',
|
||||||
] }
|
] }
|
||||||
tauri-plugin-log = "2.7.1"
|
tauri-plugin-log = "2.7.1"
|
||||||
tauri-plugin-opener = "2.5.2"
|
tauri-plugin-opener = "2.5.2"
|
||||||
|
|
@ -68,6 +68,9 @@ tar = "0.4.44"
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
transcribe-rs = "0.1.4"
|
transcribe-rs = "0.1.4"
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
signal-hook = "0.3"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-autostart = "2.5.1"
|
tauri-plugin-autostart = "2.5.1"
|
||||||
tauri-plugin-global-shortcut = "2.3.1"
|
tauri-plugin-global-shortcut = "2.3.1"
|
||||||
|
|
@ -76,9 +79,9 @@ tauri-plugin-updater = "2.9.0"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows = { version = "0.61.3", features = [
|
windows = { version = "0.61.3", features = [
|
||||||
"Win32_Media_Audio_Endpoints",
|
"Win32_Media_Audio_Endpoints",
|
||||||
"Win32_System_Com_StructuredStorage",
|
"Win32_System_Com_StructuredStorage",
|
||||||
"Win32_System_Variant",
|
"Win32_System_Variant",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ pub fn is_laptop() -> Result<bool, String> {
|
||||||
.arg("batt")
|
.arg("batt")
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
||||||
// Check if InternalBattery is present (laptops have batteries, desktops typically don't)
|
// Check if InternalBattery is present (laptops have batteries, desktops typically don't)
|
||||||
Ok(stdout.contains("InternalBattery"))
|
Ok(stdout.contains("InternalBattery"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ mod managers;
|
||||||
mod overlay;
|
mod overlay;
|
||||||
mod settings;
|
mod settings;
|
||||||
mod shortcut;
|
mod shortcut;
|
||||||
|
mod signal_handle;
|
||||||
mod tray;
|
mod tray;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
|
@ -17,6 +18,8 @@ use managers::audio::AudioRecordingManager;
|
||||||
use managers::history::HistoryManager;
|
use managers::history::HistoryManager;
|
||||||
use managers::model::ModelManager;
|
use managers::model::ModelManager;
|
||||||
use managers::transcription::TranscriptionManager;
|
use managers::transcription::TranscriptionManager;
|
||||||
|
use signal_hook::consts::SIGUSR2;
|
||||||
|
use signal_hook::iterator::Signals;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::atomic::{AtomicU8, Ordering};
|
use std::sync::atomic::{AtomicU8, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
@ -119,6 +122,12 @@ fn initialize_core_logic(app_handle: &AppHandle) {
|
||||||
// Initialize the shortcuts
|
// Initialize the shortcuts
|
||||||
shortcut::init_shortcuts(app_handle);
|
shortcut::init_shortcuts(app_handle);
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let signals = Signals::new(&[SIGUSR2]).unwrap();
|
||||||
|
// Set up SIGUSR2 signal handler for toggling transcription
|
||||||
|
#[cfg(unix)]
|
||||||
|
signal_handle::setup_signal_handler(app_handle.clone(), signals);
|
||||||
|
|
||||||
// Apply macOS Accessory policy if starting hidden
|
// Apply macOS Accessory policy if starting hidden
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
|
|
|
||||||
63
src-tauri/src/signal_handle.rs
Normal file
63
src-tauri/src/signal_handle.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
use crate::actions::ACTION_MAP;
|
||||||
|
use crate::ManagedToggleState;
|
||||||
|
use log::{debug, info, warn};
|
||||||
|
use std::thread;
|
||||||
|
use tauri::{AppHandle, Manager};
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use signal_hook::consts::SIGUSR2;
|
||||||
|
#[cfg(unix)]
|
||||||
|
use signal_hook::iterator::Signals;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub fn setup_signal_handler(app_handle: AppHandle, mut signals: Signals) {
|
||||||
|
let app_handle_for_signal = app_handle.clone();
|
||||||
|
|
||||||
|
debug!("SIGUSR2 signal handler registered successfully");
|
||||||
|
thread::spawn(move || {
|
||||||
|
debug!("SIGUSR2 signal handler thread started");
|
||||||
|
for sig in signals.forever() {
|
||||||
|
match sig {
|
||||||
|
SIGUSR2 => {
|
||||||
|
debug!("Received SIGUSR2 signal (signal number: {sig})");
|
||||||
|
|
||||||
|
let binding_id = "transcribe";
|
||||||
|
let shortcut_string = "SIGUSR2";
|
||||||
|
|
||||||
|
if let Some(action) = ACTION_MAP.get(binding_id) {
|
||||||
|
let toggle_state_manager =
|
||||||
|
app_handle_for_signal.state::<ManagedToggleState>();
|
||||||
|
|
||||||
|
let mut states = match toggle_state_manager.lock() {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to lock toggle state manager: {e}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_currently_active = states
|
||||||
|
.active_toggles
|
||||||
|
.entry(binding_id.to_string())
|
||||||
|
.or_insert(false);
|
||||||
|
|
||||||
|
if *is_currently_active {
|
||||||
|
debug!("SIGUSR2: Stopping transcription (currently active)");
|
||||||
|
action.stop(&app_handle_for_signal, binding_id, shortcut_string);
|
||||||
|
*is_currently_active = false; // Update state to inactive
|
||||||
|
debug!("SIGUSR2: Transcription stopped");
|
||||||
|
} else {
|
||||||
|
debug!("SIGUSR2: Starting transcription (currently inactive)");
|
||||||
|
action.start(&app_handle_for_signal, binding_id, shortcut_string);
|
||||||
|
*is_currently_active = true; // Update state to active
|
||||||
|
info!("SIGUSR2: Transcription started");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("No action defined in ACTION_MAP for binding ID '{binding_id}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue