generated from Labyricorn/labyricorn-project-template
rebrand: rename VoiceBox to TalkBox throughout codebase
CI / frontend-quality (push) Canceled after 0s
CI / frontend-quality (push) Canceled after 0s
- All 'voicebox'/'Voicebox'/'VOICEBOX' strings replaced with 'talkbox'/'TalkBox'/'TALKBOX' - Port changed from 17493 to 17494 (avoids conflict with upstream VoiceBox) - MCP tool namespace: voicebox.* -> talkbox.* - App bundle ID: sh.voicebox.app -> com.talkbox.app - Binary names: voicebox-server -> talkbox-server, voicebox-mcp -> talkbox-mcp - Docker user/group: voicebox -> talkbox - Database: voicebox.db -> talkbox.db - Env vars: VOICEBOX_* -> TALKBOX_* - Asset files renamed: voicebox-logo.* -> talkbox-logo.*, etc. - External binaries in tauri.conf.json updated to talkbox-server/talkbox-mcp
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "voicebox"
|
||||
name = "talkbox"
|
||||
version = "0.5.0"
|
||||
description = "A production-quality desktop app for Qwen3-TTS voice cloning and generation"
|
||||
authors = ["you"]
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>voicebox</string>
|
||||
<string>talkbox</string>
|
||||
<key>CFBundleIconName</key>
|
||||
<string>voicebox</string>
|
||||
<string>talkbox</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>voicebox needs microphone access to record voice samples for voice cloning.</string>
|
||||
<string>talkbox needs microphone access to record voice samples for voice cloning.</string>
|
||||
<key>NSScreenCaptureUsageDescription</key>
|
||||
<string>Voicebox needs screen capture access to record system audio for voice samples.</string>
|
||||
<string>TalkBox needs screen capture access to record system audio for voice samples.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -34,8 +34,8 @@ fn main() {
|
||||
// Compile macOS Liquid Glass icon
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
// voicebox.icon is in tauri/assets/voicebox.icon (one level up from src-tauri)
|
||||
let icon_source = format!("{}/../assets/voicebox.icon", project_root);
|
||||
// talkbox.icon is in tauri/assets/talkbox.icon (one level up from src-tauri)
|
||||
let icon_source = format!("{}/../assets/talkbox.icon", project_root);
|
||||
|
||||
if std::path::Path::new(&icon_source).exists() {
|
||||
println!("cargo:rerun-if-changed={}", icon_source);
|
||||
@@ -53,7 +53,7 @@ fn main() {
|
||||
"--output-partial-info-plist",
|
||||
&partial_plist,
|
||||
"--app-icon",
|
||||
"voicebox",
|
||||
"talkbox",
|
||||
"--include-all-app-icons",
|
||||
"--target-device",
|
||||
"mac",
|
||||
@@ -81,12 +81,12 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Generate voicebox.icns from the source PNG via sips + iconutil
|
||||
let icns_path = format!("{}/voicebox.icns", gen_dir);
|
||||
// Generate talkbox.icns from the source PNG via sips + iconutil
|
||||
let icns_path = format!("{}/talkbox.icns", gen_dir);
|
||||
if !std::path::Path::new(&icns_path).exists() {
|
||||
let source_png = format!("{}/Assets/Voicebox.png", icon_source);
|
||||
let source_png = format!("{}/Assets/TalkBox.png", icon_source);
|
||||
if std::path::Path::new(&source_png).exists() {
|
||||
let iconset_dir = format!("{}/voicebox.iconset", gen_dir);
|
||||
let iconset_dir = format!("{}/talkbox.iconset", gen_dir);
|
||||
std::fs::create_dir_all(&iconset_dir).ok();
|
||||
|
||||
let sizes: &[(u32, &str)] = &[
|
||||
@@ -131,7 +131,7 @@ fn main() {
|
||||
|
||||
match iconutil_output {
|
||||
Ok(out) if out.status.success() => {
|
||||
println!("Generated voicebox.icns");
|
||||
println!("Generated talkbox.icns");
|
||||
}
|
||||
Ok(out) => {
|
||||
eprintln!("iconutil failed: {}", String::from_utf8_lossy(&out.stderr));
|
||||
@@ -157,7 +157,7 @@ fn main() {
|
||||
// On non-macOS these are always stubs. On macOS, actool may not produce
|
||||
// Assets.car if the Xcode version doesn't support the .icon format.
|
||||
{
|
||||
let required = ["Assets.car", "voicebox.icns", "partial.plist"];
|
||||
let required = ["Assets.car", "talkbox.icns", "partial.plist"];
|
||||
for name in required {
|
||||
let path = format!("{}/{}", gen_dir, name);
|
||||
if !std::path::Path::new(&path).exists() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"identifier": "default",
|
||||
"description": "Default permissions for voicebox",
|
||||
"description": "Default permissions for talkbox",
|
||||
"platforms": ["linux", "macOS", "windows"],
|
||||
"windows": ["main", "dictate"],
|
||||
"remote": {
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"default":{"identifier":"default","description":"Default permissions for voicebox","remote":{"urls":["http://localhost:*"]},"local":true,"windows":["main","dictate"],"permissions":["core:default","core:window:default","core:window:allow-start-dragging","core:webview:default","core:webview:allow-internal-toggle-devtools","shell:allow-open","shell:allow-execute","shell:allow-spawn","updater:default","process:default","dialog:default","dialog:allow-save","dialog:allow-open","fs:default","fs:read-all","fs:write-all"],"platforms":["linux","macOS","windows"]}}
|
||||
{"default":{"identifier":"default","description":"Default permissions for talkbox","remote":{"urls":["http://localhost:*"]},"local":true,"windows":["main","dictate"],"permissions":["core:default","core:window:default","core:window:allow-start-dragging","core:webview:default","core:webview:allow-internal-toggle-devtools","shell:allow-open","shell:allow-execute","shell:allow-spawn","updater:default","process:default","dialog:default","dialog:allow-save","dialog:allow-open","fs:default","fs:read-all","fs:write-all"],"platforms":["linux","macOS","windows"]}}
|
||||
@@ -25,8 +25,8 @@
|
||||
//!
|
||||
//! PID + bundle id + role are all captured for diagnostics — the bundle
|
||||
//! id lets step 6 (internal direct injection) detect "focus was inside
|
||||
//! Voicebox itself" and short-circuit the synthetic-paste path. On
|
||||
//! Windows, `bundle_id` holds the lowercased exe basename (`"voicebox.exe"`)
|
||||
//! TalkBox itself" and short-circuit the synthetic-paste path. On
|
||||
//! Windows, `bundle_id` holds the lowercased exe basename (`"talkbox.exe"`)
|
||||
//! since there's no equivalent of macOS' reverse-DNS bundle identifier.
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
@@ -350,7 +350,7 @@ mod win {
|
||||
}
|
||||
|
||||
/// Query a PID's executable path and return its lowercased basename
|
||||
/// (e.g. `"voicebox.exe"`). This is the Windows analogue of macOS'
|
||||
/// (e.g. `"talkbox.exe"`). This is the Windows analogue of macOS'
|
||||
/// `bundleIdentifier`, just less globally unique — two apps with the
|
||||
/// same exe name can collide, but that's rare enough to accept for
|
||||
/// the self-paste short-circuit.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//! job is:
|
||||
//!
|
||||
//! 1. Build a `ChordMatcher` from the user's saved PTT + Toggle chords.
|
||||
//! 2. Translate `ChordEvent` → voicebox's [`Effect`] on a dispatcher
|
||||
//! 2. Translate `ChordEvent` → talkbox's [`Effect`] on a dispatcher
|
||||
//! thread.
|
||||
//! 3. Fan [`Effect`]s out into Tauri events + dictate-window show/hide.
|
||||
//!
|
||||
@@ -128,7 +128,7 @@ impl HotkeyMonitor {
|
||||
let shutdown_for_thread = shutdown.clone();
|
||||
let app = self.app.clone();
|
||||
let dispatcher = thread::Builder::new()
|
||||
.name("voicebox-hotkey-dispatcher".into())
|
||||
.name("talkbox-hotkey-dispatcher".into())
|
||||
.spawn(move || dispatcher_loop(app, matcher, shutdown_for_thread))
|
||||
.expect("spawn hotkey dispatcher thread");
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
//! grant without prompting. We call this from the Captures settings UI
|
||||
//! so the row can show "granted" / "missing" without surprising the user.
|
||||
//! - `IOHIDRequestAccess(kIOHIDRequestTypeListenEvent)` — fire the
|
||||
//! "Voicebox would like to receive keystrokes from any application"
|
||||
//! dialog and add Voicebox to the Input Monitoring pane (toggle off).
|
||||
//! "TalkBox would like to receive keystrokes from any application"
|
||||
//! dialog and add TalkBox to the Input Monitoring pane (toggle off).
|
||||
//! Returns true when access is already granted; otherwise returns false
|
||||
//! and queues the prompt. The user still has to flip the toggle on; this
|
||||
//! just gets us into the list.
|
||||
|
||||
+53
-53
@@ -35,7 +35,7 @@ fn build_dictate_window(app: &tauri::AppHandle) -> tauri::Result<tauri::WebviewW
|
||||
DICTATE_WINDOW_LABEL,
|
||||
WebviewUrl::App("?view=dictate".into()),
|
||||
)
|
||||
.title("Voicebox Dictate")
|
||||
.title("TalkBox Dictate")
|
||||
.inner_size(DICTATE_WINDOW_WIDTH, DICTATE_WINDOW_HEIGHT)
|
||||
.decorations(false)
|
||||
.transparent(true)
|
||||
@@ -121,17 +121,17 @@ pub fn show_dictate_window(app: &tauri::AppHandle) {
|
||||
}
|
||||
|
||||
const LEGACY_PORT: u16 = 8000;
|
||||
pub(crate) const SERVER_PORT: u16 = 17493;
|
||||
pub(crate) const SERVER_PORT: u16 = 17494;
|
||||
|
||||
/// Find a voicebox-server process listening on a given port (Windows only).
|
||||
/// Find a talkbox-server process listening on a given port (Windows only).
|
||||
///
|
||||
/// Uses PowerShell `Get-NetTCPConnection` to look up the PID owning the port,
|
||||
/// then verifies via `tasklist` that it's a voicebox process. The caller is
|
||||
/// then verifies via `tasklist` that it's a talkbox process. The caller is
|
||||
/// responsible for checking port occupancy first (e.g. `TcpStream::connect_timeout`).
|
||||
/// Replaces the previous `netstat -ano` approach which failed on systems with
|
||||
/// corrupted system DLLs (see #277).
|
||||
#[cfg(windows)]
|
||||
fn find_voicebox_pid_on_port(port: u16) -> Option<u32> {
|
||||
fn find_talkbox_pid_on_port(port: u16) -> Option<u32> {
|
||||
use std::process::Command;
|
||||
|
||||
// Use PowerShell's Get-NetTCPConnection to find the PID listening on the port.
|
||||
@@ -147,13 +147,13 @@ fn find_voicebox_pid_on_port(port: u16) -> Option<u32> {
|
||||
let output_str = String::from_utf8_lossy(&output.stdout);
|
||||
for line in output_str.lines() {
|
||||
if let Ok(pid) = line.trim().parse::<u32>() {
|
||||
// Verify this PID is a voicebox process
|
||||
// Verify this PID is a talkbox process
|
||||
if let Ok(tasklist_output) = Command::new("tasklist")
|
||||
.args(["/FI", &format!("PID eq {}", pid), "/FO", "CSV", "/NH"])
|
||||
.output()
|
||||
{
|
||||
let tasklist_str = String::from_utf8_lossy(&tasklist_output.stdout);
|
||||
if tasklist_str.to_lowercase().contains("voicebox") {
|
||||
if tasklist_str.to_lowercase().contains("talkbox") {
|
||||
return Some(pid);
|
||||
}
|
||||
}
|
||||
@@ -164,10 +164,10 @@ fn find_voicebox_pid_on_port(port: u16) -> Option<u32> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Check if a Voicebox server is responding on the given port.
|
||||
/// Check if a TalkBox server is responding on the given port.
|
||||
///
|
||||
/// Sends an HTTP GET to `/health` and returns `true` only if the response
|
||||
/// is valid JSON matching the Voicebox `HealthResponse` schema — specifically
|
||||
/// is valid JSON matching the TalkBox `HealthResponse` schema — specifically
|
||||
/// `status` must be `"healthy"`, and both `model_loaded` and `gpu_available`
|
||||
/// must be present as booleans. This prevents misidentifying an unrelated
|
||||
/// service that happens to expose a `/health` endpoint.
|
||||
@@ -183,7 +183,7 @@ fn check_health(port: u16) -> bool {
|
||||
if !resp.status().is_success() {
|
||||
return false;
|
||||
}
|
||||
// Parse as JSON and validate Voicebox-specific fields
|
||||
// Parse as JSON and validate TalkBox-specific fields
|
||||
match resp.json::<serde_json::Value>() {
|
||||
Ok(body) => {
|
||||
body.get("status").and_then(|v| v.as_str()) == Some("healthy")
|
||||
@@ -283,7 +283,7 @@ async fn start_server(
|
||||
return Ok(format!("http://127.0.0.1:{}", SERVER_PORT));
|
||||
}
|
||||
|
||||
// Check if a voicebox server is already running on our port (from previous session with keep_running=true,
|
||||
// Check if a talkbox server is already running on our port (from previous session with keep_running=true,
|
||||
// or an externally started server e.g. via `python`, `uvicorn`, Docker, etc.)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
@@ -298,25 +298,25 @@ async fn start_server(
|
||||
if parts.len() >= 2 {
|
||||
let command = parts[0];
|
||||
let pid_str = parts[1];
|
||||
if command.contains("voicebox") {
|
||||
if command.contains("talkbox") {
|
||||
if let Ok(pid) = pid_str.parse::<u32>() {
|
||||
println!("Found existing voicebox-server on port {} (PID: {}), reusing it", SERVER_PORT, pid);
|
||||
println!("Found existing talkbox-server on port {} (PID: {}), reusing it", SERVER_PORT, pid);
|
||||
// Store the PID so we can kill it on exit if needed
|
||||
*state.server_pid.lock().unwrap() = Some(pid);
|
||||
return Ok(format!("http://127.0.0.1:{}", SERVER_PORT));
|
||||
}
|
||||
} else {
|
||||
// Process name doesn't contain "voicebox" — could be an external
|
||||
// Process name doesn't contain "talkbox" — could be an external
|
||||
// Python/uvicorn/Docker server. Verify via HTTP health check.
|
||||
println!("Port {} in use by '{}' (PID: {}), checking if it's a Voicebox server...", SERVER_PORT, command, pid_str);
|
||||
println!("Port {} in use by '{}' (PID: {}), checking if it's a TalkBox server...", SERVER_PORT, command, pid_str);
|
||||
if check_health(SERVER_PORT) {
|
||||
println!("Health check passed — reusing external server on port {}", SERVER_PORT);
|
||||
return Ok(format!("http://127.0.0.1:{}", SERVER_PORT));
|
||||
}
|
||||
println!("Health check failed — port is occupied by a non-Voicebox process");
|
||||
println!("Health check failed — port is occupied by a non-TalkBox process");
|
||||
return Err(format!(
|
||||
"Port {} is already in use by another application ({}). \
|
||||
Close it or change the Voicebox server port.",
|
||||
Close it or change the TalkBox server port.",
|
||||
SERVER_PORT, command
|
||||
));
|
||||
}
|
||||
@@ -332,28 +332,28 @@ async fn start_server(
|
||||
&format!("127.0.0.1:{}", SERVER_PORT).parse().unwrap(),
|
||||
std::time::Duration::from_secs(1),
|
||||
).is_ok() {
|
||||
// Port is in use — check if it's a voicebox process by name first
|
||||
if let Some(pid) = find_voicebox_pid_on_port(SERVER_PORT) {
|
||||
println!("Found existing voicebox-server on port {} (PID: {}), reusing it", SERVER_PORT, pid);
|
||||
// Port is in use — check if it's a talkbox process by name first
|
||||
if let Some(pid) = find_talkbox_pid_on_port(SERVER_PORT) {
|
||||
println!("Found existing talkbox-server on port {} (PID: {}), reusing it", SERVER_PORT, pid);
|
||||
*state.server_pid.lock().unwrap() = Some(pid);
|
||||
return Ok(format!("http://127.0.0.1:{}", SERVER_PORT));
|
||||
}
|
||||
// Process name doesn't match — could be an external Python/Docker server.
|
||||
// Verify via HTTP health check before giving up.
|
||||
println!("Port {} in use by unknown process, checking if it's a Voicebox server...", SERVER_PORT);
|
||||
println!("Port {} in use by unknown process, checking if it's a TalkBox server...", SERVER_PORT);
|
||||
if check_health(SERVER_PORT) {
|
||||
println!("Health check passed — reusing external server on port {}", SERVER_PORT);
|
||||
return Ok(format!("http://127.0.0.1:{}", SERVER_PORT));
|
||||
}
|
||||
return Err(format!(
|
||||
"Port {} is already in use by another application. \
|
||||
Close the other application or change the Voicebox port.",
|
||||
Close the other application or change the TalkBox port.",
|
||||
SERVER_PORT
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Kill any orphaned voicebox-server from previous session on legacy port 8000
|
||||
// Kill any orphaned talkbox-server from previous session on legacy port 8000
|
||||
// This handles upgrades from older versions that used a fixed port
|
||||
#[cfg(unix)]
|
||||
{
|
||||
@@ -369,9 +369,9 @@ async fn start_server(
|
||||
let command = parts[0];
|
||||
let pid_str = parts[1];
|
||||
|
||||
if command.contains("voicebox") {
|
||||
if command.contains("talkbox") {
|
||||
if let Ok(pid) = pid_str.parse::<i32>() {
|
||||
println!("Found orphaned voicebox-server on legacy port {} (PID: {}, CMD: {}), killing it...", LEGACY_PORT, pid, command);
|
||||
println!("Found orphaned talkbox-server on legacy port {} (PID: {}, CMD: {}), killing it...", LEGACY_PORT, pid, command);
|
||||
let _ = Command::new("kill")
|
||||
.args(["-9", "--", &format!("-{}", pid)])
|
||||
.output();
|
||||
@@ -380,7 +380,7 @@ async fn start_server(
|
||||
.output();
|
||||
}
|
||||
} else {
|
||||
println!("Legacy port {} is in use by non-voicebox process: {} (PID: {}), not killing", LEGACY_PORT, command, pid_str);
|
||||
println!("Legacy port {} is in use by non-talkbox process: {} (PID: {}), not killing", LEGACY_PORT, command, pid_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,8 +394,8 @@ async fn start_server(
|
||||
&format!("127.0.0.1:{}", LEGACY_PORT).parse().unwrap(),
|
||||
std::time::Duration::from_secs(1),
|
||||
).is_ok() {
|
||||
if let Some(pid) = find_voicebox_pid_on_port(LEGACY_PORT) {
|
||||
println!("Found orphaned voicebox-server on legacy port {} (PID: {}), killing it...", LEGACY_PORT, pid);
|
||||
if let Some(pid) = find_talkbox_pid_on_port(LEGACY_PORT) {
|
||||
println!("Found orphaned talkbox-server on legacy port {} (PID: {}), killing it...", LEGACY_PORT, pid);
|
||||
let _ = std::process::Command::new("taskkill")
|
||||
.args(["/PID", &pid.to_string(), "/T", "/F"])
|
||||
.output();
|
||||
@@ -417,7 +417,7 @@ async fn start_server(
|
||||
.map_err(|e| format!("Failed to create data dir: {}", e))?;
|
||||
|
||||
println!("=================================================================");
|
||||
println!("Starting voicebox-server sidecar");
|
||||
println!("Starting talkbox-server sidecar");
|
||||
println!("Data directory: {:?}", data_dir);
|
||||
println!("Remote mode: {}", remote.unwrap_or(false));
|
||||
|
||||
@@ -425,9 +425,9 @@ async fn start_server(
|
||||
let rocm_binary = {
|
||||
let rocm_dir = data_dir.join("backends").join("rocm");
|
||||
let rocm_name = if cfg!(windows) {
|
||||
"voicebox-server-rocm.exe"
|
||||
"talkbox-server-rocm.exe"
|
||||
} else {
|
||||
"voicebox-server-rocm"
|
||||
"talkbox-server-rocm"
|
||||
};
|
||||
let exe_path = rocm_dir.join(rocm_name);
|
||||
if exe_path.exists() {
|
||||
@@ -464,9 +464,9 @@ async fn start_server(
|
||||
let cuda_binary = {
|
||||
let cuda_dir = data_dir.join("backends").join("cuda");
|
||||
let cuda_name = if cfg!(windows) {
|
||||
"voicebox-server-cuda.exe"
|
||||
"talkbox-server-cuda.exe"
|
||||
} else {
|
||||
"voicebox-server-cuda"
|
||||
"talkbox-server-cuda"
|
||||
};
|
||||
let exe_path = cuda_dir.join(cuda_name);
|
||||
if exe_path.exists() {
|
||||
@@ -501,7 +501,7 @@ async fn start_server(
|
||||
}
|
||||
};
|
||||
|
||||
let sidecar_result = app.shell().sidecar("voicebox-server");
|
||||
let sidecar_result = app.shell().sidecar("talkbox-server");
|
||||
|
||||
let mut sidecar = match sidecar_result {
|
||||
Ok(s) => s,
|
||||
@@ -586,7 +586,7 @@ async fn start_server(
|
||||
cmd = cmd.current_dir(rocm_dir);
|
||||
cmd = cmd.args(["--data-dir", &data_dir_str, "--port", &port_str, "--parent-pid", &parent_pid_str]);
|
||||
if is_remote { cmd = cmd.args(["--host", "0.0.0.0"]); }
|
||||
if let Some(ref dir) = effective_models_dir { cmd = cmd.env("VOICEBOX_MODELS_DIR", dir); }
|
||||
if let Some(ref dir) = effective_models_dir { cmd = cmd.env("TALKBOX_MODELS_DIR", dir); }
|
||||
match cmd.spawn() {
|
||||
Ok(r) => { gpu_spawn = Some(Ok(r)); }
|
||||
Err(e) => { println!("ROCm spawn failed ({}), trying CUDA/CPU fallback", e); }
|
||||
@@ -601,7 +601,7 @@ async fn start_server(
|
||||
cmd = cmd.current_dir(cuda_dir);
|
||||
cmd = cmd.args(["--data-dir", &data_dir_str, "--port", &port_str, "--parent-pid", &parent_pid_str]);
|
||||
if is_remote { cmd = cmd.args(["--host", "0.0.0.0"]); }
|
||||
if let Some(ref dir) = effective_models_dir { cmd = cmd.env("VOICEBOX_MODELS_DIR", dir); }
|
||||
if let Some(ref dir) = effective_models_dir { cmd = cmd.env("TALKBOX_MODELS_DIR", dir); }
|
||||
match cmd.spawn() {
|
||||
Ok(r) => { gpu_spawn = Some(Ok(r)); }
|
||||
Err(e) => { println!("CUDA spawn failed ({}), falling back to CPU", e); }
|
||||
@@ -615,7 +615,7 @@ async fn start_server(
|
||||
// Fall back to bundled CPU sidecar
|
||||
sidecar = sidecar.args(["--data-dir", &data_dir_str, "--port", &port_str, "--parent-pid", &parent_pid_str]);
|
||||
if is_remote { sidecar = sidecar.args(["--host", "0.0.0.0"]); }
|
||||
if let Some(ref dir) = effective_models_dir { sidecar = sidecar.env("VOICEBOX_MODELS_DIR", dir); }
|
||||
if let Some(ref dir) = effective_models_dir { sidecar = sidecar.env("TALKBOX_MODELS_DIR", dir); }
|
||||
println!("Spawning bundled CPU server process...");
|
||||
sidecar.spawn()
|
||||
}
|
||||
@@ -627,7 +627,7 @@ async fn start_server(
|
||||
sidecar = sidecar.args(["--host", "0.0.0.0"]);
|
||||
}
|
||||
if let Some(ref dir) = effective_models_dir {
|
||||
sidecar = sidecar.env("VOICEBOX_MODELS_DIR", dir);
|
||||
sidecar = sidecar.env("TALKBOX_MODELS_DIR", dir);
|
||||
}
|
||||
sidecar.spawn()
|
||||
};
|
||||
@@ -786,7 +786,7 @@ async fn start_server(
|
||||
{
|
||||
eprintln!("Server process ended unexpectedly during startup!");
|
||||
eprintln!("The server binary may have crashed or exited with an error.");
|
||||
eprintln!("Check Console.app logs for more details (search for 'voicebox')");
|
||||
eprintln!("Check Console.app logs for more details (search for 'talkbox')");
|
||||
return Err("Server process ended unexpectedly".to_string());
|
||||
}
|
||||
}
|
||||
@@ -967,20 +967,20 @@ fn stop_audio_playback(
|
||||
state.stop_all_playback()
|
||||
}
|
||||
|
||||
/// Identifier of the Voicebox app itself — used to short-circuit auto-paste
|
||||
/// Identifier of the TalkBox app itself — used to short-circuit auto-paste
|
||||
/// when the user fires a chord while focus was inside one of our own
|
||||
/// windows. Paste into Voicebox-internal targets is step 6 territory and
|
||||
/// windows. Paste into TalkBox-internal targets is step 6 territory and
|
||||
/// goes through a different (JS-side) injection path.
|
||||
///
|
||||
/// Value matches what `focus_capture::capture_focus` writes into
|
||||
/// `FocusSnapshot::bundle_id` on the current platform — reverse-DNS bundle
|
||||
/// id on macOS, lowercased exe basename on Windows/Linux.
|
||||
#[cfg(target_os = "macos")]
|
||||
const VOICEBOX_BUNDLE_ID: &str = "sh.voicebox.app";
|
||||
const TALKBOX_BUNDLE_ID: &str = "sh.talkbox.app";
|
||||
#[cfg(target_os = "windows")]
|
||||
const VOICEBOX_BUNDLE_ID: &str = "voicebox.exe";
|
||||
const TALKBOX_BUNDLE_ID: &str = "talkbox.exe";
|
||||
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||
const VOICEBOX_BUNDLE_ID: &str = "voicebox";
|
||||
const TALKBOX_BUNDLE_ID: &str = "talkbox";
|
||||
|
||||
/// Milliseconds to wait between activating the target app and firing the
|
||||
/// synthetic ⌘V, giving AppKit time to finish re-ordering windows and
|
||||
@@ -1060,7 +1060,7 @@ fn build_chord_bindings(
|
||||
/// frontend invokes this both at startup (when `capture_settings.hotkey_enabled`
|
||||
/// is true) and from the settings toggle.
|
||||
///
|
||||
/// On macOS this is the call that triggers the "Voicebox would like to receive
|
||||
/// On macOS this is the call that triggers the "TalkBox would like to receive
|
||||
/// keystrokes from any application" TCC prompt, since keytap's `Tap` creates
|
||||
/// the CGEventTap inside `HotkeyMonitor::spawn`.
|
||||
#[cfg(desktop)]
|
||||
@@ -1204,7 +1204,7 @@ fn open_input_monitoring_settings(app: tauri::AppHandle) -> Result<(), String> {
|
||||
/// clipboard stuck on the transcript.
|
||||
///
|
||||
/// Skips (returns `false`) without touching anything when:
|
||||
/// - `focus.bundle_id` is Voicebox itself — step 6 will inject directly
|
||||
/// - `focus.bundle_id` is TalkBox itself — step 6 will inject directly
|
||||
/// into our own webview; pasting would just double-insert or miss the
|
||||
/// real target.
|
||||
/// - Accessibility is not trusted — `CGEventPost` would silently drop the
|
||||
@@ -1217,12 +1217,12 @@ async fn paste_final_text(
|
||||
text: String,
|
||||
focus: focus_capture::FocusSnapshot,
|
||||
) -> Result<bool, String> {
|
||||
if focus.bundle_id.as_deref() == Some(VOICEBOX_BUNDLE_ID) {
|
||||
if focus.bundle_id.as_deref() == Some(TALKBOX_BUNDLE_ID) {
|
||||
return Ok(false);
|
||||
}
|
||||
if !accessibility::is_trusted() {
|
||||
return Err(
|
||||
"Accessibility permission required for auto-paste. Open System Settings → Privacy & Security → Accessibility and enable Voicebox."
|
||||
"Accessibility permission required for auto-paste. Open System Settings → Privacy & Security → Accessibility and enable TalkBox."
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
@@ -1244,7 +1244,7 @@ async fn paste_final_text(
|
||||
clipboard::restore_clipboard(&snapshot)?;
|
||||
} else {
|
||||
eprintln!(
|
||||
"[voicebox] clipboard mutated during paste window — skipping restore to preserve newer content"
|
||||
"[talkbox] clipboard mutated during paste window — skipping restore to preserve newer content"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1273,7 +1273,7 @@ async fn debug_focus_roundtrip(
|
||||
) -> Result<serde_json::Value, String> {
|
||||
if !accessibility::is_trusted() {
|
||||
return Err(
|
||||
"Accessibility permission not granted. Open System Settings → Privacy & Security → Accessibility and enable Voicebox."
|
||||
"Accessibility permission not granted. Open System Settings → Privacy & Security → Accessibility and enable TalkBox."
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
@@ -1320,7 +1320,7 @@ async fn debug_paste_text(
|
||||
) -> Result<serde_json::Value, String> {
|
||||
if !accessibility::is_trusted() {
|
||||
return Err(
|
||||
"Accessibility permission not granted. Open System Settings → Privacy & Security → Accessibility and enable Voicebox, then try again."
|
||||
"Accessibility permission not granted. Open System Settings → Privacy & Security → Accessibility and enable TalkBox, then try again."
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
@@ -1418,7 +1418,7 @@ pub fn run() {
|
||||
// finishes (rest-fade → hidden). `hide()` alone has been
|
||||
// unreliable for transparent always-on-top windows on macOS
|
||||
// — the NSWindow lingers as an invisible click target that
|
||||
// steals focus to the Voicebox app when the user clicks
|
||||
// steals focus to the TalkBox app when the user clicks
|
||||
// where it used to be. Park the window off-screen and mark
|
||||
// it click-through as well, so even if `hide()` no-ops the
|
||||
// user sees and interacts with nothing.
|
||||
@@ -1434,7 +1434,7 @@ pub fn run() {
|
||||
}
|
||||
});
|
||||
|
||||
// Agent-initiated speech (voicebox.speak over MCP or POST /speak)
|
||||
// Agent-initiated speech (talkbox.speak over MCP or POST /speak)
|
||||
// pops the pill up so the user can see what's coming out of their
|
||||
// machine. The `dictate:show` listener is kept for any frontend
|
||||
// caller that wants to force-surface the pill directly, but the
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Voicebox",
|
||||
"productName": "TalkBox",
|
||||
"version": "0.5.0",
|
||||
"identifier": "sh.voicebox.app",
|
||||
"identifier": "sh.talkbox.app",
|
||||
"build": {
|
||||
"beforeDevCommand": "bun run dev",
|
||||
"beforeBuildCommand": "bun run build",
|
||||
@@ -13,7 +13,7 @@
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"createUpdaterArtifacts": "v1Compatible",
|
||||
"externalBin": ["binaries/voicebox-server", "binaries/voicebox-mcp"],
|
||||
"externalBin": ["binaries/talkbox-server", "binaries/talkbox-mcp"],
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"resources": {
|
||||
"gen/Assets.car": "./",
|
||||
"gen/voicebox.icns": "./",
|
||||
"gen/talkbox.icns": "./",
|
||||
"gen/partial.plist": "./"
|
||||
}
|
||||
},
|
||||
@@ -61,7 +61,7 @@
|
||||
},
|
||||
"updater": {
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEUxRENBQkRBQjdBNTM1OTIKUldTU05hVzMycXZjNGJGcUxmcVVocll2QjdSaTJNdlFxR2M3VDJsMnVvbDdyZGRPMmRlOW9aWTcK",
|
||||
"endpoints": ["https://github.com/jamiepine/voicebox/releases/latest/download/latest.json"]
|
||||
"endpoints": ["https://github.com/jamiepine/talkbox/releases/latest/download/latest.json"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// 2. Run: cargo test --test audio_capture_test -- --nocapture
|
||||
// 3. The test will capture audio for 5 seconds and verify the output
|
||||
|
||||
use voicebox::audio_capture::{AudioCaptureState, start_capture, stop_capture};
|
||||
use talkbox::audio_capture::{AudioCaptureState, start_capture, stop_capture};
|
||||
use base64::Engine;
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user