ssh audio forwarding from mac to linux

This commit is contained in:
2026-03-10 15:51:41 +00:00
committed by Thomas G. Lopes
parent c76a74ca6f
commit 597b3edcff
+79 -16
View File
@@ -29,9 +29,36 @@ const PACKS_DIR = path.join(process.env.HOME || "~", ".config/openpeon/packs");
const CONFIG_FILE = path.join(process.env.HOME || "~", ".config/openpeon/config.json");
const DEFAULT_PACK = "peon";
const DEBOUNCE_MS = 500;
const REMOTE_HOST = "linux-pc"; // SSH host for remote notifications
// =======================================
// Get the remote host to SSH back to (the machine the user is physically on)
function getRemoteHost(): string | null {
// Try SSH_CONNECTION to get client's IP (format: client_ip client_port server_ip server_port)
const sshConn = process.env.SSH_CONNECTION || "";
const clientIP = sshConn.split(" ")[0];
if (clientIP && clientIP !== "::1" && clientIP !== "127.0.0.1") {
return clientIP;
}
// Fall back to SSH_CLIENT (older format)
const sshClient = process.env.SSH_CLIENT || "";
const clientIP2 = sshClient.split(" ")[0];
if (clientIP2 && clientIP2 !== "::1" && clientIP2 !== "127.0.0.1") {
return clientIP2;
}
return null;
}
// Map Mac paths to Linux paths for SSH playback
function mapPathToRemote(soundPath: string): string {
// Mac home → Linux home (different username)
if (soundPath.startsWith("/Users/thomasglopes/")) {
return soundPath.replace("/Users/thomasglopes/", "/home/thomasgl/");
}
return soundPath;
}
// ============ SSH DETECTION ============
function isSSH(): boolean {
if (
@@ -168,31 +195,67 @@ function playSoundLocal(soundPath: string, volume: number): void {
}
}
function playSoundRemote(soundPath: string, volume: number): void {
// Play sound on remote host via SSH
const vol = Math.round(volume * 100);
exec(
`ssh -o ConnectTimeout=2 -o BatchMode=yes ${REMOTE_HOST} "pw-play --volume=${vol} '${soundPath}'" 2>/dev/null || true`,
{ timeout: 5000 }
);
}
function playSound(soundPath: string, volume: number): void {
// Always play locally
playSoundLocal(soundPath, volume);
// If on SSH, also play remotely
if (isSSH()) {
playSoundRemote(soundPath, volume);
const remoteHost = getRemoteHost();
// If in SSH session from Mac, play only on the remote Linux machine (where user physically is)
if (remoteHost && isSSH() && process.platform === "darwin") {
const remotePath = mapPathToRemote(soundPath);
// SSH back to Linux with correct username and mapped path
// pw-play expects volume as 0.0-1.0 float
exec(
`ssh -o ConnectTimeout=2 -o BatchMode=yes thomasgl@${remoteHost} "pw-play --volume=${volume} '${remotePath}' 2>/dev/null" 2>/dev/null || true`,
{ timeout: 5000 }
);
return; // Don't play locally - user is on Linux
}
// If in SSH session from Linux, play only on remote Mac
if (remoteHost && isSSH() && process.platform === "linux") {
const vol = Math.round(volume * 100);
exec(
`ssh -o ConnectTimeout=2 -o BatchMode=yes ${remoteHost} "afplay -v ${vol/100} '${soundPath}' 2>/dev/null" 2>/dev/null || true`,
{ timeout: 5000 }
);
return; // Don't play locally - user is on Mac
}
// Play locally when not in SSH session
playSoundLocal(soundPath, volume);
}
function sendNotification(title: string, message: string): void {
const remoteHost = getRemoteHost();
// If SSH'd from Mac to Linux, send notification to Linux (where user is)
if (remoteHost && isSSH() && process.platform === "darwin") {
exec(
`ssh -o ConnectTimeout=2 -o BatchMode=yes thomasgl@${remoteHost} "notify-send -i ~/.pi/agent/extensions/assets/pi-logo.svg '${title}' '${message}'" 2>/dev/null || true`,
{ timeout: 5000 }
);
return;
}
// If SSH'd from Linux to Mac, send notification to Mac (where user is)
if (remoteHost && isSSH() && process.platform === "linux") {
exec(
`ssh -o ConnectTimeout=2 -o BatchMode=yes ${remoteHost} "osascript -e 'display notification \"${message}\" with title \"${title}\"'" 2>/dev/null || true`,
{ timeout: 5000 }
);
return;
}
// Send locally when not in SSH session
if (process.platform === "linux") {
exec(
`notify-send -i ~/.pi/agent/extensions/assets/pi-logo.svg '${title}' '${message}' 2>/dev/null || true`,
{ timeout: 5000 }
);
} else if (process.platform === "darwin") {
exec(
`osascript -e 'display notification "${message}" with title "${title}"' 2>/dev/null || true`,
{ timeout: 5000 }
);
}
}