1use sim_kernel::{Expr, Symbol};
4use sim_lib_scene::{data_map, node, sym};
5use sim_value::build::{list, text, uint};
6
7use crate::keyboard::performance_keyboard_demo_scene;
8use crate::piano_roll::piano_roll_demo_scene;
9
10pub const PLAYER_RACK_VIEW_ID: &str = "view:player-rack";
12
13pub const PLAYER_RACK_ACTIONS: &[&str] = &[
15 "add",
16 "remove",
17 "reorder",
18 "bypass",
19 "direct-record",
20 "freeze",
21 "trace",
22 "route",
23 "placement-hint",
24];
25
26#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct PlayerRackDevice {
29 pub id: Symbol,
31 pub label: String,
33 pub player_kind: Symbol,
35 pub order: u64,
37 pub bypassed: bool,
39 pub direct_record: bool,
41 pub frozen: bool,
43 pub trace: bool,
45 pub route: Symbol,
47 pub placement_hint: String,
49}
50
51#[derive(Clone, Debug, PartialEq, Eq)]
53pub struct PlayerRackView {
54 pub target: Symbol,
56 pub player_chain: Symbol,
58 pub instrument: Symbol,
60 pub source: Symbol,
62 pub stream: Symbol,
64 pub placement_hint: String,
66 pub players: Vec<PlayerRackDevice>,
68}
69
70pub fn player_rack_view(view: &PlayerRackView) -> Expr {
72 node(
73 "player-rack",
74 vec![
75 ("lens", sym(PLAYER_RACK_VIEW_ID)),
76 ("role", sym("player-rack")),
77 ("target", Expr::Symbol(view.target.clone())),
78 ("player-chain", Expr::Symbol(view.player_chain.clone())),
79 ("instrument", Expr::Symbol(view.instrument.clone())),
80 ("source", Expr::Symbol(view.source.clone())),
81 ("stream", Expr::Symbol(view.stream.clone())),
82 ("placement-hint", text(view.placement_hint.clone())),
83 (
84 "actions",
85 list(
86 PLAYER_RACK_ACTIONS
87 .iter()
88 .map(|action| text(*action))
89 .collect(),
90 ),
91 ),
92 (
93 "players",
94 list(view.players.iter().map(player_rack_device_expr).collect()),
95 ),
96 ],
97 )
98}
99
100pub fn player_rack_demo_view() -> PlayerRackView {
102 let chain = Symbol::qualified("music/player-chain", "onscreen-keyboard");
103 let source = Symbol::qualified("music/performance-source", "keyboard");
104 PlayerRackView {
105 target: chain.clone(),
106 player_chain: chain.clone(),
107 instrument: Symbol::qualified("audio-synth/instrument", "dx7"),
108 source,
109 stream: Symbol::qualified("stream/browser", "performance-keyboard"),
110 placement_hint: "browser-wasm".to_owned(),
111 players: vec![
112 PlayerRackDevice {
113 id: Symbol::qualified("music/player", "scales-chords"),
114 label: "Scales and chords".to_owned(),
115 player_kind: Symbol::qualified("music/player-kind", "scales-chords"),
116 order: 0,
117 bypassed: false,
118 direct_record: false,
119 frozen: false,
120 trace: true,
121 route: chain.clone(),
122 placement_hint: "browser-wasm".to_owned(),
123 },
124 PlayerRackDevice {
125 id: Symbol::qualified("music/player", "dual-arpeggio"),
126 label: "Dual arpeggio".to_owned(),
127 player_kind: Symbol::qualified("music/player-kind", "dual-arpeggio"),
128 order: 1,
129 bypassed: false,
130 direct_record: true,
131 frozen: false,
132 trace: true,
133 route: chain.clone(),
134 placement_hint: "worker".to_owned(),
135 },
136 PlayerRackDevice {
137 id: Symbol::qualified("music/player", "note-echo"),
138 label: "Note echo".to_owned(),
139 player_kind: Symbol::qualified("music/player-kind", "note-echo"),
140 order: 2,
141 bypassed: true,
142 direct_record: false,
143 frozen: true,
144 trace: false,
145 route: Symbol::qualified("audio-synth/instrument", "dx7"),
146 placement_hint: "audio-worklet".to_owned(),
147 },
148 ],
149 }
150}
151
152pub fn player_rack_demo_scene() -> Expr {
154 player_rack_view(&player_rack_demo_view())
155}
156
157pub fn performance_workbench_demo_scene() -> Expr {
159 node(
160 "stack",
161 vec![
162 ("role", sym("performance-workbench")),
163 ("dir", sym("column")),
164 (
165 "children",
166 list(vec![
167 performance_keyboard_demo_scene(),
168 player_rack_demo_scene(),
169 piano_roll_demo_scene(),
170 ]),
171 ),
172 ],
173 )
174}
175
176fn player_rack_device_expr(device: &PlayerRackDevice) -> Expr {
177 data_map(vec![
178 ("id", Expr::Symbol(device.id.clone())),
179 ("label", text(device.label.clone())),
180 ("player-kind", Expr::Symbol(device.player_kind.clone())),
181 ("order", uint(device.order)),
182 ("bypassed", Expr::Bool(device.bypassed)),
183 ("direct-record", Expr::Bool(device.direct_record)),
184 ("frozen", Expr::Bool(device.frozen)),
185 ("trace", Expr::Bool(device.trace)),
186 ("route", Expr::Symbol(device.route.clone())),
187 ("placement-hint", text(device.placement_hint.clone())),
188 ])
189}