com.harryaskham.pulse · Kotlin · PulseAudio 17
PulseServer
Runs a PulseAudio 17 server as an Android app. Linux programs on the phone, such as those in Nix-on-Droid, play and record through it at 127.0.0.1:4713, and so can other machines on the same network. It routes audio between Android's outputs and microphones, Bluetooth devices, virtual devices and other PulseAudio servers, and keeps every route across restarts.
Use it on a trusted network only. The listener accepts anonymous PulseAudio clients on every IPv4 interface, so anyone who can reach the phone's port can play to it and record from any source it exposes, including microphones and captured app audio once you enable them.
Sources, routes and outputs
The app has Inputs, Outputs, Routing, Remote and Settings tabs. Each input and output is one row with mute, a default star and a volume slider; routes show as chips on the rows they connect. The Routing tab draws them as a graph: drag from an input to an output, or tap one then the other, to connect them.
Each route is a PulseAudio loopback with its own buffer (50 ms to 2 s, 100 ms by default), its own volume, and a channel setting: stereo, mono mix, left only, right only or swapped. Loopbacks are created with source_dont_move and sink_dont_move, so when a Bluetooth headset or a remote server goes away the route waits rather than switching to the phone's microphone or speaker. Named setups save every route plus the default input and output, and the first three appear as launcher shortcuts.
Virtual devices
- Virtual sources (
vsource_<name>) look like an ordinary microphone to recording programs. Routes feed them, and by default those routes only run while something is reading, so a Bluetooth headset is not held in call mode for nothing. - Combined outputs play to two to eight outputs at once and keep them in step.
- Another app's playback becomes a temporary source after Android's own capture consent, on Android 10 and later.
Other PulseAudio servers
A remote server is saved with its name, address and port, and an optional 256-byte PulseAudio cookie kept in the app's private storage. Browsing it lists its sources and sinks; exposing one makes it a local source or sink that routes can use. Saved servers, references and routes never expire while a server is offline: the app retries with a back-off of up to 256 seconds and recreates the endpoints when it returns.
Android outputs
hw_output plays straight to Android's audio output. Optional profiles, off by default on a new install, ask Android for a particular kind of playback so its volume controls and policies apply:
| Sink | Android stream or usage | What to expect |
|---|---|---|
vsink_media | music stream | Media volume and output policy apply. |
vsink_notification | notification stream | Notification volume, linked ring volume and Do Not Disturb depend on the phone. |
vsink_alarm | alarm stream | Alarm volume and policy apply. |
vsink_voice | voice-call stream | Does not itself start call mode. |
vsink_assistant | assistant usage | A hint; often shares media volume. |
vsink_game | game usage | Normally shares media volume. |
Ducking lowers chosen outputs, such as music, to 10–70 % while something plays to others, such as speech, with adjustable fade-down, hold and fade-up times. It reacts to a stream playing, not to its loudness, so it never reads the audio, and a slider you move while ducked keeps your value.
Outside the app
- Widgets: a dashboard for the default output and input, and a controls widget for up to four chosen outputs or inputs, with level bars, mute and a default star.
- Quick volume: a floating window with the same rows, opened from settings, a launcher shortcut, an intent, or Flotilla, which can move, tile and minimise it.
- Staying up: Android's low-memory killer can stop any app. PulseServer restarts after such a kill, and restores microphone access, which Android withholds from services restarted in the background, by briefly opening an invisible activity.
Limits
- There is no authentication on the listener; see the warning above.
- A classic Bluetooth headset's microphone only works in call mode, which lowers the headset's playback quality.
- Captured app audio can be silent: Android blocks calls, protected media, work-profile apps and apps that opt out, and PulseServer reports silence rather than hiding it.
- Phone makers can silence or redirect competing recorders, and some ignore the requested output kinds.
- Level readouts are dBFS, not calibrated sound pressure.