Flesh out protocol descriptions more
This commit is contained in:
parent
b686080af0
commit
8e304902a8
|
@ -1 +1,60 @@
|
|||
# Audio control
|
||||
|
||||
- [`[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.
|
||||
|
|
|
@ -1 +1,17 @@
|
|||
# MIME type support
|
||||
|
||||
- [`[synit]/protocols/schemas/mime.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/mime.prs)
|
||||
|
||||
Various protocols (e.g. the [sound effects](./soundEffects.md) protocols) rely on the
|
||||
definition of a [MIME](https://en.wikipedia.org/wiki/MIME) `Value`, compatible with the
|
||||
[suggested Preserves
|
||||
convention](https://preserves.dev/conventions.html#mime-type-tagged-binary-data) for MIME
|
||||
values.
|
||||
|
||||
The `type` is a symbol describing the MIME type, for example `application/octet-stream` or
|
||||
`text/plain`. The `data` is the associated binary data, expected to be in the correct format
|
||||
for the given `type`.
|
||||
|
||||
```
|
||||
Value = <mime @type symbol @data bytes> .
|
||||
```
|
||||
|
|
|
@ -1 +1,118 @@
|
|||
# Modem support
|
||||
|
||||
- [`[synit]/protocols/schemas/hayes.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/hayes.prs)
|
||||
- [`[synit]/protocols/schemas/samsungGalaxyS7.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/samsungGalaxyS7.prs)
|
||||
|
||||
Each particular class of modem has internal protocols needed for controlling it. So far, Synit
|
||||
is able to interact with generic Hayes-style ("AT-command") modems, as seen in the PinePhone,
|
||||
as well as with the modem in the Samsung Galaxy S7.
|
||||
|
||||
Each modem's internal protocol is spoken across the modem's distinguished dataspace, a
|
||||
reference to which is held in the modem's [`ModemPresent`](./telephony.md#ModemPresent)
|
||||
assertion.
|
||||
|
||||
## Hayes-style ("AT-command") Modems
|
||||
|
||||
As of October 2022, this protocol is implemented entirely in the SqueakPhone Smalltalk image,
|
||||
in class `HayesModemActor` and friends.
|
||||
|
||||
### Presence
|
||||
|
||||
Hayes-style modems announce their presence with a subtype of the general `ModemPresent`
|
||||
assertion schema.
|
||||
|
||||
```
|
||||
ModemPresent = <modem =hayes @devicePath string @dataspace #!InternalProtocol> .
|
||||
```
|
||||
|
||||
(TODO: specify the `InternalProtocol` properly)
|
||||
|
||||
```
|
||||
InternalProtocol = any .
|
||||
```
|
||||
|
||||
### Unsolicited Result Codes
|
||||
|
||||
An `UnsolicitedResultCode` message is sent when the modem sends us a "URC", an Unsolicited
|
||||
Result Code.
|
||||
|
||||
```
|
||||
UnsolicitedResultCode = <unsolicited @result Result> .
|
||||
```
|
||||
|
||||
### Executing AT commands
|
||||
|
||||
Assert a `CommandRPC` record to request execution of an AT command string. The completion,
|
||||
along with any responses, will be send to the `replyTo` entity reference. Alternatively, if no
|
||||
completion notification or response is desired, send a `CommandEvent` message.
|
||||
|
||||
```
|
||||
CommandRPC = <execute-command @commandText string @replyTo #!CommandResult> .
|
||||
CommandEvent = <execute-command @commandText string> .
|
||||
```
|
||||
|
||||
The result of a command execution is *asserted* as a `CommandResult` record to the `replyTo`
|
||||
entity in the `CommandRPC`.
|
||||
|
||||
```
|
||||
CommandResult = <command-result @commandText string @results [Result ...] @finalResult string> .
|
||||
```
|
||||
|
||||
### Responses and Unsolicited Results
|
||||
|
||||
The `Result` type appears in both `UnsolicitedResultCode` and `CommandResult` records.
|
||||
|
||||
```
|
||||
Result = <result @text string @tag MaybeString @fields MaybeStrings> .
|
||||
MaybeString = @present string / @absent #f .
|
||||
MaybeStrings = @present [string ...] / @absent #f .
|
||||
```
|
||||
**Examples.**
|
||||
- `<unsolicited <result "NO CARRIER" #f #f>>`
|
||||
- `<unsolicited <result "+CRING: VOICE" "CRING" ["VOICE"]>>`
|
||||
- `<unsolicited <result "+CLIP: \"+31655555555\",145,,,,0" "CLIP" ["+31655555555" "145" "" "" "" "0"]>>`
|
||||
- `<unsolicited <result "^DSCI: 2,1,4,0,+31655555555,145" "DSCI" ["2" "1" "4" "0" "+31655555555" "145"]>>`
|
||||
- `<unsolicited <result "+QIND: \"csq\",12,99" "QIND" ["csq" "12" "99"]>>`
|
||||
|
||||
## Samsung Galaxy S7
|
||||
|
||||
The Samsung Galaxy S7 was the first modem supported by Synit, but because of problems with the
|
||||
relevant PostmarketOS kernel, support for it has languished a bit while development has
|
||||
proceeded based around the PinePhone. As of October 2022, the Samsung modem support protocols
|
||||
are implemented entirely in the SqueakPhone Smalltalk image, in class
|
||||
`SamsungGalaxyS7ModemActor` and friends.
|
||||
|
||||
### Presence
|
||||
|
||||
The modem announces its presence with a subtype of the general `ModemPresent` assertion schema.
|
||||
|
||||
```
|
||||
ModemPresent = <modem =samsung-galaxy-s7 @devicePath string @dataspace #!InternalProtocol> .
|
||||
```
|
||||
|
||||
(TODO: specify the `InternalProtocol` properly)
|
||||
|
||||
```
|
||||
InternalProtocol = any .
|
||||
```
|
||||
|
||||
### Low-level packet I/O
|
||||
|
||||
```
|
||||
ModemPacket = @in <from-modem @packet any> / @out <to-modem @packet any> .
|
||||
|
||||
; The bodies are instances of SamsungFmtMessage and SamsungRfsMessage, respectively.
|
||||
FmtPacket = <fmt @body #!any> .
|
||||
RfsPacket = <rfs @body #!any> .
|
||||
```
|
||||
|
||||
### Executing commands
|
||||
|
||||
Analogous to AT command execution for Hayes-style modems.
|
||||
|
||||
```
|
||||
; Assertion. Asks the modem to execute the given command.
|
||||
CommandRPC = <execute-command @command FmtPacket @replyTo #!FmtPacket> .
|
||||
; Message. Asks the modem to execute the given command, but not to send back the reply.
|
||||
CommandEvent = <execute-command @command FmtPacket> .
|
||||
```
|
||||
|
|
|
@ -1 +1,195 @@
|
|||
# Network core status and configuration
|
||||
|
||||
- [`[synit]/protocols/schemas/network.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/network.prs)
|
||||
|
||||
[interface monitor]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/usr/lib/synit/python/synit/daemon/interface_monitor.py
|
||||
[wifi daemon]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/usr/lib/synit/python/synit/daemon/wifi_daemon.py
|
||||
[network.pr]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/etc/syndicate/services/network.pr
|
||||
[wifi.pr]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/etc/syndicate/services/wifi.pr
|
||||
[modem.pr]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/etc/syndicate/services/modem.pr
|
||||
|
||||
The definitions in this protocol are used by the Synit daemons responsible for detecting and
|
||||
responding to changes in the configuration of network devices.
|
||||
|
||||
**Implementation.** As of October 2022, this protocol is mostly implemented in
|
||||
- the [interface monitor][],
|
||||
- the [wifi daemon][], and
|
||||
- the scripting around [network state changes][network.pr].
|
||||
- the scripting around the [wifi subsystem][wifi.pr].
|
||||
- the scripting around [mobile data][modem.pr].
|
||||
|
||||
## Network interface presence and state
|
||||
|
||||
The [interface monitor][] daemon uses the Linux netlink protocol to monitor changes in
|
||||
interface presence and state. In response to netlink messages, it maintains an `Interface`
|
||||
assertion for each network interface in the system.
|
||||
|
||||
```
|
||||
Interface = <interface
|
||||
@name string
|
||||
@index int
|
||||
@type InterfaceType
|
||||
@administrativeState AdministrativeState
|
||||
@operationalState OperationalState
|
||||
@carrier CarrierState
|
||||
@linkAddr string> .
|
||||
```
|
||||
|
||||
The `InterfaceType` is synthesised by the interface monitor daemon based on somewhat ad-hoc
|
||||
heuristics.
|
||||
|
||||
```
|
||||
InterfaceType =
|
||||
/ ; `lo` and friends
|
||||
=loopback
|
||||
/ ; `eth0`, bridges, anything that isn't loopback and isn't wireless
|
||||
=normal
|
||||
/ ; 'wlan0' and friends
|
||||
=wireless
|
||||
.
|
||||
```
|
||||
|
||||
The `AdministrativeState` of an interface describes the state that the operator of the machine
|
||||
wishes the interface to be in (according to the kernel).
|
||||
|
||||
```
|
||||
AdministrativeState = =unknown / =down / =up .
|
||||
```
|
||||
|
||||
The `OperationalState` and `CarrierState` taken together, by contrast, describe the *actual*
|
||||
state of the interface.
|
||||
|
||||
```
|
||||
OperationalState =
|
||||
/ =unknown
|
||||
/ =down
|
||||
/ @lowerLayerDown =lower-layer-down
|
||||
/ =testing
|
||||
/ =dormant
|
||||
/ =up
|
||||
.
|
||||
|
||||
CarrierState =
|
||||
/ @noCarrier =no-carrier
|
||||
/ =carrier
|
||||
.
|
||||
```
|
||||
|
||||
## Route presence and state
|
||||
|
||||
The [interface monitor][] daemon also listens for netlink messages describing network route
|
||||
presence and state changes, maintaining a `Route` assertion for each route present.
|
||||
|
||||
```
|
||||
Route = <route
|
||||
@addressFamily AddressFamily
|
||||
@destination RouteDestination
|
||||
@priority int
|
||||
@typeOfService int
|
||||
@interfaceName RouteInterface
|
||||
@gateway Gateway> .
|
||||
|
||||
AddressFamily = =ipv4 / =ipv6 / @other int .
|
||||
RouteDestination = =default / @prefix <prefix @net string @bits int> .
|
||||
RouteInterface = @name string / @none #f .
|
||||
Gateway = @addr string / @none #f .
|
||||
```
|
||||
|
||||
## Default route presence
|
||||
|
||||
The [network.pr][] scripts respond to presence of `Route` records with a `default`
|
||||
`destination` field by asserting a `DefaultRoute` record. Applications may use the presence or
|
||||
absence of a `DefaultRoute` record to decide whether or not internet access is currently
|
||||
present.
|
||||
|
||||
```
|
||||
DefaultRoute = <default-route @addressFamily AddressFamily> .
|
||||
```
|
||||
|
||||
## Wi-fi associations
|
||||
|
||||
The [wifi.pr][] script starts an instance of the [wifi daemon][] and an instance of
|
||||
[`wpa_supplicant`](https://w1.fi/cgit/hostap/tree/README) for each `Interface` of type
|
||||
`wireless`. The wifi daemon speaks with the `wpa_supplicant` instance to do network scanning as
|
||||
well as managing network attachments. It publishes a `WifiAssociation` for each active
|
||||
connection to a wifi access point.
|
||||
|
||||
```
|
||||
WifiAssociation = <wifi-association @interfaceName string @ssid string @state WifiAssociationState> .
|
||||
WifiAssociationState = @inProgress =in-progress / =ready .
|
||||
```
|
||||
|
||||
## Hotspots
|
||||
|
||||
In future, the software will use `HotspotState` assertions to publish the presence and state of
|
||||
wifi hotspots hosted by the device.
|
||||
|
||||
```
|
||||
HotspotState = <hotspot-state @interfaceName string @ssid string @stationCount int> .
|
||||
```
|
||||
|
||||
## AP scanning
|
||||
|
||||
In future, the software will assert `AvailableAccessPoint` with information it learns from
|
||||
network scanning.
|
||||
|
||||
```
|
||||
AvailableAccessPoint = <available-ap @interfaceName string @ssid string> .
|
||||
```
|
||||
|
||||
## Network-related user settings
|
||||
|
||||
A number of user setting assertions control the network.
|
||||
|
||||
### Mobile Data
|
||||
|
||||
Asserting `MobileDataApn` and `MobileDataEnabled` causes the [modem.pr][] script to enable a
|
||||
cellular data link.
|
||||
|
||||
```
|
||||
MobileDataApn = <mobile-data-apn @apn string> .
|
||||
MobileDataEnabled = <mobile-data-enabled> .
|
||||
```
|
||||
|
||||
### Wifi network preferences
|
||||
|
||||
```
|
||||
WifiAuthentication =
|
||||
/ ; No authentication necessary: open network
|
||||
=open
|
||||
/ ; Pre-shared key (WPA2-PSK etc)
|
||||
<psk @password string>
|
||||
/ ; Other, not-yet-implemented
|
||||
@other any
|
||||
.
|
||||
```
|
||||
|
||||
Each [wifi daemon][] responds to `SelectedWifiNetwork` assertions for its interface by trying
|
||||
to connect to the named SSID using the provided credentials. The daemon asserts a
|
||||
`WifiAssociation` in response.
|
||||
|
||||
```
|
||||
SelectedWifiNetwork = <selected-wifi-network
|
||||
@interfaceName string
|
||||
@ssid string
|
||||
@authentication WifiAuthentication> .
|
||||
```
|
||||
|
||||
In future, user `Hotspot` assertions will cause setup of a wifi hotspot, hosted by the device.
|
||||
|
||||
```
|
||||
Hotspot = <hotspot
|
||||
@interfaceName string
|
||||
@ssid string
|
||||
@authentication WifiAuthentication> .
|
||||
```
|
||||
|
||||
In future, `SavedWifiNetwork` assertions will hold records of previously-configured wifi
|
||||
connection details.
|
||||
|
||||
```
|
||||
SavedWifiNetwork = <saved-wifi-network
|
||||
@ssid string
|
||||
@authentication WifiAuthentication
|
||||
@priority double> .
|
||||
```
|
||||
|
|
|
@ -1 +1,31 @@
|
|||
# Sound effects
|
||||
|
||||
- [`[synit]/protocols/schemas/soundEffects.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/soundEffects.prs)
|
||||
|
||||
From time to time, it makes sense for the device to use sound to communicate with the user.
|
||||
|
||||
**Implementation.** As of October 2022, the implementation resides within classes
|
||||
`RingToneDaemon` and `SoundEffectsDaemon` in the SqueakPhone Smalltalk image.
|
||||
|
||||
## Continuous sounds
|
||||
|
||||
Continuous sounds such as a user's ringtone may be produced by asserting `ContinuousSound` with
|
||||
an appropriately-type-tagged sound file (such as an mp3 file) as `data`. In response, the sound
|
||||
effects daemon play the file in a loop and will assert `ContinuousSoundPlaying`.
|
||||
|
||||
```
|
||||
ContinuousSound = <continuous-sound @data mime.Value> .
|
||||
ContinuousSoundPlaying = <continuous-sound-playing> .
|
||||
```
|
||||
|
||||
## <span id="AlertSoundPlaying"></span>Alert sounds
|
||||
|
||||
One-off sound effects such as the notification of a received SMS may be produced by sending an
|
||||
`AlertSound` message with an appropriately-type-tagged sound file (such as an mp3 file) as
|
||||
`data`. In response, the sound effects daemon will play the file once and will assert
|
||||
`AlertSoundPlaying` until the playback is complete.
|
||||
|
||||
```
|
||||
AlertSound = <alert-sound @data mime.Value> .
|
||||
AlertSoundPlaying = <alert-sound-playing> .
|
||||
```
|
||||
|
|
|
@ -1 +1,159 @@
|
|||
# Telephony (call and SMS) support
|
||||
|
||||
- [`[synit]/protocols/schemas/telephony.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/telephony.prs)
|
||||
|
||||
The telephony protocol defines record and message types for non-modem-hardware-specific
|
||||
telephony interactions.
|
||||
|
||||
**Implementation.** The protocol is (as of October 2022) implemented entirely within the
|
||||
SqueakPhone Smalltalk image, in class `CallManager`, `HayesModemActor`,
|
||||
`SamsungGalaxyS7ModemActor`, and so on.
|
||||
|
||||
## <span id="ModemPresent"></span>Available modem devices
|
||||
|
||||
A `ModemPresent` record is asserted for each modem available to the telephony subsystem. The
|
||||
`type` field can, for example, be the symbol `hayes` for a Hayes modem, `samsung-galaxy-s7` for
|
||||
a Samsung Galaxy S7, and so on. Each modem variant speaks a [variant-specific
|
||||
protocol](./modem.md) across the `dataspace` reference in the `ModemPresent` record. Finally,
|
||||
the `devicePath` is a Linux device path representative of the modem, for example
|
||||
`/dev/umts_boot0` or `/dev/EG25.AT`.
|
||||
|
||||
```
|
||||
ModemPresent = <modem @type symbol @devicePath string @dataspace #!any> .
|
||||
```
|
||||
|
||||
## Telephony addresses (telephone numbers)
|
||||
|
||||
An `Address` represents a phone number. The `numberType` selects the numbering plan; the
|
||||
`number` is the actual address. Numbering plans are complex! The GSM specifications are the
|
||||
place to go for details. In general, using `international` with numbers like `+31 6 ...` is the
|
||||
best way forward.
|
||||
|
||||
```
|
||||
Address = <address @numberType NumberType @number string> .
|
||||
NumberType = =unknown / =international / =national / =gsm0338 .
|
||||
```
|
||||
|
||||
## Ongoing calls
|
||||
|
||||
An `ActiveCall` assertion describes an active, ongoing call.
|
||||
|
||||
The `callId` is a modem-specific call identification number. (TODO: if two modems are active,
|
||||
their `callId`s may clash.) The `direction` is `mo` for calls placed by the local phone
|
||||
endpoint, i.e. those dialed by the local user, and `mt` for calls placed by a remote phone,
|
||||
i.e. incoming calls, those answered by the local user. The `type` field describes whether the
|
||||
call is for voice or data; usually, this will be `voice`, but `data` is reported by some modems
|
||||
when using mobile data connections. As you might imagine, `fax`-type calls are uncommon. The
|
||||
`peer` field describes the other phone's network address (phone number). Finally, `state`
|
||||
describes the state of the call.
|
||||
|
||||
```
|
||||
ActiveCall = <call-state @callId CallId @direction CallDirection @type CallType @peer Address @state CallState> .
|
||||
CallId = int .
|
||||
CallDirection = =mo / =mt .
|
||||
CallType = =voice / =data / =fax .
|
||||
CallState = =hold / =original / =connect / =incoming / =waiting / =end / =alerting .
|
||||
```
|
||||
|
||||
## Answering an incoming call
|
||||
|
||||
When an `ActiveCall` record is asserted by the modem, if it has direction `mt` and state
|
||||
`incoming`, the system should let the user choose to answer the call (or ignore it, etc.). If
|
||||
the user chooses to answer, an `AnswerCall` message tells the modem to do the necessary. The
|
||||
`callId` is the same value as in the `ActiveCall` assertion.
|
||||
|
||||
```
|
||||
; Message. Triggers call answering.
|
||||
AnswerCall = <answer-call @callId int> .
|
||||
```
|
||||
|
||||
## Rejecting and/or disconnecting a call
|
||||
|
||||
Sending a `DisconnectCall` message causes the modem to release an active call, either without
|
||||
answering it (rejection) or while it is established (disconnection). The `callId` is taken from
|
||||
the `ActiveCall` assertion, or is the symbol `all` to request disconnection of all active
|
||||
calls. The `cause` field describes the release reason; it should usually be `normal`, but
|
||||
`busy` or `callRejected` may also be appropriate.
|
||||
|
||||
```
|
||||
DisconnectCall = <disconnect-call @callId CallIdSelector @cause ReleaseCause> .
|
||||
CallIdSelector = @specificCall int / @allCalls =all .
|
||||
ReleaseCause =
|
||||
/ =unassignedNumber
|
||||
/ =normal
|
||||
/ =busy
|
||||
/ =noUserResponding
|
||||
/ =callRejected
|
||||
/ =destinationOutOfOrder
|
||||
/ =normalUnspecified
|
||||
/ =incompatibleDestination
|
||||
.
|
||||
```
|
||||
|
||||
## Placing an outbound call
|
||||
|
||||
Sending a `PlaceCall` message causes the matching modem (named by its `devicePath`, which
|
||||
should match a `ModemPresent` assertion) to place an outbound call to the named `peer` (a phone
|
||||
number).
|
||||
|
||||
```
|
||||
; Message. Starts an outgoing call.
|
||||
PlaceCall = <place-call @devicePath string @peer Address> .
|
||||
```
|
||||
|
||||
## <span id="CallInProgress"></span>Whole-device call state
|
||||
|
||||
Many applications don't care about precise details of individual calls, but only whether or not
|
||||
some ongoing call is active (alerting, connected, ringing etc.). Those applications may monitor
|
||||
the `CallInProgress` assertion.
|
||||
|
||||
```
|
||||
CallInProgress = <call-in-progress> .
|
||||
```
|
||||
|
||||
## <span id="PhoneRinging"></span>Whole-device ringing state
|
||||
|
||||
A `PhoneRinging` assertion means that an incoming call is signalling the user, asking for a
|
||||
decision about whether to answer, reject, or ignore the call.
|
||||
|
||||
```
|
||||
PhoneRinging = <phone-ringing> .
|
||||
```
|
||||
|
||||
A `PeerRinging` assertion means that, during the establishment phase of an outgoing call, the
|
||||
remote party's phone should be ringing.
|
||||
|
||||
```
|
||||
PeerRinging = <peer-ringing> .
|
||||
```
|
||||
|
||||
## SMS deliveries and transmissions
|
||||
|
||||
An `SmsDelivery` message indicates that an incoming SMS message has been received. The `smsc`
|
||||
is the message relay server that forwarded the message on to us; this is usually some carrier-
|
||||
and even plan-specific address, see the GSM specifications for details. The `peer` is the
|
||||
sender's phone number. The `timestamp` describes the time associated with the SMS, and the
|
||||
`body` is the message itself.
|
||||
|
||||
```
|
||||
SmsDelivery = <sms-delivery @smsc Address @peer Address @timestamp time.Stamp @body string> .
|
||||
```
|
||||
|
||||
To send an SMS message, assert an `SmsTransmission` record with the correct `smsc`, the
|
||||
`peer`'s destination phone number, and the `body` of the message to send. The `continuation`
|
||||
field should be a reference to an entity that expects the `ok` symbol as a message when the
|
||||
transmission has been processed by the modem.
|
||||
|
||||
```
|
||||
; Assertion. An outgoing SMS should be transmitted.
|
||||
SmsTransmission = <sms-transmission @smsc Address @peer Address @body string @continuation #!=ok > .
|
||||
```
|
||||
|
||||
## <span id="Speakerphone"></span>Speakerphone mode
|
||||
|
||||
The user may choose to assert a `Speakerphone` record in order to request that the local audio
|
||||
hardware switch profile to speakerphone mode during a call.
|
||||
|
||||
```
|
||||
Speakerphone = <speakerphone> .
|
||||
```
|
||||
|
|
|
@ -1 +1,21 @@
|
|||
# Time stamps
|
||||
|
||||
- [`[synit]/protocols/schemas/time.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/time.prs)
|
||||
|
||||
Various protocols rely on the definition of a time stamp type, `Stamp`, compatible with the
|
||||
[suggested Preserves convention](https://preserves.dev/conventions.html#dates-and-times) for
|
||||
dates and times.
|
||||
|
||||
```
|
||||
Stamp = <rfc3339 @value string> .
|
||||
```
|
||||
|
||||
From the Preserves convention document:
|
||||
|
||||
> Dates, times, moments, and timestamps can be represented with a Record with label `rfc3339`
|
||||
> having a single field, a `String`, which MUST conform to one of the `full-date`,
|
||||
> `partial-time`, `full-time`, or `date-time` productions of
|
||||
> [section 5.6 of RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6).
|
||||
> (In `date-time`, “T” and
|
||||
> “Z” MUST be upper-case and “T” MUST be used; a space separating the `full-date` and
|
||||
> `full-time` MUST NOT be used.)
|
||||
|
|
|
@ -1 +1,204 @@
|
|||
# User interface definitions and interaction
|
||||
|
||||
- [`[synit]/protocols/schemas/ui.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/ui.prs)
|
||||
|
||||
The user interface protocol is perhaps the most subject-to-change part of the whole system. It
|
||||
is a client-server protocol, similar in spirit to X-Windows, where *clients* request display
|
||||
and input services from a *server*, to which is attached a display and input devices.
|
||||
|
||||
At present, it is a simple system with a fixed set of widget types, a TeX-inspired box-and-glue
|
||||
layout model, and a very limited set of event types. In future, a
|
||||
NeWS/Display-PostScript-inspired model could dovetail very nicely with the capability and
|
||||
dataspace features of Syndicate.
|
||||
|
||||
**Implementation.** The SqueakPhone Smalltalk image includes the initial implementation of the
|
||||
protocol, in classes `WidgetDaemon`, `WidgetBuilder`, `WidgetWindow`, and so on.
|
||||
|
||||
## Creating a window
|
||||
|
||||
A client *observes* `Window` assertions with an `id` of its choice. The server notices the
|
||||
client's interest, and in response, creates a fresh dataspace for configuration and interaction
|
||||
relating to the new window, and asserts a `Window` record mapping the `id` to the new `space`.
|
||||
|
||||
```
|
||||
Window = <window @id WidgetId @space #!any> .
|
||||
WidgetId = any .
|
||||
```
|
||||
|
||||
## Configuring a window
|
||||
|
||||
Within the dataspace referred to by a `Window` assertion—henceforth the *window dataspace*—the
|
||||
client may assert `WindowCloseable` to add a close button to the window decoration, and may
|
||||
assert `WindowTitle` to give the window a name.
|
||||
|
||||
```
|
||||
WindowCloseable = <window-closeable> .
|
||||
WindowTitle = <window-title @title string> .
|
||||
```
|
||||
|
||||
## Creating widget trees
|
||||
|
||||
The client may place `Widget` assertions within the window dataspace to create new widgets
|
||||
within the window. The window is hidden until the first `Widget` is asserted.
|
||||
|
||||
`Root` and `Parent` assertions connect new widgets to the overall window layout tree. A `Root`
|
||||
assertion places the widget directly in the containing window, while a `Parent` assertion marks
|
||||
a widget as child of another widget. In both cases, the `order` sort key is used when multiple
|
||||
children are present within a container that supports widget ordering.
|
||||
|
||||
```
|
||||
Widget = <widget @id WidgetId @type WidgetType> .
|
||||
|
||||
Parent = <parent @id WidgetId @parentId WidgetId @order SortKey> .
|
||||
Root = <root @id WidgetId @order SortKey> .
|
||||
|
||||
SortKey = @double double / @string string .
|
||||
```
|
||||
|
||||
## Widget Types
|
||||
|
||||
Widgets acting as containers for other widgets may be of either `column` or `row` type. Leaf
|
||||
widgets may be `blank` (for spacing/padding/layout), `text` (a label or editable field), a
|
||||
`slider`, an `image`, or a [FontAwesome](https://fontawesome.com/) `icon`.
|
||||
|
||||
```
|
||||
WidgetType = NodeType / LeafType .
|
||||
NodeType = =column / =row .
|
||||
LeafType = =blank / =text / =slider / =image / =icon .
|
||||
```
|
||||
|
||||
## Configuring widgets
|
||||
|
||||
Widgets have *attributes* attached to them. An attribute is a pair of a symbol `key` and a
|
||||
`value` (of `key`-specific type) attached to a particular widget. Most attribute keys are
|
||||
expected to have either zero or one `Attribute` records for any given widget, but the
|
||||
Syndicated Actor Model naturally supports *multiple* values for a given attribute, and some
|
||||
attribute keys take advantage of this. See [below](#attribute-keys) for more on the available
|
||||
attribute keys.
|
||||
|
||||
```
|
||||
Attribute = <attribute @id WidgetId @key symbol @value any> .
|
||||
```
|
||||
|
||||
## Events and Widget State
|
||||
|
||||
Widgets marked with the [`interactive` attribute](#interactive) generate events in response to
|
||||
user interaction.
|
||||
|
||||
Clients can observe `Touch` assertions to receive information about when the user has a finger
|
||||
touching the displayed widget on a touchscreen. The assertion for a given widget will appear
|
||||
when the touch starts, and disappear when the touch ends. Multiple touches, uniquely
|
||||
identified, may be active simultaneously.
|
||||
|
||||
```
|
||||
Touch = <touch @widget WidgetId @touchId any> .
|
||||
```
|
||||
|
||||
Clients can observe `Click` messages to receive information about when the user removes a
|
||||
touching finger from a widget while the finger is within the widget's bounds.
|
||||
|
||||
```
|
||||
Click = <click @widget WidgetId> .
|
||||
```
|
||||
|
||||
Finally, whether a widget is marked interactive or not, the UI server actor asserts `State`
|
||||
assertions containing facts about a given widget's state. For example, a text widget asserts a
|
||||
`State` assertion with the symbol `text` as its `key` and a string as its `value`; a slider
|
||||
asserts a `value`-keyed `State`; and a scrollable widget asserts a `visible-scroll-range`-keyed
|
||||
`State` with a `VisibleScrollRange` value.
|
||||
|
||||
```
|
||||
State = <state @widget WidgetId @key any @value any> .
|
||||
|
||||
VisibleScrollRange =
|
||||
/ =none
|
||||
/ @visibleScrollRange <visible-scroll-range
|
||||
<min @minId WidgetId @minSortKey SortKey>
|
||||
<max @maxId WidgetId @maxSortKey SortKey>>
|
||||
.
|
||||
```
|
||||
|
||||
## Accessing widget instances
|
||||
|
||||
Within the current implementation, access to the raw
|
||||
[Morphic](http://wiki.squeak.org/squeak/morphic) object representing the widget can be gained
|
||||
by monitoring `WidgetInstance` assertions. (This is not a sustainable technique, and it will be
|
||||
replaced in future by an entity-reference-based system.)
|
||||
|
||||
```
|
||||
WidgetInstance = <widget-instance @id WidgetId @instance #!any> .
|
||||
```
|
||||
|
||||
## <span id="attribute-keys"></span>Widget Attributes
|
||||
|
||||
### General attributes
|
||||
|
||||
interactive - boolean - ?
|
||||
name - string - morphic name for the widget
|
||||
|
||||
### Color and style
|
||||
|
||||
The `Color` type describes an RGBA color value where the components are `double`s in the range
|
||||
`0.0` to `1.0` (inclusive).
|
||||
|
||||
```
|
||||
Color = <rgba @red double @green double @blue double @alpha double> .
|
||||
```
|
||||
|
||||
#### backgroundColor: Color
|
||||
|
||||
Sets the background color of the widget.
|
||||
|
||||
#### foregroundColor: Color
|
||||
|
||||
Text color in a label or editable field; icon color for FontAwesome icons.
|
||||
|
||||
#### cornerStyle: `square` or `rounded`
|
||||
|
||||
Sets the widget's corner style. Defaults to `square`.
|
||||
|
||||
#### cornerRadius: number
|
||||
|
||||
Sets the widget's corner radius (where `cornerStyle` is `rounded`), measured in points.
|
||||
|
||||
#### fontSize: number
|
||||
|
||||
Sets the font size, measured in points.
|
||||
|
||||
#### icon: symbol
|
||||
|
||||
Sets the FontAwesome icon name for icons.
|
||||
|
||||
#### icon-style: symbol
|
||||
|
||||
Sets the FontAwesome icon style name for icons.
|
||||
|
||||
### Layout
|
||||
|
||||
```
|
||||
; Box-and-glue layout
|
||||
Fill = @fixed double / <fill @weight int @rank int> .
|
||||
Sizing = <sizing @ideal double @stretch Fill @shrink Fill> .
|
||||
BoxSize = <box-size @horizontal Sizing @vertical Sizing> .
|
||||
```
|
||||
|
||||
padding - BoxSize - layout padding
|
||||
size - BoxSize
|
||||
spacing - BoxSize
|
||||
|
||||
### Sliders
|
||||
|
||||
max - number
|
||||
min - number
|
||||
orientation - `vertical` or `horizontal` - for sliders
|
||||
value - number - slider value
|
||||
|
||||
### Text fields (labels and editable fields)
|
||||
|
||||
readOnly - boolean - set to false to turn a label into an editable field
|
||||
value - string - label or editable field contents
|
||||
|
||||
### Column and row attributes
|
||||
|
||||
cells - integer - number of cells per row (column) of the layout matrix - if none, just one row (column) exists
|
||||
scrollable - boolean
|
||||
|
|
|
@ -1 +1,18 @@
|
|||
# User settings
|
||||
|
||||
- [`[synit]/protocols/schemas/userSettings.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/userSettings.prs)
|
||||
|
||||
```
|
||||
version 1 .
|
||||
|
||||
; Assertion.
|
||||
CommandRPC = <user-settings-command @action Action @reply #!CommandReply> .
|
||||
; Message.
|
||||
CommandEvent = <user-settings-command @action Action> .
|
||||
|
||||
CommandReply = =done .
|
||||
Action = <assert @item any> / <retract @item any> .
|
||||
|
||||
; Assertion.
|
||||
Value = <user-setting @item any> .
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue