-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTransport.tish
More file actions
109 lines (108 loc) · 5.45 KB
/
Copy pathTransport.tish
File metadata and controls
109 lines (108 loc) · 5.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { h, Fragment } from '@tishlang/lattish'
import { IkSelect } from './InstrumentKit.tish'
// Transport bar — global play controls. Two play modes:
// Play Sequence (Space) — monitor the pattern you are editing (the rack)
// Play Song (Enter) — play the live arrangement of launched patterns (session)
// Pattern LOAD / SAVE / LAUNCH lives in the PatternBank beside the sequencer, not here.
export fn TransportBar(
bpm,
playing,
playMode,
previewing,
onPreview,
onPlayStop,
onSelectMode,
onBpmInput,
onBpmStep,
onExport,
onImport,
mainDeck,
onDeckMain,
launchQuant,
onLaunchQuant,
onUndo,
onRedo,
canUndo,
canRedo,
liveLocked
) {
// Preview = audition the rack on its OWN clock (separate, never live). The Sequence | Session toggle
// + Play are the LIVE transport: both modes share one clock; flip between them live, no restart.
// liveLocked = this client is a co-DJ FOLLOWER → the host owns the live transport; Play + the source
// toggle are disabled (the follower auto-follows the host) and only Preview is available.
let locked = liveLocked === true
let prevCls = previewing ? "btn-play btn-play-seq btn-play-on" : "btn-play btn-play-seq"
let isSeq = playMode !== "song"
let seqCls = isSeq ? "mode-seg mode-seg-on" : "mode-seg"
let sesCls = isSeq ? "mode-seg" : "mode-seg mode-seg-on"
let playCls = playing ? "btn-play btn-play-song btn-play-on" : "btn-play btn-play-song"
let qv = typeof launchQuant === "number" ? String(Math.floor(launchQuant)) : "16"
return (
<div class="transport-bar">
<button class={prevCls} onclick={onPreview} title={"Preview the rack pattern on its own clock — a monitor, fully separate from the live transport (Space)"}>
{previewing ? "■ Preview" : "▶ Preview"}
<span class="btn-key">{"Space"}</span>
</button>
<span class="transport-div" />
<div class="mode-switch" title={locked ? "The host controls the live source while you're following." : "The LIVE source — Sequence (the rack as a live song) or Session (the launched clips). Both share one clock; switch between them live."}>
<button type="button" class={seqCls} disabled={locked} onclick={() => onSelectMode("sequence")}>
{"Sequence"}
</button>
<button type="button" class={sesCls} disabled={locked} onclick={() => onSelectMode("song")}>
{"Session"}
</button>
</div>
<button
class={locked ? (playCls + " btn-play-locked") : playCls}
disabled={locked}
onclick={onPlayStop}
title={locked ? "Host controls playback — you auto-follow the host's transport. Use ▶ Preview to audition privately." : "Play / stop the live transport in the selected mode (Enter)"}
>
{playing ? "■ Stop" : "▶ Play"}
<span class="btn-key">{"Enter"}</span>
</button>
<div class="bpm-stepper" title={"Tempo — tap − / + to nudge a BPM (like a deck), or type a value"}>
<span class="bpm-stepper-cap">{"BPM"}</span>
<button type="button" class="bpm-btn bpm-btn-down" title={"−1 BPM"} onmousedown={(e) => e.preventDefault()} onclick={() => onBpmStep(-1)}>{"−"}</button>
<input type="number" class="bpm-input" min="40" max="240" value={String(bpm)} oninput={onBpmInput} />
<button type="button" class="bpm-btn bpm-btn-up" title={"+1 BPM"} onmousedown={(e) => e.preventDefault()} onclick={() => onBpmStep(1)}>{"+"}</button>
</div>
<label class="quant-label" title={"Launch quantize — clip / scene launches drop on this grid"}>
{"Q "}
{IkSelect({
class: "quant-select",
value: qv,
options: [
{ value: "4", label: "1/4" },
{ value: "8", label: "1/2" },
{ value: "16", label: "1 Bar" },
{ value: "32", label: "2 Bars" }
],
onChange: (v) => onLaunchQuant(Number(v))
})}
</label>
<span class="bpm-debug ok" title={"Transport health (♥) — green when steady. Expands to target→measured BPM on tempo drift, ·NNms when scheduler headroom runs low, ·✕N on audio underruns. Colour = health."}>{"♥"}</span>
<span class="transport-spacer" />
<button class="btn-ghost btn-undo" disabled={!canUndo} onclick={onUndo} title={"Undo (Cmd/Ctrl+Z) — reverts mixer / FX / BPM / crossfader / swing edits (step & note edits aren't undoable yet)"}>
{"↶"}
</button>
<button class="btn-ghost btn-undo" disabled={!canRedo} onclick={onRedo} title={"Redo (Cmd/Ctrl+Shift+Z)"}>
{"↷"}
</button>
<button class="btn-ghost" onclick={onExport} title="Export Project JSON">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" x2="12" y1="15" y2="3"/>
</svg>
</button>
<button class="btn-ghost" onclick={onImport} title="Import Project JSON">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17 8 12 3 7 8"/>
<line x1="12" x2="12" y1="3" y2="15"/>
</svg>
</button>
</div>
)
}