@cssints/apg-specs 0.0.0-stage → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +65 -2
- package/dist/apg/accordion.bridge.d.mts +35 -0
- package/dist/apg/accordion.bridge.mjs +326 -0
- package/dist/apg/accordion.model.json +8397 -0
- package/dist/apg/alert.bridge.d.mts +22 -0
- package/dist/apg/alert.bridge.mjs +86 -0
- package/dist/apg/alert.model.json +871 -0
- package/dist/apg/alertdialog.bridge.d.mts +21 -0
- package/dist/apg/alertdialog.bridge.mjs +221 -0
- package/dist/apg/alertdialog.model.json +5232 -0
- package/dist/apg/breadcrumb.bridge.d.mts +26 -0
- package/dist/apg/breadcrumb.bridge.mjs +120 -0
- package/dist/apg/breadcrumb.model.json +574 -0
- package/dist/apg/button.bridge.d.mts +35 -0
- package/dist/apg/button.bridge.mjs +208 -0
- package/dist/apg/button.model.json +5814 -0
- package/dist/apg/carousel.bridge.d.mts +44 -0
- package/dist/apg/carousel.bridge.mjs +262 -0
- package/dist/apg/carousel.model.json +8963 -0
- package/dist/apg/checkbox-group.bridge.d.mts +25 -0
- package/dist/apg/checkbox-group.bridge.mjs +276 -0
- package/dist/apg/checkbox-group.model.json +3863 -0
- package/dist/apg/checkbox.bridge.d.mts +34 -0
- package/dist/apg/checkbox.bridge.mjs +253 -0
- package/dist/apg/checkbox.model.json +3158 -0
- package/dist/apg/combobox-autocomplete.bridge.d.mts +14 -0
- package/dist/apg/combobox-autocomplete.bridge.mjs +326 -0
- package/dist/apg/combobox-autocomplete.model.json +11586 -0
- package/dist/apg/combobox-dialog.bridge.d.mts +17 -0
- package/dist/apg/combobox-dialog.bridge.mjs +250 -0
- package/dist/apg/combobox-dialog.model.json +8981 -0
- package/dist/apg/combobox-grid.bridge.d.mts +17 -0
- package/dist/apg/combobox-grid.bridge.mjs +227 -0
- package/dist/apg/combobox-grid.model.json +8554 -0
- package/dist/apg/combobox-select-only.bridge.d.mts +24 -0
- package/dist/apg/combobox-select-only.bridge.mjs +304 -0
- package/dist/apg/combobox-select-only.model.json +7846 -0
- package/dist/apg/combobox-tree.bridge.d.mts +17 -0
- package/dist/apg/combobox-tree.bridge.mjs +211 -0
- package/dist/apg/combobox-tree.model.json +9345 -0
- package/dist/apg/dialog-modal.bridge.d.mts +35 -0
- package/dist/apg/dialog-modal.bridge.mjs +186 -0
- package/dist/apg/dialog-modal.model.json +7580 -0
- package/dist/apg/disclosure.bridge.d.mts +25 -0
- package/dist/apg/disclosure.bridge.mjs +202 -0
- package/dist/apg/disclosure.model.json +4703 -0
- package/dist/apg/feed.bridge.d.mts +31 -0
- package/dist/apg/feed.bridge.mjs +246 -0
- package/dist/apg/feed.model.json +4523 -0
- package/dist/apg/grid-selection.bridge.d.mts +13 -0
- package/dist/apg/grid-selection.bridge.mjs +160 -0
- package/dist/apg/grid-selection.model.json +6974 -0
- package/dist/apg/grid-sort.bridge.d.mts +12 -0
- package/dist/apg/grid-sort.bridge.mjs +138 -0
- package/dist/apg/grid-sort.model.json +3799 -0
- package/dist/apg/grid.bridge.d.mts +54 -0
- package/dist/apg/grid.bridge.mjs +441 -0
- package/dist/apg/grid.model.json +3802 -0
- package/dist/apg/link.bridge.d.mts +24 -0
- package/dist/apg/link.bridge.mjs +126 -0
- package/dist/apg/link.model.json +694 -0
- package/dist/apg/listbox-multi.bridge.d.mts +10 -0
- package/dist/apg/listbox-multi.bridge.mjs +261 -0
- package/dist/apg/listbox-multi.model.json +10893 -0
- package/dist/apg/listbox-rearrangeable.bridge.d.mts +20 -0
- package/dist/apg/listbox-rearrangeable.bridge.mjs +237 -0
- package/dist/apg/listbox-rearrangeable.model.json +17592 -0
- package/dist/apg/listbox-shared.d.mts +58 -0
- package/dist/apg/listbox-shared.mjs +171 -0
- package/dist/apg/listbox-single.bridge.d.mts +10 -0
- package/dist/apg/listbox-single.bridge.mjs +196 -0
- package/dist/apg/listbox-single.model.json +8024 -0
- package/dist/apg/listbox-typeahead.bridge.d.mts +10 -0
- package/dist/apg/listbox-typeahead.bridge.mjs +153 -0
- package/dist/apg/listbox-typeahead.model.json +5615 -0
- package/dist/apg/menu-button.bridge.d.mts +29 -0
- package/dist/apg/menu-button.bridge.mjs +259 -0
- package/dist/apg/menu-button.model.json +5706 -0
- package/dist/apg/menu-checkable.bridge.d.mts +25 -0
- package/dist/apg/menu-checkable.bridge.mjs +226 -0
- package/dist/apg/menu-checkable.model.json +4277 -0
- package/dist/apg/menu-menubar.bridge.d.mts +27 -0
- package/dist/apg/menu-menubar.bridge.mjs +273 -0
- package/dist/apg/menu-menubar.model.json +9540 -0
- package/dist/apg/meter.bridge.d.mts +28 -0
- package/dist/apg/meter.bridge.mjs +159 -0
- package/dist/apg/meter.model.json +1185 -0
- package/dist/apg/player.bridge.d.mts +24 -0
- package/dist/apg/player.bridge.mjs +342 -0
- package/dist/apg/player.model.json +11013 -0
- package/dist/apg/radio.bridge.d.mts +35 -0
- package/dist/apg/radio.bridge.mjs +371 -0
- package/dist/apg/radio.model.json +5011 -0
- package/dist/apg/slider-multithumb.bridge.d.mts +34 -0
- package/dist/apg/slider-multithumb.bridge.mjs +365 -0
- package/dist/apg/slider-multithumb.model.json +5774 -0
- package/dist/apg/slider.bridge.d.mts +54 -0
- package/dist/apg/slider.bridge.mjs +359 -0
- package/dist/apg/slider.model.json +4881 -0
- package/dist/apg/spinbutton.bridge.d.mts +41 -0
- package/dist/apg/spinbutton.bridge.mjs +327 -0
- package/dist/apg/spinbutton.model.json +7571 -0
- package/dist/apg/switch.bridge.d.mts +30 -0
- package/dist/apg/switch.bridge.mjs +243 -0
- package/dist/apg/switch.model.json +3159 -0
- package/dist/apg/tabs.bridge.d.mts +41 -0
- package/dist/apg/tabs.bridge.mjs +294 -0
- package/dist/apg/tabs.model.json +7659 -0
- package/dist/apg/timeline.bridge.d.mts +36 -0
- package/dist/apg/timeline.bridge.mjs +265 -0
- package/dist/apg/timeline.model.json +6189 -0
- package/dist/apg/toolbar.bridge.d.mts +25 -0
- package/dist/apg/toolbar.bridge.mjs +307 -0
- package/dist/apg/toolbar.model.json +6616 -0
- package/dist/apg/tooltip.bridge.d.mts +36 -0
- package/dist/apg/tooltip.bridge.mjs +208 -0
- package/dist/apg/tooltip.model.json +8295 -0
- package/dist/apg/treegrid.bridge.d.mts +28 -0
- package/dist/apg/treegrid.bridge.mjs +311 -0
- package/dist/apg/treegrid.model.json +17358 -0
- package/dist/apg/treeview.bridge.d.mts +26 -0
- package/dist/apg/treeview.bridge.mjs +396 -0
- package/dist/apg/treeview.model.json +13745 -0
- package/dist/apg/windowsplitter.bridge.d.mts +36 -0
- package/dist/apg/windowsplitter.bridge.mjs +242 -0
- package/dist/apg/windowsplitter.model.json +6253 -0
- package/dist/canvas/camera.model.json +6568 -0
- package/dist/canvas/canvas.bridge.d.mts +190 -0
- package/dist/canvas/canvas.bridge.mjs +729 -0
- package/dist/canvas/pointer.model.json +17095 -0
- package/dist/scenario.d.mts +233 -0
- package/dist/scenario.mjs +313 -0
- package/package.json +57 -4
- package/scenarios/apg/README.md +221 -0
- package/scenarios/apg/accordion.base-ui.json +1005 -0
- package/scenarios/apg/accordion.react-aria.json +929 -0
- package/scenarios/apg/alert.base-ui.json +81 -0
- package/scenarios/apg/alert.react-aria.json +98 -0
- package/scenarios/apg/alertdialog.base-ui.json +331 -0
- package/scenarios/apg/alertdialog.react-aria.json +225 -0
- package/scenarios/apg/breadcrumb.react-aria.json +312 -0
- package/scenarios/apg/button.ariakit.json +136 -0
- package/scenarios/apg/button.base-ui.json +747 -0
- package/scenarios/apg/button.react-aria.json +443 -0
- package/scenarios/apg/carousel.apg.json +909 -0
- package/scenarios/apg/checkbox.ariakit.json +299 -0
- package/scenarios/apg/checkbox.base-ui.json +1126 -0
- package/scenarios/apg/checkbox.react-aria.json +518 -0
- package/scenarios/apg/combobox.ariakit.json +945 -0
- package/scenarios/apg/combobox.base-ui.json +2444 -0
- package/scenarios/apg/combobox.react-aria.json +845 -0
- package/scenarios/apg/dialog-modal.ariakit.json +1102 -0
- package/scenarios/apg/dialog-modal.base-ui.json +775 -0
- package/scenarios/apg/dialog-modal.react-aria.json +638 -0
- package/scenarios/apg/disclosure.apg.json +349 -0
- package/scenarios/apg/disclosure.ariakit.json +163 -0
- package/scenarios/apg/disclosure.base-ui.json +451 -0
- package/scenarios/apg/disclosure.react-aria.json +643 -0
- package/scenarios/apg/feed.apg.json +442 -0
- package/scenarios/apg/grid.ariakit.json +197 -0
- package/scenarios/apg/grid.base-ui.json +720 -0
- package/scenarios/apg/grid.react-aria.json +969 -0
- package/scenarios/apg/landmarks.ariakit.json +93 -0
- package/scenarios/apg/landmarks.react-aria.json +330 -0
- package/scenarios/apg/link.ariakit.json +83 -0
- package/scenarios/apg/link.base-ui.json +88 -0
- package/scenarios/apg/link.react-aria.json +186 -0
- package/scenarios/apg/listbox.ariakit.json +78 -0
- package/scenarios/apg/listbox.base-ui.json +163 -0
- package/scenarios/apg/listbox.react-aria.json +1118 -0
- package/scenarios/apg/menu-button.ariakit.json +924 -0
- package/scenarios/apg/menu-button.base-ui.json +1155 -0
- package/scenarios/apg/menu-button.react-aria.json +1080 -0
- package/scenarios/apg/menubar.ariakit.json +758 -0
- package/scenarios/apg/menubar.base-ui.json +673 -0
- package/scenarios/apg/meter.base-ui.json +243 -0
- package/scenarios/apg/meter.react-aria.json +201 -0
- package/scenarios/apg/radio.ariakit.json +459 -0
- package/scenarios/apg/radio.base-ui.json +581 -0
- package/scenarios/apg/radio.react-aria.json +576 -0
- package/scenarios/apg/slider-multithumb.base-ui.json +316 -0
- package/scenarios/apg/slider-multithumb.react-aria.json +363 -0
- package/scenarios/apg/slider.base-ui.json +544 -0
- package/scenarios/apg/slider.react-aria.json +456 -0
- package/scenarios/apg/spinbutton.base-ui.json +1688 -0
- package/scenarios/apg/spinbutton.react-aria.json +426 -0
- package/scenarios/apg/switch.base-ui.json +456 -0
- package/scenarios/apg/switch.react-aria.json +303 -0
- package/scenarios/apg/table.ariakit.json +65 -0
- package/scenarios/apg/table.react-aria.json +221 -0
- package/scenarios/apg/tabs.ariakit.json +329 -0
- package/scenarios/apg/tabs.base-ui.json +875 -0
- package/scenarios/apg/tabs.react-aria.json +644 -0
- package/scenarios/apg/toolbar.ariakit.json +595 -0
- package/scenarios/apg/toolbar.base-ui.json +1189 -0
- package/scenarios/apg/toolbar.react-aria.json +383 -0
- package/scenarios/apg/tooltip.ariakit.json +441 -0
- package/scenarios/apg/tooltip.base-ui.json +411 -0
- package/scenarios/apg/tooltip.react-aria.json +454 -0
- package/scenarios/apg/treegrid.apg.json +2558 -0
- package/scenarios/apg/treegrid.react-aria.json +5094 -0
- package/scenarios/apg/treeview.apg.json +928 -0
- package/scenarios/apg/windowsplitter.apg.json +557 -0
- package/scenarios/canvas/README.md +69 -0
- package/scenarios/canvas/camera.contract.json +237 -0
- package/scenarios/canvas/camera.excalidraw.json +57 -0
- package/scenarios/canvas/marquee.excalidraw.json +122 -0
- package/scenarios/canvas/pan.excalidraw.json +46 -0
- package/scenarios/canvas/pointer.contract.json +528 -0
- package/scenarios/parts.json +291 -0
- package/shared/aria.qnt +186 -0
- package/shared/details-group.qnt +50 -0
- package/shared/focusgroup.qnt +152 -0
- package/shared/invokers.qnt +81 -0
- package/shared/popover.qnt +71 -0
- package/specs/apg/STATIC.md +103 -0
- package/specs/apg/accordion.qnt +578 -0
- package/specs/apg/alert.qnt +131 -0
- package/specs/apg/alertdialog.qnt +455 -0
- package/specs/apg/breadcrumb.qnt +88 -0
- package/specs/apg/button.qnt +445 -0
- package/specs/apg/carousel.qnt +732 -0
- package/specs/apg/checkbox-group.qnt +388 -0
- package/specs/apg/checkbox.qnt +394 -0
- package/specs/apg/combobox-autocomplete.qnt +764 -0
- package/specs/apg/combobox-dialog.qnt +627 -0
- package/specs/apg/combobox-grid.qnt +632 -0
- package/specs/apg/combobox-select-only.qnt +626 -0
- package/specs/apg/combobox-tree.qnt +633 -0
- package/specs/apg/dialog-modal.qnt +499 -0
- package/specs/apg/disclosure.qnt +309 -0
- package/specs/apg/feed.qnt +485 -0
- package/specs/apg/grid-selection.qnt +512 -0
- package/specs/apg/grid-sort.qnt +330 -0
- package/specs/apg/grid.qnt +360 -0
- package/specs/apg/link.qnt +119 -0
- package/specs/apg/listbox-multi.qnt +799 -0
- package/specs/apg/listbox-rearrangeable.qnt +801 -0
- package/specs/apg/listbox-single.qnt +511 -0
- package/specs/apg/listbox-typeahead.qnt +396 -0
- package/specs/apg/menu-button.qnt +363 -0
- package/specs/apg/menu-checkable.qnt +304 -0
- package/specs/apg/menu-menubar.qnt +531 -0
- package/specs/apg/meter.qnt +129 -0
- package/specs/apg/player.qnt +1081 -0
- package/specs/apg/radio.qnt +394 -0
- package/specs/apg/slider-multithumb.qnt +441 -0
- package/specs/apg/slider.qnt +396 -0
- package/specs/apg/spinbutton.qnt +494 -0
- package/specs/apg/switch.qnt +389 -0
- package/specs/apg/tabs.qnt +412 -0
- package/specs/apg/timeline.qnt +612 -0
- package/specs/apg/toolbar.qnt +364 -0
- package/specs/apg/tooltip.qnt +553 -0
- package/specs/apg/treegrid.qnt +983 -0
- package/specs/apg/treeview.qnt +1004 -0
- package/specs/apg/windowsplitter.qnt +487 -0
- package/specs/canvas/camera.qnt +407 -0
- package/specs/canvas/pointer.qnt +841 -0
|
@@ -0,0 +1,1081 @@
|
|
|
1
|
+
// APG Media Player — a composition, because W3C ships no media-player pattern.
|
|
2
|
+
// https://www.w3.org/WAI/ARIA/apg/patterns/ (no player pattern exists)
|
|
3
|
+
//
|
|
4
|
+
// The control surface is three APG patterns, re-stated here as contracts (the
|
|
5
|
+
// generator's import closure accepts pure-def `shared/*` modules only, so
|
|
6
|
+
// slider/toolbar/button cannot be imported):
|
|
7
|
+
// - Slider + the "Media Seek Slider" example
|
|
8
|
+
// (https://www.w3.org/WAI/ARIA/apg/patterns/slider/examples/slider-seek/):
|
|
9
|
+
// role=slider, aria-valuemin/now/max, aria-valuetext as m:ss; the thumb keys
|
|
10
|
+
// are ArrowLeft/Down -1s, ArrowRight/Up +1s, PageDown/Up -15/+15s, Home/End.
|
|
11
|
+
// Deliberate divergence from slider.qnt: the timeline does NOT mirror in RTL.
|
|
12
|
+
// - Toolbar: the controls row is one tab stop with roving focus; modelled only
|
|
13
|
+
// as a `focus` scope so the seek thumb and the surface keys do not fight.
|
|
14
|
+
// - Button / Menu Button: play-pause, mute, fullscreen toggles, and the v1
|
|
15
|
+
// speed menu; modelled as `plays`/`pauses` callbacks and the `rate` set.
|
|
16
|
+
//
|
|
17
|
+
// The playback machine is not ARIA: it comes from the HTML `HTMLMediaElement`
|
|
18
|
+
// state/event contract (https://html.spec.whatwg.org/multipage/media.html),
|
|
19
|
+
// reduced to the states with an observable UI consequence. bsky HLS is VOD, so
|
|
20
|
+
// live is out of v1 scope.
|
|
21
|
+
//
|
|
22
|
+
// Request vs commit (map ticket rt1p) covers the four preferences — volume,
|
|
23
|
+
// muted, rate, fullscreen — which a host may own. `setVolume`, `toggleMute`,
|
|
24
|
+
// `setRate`, `toggleFullscreen` are requests; `propVolume`, `propMuted`,
|
|
25
|
+
// `propRate`, `propFullscreen` are the host writing the controlled props;
|
|
26
|
+
// `control` / `acceptRequests` configure the host (init is literal-only).
|
|
27
|
+
// Invariants: ControlledFollowsProps (no event commits while controlled),
|
|
28
|
+
// RejectedRequestUntouched, AcceptedRequestCommits.
|
|
29
|
+
//
|
|
30
|
+
// The generator has no action guards, so each action assigns every variable and
|
|
31
|
+
// out-of-phase events are no-ops via `if (<phase>) new else current`.
|
|
32
|
+
//
|
|
33
|
+
// ponytail: transport (play/pause/seek) and the playback stage stay adapter-driven
|
|
34
|
+
// and uncontrolled: they are device state, and a host steers them through the
|
|
35
|
+
// `play()` / `pause()` / `seek()` requests the adapter answers, not a value prop.
|
|
36
|
+
// Add `paused` / `position` props when a host must own the transport.
|
|
37
|
+
// ponytail: `live` (duration === Infinity) is not carried; add a flag + a live
|
|
38
|
+
// edge when a PDS serves live video. Drag cadence (preview vs commit) is modelled
|
|
39
|
+
// as two events; the consumer chooses how often to fire the commit.
|
|
40
|
+
module apg_player {
|
|
41
|
+
var stage: str // "loading" | "ready" | "playing" | "paused" | "buffering" | "ended" | "error"
|
|
42
|
+
var seeking: bool // a seek is in flight (HTMLMediaElement.seeking)
|
|
43
|
+
var pos: int // currentTime, whole seconds (seek aria-valuenow)
|
|
44
|
+
var dur: int // duration, whole seconds (seek aria-valuemax); 0 until known
|
|
45
|
+
var known: bool // loadedmetadata fired → duration known, seeking allowed
|
|
46
|
+
var paused: bool // exposed .paused mirror
|
|
47
|
+
var ended: bool // exposed .ended mirror
|
|
48
|
+
var vol: int // 0..100 (volume thumb aria-valuenow)
|
|
49
|
+
var applied: int // gain actually handed to the adapter (0 while muted)
|
|
50
|
+
var muted: bool
|
|
51
|
+
var rate: int // percent: 50 | 100 | 150 | 200 (100 = 1x)
|
|
52
|
+
var full: bool // fullscreen is on (Fullscreen API on the container)
|
|
53
|
+
var textMin: int // minutes shown in aria-valuetext
|
|
54
|
+
var textSec: int // seconds shown in aria-valuetext (0..59)
|
|
55
|
+
var focus: str // "none" | "surface" | "seek" | "control"
|
|
56
|
+
var plays: int // onPlay callbacks
|
|
57
|
+
var pauses: int // onPause callbacks
|
|
58
|
+
var seeks: int // committed seeks (onSeek)
|
|
59
|
+
var controlled: bool // the host owns the preferences (volume/muted/rate/fullscreen props)
|
|
60
|
+
var accepting: bool // controlled host that answers every request with its intent
|
|
61
|
+
var prefs: int // the controlled props, packed with `snap` (meaningful while controlled)
|
|
62
|
+
var reqs: int // preference requests that fired a change callback
|
|
63
|
+
var reqKind: str // "none" | "volume" | "muted" | "rate" | "fullscreen": the last request
|
|
64
|
+
var askNum: int // intent of the last request (volume / rate, or 1 / 0 for a toggle)
|
|
65
|
+
var outcome: str // "none" | "accepted" | "rejected": fate of the last request
|
|
66
|
+
var base: int // `snap` of the preferences when the last request was received
|
|
67
|
+
|
|
68
|
+
// --- pure behaviour ----------------------------------------------------
|
|
69
|
+
def effVol(v: int, m: bool): int = if (m) 0 else v
|
|
70
|
+
def isLoading(s: str): bool = s == "loading"
|
|
71
|
+
def isActive(s: str): bool = or(s == "playing", s == "buffering")
|
|
72
|
+
def canPlay(s: str): bool =
|
|
73
|
+
or(or(s == "ready", s == "paused"), or(s == "ended", s == "buffering"))
|
|
74
|
+
def clampTo(p: int, k: bool, d: int): int =
|
|
75
|
+
if (k) (if (p < 0) 0 else if (p > d) d else p) else p
|
|
76
|
+
def tm(p: int): int = p / 60
|
|
77
|
+
def ts(p: int): int = p % 60
|
|
78
|
+
def keyDelta(k: str): int =
|
|
79
|
+
if (or(k == "ArrowLeft", k == "ArrowDown")) -1
|
|
80
|
+
else if (or(k == "ArrowRight", k == "ArrowUp")) 1
|
|
81
|
+
else if (k == "PageUp") 15
|
|
82
|
+
else if (k == "PageDown") -15
|
|
83
|
+
else 0
|
|
84
|
+
def seekTarget(k: str, p: int, d: int): int =
|
|
85
|
+
if (k == "Home") 0
|
|
86
|
+
else if (k == "End") d
|
|
87
|
+
else clampTo(p + keyDelta(k), true, d)
|
|
88
|
+
def surfaceDelta(k: str): int = if (k == "ArrowRight") 5 else -5
|
|
89
|
+
|
|
90
|
+
// --- request / commit (map ticket rt1p) ----------------------------------
|
|
91
|
+
// The four preferences (volume, muted, rate, fullscreen) are user-changeable
|
|
92
|
+
// and host-ownable. A request fires its callback when the intent differs from
|
|
93
|
+
// the current value; then, uncontrolled the request is accepted (it commits),
|
|
94
|
+
// controlled and `holds` the host ignores it (rejected, state untouched), and
|
|
95
|
+
// controlled and `follows` the host writes the intent back through the prop.
|
|
96
|
+
def b2i(b: bool): int = if (b) 1 else 0
|
|
97
|
+
// injective for vol 0..100, rate 0..200: ((vol*2 + muted) * 201 + rate) * 2 + full
|
|
98
|
+
def snap(v: int, m: bool, r: int, f: bool): int = ((v * 2 + b2i(m)) * 201 + r) * 2 + b2i(f)
|
|
99
|
+
def holds: bool = and(controlled, not(accepting))
|
|
100
|
+
def follows: bool = and(controlled, accepting)
|
|
101
|
+
def verdict: str = if (holds) "rejected" else "accepted"
|
|
102
|
+
|
|
103
|
+
// --- ARIA contract (derived from the state) -----------------------------
|
|
104
|
+
def ariaValueNow: int = pos
|
|
105
|
+
def ariaValueMin: int = 0
|
|
106
|
+
def ariaValueMax: int = dur
|
|
107
|
+
|
|
108
|
+
// --- machine -----------------------------------------------------------
|
|
109
|
+
action init = all {
|
|
110
|
+
stage' = "loading",
|
|
111
|
+
seeking' = false,
|
|
112
|
+
pos' = 0,
|
|
113
|
+
dur' = 0,
|
|
114
|
+
known' = false,
|
|
115
|
+
paused' = true,
|
|
116
|
+
ended' = false,
|
|
117
|
+
vol' = 100,
|
|
118
|
+
applied' = 100,
|
|
119
|
+
muted' = false,
|
|
120
|
+
rate' = 100,
|
|
121
|
+
full' = false,
|
|
122
|
+
textMin' = 0,
|
|
123
|
+
textSec' = 0,
|
|
124
|
+
focus' = "none",
|
|
125
|
+
plays' = 0,
|
|
126
|
+
pauses' = 0,
|
|
127
|
+
seeks' = 0,
|
|
128
|
+
controlled' = false,
|
|
129
|
+
accepting' = false,
|
|
130
|
+
prefs' = 0,
|
|
131
|
+
reqs' = 0,
|
|
132
|
+
reqKind' = "none",
|
|
133
|
+
askNum' = 0,
|
|
134
|
+
outcome' = "none",
|
|
135
|
+
base' = 0
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
action onLoadedMetadata = {
|
|
139
|
+
nondet d = Set(0, 1, 5, 60, 90).oneOf()
|
|
140
|
+
all {
|
|
141
|
+
stage' = if (isLoading(stage)) "ready" else stage,
|
|
142
|
+
seeking' = if (isLoading(stage)) false else seeking,
|
|
143
|
+
pos' = if (isLoading(stage)) 0 else pos,
|
|
144
|
+
dur' = if (isLoading(stage)) d else dur,
|
|
145
|
+
known' = if (isLoading(stage)) true else known,
|
|
146
|
+
paused' = paused,
|
|
147
|
+
ended' = ended,
|
|
148
|
+
vol' = vol,
|
|
149
|
+
applied' = applied,
|
|
150
|
+
muted' = muted,
|
|
151
|
+
rate' = rate,
|
|
152
|
+
full' = full,
|
|
153
|
+
textMin' = if (isLoading(stage)) 0 else textMin,
|
|
154
|
+
textSec' = if (isLoading(stage)) 0 else textSec,
|
|
155
|
+
focus' = focus,
|
|
156
|
+
plays' = plays,
|
|
157
|
+
pauses' = pauses,
|
|
158
|
+
seeks' = seeks,
|
|
159
|
+
controlled' = controlled,
|
|
160
|
+
accepting' = accepting,
|
|
161
|
+
prefs' = prefs,
|
|
162
|
+
reqs' = reqs,
|
|
163
|
+
reqKind' = reqKind,
|
|
164
|
+
askNum' = askNum,
|
|
165
|
+
outcome' = outcome,
|
|
166
|
+
base' = base
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
action onCanPlay = all {
|
|
171
|
+
stage' = if (isLoading(stage)) "ready" else stage,
|
|
172
|
+
seeking' = seeking,
|
|
173
|
+
pos' = pos,
|
|
174
|
+
dur' = dur,
|
|
175
|
+
known' = known,
|
|
176
|
+
paused' = paused,
|
|
177
|
+
ended' = ended,
|
|
178
|
+
vol' = vol,
|
|
179
|
+
applied' = applied,
|
|
180
|
+
muted' = muted,
|
|
181
|
+
rate' = rate,
|
|
182
|
+
full' = full,
|
|
183
|
+
textMin' = textMin,
|
|
184
|
+
textSec' = textSec,
|
|
185
|
+
focus' = focus,
|
|
186
|
+
plays' = plays,
|
|
187
|
+
pauses' = pauses,
|
|
188
|
+
seeks' = seeks,
|
|
189
|
+
controlled' = controlled,
|
|
190
|
+
accepting' = accepting,
|
|
191
|
+
prefs' = prefs,
|
|
192
|
+
reqs' = reqs,
|
|
193
|
+
reqKind' = reqKind,
|
|
194
|
+
askNum' = askNum,
|
|
195
|
+
outcome' = outcome,
|
|
196
|
+
base' = base
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
action onWaiting = all {
|
|
200
|
+
stage' = if (stage == "playing") "buffering" else stage,
|
|
201
|
+
seeking' = seeking,
|
|
202
|
+
pos' = pos,
|
|
203
|
+
dur' = dur,
|
|
204
|
+
known' = known,
|
|
205
|
+
paused' = paused,
|
|
206
|
+
ended' = ended,
|
|
207
|
+
vol' = vol,
|
|
208
|
+
applied' = applied,
|
|
209
|
+
muted' = muted,
|
|
210
|
+
rate' = rate,
|
|
211
|
+
full' = full,
|
|
212
|
+
textMin' = textMin,
|
|
213
|
+
textSec' = textSec,
|
|
214
|
+
focus' = focus,
|
|
215
|
+
plays' = plays,
|
|
216
|
+
pauses' = pauses,
|
|
217
|
+
seeks' = seeks,
|
|
218
|
+
controlled' = controlled,
|
|
219
|
+
accepting' = accepting,
|
|
220
|
+
prefs' = prefs,
|
|
221
|
+
reqs' = reqs,
|
|
222
|
+
reqKind' = reqKind,
|
|
223
|
+
askNum' = askNum,
|
|
224
|
+
outcome' = outcome,
|
|
225
|
+
base' = base
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
action onPlaying = all {
|
|
229
|
+
stage' = if (stage == "buffering") "playing" else stage,
|
|
230
|
+
seeking' = seeking,
|
|
231
|
+
pos' = pos,
|
|
232
|
+
dur' = dur,
|
|
233
|
+
known' = known,
|
|
234
|
+
paused' = if (stage == "buffering") false else paused,
|
|
235
|
+
ended' = ended,
|
|
236
|
+
vol' = vol,
|
|
237
|
+
applied' = applied,
|
|
238
|
+
muted' = muted,
|
|
239
|
+
rate' = rate,
|
|
240
|
+
full' = full,
|
|
241
|
+
textMin' = textMin,
|
|
242
|
+
textSec' = textSec,
|
|
243
|
+
focus' = focus,
|
|
244
|
+
plays' = plays,
|
|
245
|
+
pauses' = pauses,
|
|
246
|
+
seeks' = seeks,
|
|
247
|
+
controlled' = controlled,
|
|
248
|
+
accepting' = accepting,
|
|
249
|
+
prefs' = prefs,
|
|
250
|
+
reqs' = reqs,
|
|
251
|
+
reqKind' = reqKind,
|
|
252
|
+
askNum' = askNum,
|
|
253
|
+
outcome' = outcome,
|
|
254
|
+
base' = base
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
action onTimeUpdate = {
|
|
258
|
+
nondet t = Set(0, 1, 2, 30, 59, 60, 90).oneOf()
|
|
259
|
+
all {
|
|
260
|
+
stage' = stage,
|
|
261
|
+
seeking' = seeking,
|
|
262
|
+
pos' = if (stage == "playing") clampTo(t, known, dur) else pos,
|
|
263
|
+
dur' = dur,
|
|
264
|
+
known' = known,
|
|
265
|
+
paused' = paused,
|
|
266
|
+
ended' = ended,
|
|
267
|
+
vol' = vol,
|
|
268
|
+
applied' = applied,
|
|
269
|
+
muted' = muted,
|
|
270
|
+
rate' = rate,
|
|
271
|
+
full' = full,
|
|
272
|
+
textMin' = if (stage == "playing") tm(clampTo(t, known, dur)) else textMin,
|
|
273
|
+
textSec' = if (stage == "playing") ts(clampTo(t, known, dur)) else textSec,
|
|
274
|
+
focus' = focus,
|
|
275
|
+
plays' = plays,
|
|
276
|
+
pauses' = pauses,
|
|
277
|
+
seeks' = seeks,
|
|
278
|
+
controlled' = controlled,
|
|
279
|
+
accepting' = accepting,
|
|
280
|
+
prefs' = prefs,
|
|
281
|
+
reqs' = reqs,
|
|
282
|
+
reqKind' = reqKind,
|
|
283
|
+
askNum' = askNum,
|
|
284
|
+
outcome' = outcome,
|
|
285
|
+
base' = base
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
action onPause = all {
|
|
290
|
+
stage' = if (isActive(stage)) "paused" else stage,
|
|
291
|
+
seeking' = seeking,
|
|
292
|
+
pos' = pos,
|
|
293
|
+
dur' = dur,
|
|
294
|
+
known' = known,
|
|
295
|
+
paused' = if (isActive(stage)) true else paused,
|
|
296
|
+
ended' = ended,
|
|
297
|
+
vol' = vol,
|
|
298
|
+
applied' = applied,
|
|
299
|
+
muted' = muted,
|
|
300
|
+
rate' = rate,
|
|
301
|
+
full' = full,
|
|
302
|
+
textMin' = textMin,
|
|
303
|
+
textSec' = textSec,
|
|
304
|
+
focus' = focus,
|
|
305
|
+
plays' = plays,
|
|
306
|
+
pauses' = pauses,
|
|
307
|
+
seeks' = seeks,
|
|
308
|
+
controlled' = controlled,
|
|
309
|
+
accepting' = accepting,
|
|
310
|
+
prefs' = prefs,
|
|
311
|
+
reqs' = reqs,
|
|
312
|
+
reqKind' = reqKind,
|
|
313
|
+
askNum' = askNum,
|
|
314
|
+
outcome' = outcome,
|
|
315
|
+
base' = base
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
action onEnded = all {
|
|
319
|
+
stage' = if (stage == "playing") "ended" else stage,
|
|
320
|
+
seeking' = seeking,
|
|
321
|
+
pos' = if (and(stage == "playing", known)) dur else pos,
|
|
322
|
+
dur' = dur,
|
|
323
|
+
known' = known,
|
|
324
|
+
paused' = if (stage == "playing") true else paused,
|
|
325
|
+
ended' = if (stage == "playing") true else ended,
|
|
326
|
+
vol' = vol,
|
|
327
|
+
applied' = applied,
|
|
328
|
+
muted' = muted,
|
|
329
|
+
rate' = rate,
|
|
330
|
+
full' = full,
|
|
331
|
+
textMin' = if (and(stage == "playing", known)) tm(dur) else textMin,
|
|
332
|
+
textSec' = if (and(stage == "playing", known)) ts(dur) else textSec,
|
|
333
|
+
focus' = focus,
|
|
334
|
+
plays' = plays,
|
|
335
|
+
pauses' = pauses,
|
|
336
|
+
seeks' = seeks,
|
|
337
|
+
controlled' = controlled,
|
|
338
|
+
accepting' = accepting,
|
|
339
|
+
prefs' = prefs,
|
|
340
|
+
reqs' = reqs,
|
|
341
|
+
reqKind' = reqKind,
|
|
342
|
+
askNum' = askNum,
|
|
343
|
+
outcome' = outcome,
|
|
344
|
+
base' = base
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
action onError = all {
|
|
348
|
+
stage' = "error",
|
|
349
|
+
seeking' = false,
|
|
350
|
+
pos' = pos,
|
|
351
|
+
dur' = dur,
|
|
352
|
+
known' = known,
|
|
353
|
+
paused' = true,
|
|
354
|
+
ended' = false,
|
|
355
|
+
vol' = vol,
|
|
356
|
+
applied' = applied,
|
|
357
|
+
muted' = muted,
|
|
358
|
+
rate' = rate,
|
|
359
|
+
full' = full,
|
|
360
|
+
textMin' = textMin,
|
|
361
|
+
textSec' = textSec,
|
|
362
|
+
focus' = focus,
|
|
363
|
+
plays' = plays,
|
|
364
|
+
pauses' = pauses,
|
|
365
|
+
seeks' = seeks,
|
|
366
|
+
controlled' = controlled,
|
|
367
|
+
accepting' = accepting,
|
|
368
|
+
prefs' = prefs,
|
|
369
|
+
reqs' = reqs,
|
|
370
|
+
reqKind' = reqKind,
|
|
371
|
+
askNum' = askNum,
|
|
372
|
+
outcome' = outcome,
|
|
373
|
+
base' = base
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
action play = all {
|
|
377
|
+
stage' = if (canPlay(stage)) "playing" else stage,
|
|
378
|
+
seeking' = seeking,
|
|
379
|
+
pos' = if (and(canPlay(stage), stage == "ended")) 0 else pos,
|
|
380
|
+
dur' = dur,
|
|
381
|
+
known' = known,
|
|
382
|
+
paused' = if (canPlay(stage)) false else paused,
|
|
383
|
+
ended' = if (canPlay(stage)) false else ended,
|
|
384
|
+
vol' = vol,
|
|
385
|
+
applied' = applied,
|
|
386
|
+
muted' = muted,
|
|
387
|
+
rate' = rate,
|
|
388
|
+
full' = full,
|
|
389
|
+
textMin' = if (and(canPlay(stage), stage == "ended")) 0 else textMin,
|
|
390
|
+
textSec' = if (and(canPlay(stage), stage == "ended")) 0 else textSec,
|
|
391
|
+
focus' = focus,
|
|
392
|
+
plays' = if (canPlay(stage)) plays + 1 else plays,
|
|
393
|
+
pauses' = pauses,
|
|
394
|
+
seeks' = seeks,
|
|
395
|
+
controlled' = controlled,
|
|
396
|
+
accepting' = accepting,
|
|
397
|
+
prefs' = prefs,
|
|
398
|
+
reqs' = reqs,
|
|
399
|
+
reqKind' = reqKind,
|
|
400
|
+
askNum' = askNum,
|
|
401
|
+
outcome' = outcome,
|
|
402
|
+
base' = base
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
action pause = all {
|
|
406
|
+
stage' = if (isActive(stage)) "paused" else stage,
|
|
407
|
+
seeking' = seeking,
|
|
408
|
+
pos' = pos,
|
|
409
|
+
dur' = dur,
|
|
410
|
+
known' = known,
|
|
411
|
+
paused' = if (isActive(stage)) true else paused,
|
|
412
|
+
ended' = ended,
|
|
413
|
+
vol' = vol,
|
|
414
|
+
applied' = applied,
|
|
415
|
+
muted' = muted,
|
|
416
|
+
rate' = rate,
|
|
417
|
+
full' = full,
|
|
418
|
+
textMin' = textMin,
|
|
419
|
+
textSec' = textSec,
|
|
420
|
+
focus' = focus,
|
|
421
|
+
plays' = plays,
|
|
422
|
+
pauses' = if (isActive(stage)) pauses + 1 else pauses,
|
|
423
|
+
seeks' = seeks,
|
|
424
|
+
controlled' = controlled,
|
|
425
|
+
accepting' = accepting,
|
|
426
|
+
prefs' = prefs,
|
|
427
|
+
reqs' = reqs,
|
|
428
|
+
reqKind' = reqKind,
|
|
429
|
+
askNum' = askNum,
|
|
430
|
+
outcome' = outcome,
|
|
431
|
+
base' = base
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
action togglePlay = all {
|
|
435
|
+
stage' = if (isActive(stage)) "paused" else if (canPlay(stage)) "playing" else stage,
|
|
436
|
+
seeking' = seeking,
|
|
437
|
+
pos' = if (and(not(isActive(stage)), and(canPlay(stage), stage == "ended"))) 0 else pos,
|
|
438
|
+
dur' = dur,
|
|
439
|
+
known' = known,
|
|
440
|
+
paused' = if (isActive(stage)) true else if (canPlay(stage)) false else paused,
|
|
441
|
+
ended' = if (isActive(stage)) ended else if (canPlay(stage)) false else ended,
|
|
442
|
+
vol' = vol,
|
|
443
|
+
applied' = applied,
|
|
444
|
+
muted' = muted,
|
|
445
|
+
rate' = rate,
|
|
446
|
+
full' = full,
|
|
447
|
+
textMin' = if (and(not(isActive(stage)), and(canPlay(stage), stage == "ended"))) 0 else textMin,
|
|
448
|
+
textSec' = if (and(not(isActive(stage)), and(canPlay(stage), stage == "ended"))) 0 else textSec,
|
|
449
|
+
focus' = focus,
|
|
450
|
+
plays' = if (and(not(isActive(stage)), canPlay(stage))) plays + 1 else plays,
|
|
451
|
+
pauses' = if (isActive(stage)) pauses + 1 else pauses,
|
|
452
|
+
seeks' = seeks,
|
|
453
|
+
controlled' = controlled,
|
|
454
|
+
accepting' = accepting,
|
|
455
|
+
prefs' = prefs,
|
|
456
|
+
reqs' = reqs,
|
|
457
|
+
reqKind' = reqKind,
|
|
458
|
+
askNum' = askNum,
|
|
459
|
+
outcome' = outcome,
|
|
460
|
+
base' = base
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
action seekPreview = {
|
|
464
|
+
nondet t = Set(0, 1, 2, 30, 59, 60, 90).oneOf()
|
|
465
|
+
all {
|
|
466
|
+
stage' = if (and(known, stage == "ended")) "paused" else stage,
|
|
467
|
+
seeking' = if (known) true else seeking,
|
|
468
|
+
pos' = if (known) clampTo(t, true, dur) else pos,
|
|
469
|
+
dur' = dur,
|
|
470
|
+
known' = known,
|
|
471
|
+
paused' = paused,
|
|
472
|
+
ended' = if (known) false else ended,
|
|
473
|
+
vol' = vol,
|
|
474
|
+
applied' = applied,
|
|
475
|
+
muted' = muted,
|
|
476
|
+
rate' = rate,
|
|
477
|
+
full' = full,
|
|
478
|
+
textMin' = if (known) tm(clampTo(t, true, dur)) else textMin,
|
|
479
|
+
textSec' = if (known) ts(clampTo(t, true, dur)) else textSec,
|
|
480
|
+
focus' = focus,
|
|
481
|
+
plays' = plays,
|
|
482
|
+
pauses' = pauses,
|
|
483
|
+
seeks' = seeks,
|
|
484
|
+
controlled' = controlled,
|
|
485
|
+
accepting' = accepting,
|
|
486
|
+
prefs' = prefs,
|
|
487
|
+
reqs' = reqs,
|
|
488
|
+
reqKind' = reqKind,
|
|
489
|
+
askNum' = askNum,
|
|
490
|
+
outcome' = outcome,
|
|
491
|
+
base' = base
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
action seekCommit = {
|
|
496
|
+
nondet t = Set(0, 1, 2, 30, 59, 60, 90).oneOf()
|
|
497
|
+
all {
|
|
498
|
+
stage' = if (and(known, stage == "ended")) "paused" else stage,
|
|
499
|
+
seeking' = if (known) true else seeking,
|
|
500
|
+
pos' = if (known) clampTo(t, true, dur) else pos,
|
|
501
|
+
dur' = dur,
|
|
502
|
+
known' = known,
|
|
503
|
+
paused' = paused,
|
|
504
|
+
ended' = if (known) false else ended,
|
|
505
|
+
vol' = vol,
|
|
506
|
+
applied' = applied,
|
|
507
|
+
muted' = muted,
|
|
508
|
+
rate' = rate,
|
|
509
|
+
full' = full,
|
|
510
|
+
textMin' = if (known) tm(clampTo(t, true, dur)) else textMin,
|
|
511
|
+
textSec' = if (known) ts(clampTo(t, true, dur)) else textSec,
|
|
512
|
+
focus' = focus,
|
|
513
|
+
plays' = plays,
|
|
514
|
+
pauses' = pauses,
|
|
515
|
+
seeks' = if (known) seeks + 1 else seeks,
|
|
516
|
+
controlled' = controlled,
|
|
517
|
+
accepting' = accepting,
|
|
518
|
+
prefs' = prefs,
|
|
519
|
+
reqs' = reqs,
|
|
520
|
+
reqKind' = reqKind,
|
|
521
|
+
askNum' = askNum,
|
|
522
|
+
outcome' = outcome,
|
|
523
|
+
base' = base
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
action seekKey = {
|
|
528
|
+
nondet key = Set(
|
|
529
|
+
"ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown",
|
|
530
|
+
"PageUp", "PageDown", "Home", "End"
|
|
531
|
+
).oneOf()
|
|
532
|
+
all {
|
|
533
|
+
stage' = if (and(and(focus == "seek", known), stage == "ended")) "paused" else stage,
|
|
534
|
+
seeking' = if (and(focus == "seek", known)) true else seeking,
|
|
535
|
+
pos' = if (and(focus == "seek", known)) seekTarget(key, pos, dur) else pos,
|
|
536
|
+
dur' = dur,
|
|
537
|
+
known' = known,
|
|
538
|
+
paused' = paused,
|
|
539
|
+
ended' = if (and(focus == "seek", known)) false else ended,
|
|
540
|
+
vol' = vol,
|
|
541
|
+
applied' = applied,
|
|
542
|
+
muted' = muted,
|
|
543
|
+
rate' = rate,
|
|
544
|
+
full' = full,
|
|
545
|
+
textMin' = if (and(focus == "seek", known)) tm(seekTarget(key, pos, dur)) else textMin,
|
|
546
|
+
textSec' = if (and(focus == "seek", known)) ts(seekTarget(key, pos, dur)) else textSec,
|
|
547
|
+
focus' = focus,
|
|
548
|
+
plays' = plays,
|
|
549
|
+
pauses' = pauses,
|
|
550
|
+
seeks' = if (and(focus == "seek", known)) seeks + 1 else seeks,
|
|
551
|
+
controlled' = controlled,
|
|
552
|
+
accepting' = accepting,
|
|
553
|
+
prefs' = prefs,
|
|
554
|
+
reqs' = reqs,
|
|
555
|
+
reqKind' = reqKind,
|
|
556
|
+
askNum' = askNum,
|
|
557
|
+
outcome' = outcome,
|
|
558
|
+
base' = base
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
action surfaceSeekKey = {
|
|
563
|
+
nondet key = Set("ArrowLeft", "ArrowRight").oneOf()
|
|
564
|
+
all {
|
|
565
|
+
stage' = if (and(and(focus == "surface", known), stage == "ended")) "paused" else stage,
|
|
566
|
+
seeking' = if (and(focus == "surface", known)) true else seeking,
|
|
567
|
+
pos' = if (and(focus == "surface", known)) clampTo(pos + surfaceDelta(key), true, dur) else pos,
|
|
568
|
+
dur' = dur,
|
|
569
|
+
known' = known,
|
|
570
|
+
paused' = paused,
|
|
571
|
+
ended' = if (and(focus == "surface", known)) false else ended,
|
|
572
|
+
vol' = vol,
|
|
573
|
+
applied' = applied,
|
|
574
|
+
muted' = muted,
|
|
575
|
+
rate' = rate,
|
|
576
|
+
full' = full,
|
|
577
|
+
textMin' = if (and(focus == "surface", known)) tm(clampTo(pos + surfaceDelta(key), true, dur)) else textMin,
|
|
578
|
+
textSec' = if (and(focus == "surface", known)) ts(clampTo(pos + surfaceDelta(key), true, dur)) else textSec,
|
|
579
|
+
focus' = focus,
|
|
580
|
+
plays' = plays,
|
|
581
|
+
pauses' = pauses,
|
|
582
|
+
seeks' = if (and(focus == "surface", known)) seeks + 1 else seeks,
|
|
583
|
+
controlled' = controlled,
|
|
584
|
+
accepting' = accepting,
|
|
585
|
+
prefs' = prefs,
|
|
586
|
+
reqs' = reqs,
|
|
587
|
+
reqKind' = reqKind,
|
|
588
|
+
askNum' = askNum,
|
|
589
|
+
outcome' = outcome,
|
|
590
|
+
base' = base
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
action onSeeked = all {
|
|
595
|
+
stage' = stage,
|
|
596
|
+
seeking' = false,
|
|
597
|
+
pos' = pos,
|
|
598
|
+
dur' = dur,
|
|
599
|
+
known' = known,
|
|
600
|
+
paused' = paused,
|
|
601
|
+
ended' = ended,
|
|
602
|
+
vol' = vol,
|
|
603
|
+
applied' = applied,
|
|
604
|
+
muted' = muted,
|
|
605
|
+
rate' = rate,
|
|
606
|
+
full' = full,
|
|
607
|
+
textMin' = textMin,
|
|
608
|
+
textSec' = textSec,
|
|
609
|
+
focus' = focus,
|
|
610
|
+
plays' = plays,
|
|
611
|
+
pauses' = pauses,
|
|
612
|
+
seeks' = seeks,
|
|
613
|
+
controlled' = controlled,
|
|
614
|
+
accepting' = accepting,
|
|
615
|
+
prefs' = prefs,
|
|
616
|
+
reqs' = reqs,
|
|
617
|
+
reqKind' = reqKind,
|
|
618
|
+
askNum' = askNum,
|
|
619
|
+
outcome' = outcome,
|
|
620
|
+
base' = base
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
action setVolume = {
|
|
624
|
+
nondet v = Set(0, 25, 50, 75, 100).oneOf()
|
|
625
|
+
all {
|
|
626
|
+
stage' = stage,
|
|
627
|
+
seeking' = seeking,
|
|
628
|
+
pos' = pos,
|
|
629
|
+
dur' = dur,
|
|
630
|
+
known' = known,
|
|
631
|
+
paused' = paused,
|
|
632
|
+
ended' = ended,
|
|
633
|
+
vol' = if (holds) vol else v,
|
|
634
|
+
applied' = effVol(if (holds) vol else v, muted),
|
|
635
|
+
muted' = muted,
|
|
636
|
+
rate' = rate,
|
|
637
|
+
full' = full,
|
|
638
|
+
textMin' = textMin,
|
|
639
|
+
textSec' = textSec,
|
|
640
|
+
focus' = focus,
|
|
641
|
+
plays' = plays,
|
|
642
|
+
pauses' = pauses,
|
|
643
|
+
seeks' = seeks,
|
|
644
|
+
controlled' = controlled,
|
|
645
|
+
accepting' = accepting,
|
|
646
|
+
prefs' = if (follows) snap(v, muted, rate, full) else prefs,
|
|
647
|
+
reqs' = if (v == vol) reqs else reqs + 1,
|
|
648
|
+
reqKind' = if (v == vol) reqKind else "volume",
|
|
649
|
+
askNum' = if (v == vol) askNum else v,
|
|
650
|
+
outcome' = if (v == vol) outcome else verdict,
|
|
651
|
+
base' = if (v == vol) base else snap(vol, muted, rate, full)
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
action toggleMute = all {
|
|
656
|
+
stage' = stage,
|
|
657
|
+
seeking' = seeking,
|
|
658
|
+
pos' = pos,
|
|
659
|
+
dur' = dur,
|
|
660
|
+
known' = known,
|
|
661
|
+
paused' = paused,
|
|
662
|
+
ended' = ended,
|
|
663
|
+
vol' = vol,
|
|
664
|
+
applied' = effVol(vol, if (holds) muted else not(muted)),
|
|
665
|
+
muted' = if (holds) muted else not(muted),
|
|
666
|
+
rate' = rate,
|
|
667
|
+
full' = full,
|
|
668
|
+
textMin' = textMin,
|
|
669
|
+
textSec' = textSec,
|
|
670
|
+
focus' = focus,
|
|
671
|
+
plays' = plays,
|
|
672
|
+
pauses' = pauses,
|
|
673
|
+
seeks' = seeks,
|
|
674
|
+
controlled' = controlled,
|
|
675
|
+
accepting' = accepting,
|
|
676
|
+
prefs' = if (follows) snap(vol, not(muted), rate, full) else prefs,
|
|
677
|
+
reqs' = reqs + 1,
|
|
678
|
+
reqKind' = "muted",
|
|
679
|
+
askNum' = if (muted) 0 else 1,
|
|
680
|
+
outcome' = verdict,
|
|
681
|
+
base' = snap(vol, muted, rate, full)
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
action setRate = {
|
|
685
|
+
nondet r = Set(50, 100, 150, 200).oneOf()
|
|
686
|
+
all {
|
|
687
|
+
stage' = stage,
|
|
688
|
+
seeking' = seeking,
|
|
689
|
+
pos' = pos,
|
|
690
|
+
dur' = dur,
|
|
691
|
+
known' = known,
|
|
692
|
+
paused' = paused,
|
|
693
|
+
ended' = ended,
|
|
694
|
+
vol' = vol,
|
|
695
|
+
applied' = applied,
|
|
696
|
+
muted' = muted,
|
|
697
|
+
rate' = if (holds) rate else r,
|
|
698
|
+
full' = full,
|
|
699
|
+
textMin' = textMin,
|
|
700
|
+
textSec' = textSec,
|
|
701
|
+
focus' = focus,
|
|
702
|
+
plays' = plays,
|
|
703
|
+
pauses' = pauses,
|
|
704
|
+
seeks' = seeks,
|
|
705
|
+
controlled' = controlled,
|
|
706
|
+
accepting' = accepting,
|
|
707
|
+
prefs' = if (follows) snap(vol, muted, r, full) else prefs,
|
|
708
|
+
reqs' = if (r == rate) reqs else reqs + 1,
|
|
709
|
+
reqKind' = if (r == rate) reqKind else "rate",
|
|
710
|
+
askNum' = if (r == rate) askNum else r,
|
|
711
|
+
outcome' = if (r == rate) outcome else verdict,
|
|
712
|
+
base' = if (r == rate) base else snap(vol, muted, rate, full)
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
action toggleFullscreen = all {
|
|
717
|
+
stage' = stage,
|
|
718
|
+
seeking' = seeking,
|
|
719
|
+
pos' = pos,
|
|
720
|
+
dur' = dur,
|
|
721
|
+
known' = known,
|
|
722
|
+
paused' = paused,
|
|
723
|
+
ended' = ended,
|
|
724
|
+
vol' = vol,
|
|
725
|
+
applied' = applied,
|
|
726
|
+
muted' = muted,
|
|
727
|
+
rate' = rate,
|
|
728
|
+
full' = if (holds) full else not(full),
|
|
729
|
+
textMin' = textMin,
|
|
730
|
+
textSec' = textSec,
|
|
731
|
+
focus' = focus,
|
|
732
|
+
plays' = plays,
|
|
733
|
+
pauses' = pauses,
|
|
734
|
+
seeks' = seeks,
|
|
735
|
+
controlled' = controlled,
|
|
736
|
+
accepting' = accepting,
|
|
737
|
+
prefs' = if (follows) snap(vol, muted, rate, not(full)) else prefs,
|
|
738
|
+
reqs' = reqs + 1,
|
|
739
|
+
reqKind' = "fullscreen",
|
|
740
|
+
askNum' = if (full) 0 else 1,
|
|
741
|
+
outcome' = verdict,
|
|
742
|
+
base' = snap(vol, muted, rate, full)
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
action focusOn = {
|
|
746
|
+
nondet target = Set("none", "surface", "seek", "control").oneOf()
|
|
747
|
+
all {
|
|
748
|
+
stage' = stage,
|
|
749
|
+
seeking' = seeking,
|
|
750
|
+
pos' = pos,
|
|
751
|
+
dur' = dur,
|
|
752
|
+
known' = known,
|
|
753
|
+
paused' = paused,
|
|
754
|
+
ended' = ended,
|
|
755
|
+
vol' = vol,
|
|
756
|
+
applied' = applied,
|
|
757
|
+
muted' = muted,
|
|
758
|
+
rate' = rate,
|
|
759
|
+
full' = full,
|
|
760
|
+
textMin' = textMin,
|
|
761
|
+
textSec' = textSec,
|
|
762
|
+
focus' = target,
|
|
763
|
+
plays' = plays,
|
|
764
|
+
pauses' = pauses,
|
|
765
|
+
seeks' = seeks,
|
|
766
|
+
controlled' = controlled,
|
|
767
|
+
accepting' = accepting,
|
|
768
|
+
prefs' = prefs,
|
|
769
|
+
reqs' = reqs,
|
|
770
|
+
reqKind' = reqKind,
|
|
771
|
+
askNum' = askNum,
|
|
772
|
+
outcome' = outcome,
|
|
773
|
+
base' = base
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
action blur = all {
|
|
778
|
+
stage' = stage,
|
|
779
|
+
seeking' = seeking,
|
|
780
|
+
pos' = pos,
|
|
781
|
+
dur' = dur,
|
|
782
|
+
known' = known,
|
|
783
|
+
paused' = paused,
|
|
784
|
+
ended' = ended,
|
|
785
|
+
vol' = vol,
|
|
786
|
+
applied' = applied,
|
|
787
|
+
muted' = muted,
|
|
788
|
+
rate' = rate,
|
|
789
|
+
full' = full,
|
|
790
|
+
textMin' = textMin,
|
|
791
|
+
textSec' = textSec,
|
|
792
|
+
focus' = "none",
|
|
793
|
+
plays' = plays,
|
|
794
|
+
pauses' = pauses,
|
|
795
|
+
seeks' = seeks,
|
|
796
|
+
controlled' = controlled,
|
|
797
|
+
accepting' = accepting,
|
|
798
|
+
prefs' = prefs,
|
|
799
|
+
reqs' = reqs,
|
|
800
|
+
reqKind' = reqKind,
|
|
801
|
+
askNum' = askNum,
|
|
802
|
+
outcome' = outcome,
|
|
803
|
+
base' = base
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
action loadStart = all {
|
|
807
|
+
stage' = "loading",
|
|
808
|
+
seeking' = false,
|
|
809
|
+
pos' = 0,
|
|
810
|
+
dur' = 0,
|
|
811
|
+
known' = false,
|
|
812
|
+
paused' = true,
|
|
813
|
+
ended' = false,
|
|
814
|
+
vol' = vol,
|
|
815
|
+
applied' = applied,
|
|
816
|
+
muted' = muted,
|
|
817
|
+
rate' = rate,
|
|
818
|
+
full' = full,
|
|
819
|
+
textMin' = 0,
|
|
820
|
+
textSec' = 0,
|
|
821
|
+
focus' = focus,
|
|
822
|
+
plays' = plays,
|
|
823
|
+
pauses' = pauses,
|
|
824
|
+
seeks' = seeks,
|
|
825
|
+
controlled' = controlled,
|
|
826
|
+
accepting' = accepting,
|
|
827
|
+
prefs' = prefs,
|
|
828
|
+
reqs' = reqs,
|
|
829
|
+
reqKind' = reqKind,
|
|
830
|
+
askNum' = askNum,
|
|
831
|
+
outcome' = outcome,
|
|
832
|
+
base' = base
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// commit: the host writes a controlled preference (a no-op while uncontrolled)
|
|
836
|
+
action propVolume = {
|
|
837
|
+
nondet v = Set(0, 25, 50, 75, 100).oneOf()
|
|
838
|
+
all {
|
|
839
|
+
stage' = stage,
|
|
840
|
+
seeking' = seeking,
|
|
841
|
+
pos' = pos,
|
|
842
|
+
dur' = dur,
|
|
843
|
+
known' = known,
|
|
844
|
+
paused' = paused,
|
|
845
|
+
ended' = ended,
|
|
846
|
+
vol' = if (controlled) v else vol,
|
|
847
|
+
applied' = if (controlled) effVol(v, muted) else applied,
|
|
848
|
+
muted' = muted,
|
|
849
|
+
rate' = rate,
|
|
850
|
+
full' = full,
|
|
851
|
+
textMin' = textMin,
|
|
852
|
+
textSec' = textSec,
|
|
853
|
+
focus' = focus,
|
|
854
|
+
plays' = plays,
|
|
855
|
+
pauses' = pauses,
|
|
856
|
+
seeks' = seeks,
|
|
857
|
+
controlled' = controlled,
|
|
858
|
+
accepting' = accepting,
|
|
859
|
+
prefs' = if (controlled) snap(v, muted, rate, full) else prefs,
|
|
860
|
+
reqs' = reqs,
|
|
861
|
+
reqKind' = reqKind,
|
|
862
|
+
askNum' = askNum,
|
|
863
|
+
outcome' = if (controlled) "none" else outcome,
|
|
864
|
+
base' = base
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
action propMuted = {
|
|
869
|
+
nondet m = Set(true, false).oneOf()
|
|
870
|
+
all {
|
|
871
|
+
stage' = stage,
|
|
872
|
+
seeking' = seeking,
|
|
873
|
+
pos' = pos,
|
|
874
|
+
dur' = dur,
|
|
875
|
+
known' = known,
|
|
876
|
+
paused' = paused,
|
|
877
|
+
ended' = ended,
|
|
878
|
+
vol' = vol,
|
|
879
|
+
applied' = if (controlled) effVol(vol, m) else applied,
|
|
880
|
+
muted' = if (controlled) m else muted,
|
|
881
|
+
rate' = rate,
|
|
882
|
+
full' = full,
|
|
883
|
+
textMin' = textMin,
|
|
884
|
+
textSec' = textSec,
|
|
885
|
+
focus' = focus,
|
|
886
|
+
plays' = plays,
|
|
887
|
+
pauses' = pauses,
|
|
888
|
+
seeks' = seeks,
|
|
889
|
+
controlled' = controlled,
|
|
890
|
+
accepting' = accepting,
|
|
891
|
+
prefs' = if (controlled) snap(vol, m, rate, full) else prefs,
|
|
892
|
+
reqs' = reqs,
|
|
893
|
+
reqKind' = reqKind,
|
|
894
|
+
askNum' = askNum,
|
|
895
|
+
outcome' = if (controlled) "none" else outcome,
|
|
896
|
+
base' = base
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
action propRate = {
|
|
901
|
+
nondet r = Set(50, 100, 150, 200).oneOf()
|
|
902
|
+
all {
|
|
903
|
+
stage' = stage,
|
|
904
|
+
seeking' = seeking,
|
|
905
|
+
pos' = pos,
|
|
906
|
+
dur' = dur,
|
|
907
|
+
known' = known,
|
|
908
|
+
paused' = paused,
|
|
909
|
+
ended' = ended,
|
|
910
|
+
vol' = vol,
|
|
911
|
+
applied' = applied,
|
|
912
|
+
muted' = muted,
|
|
913
|
+
rate' = if (controlled) r else rate,
|
|
914
|
+
full' = full,
|
|
915
|
+
textMin' = textMin,
|
|
916
|
+
textSec' = textSec,
|
|
917
|
+
focus' = focus,
|
|
918
|
+
plays' = plays,
|
|
919
|
+
pauses' = pauses,
|
|
920
|
+
seeks' = seeks,
|
|
921
|
+
controlled' = controlled,
|
|
922
|
+
accepting' = accepting,
|
|
923
|
+
prefs' = if (controlled) snap(vol, muted, r, full) else prefs,
|
|
924
|
+
reqs' = reqs,
|
|
925
|
+
reqKind' = reqKind,
|
|
926
|
+
askNum' = askNum,
|
|
927
|
+
outcome' = if (controlled) "none" else outcome,
|
|
928
|
+
base' = base
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
action propFullscreen = {
|
|
933
|
+
nondet f = Set(true, false).oneOf()
|
|
934
|
+
all {
|
|
935
|
+
stage' = stage,
|
|
936
|
+
seeking' = seeking,
|
|
937
|
+
pos' = pos,
|
|
938
|
+
dur' = dur,
|
|
939
|
+
known' = known,
|
|
940
|
+
paused' = paused,
|
|
941
|
+
ended' = ended,
|
|
942
|
+
vol' = vol,
|
|
943
|
+
applied' = applied,
|
|
944
|
+
muted' = muted,
|
|
945
|
+
rate' = rate,
|
|
946
|
+
full' = if (controlled) f else full,
|
|
947
|
+
textMin' = textMin,
|
|
948
|
+
textSec' = textSec,
|
|
949
|
+
focus' = focus,
|
|
950
|
+
plays' = plays,
|
|
951
|
+
pauses' = pauses,
|
|
952
|
+
seeks' = seeks,
|
|
953
|
+
controlled' = controlled,
|
|
954
|
+
accepting' = accepting,
|
|
955
|
+
prefs' = if (controlled) snap(vol, muted, rate, f) else prefs,
|
|
956
|
+
reqs' = reqs,
|
|
957
|
+
reqKind' = reqKind,
|
|
958
|
+
askNum' = askNum,
|
|
959
|
+
outcome' = if (controlled) "none" else outcome,
|
|
960
|
+
base' = base
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// configuration: the host starts owning the preferences, adopting the current ones
|
|
965
|
+
action control = all {
|
|
966
|
+
stage' = stage,
|
|
967
|
+
seeking' = seeking,
|
|
968
|
+
pos' = pos,
|
|
969
|
+
dur' = dur,
|
|
970
|
+
known' = known,
|
|
971
|
+
paused' = paused,
|
|
972
|
+
ended' = ended,
|
|
973
|
+
vol' = vol,
|
|
974
|
+
applied' = applied,
|
|
975
|
+
muted' = muted,
|
|
976
|
+
rate' = rate,
|
|
977
|
+
full' = full,
|
|
978
|
+
textMin' = textMin,
|
|
979
|
+
textSec' = textSec,
|
|
980
|
+
focus' = focus,
|
|
981
|
+
plays' = plays,
|
|
982
|
+
pauses' = pauses,
|
|
983
|
+
seeks' = seeks,
|
|
984
|
+
controlled' = true,
|
|
985
|
+
accepting' = accepting,
|
|
986
|
+
prefs' = snap(vol, muted, rate, full),
|
|
987
|
+
reqs' = reqs,
|
|
988
|
+
reqKind' = reqKind,
|
|
989
|
+
askNum' = askNum,
|
|
990
|
+
outcome' = outcome,
|
|
991
|
+
base' = base
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// configuration: the controlled host answers every request with its intent
|
|
995
|
+
action acceptRequests = all {
|
|
996
|
+
stage' = stage,
|
|
997
|
+
seeking' = seeking,
|
|
998
|
+
pos' = pos,
|
|
999
|
+
dur' = dur,
|
|
1000
|
+
known' = known,
|
|
1001
|
+
paused' = paused,
|
|
1002
|
+
ended' = ended,
|
|
1003
|
+
vol' = vol,
|
|
1004
|
+
applied' = applied,
|
|
1005
|
+
muted' = muted,
|
|
1006
|
+
rate' = rate,
|
|
1007
|
+
full' = full,
|
|
1008
|
+
textMin' = textMin,
|
|
1009
|
+
textSec' = textSec,
|
|
1010
|
+
focus' = focus,
|
|
1011
|
+
plays' = plays,
|
|
1012
|
+
pauses' = pauses,
|
|
1013
|
+
seeks' = seeks,
|
|
1014
|
+
controlled' = controlled,
|
|
1015
|
+
accepting' = true,
|
|
1016
|
+
prefs' = prefs,
|
|
1017
|
+
reqs' = reqs,
|
|
1018
|
+
reqKind' = reqKind,
|
|
1019
|
+
askNum' = askNum,
|
|
1020
|
+
outcome' = outcome,
|
|
1021
|
+
base' = base
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
action step = any {
|
|
1025
|
+
init,
|
|
1026
|
+
onLoadedMetadata, onCanPlay, onWaiting, onPlaying, onTimeUpdate,
|
|
1027
|
+
onPause, onEnded, onError,
|
|
1028
|
+
play, pause, togglePlay,
|
|
1029
|
+
seekPreview, seekCommit, seekKey, surfaceSeekKey, onSeeked,
|
|
1030
|
+
setVolume, toggleMute, setRate, toggleFullscreen,
|
|
1031
|
+
propVolume, propMuted, propRate, propFullscreen, control, acceptRequests,
|
|
1032
|
+
focusOn, blur, loadStart
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// --- invariants --------------------------------------------------------
|
|
1036
|
+
// aria-valuenow stays inside [aria-valuemin, aria-valuemax]
|
|
1037
|
+
val SeekInRange: bool = and(pos >= 0, or(not(known), pos <= dur))
|
|
1038
|
+
val AriaNowWithinBounds: bool =
|
|
1039
|
+
and(ariaValueMin <= ariaValueNow, or(not(known), ariaValueNow <= ariaValueMax))
|
|
1040
|
+
// playing implies neither paused nor ended; the exposed mirrors track the stage
|
|
1041
|
+
val PlayingNotPaused: bool = or(stage != "playing", not(paused))
|
|
1042
|
+
val PlayingNotEnded: bool = or(stage != "playing", not(ended))
|
|
1043
|
+
val PausedMirrorsStage: bool = paused == not(isActive(stage))
|
|
1044
|
+
val EndedMirrorsStage: bool = ended == (stage == "ended")
|
|
1045
|
+
// the m:ss value text corresponds to the numeric value
|
|
1046
|
+
val ValueTextMirrors: bool = and(textMin == pos / 60, textSec == pos % 60)
|
|
1047
|
+
val ValueTextWellFormed: bool = and(textMin >= 0, and(textSec >= 0, textSec < 60))
|
|
1048
|
+
// muted silences; unmuted applies the slider value verbatim
|
|
1049
|
+
val MutedSilences: bool = and(
|
|
1050
|
+
applied == effVol(vol, muted),
|
|
1051
|
+
or(muted, applied == vol),
|
|
1052
|
+
or(not(muted), applied == 0)
|
|
1053
|
+
)
|
|
1054
|
+
val VolumeInRange: bool = and(vol >= 0, and(vol <= 100, and(applied >= 0, applied <= 100)))
|
|
1055
|
+
// seeking only happens once the duration is known
|
|
1056
|
+
val SeekingOnlyWhenKnown: bool = or(not(seeking), known)
|
|
1057
|
+
// the ended position is the timeline end
|
|
1058
|
+
val EndedAtDuration: bool = or(not(ended), or(not(known), pos == dur))
|
|
1059
|
+
// the speed menu offers only the modelled rates
|
|
1060
|
+
val RateAllowed: bool = or(rate == 50, or(rate == 100, or(rate == 150, rate == 200)))
|
|
1061
|
+
// focus is one of the modelled scopes
|
|
1062
|
+
val FocusKnown: bool = or(
|
|
1063
|
+
or(focus == "none", focus == "surface"),
|
|
1064
|
+
or(focus == "seek", focus == "control")
|
|
1065
|
+
)
|
|
1066
|
+
// callbacks only ever count up from zero
|
|
1067
|
+
val CallbacksNonNegative: bool = and(plays >= 0, and(pauses >= 0, and(seeks >= 0, reqs >= 0)))
|
|
1068
|
+
// controlled: only the props set the preferences, so no event commits
|
|
1069
|
+
val ControlledFollowsProps: bool = or(not(controlled), snap(vol, muted, rate, full) == prefs)
|
|
1070
|
+
// a rejected request leaves the preferences as it found them
|
|
1071
|
+
val RejectedRequestUntouched: bool = or(not(outcome == "rejected"), snap(vol, muted, rate, full) == base)
|
|
1072
|
+
// an accepted request committed exactly its intent
|
|
1073
|
+
val AcceptedRequestCommits: bool = or(
|
|
1074
|
+
not(outcome == "accepted"),
|
|
1075
|
+
if (reqKind == "volume") vol == askNum
|
|
1076
|
+
else if (reqKind == "muted") b2i(muted) == askNum
|
|
1077
|
+
else if (reqKind == "rate") rate == askNum
|
|
1078
|
+
else if (reqKind == "fullscreen") b2i(full) == askNum
|
|
1079
|
+
else false
|
|
1080
|
+
)
|
|
1081
|
+
}
|