2022-10-12 14:06:26 +00:00
|
|
|
# Audio control
|
2022-10-12 19:58:29 +00:00
|
|
|
|
|
|
|
- [`[synit]/protocols/schemas/audio.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/audio.prs)
|
|
|
|
|
|
|
|
The audio control protocol configures sound sources and sinks, for instance for call audio
|
|
|
|
control on a mobile phone. This protocol is still *experimental*, as configuration of audio
|
|
|
|
stacks is complex and I have only a few simple examples to work from thus far. As Synit is
|
|
|
|
ported to new systems (e.g. new mobile handsets, to desktop machines, and so on), this protocol
|
|
|
|
will be refined.
|
|
|
|
|
|
|
|
**Implementation.** The protocol is (as of October 2022) implemented entirely within the
|
|
|
|
SqueakPhone Smalltalk image, in class `AudioProfileDaemon`. The audio profile daemon has three
|
|
|
|
tasks: first, to track Linux input `HEADPHONE_INSERT` and `MICROPHONE_INSERT` events and state,
|
|
|
|
producing `HeadsetSpeakerPresent` and `HeadsetMicrophonePresent` assertions in response;
|
|
|
|
second, to track application state such as whether a call is in progress or not; and third, to
|
|
|
|
respond to changes in device and application state, along with changes in sink/source mapping
|
|
|
|
configuration, by using the external `amixer` program to enable and disable audio sinks and
|
|
|
|
sources. The schema definition file contains a few
|
|
|
|
[comments](https://git.syndicate-lang.org/synit/synit/src/commit/a2babb63d55743ce942562e7ccb9106fdb239cf4/protocols/schemas/audio.prs#L3-L17)
|
|
|
|
that give some of the flavour of the logic involved.
|
|
|
|
|
|
|
|
## Source/Sink mappings
|
|
|
|
|
|
|
|
Each different kind of device asserts `Mapping` records to connect abstract `Endpoint` names to
|
|
|
|
concrete ALSA device names.
|
|
|
|
|
|
|
|
```
|
|
|
|
Mapping = <alsa-mapping @abstract Endpoint @concrete string> .
|
|
|
|
Endpoint = <source @value Source> / <sink @value Sink> .
|
|
|
|
Sink = =speaker / =headset / =earpiece .
|
|
|
|
Source = =speakerphone / =headset / =handset .
|
|
|
|
```
|
|
|
|
|
|
|
|
**Example.** When the Smalltalk code detects that it is running on a PinePhone, it asserts
|
|
|
|
|
|
|
|
- `<alsa-mapping <sink speaker> "Line Out">`
|
|
|
|
- `<alsa-mapping <sink headset> "Headphone">`
|
|
|
|
- `<alsa-mapping <sink earpiece> "Earpiece">`
|
|
|
|
- `<alsa-mapping <source speakerphone> "Mic1">`
|
|
|
|
- `<alsa-mapping <source handset> "Mic1">`
|
|
|
|
|
|
|
|
## Audio device state
|
|
|
|
|
|
|
|
The current daemon interprets low-level Linux input subsystem events, asserting
|
|
|
|
`HeadsetSpeakerPresent` and `HeadsetMicrophonePresent` when the relevant hardware is physically
|
|
|
|
attached to the system. These assertions are in turn used when selecting an audio profile to
|
|
|
|
enable.
|
|
|
|
|
|
|
|
```
|
|
|
|
HeadsetSpeakerPresent = <headset-speaker-present> .
|
|
|
|
HeadsetMicrophonePresent = <headset-microphone-present> .
|
|
|
|
```
|
|
|
|
|
|
|
|
## Relevant application state
|
|
|
|
|
|
|
|
The current daemon reacts to changes in
|
|
|
|
[`AlertSoundPlaying`](./soundEffects.md#AlertSoundPlaying),
|
|
|
|
[`PhoneRinging`](./telephony.md#PhoneRinging),
|
|
|
|
[`CallInProgress`](./telephony.md#CallInProgress), and
|
|
|
|
[`Speakerphone`](./telephony.md#Speakerphone) when selecting an audio profile to enable.
|