Repository navigation
Expand file tree
/
Copy pathscreen.html
More file actions
340 lines (323 loc) · 20.7 KB
/
Copy pathscreen.html
File metadata and controls
340 lines (323 loc) · 20.7 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
<!-- Studio Plugin — Session List + Mixer -->
<div id="studio-root" class="max-w-6xl mx-auto px-6 pt-24 pb-16">
<!-- ── Session List View ─────────────────────────────────────── -->
<div id="studio-list-view">
<div class="flex items-center justify-between mb-6">
<div>
<button onclick="showScreen('home')" class="text-gray-500 hover:text-white text-sm mb-2 block">
← Back
</button>
<h2 class="text-3xl font-bold text-white">Band Studio</h2>
<p class="text-gray-500 text-sm mt-1">Record, layer, and mix band performances</p>
</div>
<button onclick="studioShowNewSession()"
class="px-4 py-2 bg-accent hover:bg-accent-light rounded-lg text-white text-sm font-medium transition-colors">
+ New Session
</button>
</div>
<!-- New Session Form (hidden by default) -->
<div id="studio-new-session" class="hidden mb-6 bg-dark-700 rounded-xl p-5 border border-gray-800">
<h3 class="text-white font-semibold mb-3">Create New Session</h3>
<div class="space-y-3">
<div>
<label class="text-gray-400 text-xs block mb-1">Session Name</label>
<input id="studio-session-name" type="text" placeholder="e.g. Master of Puppets - Our Band"
class="w-full bg-dark-800 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:border-accent/50 focus:outline-none">
</div>
<div>
<label class="text-gray-400 text-xs block mb-1">Song</label>
<div class="relative">
<input id="studio-song-search" type="text" placeholder="Search your library..."
oninput="studioSearchSongs(this.value)"
class="w-full bg-dark-800 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:border-accent/50 focus:outline-none">
<div id="studio-song-results"
class="hidden absolute z-20 mt-1 w-full bg-dark-700 border border-gray-700 rounded-lg max-h-48 overflow-y-auto shadow-xl">
</div>
</div>
<input id="studio-song-filename" type="hidden">
<div id="studio-song-selected" class="hidden mt-2 text-sm text-accent"></div>
</div>
<div>
<label class="text-gray-400 text-xs block mb-1">Your Name</label>
<input id="studio-user-name" type="text" placeholder="e.g. Byron"
class="w-full bg-dark-800 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:border-accent/50 focus:outline-none">
</div>
<div class="flex gap-2 pt-1">
<button onclick="studioCreateSession()"
class="px-4 py-2 bg-accent hover:bg-accent-light rounded-lg text-white text-sm font-medium transition-colors">
Create
</button>
<button onclick="studioHideNewSession()"
class="px-4 py-2 bg-dark-600 hover:bg-dark-500 rounded-lg text-gray-300 text-sm transition-colors">
Cancel
</button>
</div>
</div>
</div>
<!-- Sessions Grid -->
<div id="studio-sessions-grid" class="space-y-2">
<div class="text-gray-500 text-sm py-8 text-center">Loading sessions...</div>
</div>
<!-- Demucs Settings -->
<div class="mt-8">
<button onclick="studioToggleDemucsSettings()"
class="text-gray-500 hover:text-gray-300 text-sm flex items-center gap-1 transition-colors">
<span id="studio-demucs-arrow" class="text-xs">▶</span>
Demucs Server Settings
</button>
<div id="studio-demucs-settings" class="hidden mt-3 bg-dark-700 rounded-xl p-5 border border-gray-800">
<p class="text-gray-500 text-xs mb-3">Connect to a Demucs server to extract drum/bass/vocal stems from songs.</p>
<div class="space-y-3">
<div>
<label class="text-gray-400 text-xs block mb-1">Server URL</label>
<input id="studio-demucs-url" type="text" placeholder="e.g. http://192.168.1.100:7865"
class="w-full bg-dark-800 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:border-accent/50 focus:outline-none">
</div>
<div>
<label class="text-gray-400 text-xs block mb-1">API Key (optional)</label>
<input id="studio-demucs-apikey" type="password" placeholder="Leave blank if none"
class="w-full bg-dark-800 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:border-accent/50 focus:outline-none">
</div>
<div class="flex items-center gap-2">
<button onclick="studioSaveDemucsConfig()"
class="px-3 py-1.5 bg-accent hover:bg-accent-light rounded-lg text-white text-sm transition-colors">
Save
</button>
<button onclick="studioTestDemucs()"
class="px-3 py-1.5 bg-dark-600 hover:bg-dark-500 rounded-lg text-gray-300 text-sm transition-colors">
Test Connection
</button>
<span id="studio-demucs-status" class="text-xs ml-2"></span>
</div>
</div>
</div>
</div>
</div>
<!-- ── Session Detail / Mixer View ───────────────────────────── -->
<div id="studio-mixer-view" class="hidden">
<!-- Header -->
<div class="mb-4">
<button onclick="studioBackToList()" class="text-gray-500 hover:text-white text-sm mb-2 block">
← Back to Sessions
</button>
<h2 id="studio-session-title" class="text-2xl font-bold text-white"></h2>
<p id="studio-session-song" class="text-gray-400 text-sm mt-1"></p>
</div>
<!-- Toolbar -->
<div class="flex items-center gap-3 mb-4 bg-dark-700 rounded-xl px-4 py-3 border border-gray-800">
<button id="studio-btn-record" onclick="studioToggleRecord()"
class="flex items-center gap-1.5 px-3 py-1.5 bg-red-600/20 hover:bg-red-600/40 text-red-400 rounded-lg text-sm font-medium transition-colors border border-red-600/30">
<span class="w-2.5 h-2.5 rounded-full bg-red-500"></span>
Record
</button>
<button id="studio-btn-highway-record" onclick="studioHighwayRecord()"
class="flex items-center gap-1.5 px-3 py-1.5 bg-red-600/20 hover:bg-red-600/40 text-red-400 rounded-lg text-sm font-medium transition-colors border border-red-600/30"
title="Record while playing on the highway">
<span class="w-2.5 h-2.5 rounded-full bg-red-500"></span>
Record on Highway
</button>
<button id="studio-btn-play" onclick="studioTogglePlay()"
class="px-3 py-1.5 bg-dark-600 hover:bg-dark-500 rounded-lg text-white text-sm transition-colors">
▶ Play
</button>
<button onclick="studioStop()"
class="px-3 py-1.5 bg-dark-600 hover:bg-dark-500 rounded-lg text-white text-sm transition-colors">
■ Stop
</button>
<button onclick="studioPractice()"
class="px-3 py-1.5 bg-dark-600 hover:bg-dark-500 rounded-lg text-white text-sm transition-colors"
title="Open song on the highway to practice">
♫ Practice
</button>
<div class="flex-1"></div>
<!-- Record settings -->
<div class="flex items-center gap-2">
<label class="text-gray-500 text-xs">Input:</label>
<select id="studio-input-device"
class="bg-dark-800 text-gray-300 text-xs rounded px-2 py-1 border border-gray-700 max-w-[200px]">
<option value="">Default</option>
</select>
</div>
<div class="flex items-center gap-2">
<label class="text-gray-500 text-xs">As:</label>
<input id="studio-record-trackname" type="text" value="Lead" placeholder="Track name"
class="bg-dark-800 text-gray-300 text-xs rounded px-2 py-1 border border-gray-700 w-28"
list="studio-trackname-suggestions">
<datalist id="studio-trackname-suggestions">
<option value="Lead">
<option value="Lead Double">
<option value="Rhythm">
<option value="Rhythm L">
<option value="Rhythm R">
<option value="Bass">
<option value="Vocals">
<option value="Acoustic">
<option value="Clean">
<option value="Solo">
</datalist>
</div>
<button id="studio-btn-undo" onclick="studioUndo()" disabled
class="px-2 py-1.5 bg-dark-600 hover:bg-dark-500 rounded-lg text-gray-400 text-sm transition-colors opacity-30"
title="Undo (Ctrl+Z)">↶</button>
<button id="studio-btn-redo" onclick="studioRedo()" disabled
class="px-2 py-1.5 bg-dark-600 hover:bg-dark-500 rounded-lg text-gray-400 text-sm transition-colors opacity-30"
title="Redo (Ctrl+Y)">↷</button>
<button id="studio-btn-export" onclick="studioExportMix()"
class="px-3 py-1.5 bg-accent/20 hover:bg-accent/40 text-accent rounded-lg text-sm font-medium transition-colors border border-accent/30">
Export Mix
</button>
</div>
<!-- Recording indicator -->
<div id="studio-recording-bar" class="hidden mb-3 bg-red-900/30 border border-red-600/40 rounded-xl px-4 py-2 flex items-center gap-3">
<span class="w-3 h-3 rounded-full bg-red-500 animate-pulse"></span>
<span class="text-red-300 text-sm font-medium">Recording...</span>
<span id="studio-rec-time" class="text-red-400 text-sm ml-auto font-mono">0:00</span>
</div>
<!-- Upload progress -->
<div id="studio-upload-bar" class="hidden mb-3 bg-dark-700 border border-gray-800 rounded-xl px-4 py-2">
<div class="flex items-center gap-3 mb-1">
<span class="text-gray-300 text-sm">Uploading recording...</span>
<span id="studio-upload-pct" class="text-accent text-sm ml-auto font-mono">0%</span>
</div>
<div class="w-full bg-dark-800 rounded-full h-1.5">
<div id="studio-upload-progress" class="bg-accent rounded-full h-1.5 transition-all" style="width:0%"></div>
</div>
</div>
<!-- Track List / Mixer -->
<div id="studio-tracks-container" class="space-y-1 mb-4">
<!-- Original song track -->
<div id="studio-original-track"
class="bg-dark-700 rounded-xl px-4 py-3 border border-gray-800 flex items-center gap-3">
<div class="w-28 flex-shrink-0">
<div class="text-white text-sm font-medium truncate">Original</div>
<div class="text-gray-500 text-xs">Song audio</div>
</div>
<canvas id="studio-waveform-original" class="flex-1 h-12 rounded bg-dark-800 cursor-pointer"
onclick="studioSeekFromWaveform(event, this)"></canvas>
<div class="flex items-center gap-2 flex-shrink-0">
<input type="range" min="0" max="150" value="100"
class="w-16 h-1 accent-accent"
oninput="studioSetVolume('original', this.value/100)"
title="Volume">
<input type="range" min="-100" max="100" value="0"
class="w-12 h-1 accent-accent"
oninput="studioSetPan('original', this.value/100)"
title="Pan">
<button onclick="studioToggleMute('original')"
class="w-7 h-7 rounded text-xs font-bold bg-dark-600 hover:bg-dark-500 text-gray-400 transition-colors"
data-mute="original">M</button>
<button onclick="studioToggleSolo('original')"
class="w-7 h-7 rounded text-xs font-bold bg-dark-600 hover:bg-dark-500 text-gray-400 transition-colors"
data-solo="original">S</button>
</div>
</div>
<!-- Demucs stem extraction -->
<div id="studio-demucs-extract" class="bg-dark-700/50 rounded-xl px-4 py-2.5 border border-gray-800/50 border-dashed flex items-center gap-3">
<div class="w-28 flex-shrink-0">
<div class="text-gray-500 text-sm font-medium">Stems</div>
</div>
<div class="flex-1">
<button onclick="studioExtractDrums()"
class="px-3 py-1 bg-purple-600/20 hover:bg-purple-600/40 text-purple-300 rounded-lg text-xs font-medium transition-colors border border-purple-600/30">
Extract Drums
</button>
<button onclick="studioExtractAllStems()"
class="ml-1 px-3 py-1 bg-purple-600/20 hover:bg-purple-600/40 text-purple-300 rounded-lg text-xs font-medium transition-colors border border-purple-600/30">
Extract All Stems
</button>
<span id="studio-demucs-extract-status" class="ml-2 text-gray-500 text-xs"></span>
</div>
</div>
<!-- Recorded tracks inserted here -->
<div id="studio-recorded-tracks"></div>
<!-- Add Track / Import -->
<div class="flex items-center gap-2 mt-1">
<button onclick="studioAddTrack()"
class="px-3 py-1.5 bg-dark-600 hover:bg-dark-500 rounded-lg text-gray-400 text-xs transition-colors border border-gray-800 border-dashed">
+ Add Track
</button>
<label class="px-3 py-1.5 bg-dark-600 hover:bg-dark-500 rounded-lg text-gray-400 text-xs transition-colors border border-gray-800 border-dashed cursor-pointer">
Import Audio
<input type="file" accept="audio/*" class="hidden" onchange="studioImportAudioFile(this)">
</label>
</div>
</div>
<!-- Master Bus -->
<div class="bg-dark-700 rounded-xl px-4 py-2.5 border border-gray-800 flex items-center gap-3 mb-1">
<span class="text-gray-400 text-xs font-medium w-14">Master</span>
<span class="text-gray-500 text-xs">Vol</span>
<input type="range" min="0" max="200" value="100" step="1"
class="w-24 h-1 accent-accent"
oninput="studioSetMasterVolume(this.value/100)"
title="Master volume">
<span id="studio-master-vol-label" class="text-gray-400 text-xs w-10">100%</span>
<button id="studio-master-limiter-btn" onclick="studioToggleMasterLimiter()"
class="px-2 py-0.5 rounded text-xs font-medium transition-colors bg-green-600/30 text-green-400 border border-green-600/30">
Limiter ON
</button>
<div class="flex-1"></div>
<div id="studio-master-meter" class="w-32 h-3 bg-dark-800 rounded-full overflow-hidden">
<div id="studio-master-meter-bar" class="h-full bg-green-500 rounded-full transition-all" style="width:0%"></div>
</div>
</div>
<!-- Transport / Seek Bar -->
<div class="bg-dark-700 rounded-xl px-4 py-3 border border-gray-800 space-y-2">
<div class="flex items-center gap-3">
<span id="studio-time-current" class="text-white text-sm font-mono w-12 text-right">0:00</span>
<input id="studio-seek-bar" type="range" min="0" max="100" value="0" step="0.1"
class="flex-1 h-1 accent-accent cursor-pointer"
oninput="studioSeek(this.value)">
<span id="studio-time-total" class="text-gray-400 text-sm font-mono w-12">0:00</span>
</div>
<div class="flex items-center gap-2">
<button onclick="studioZoomIn()" class="text-gray-500 hover:text-white text-xs px-1.5 py-0.5 bg-dark-800 rounded transition-colors" title="Zoom in (Ctrl+scroll)">+</button>
<button onclick="studioZoomOut()" class="text-gray-500 hover:text-white text-xs px-1.5 py-0.5 bg-dark-800 rounded transition-colors" title="Zoom out">-</button>
<button onclick="studioZoomFit()" class="text-gray-500 hover:text-white text-xs px-1.5 py-0.5 bg-dark-800 rounded transition-colors" title="Fit to window">Fit</button>
<span id="studio-zoom-label" class="text-gray-600 text-xs w-8">Fit</span>
<input id="studio-scroll-bar" type="range" min="0" max="1" value="0" step="0.1"
class="flex-1 h-1 accent-accent cursor-pointer"
oninput="studioScrollTimeline(this.value)">
</div>
</div>
<!-- Punch-in Region -->
<div id="studio-punch-bar" class="mt-1 bg-dark-700 rounded-xl px-4 py-2.5 border border-gray-800">
<div class="flex items-center gap-3">
<span class="text-gray-500 text-xs w-14">Punch In</span>
<label class="text-gray-500 text-xs">In:</label>
<input id="studio-punch-in" type="text" value="0:00" placeholder="0:00"
class="w-14 bg-dark-800 text-gray-300 text-xs rounded px-1.5 py-0.5 border border-gray-700 text-center font-mono">
<button onclick="studioPunchSetIn()" class="text-gray-500 hover:text-accent text-xs transition-colors" title="Set to current position">[</button>
<label class="text-gray-500 text-xs">Out:</label>
<input id="studio-punch-out" type="text" value="0:00" placeholder="0:00"
class="w-14 bg-dark-800 text-gray-300 text-xs rounded px-1.5 py-0.5 border border-gray-700 text-center font-mono">
<button onclick="studioPunchSetOut()" class="text-gray-500 hover:text-accent text-xs transition-colors" title="Set to current position">]</button>
<label class="text-gray-500 text-xs ml-1">Track:</label>
<select id="studio-punch-track"
class="bg-dark-800 text-gray-300 text-xs rounded px-1.5 py-0.5 border border-gray-700 max-w-[140px]">
</select>
<button onclick="studioPunchRecord()" id="studio-btn-punch"
class="ml-auto flex items-center gap-1.5 px-3 py-1 bg-orange-600/20 hover:bg-orange-600/40 text-orange-300 rounded-lg text-xs font-medium transition-colors border border-orange-600/30">
<span class="w-2 h-2 rounded-full bg-orange-500"></span>
Punch Record
</button>
</div>
</div>
<!-- Markers -->
<div class="mt-1 bg-dark-700 rounded-xl px-4 py-2 border border-gray-800">
<div class="flex items-center gap-2 flex-wrap">
<span class="text-gray-500 text-xs w-14">Markers</span>
<div id="studio-markers-list" class="flex items-center gap-1 flex-wrap flex-1"></div>
<button onclick="studioAddMarker()"
class="text-gray-500 hover:text-accent text-xs transition-colors" title="Add marker at current position">+ Add</button>
<button onclick="studioImportSongMarkers()"
class="text-gray-500 hover:text-accent text-xs transition-colors" title="Import sections from song">Import from Song</button>
</div>
</div>
<!-- Export status -->
<div id="studio-export-status" class="hidden mt-3 bg-dark-700 border border-gray-800 rounded-xl px-4 py-3">
<span id="studio-export-msg" class="text-gray-300 text-sm"></span>
<a id="studio-export-link" href="#" target="_blank"
class="hidden text-accent hover:text-accent-light text-sm ml-2">Download</a>
</div>
</div>
</div>