com.harryaskham.pulse.wear · Kotlin · PulseAudio 17 · Wear OS
Wear Pulse
The PulseServer engine on a Wear OS watch. Other machines can play sound through the watch's speaker or a Bluetooth output and record from its microphone, reaching it through Wear Tailnet. On the watch itself it listens only on its own loopback address.
Reaching the watch
# on a machine on the same tailnet, once both apps are running
PULSE_SERVER=<watch's tailnet name>:4713 paplay chime.wav
PULSE_SERVER=<watch's tailnet name>:4713 parec --file-format=wav note.wav
Shared with the phone
Wear Pulse has only a few hundred lines of its own. Its build compiles PulseServer's Kotlin sources, resources and native PulseAudio 17 libraries directly, so the daemon, the playback and capture bridges and the saved-route logic are the phone's, and fixes land in both. What is new is a small round-screen control surface, a Tile and a complication showing whether it is running and whether the microphone is ready, and a fixed listening address.
The watch package carries three ABIs. For watches that run a 32-bit system on 64-bit chips, the 32-bit PulseAudio is extracted reproducibly from a pinned Termux PulseAudio 17.0 package set, checked by SHA-256. NOD Term can read a small status summary from it, which reports state and readiness but cannot start it or return audio.
What has been tested
- On a Wear OS 5 emulator: the native daemon starts from the app, binds exactly
127.0.0.1:4713, creates the speaker output and microphone source, and answers a local connection. - It survived 30 seconds with the screen off, at about 48 MB of memory; the release APK is about 13 MB.
Still needs a real watch: audible playback, a capture that is not silent, Bluetooth routing, playing and recording at once, access over the tailnet, staying up over LTE with the screen off, and the battery and heat cost.
Android 15 does not let a microphone service start itself after a reboot, so you start it from the app; the Tile and complication open the app rather than starting it in the background.