From c07cb297e32eb0aec722df023c23f561426a0008 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Fri, 21 Nov 2025 10:59:40 -0800 Subject: [PATCH] wip --- baresip/accounts | 2 +- baresip/config | 8 ++++++-- scripts/bootstrap-services.ts | 24 +++++++++++++++++------- scripts/bootstrap.ts | 3 ++- scripts/deploy.ts | 3 ++- scripts/setup-services.ts | 3 ++- src/phone.ts | 2 +- src/utils/waiting-sounds.ts | 30 +++++++++++++++++------------- 8 files changed, 48 insertions(+), 27 deletions(-) diff --git a/baresip/accounts b/baresip/accounts index 39cce39..d581311 100644 --- a/baresip/accounts +++ b/baresip/accounts @@ -1 +1 @@ -;auth_pass=zgm-kwx2bug5hwf3YGF;unregister_on_exit=yes;regint=300 \ No newline at end of file +;auth_pass=zgm-kwx2bug5hwf3YGF;unregister_on_exit=yes \ No newline at end of file diff --git a/baresip/config b/baresip/config index 26b8161..8cafe39 100644 --- a/baresip/config +++ b/baresip/config @@ -51,13 +51,17 @@ module stun.so module turn.so module ice.so +# STUN Server +stun_host stun.l.google.com +stun_port 19302 + module httpd.so #------------------------------------------------------------------------------ # Temporary Modules (loaded then unloaded) -module_tmp uuid.so -module_tmp account.so +module uuid.so +module account.so #------------------------------------------------------------------------------ diff --git a/scripts/bootstrap-services.ts b/scripts/bootstrap-services.ts index 82b6c2b..1a26163 100644 --- a/scripts/bootstrap-services.ts +++ b/scripts/bootstrap-services.ts @@ -8,6 +8,13 @@ const PHONE_SERVICE_FILE = "/etc/systemd/system/phone.service" export const setupServices = async (installDir: string) => { console.log("\nInstalling systemd services...") + // Detect user from environment or use default + // SUDO_USER is set when running with sudo, which is what we want + const serviceUser = process.env.SERVICE_USER || process.env.SUDO_USER || process.env.USER || "corey" + const userUid = await $`id -u ${serviceUser}`.text().then((s) => s.trim()) + + console.log(`Setting up services for user: ${serviceUser} (UID: ${userUid})`) + // Find where bun is installed const bunPath = await $`which bun` .quiet() @@ -61,7 +68,7 @@ WantedBy=multi-user.target writeFileSync(WEB_SERVICE_FILE, webServiceContent, "utf8") console.log("✓ Created phone-web.service") - // Create phone service + // Create phone service (system service with environment variables for audio access) const phoneServiceContent = `[Unit] Description=Phone Application After=network.target sound.target @@ -69,7 +76,10 @@ Requires=sound.target [Service] Type=simple -User=corey +User=${serviceUser} +Group=audio +Environment=XDG_RUNTIME_DIR=/run/user/${userUid} +Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${userUid}/bus ExecStart=${bunPath} ${installDir}/src/main.ts WorkingDirectory=${installDir} EnvironmentFile=${installDir}/.env @@ -90,9 +100,9 @@ WantedBy=multi-user.target await $`systemctl enable phone.service` console.log("✓ Services enabled") - console.log("\nStarting the services...") - await $`systemctl start phone-ap.service` - await $`systemctl start phone-web.service` - await $`systemctl start phone.service` - console.log("✓ Services started") + console.log("\nRestarting the services...") + await $`systemctl restart phone-ap.service` + await $`systemctl restart phone-web.service` + await $`systemctl restart phone.service` + console.log("✓ Services restarted") } diff --git a/scripts/bootstrap.ts b/scripts/bootstrap.ts index d78bdbf..63e3180 100755 --- a/scripts/bootstrap.ts +++ b/scripts/bootstrap.ts @@ -14,7 +14,8 @@ if (process.getuid && process.getuid() !== 0) { } // Get install directory from argument or use default -const INSTALL_DIR = process.argv[2] || "/home/corey/phone" +const defaultUser = process.env.USER || "corey" +const INSTALL_DIR = process.argv[2] || `/home/${defaultUser}/phone` console.log(`Install directory: ${INSTALL_DIR}`) diff --git a/scripts/deploy.ts b/scripts/deploy.ts index e4b6314..ac7a03d 100755 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -2,8 +2,9 @@ import { $ } from "bun" +const defaultUser = process.env.USER ?? "corey" const PI_HOST = process.env.PI_HOST ?? "phone.local" -const PI_DIR = process.env.PI_DIR ?? "/home/corey/phone" +const PI_DIR = process.env.PI_DIR ?? `/home/${defaultUser}/phone` // Parse command line arguments const shouldBootstrap = process.argv.includes("--bootstrap") diff --git a/scripts/setup-services.ts b/scripts/setup-services.ts index f3f397a..11033a4 100644 --- a/scripts/setup-services.ts +++ b/scripts/setup-services.ts @@ -3,7 +3,8 @@ import { setupServices } from "./bootstrap-services" // Get install directory from argument or use default -const INSTALL_DIR = process.argv[2] || "/home/corey/phone" +const defaultUser = process.env.USER || "corey" +const INSTALL_DIR = process.argv[2] || `/home/${defaultUser}/phone` console.log(`Setting up services for: ${INSTALL_DIR}`) diff --git a/src/phone.ts b/src/phone.ts index ab191ab..a1f5ab3 100644 --- a/src/phone.ts +++ b/src/phone.ts @@ -46,7 +46,7 @@ export const runPhone = async (agentId: string, agentKey: string) => { using rotaryInUse = gpio.input(22, { pull: "up", debounce: 3 }) using rotaryNumber = gpio.input(23, { pull: "up", debounce: 3 }) - await Buzz.setVolume(0.4) + await Buzz.setVolume(0.2) log(`📞 Phone is ${hook.value ? "off hook" : "on hook"}`) playStartRing(ringer) diff --git a/src/utils/waiting-sounds.ts b/src/utils/waiting-sounds.ts index 2d66f93..4a316ec 100644 --- a/src/utils/waiting-sounds.ts +++ b/src/utils/waiting-sounds.ts @@ -1,6 +1,7 @@ import Buzz from "../buzz/index.ts" import { join } from "path" import { random } from "./index.ts" +import { log } from "console" export class WaitingSounds { typingPlayback?: Buzz.Playback @@ -38,39 +39,42 @@ export class WaitingSounds { const playedSounds = new Set() let dir: SoundDir | undefined return new Promise(async (resolve) => { + // Don't start playing speaking sounds until the operator stream has been silent for a bit while (operatorStream.bufferEmptyFor < 1500) { await Bun.sleep(100) } do { const lastSoundDir = dir - const value = Math.random() * 100 if (lastSoundDir === "body-noises") { dir = "apology" - } else if (value > 99 && !lastSoundDir) { - dir = "body-noises" - } else if (value > 75 && !lastSoundDir) { - dir = "stalling" } else { - dir = undefined - await Bun.sleep(1000) + // sleep for 4-6 seconds + await Bun.sleep(4000 + Math.random() * 2000) + const value = Math.random() * 100 + + if (value > 95) { + dir = "body-noises" + } else { + dir = "stalling" + } } - if (dir) { - const speakingSound = getSound(dir, Array.from(playedSounds)) - this.speakingPlayback = await this.player.play(speakingSound) - playedSounds.add(speakingSound) - await this.speakingPlayback.finished() - } + const speakingSound = getSound(dir, Array.from(playedSounds)) + this.speakingPlayback = await this.player.play(speakingSound) + playedSounds.add(speakingSound) + await this.speakingPlayback.finished() } while (this.typingPlayback) resolve() }) } async stop() { + log(`🛑 Stopping waiting sounds. Has typingPlayback: ${!!this.typingPlayback}`) if (!this.typingPlayback) return await Promise.all([this.typingPlayback.stop(), this.speakingPlayback?.finished()]) + log("🛑 Waiting sounds stopped") this.typingPlayback = undefined } }