Skip to content

Commit 7478518

Browse files
authored
Merge pull request #41 from bananu7/read-markers-from-zdt
Read markers from zdt
2 parents cae748f + 44469f1 commit 7478518

File tree

11 files changed

+411
-84
lines changed

11 files changed

+411
-84
lines changed

src/App.css

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -42,55 +42,10 @@
4242

4343

4444
/*##################*/
45-
46-
.player {
47-
display: flex;
48-
gap: 20px;
49-
}
50-
51-
.transport {
52-
min-width: 400px;
53-
max-width: 400px;
54-
55-
height: 400px;
56-
57-
border-radius: 3px;
58-
border: 1px solid #aaa;
59-
background-color: #111;
60-
padding: 10px;
61-
62-
display: flex;
63-
justify-content: space-between;
64-
flex-direction: column;
65-
gap: 20px;
66-
}
67-
68-
.transport .screen {
69-
background-color: #baddde;
70-
color: #222;
71-
border-radius: 20px;
72-
box-shadow: inset 0 0 10px #222;
73-
border: 1px solid #111;
74-
75-
box-sizing: border-box;
76-
}
77-
78-
.transport span {
79-
font-family: monospace;
80-
font-size: 36px;
81-
padding: 3px;
82-
}
83-
84-
.transport span.inverted {
85-
background-color: #222;
86-
color: #baddde;
87-
}
88-
8945
.channels {
9046
display: flex;
9147
flex-direction: row;
9248
gap: 0;
93-
width: 1100px;
9449
height: 780px;
9550
background: linear-gradient(0deg, #3c3c3c 0%, #444 100%);
9651

src/audio.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ export type AudioState = {
1111
velocity: number,
1212
}
1313

14+
export const midFrequencies = [100, 140, 200, 250, 315, 500, 800, 1000, 1300, 2000, 3000, 5000, 8000] as const;
15+
export type EqMidFrequency = typeof midFrequencies[number];
16+
1417
export type EqController = {
1518
setLowCutEnabled: (lowCut: boolean) => void;
1619
setLowGain: (lowGain: number) => void;
1720
setMidGain: (midGain: number) => void;
18-
// setMidFrequency: (freq: number) => void
21+
setMidFrequency: (freq: EqMidFrequency) => void
1922
setHighGain: (highGain: number) => void;
2023
setPan: (pan: number) => void;
2124
}
@@ -186,14 +189,14 @@ export class AudioSystem {
186189

187190
const mid = this.audioContext.createBiquadFilter();
188191
mid.type = 'peaking';
192+
mid.frequency.value = 1000;
189193
mid.gain.value = 0;
190194

191195
const high = this.audioContext.createBiquadFilter();
192196
high.type = 'highshelf';
193197
high.frequency.value = 10000;
194198
high.gain.value = 0;
195199

196-
197200
const panNode = this.audioContext.createStereoPanner();
198201

199202
sourceNode.connect(lowCut);
@@ -207,7 +210,7 @@ export class AudioSystem {
207210
setLowCutEnabled: e => lowCut.frequency.value = e ? 75 : 0,
208211
setLowGain: g => low.gain.value = g,
209212
setMidGain: g => mid.gain.value = g,
210-
// setMidFrequency: (freq: number) => void
213+
setMidFrequency: (freq: EqMidFrequency) => mid.frequency.value = freq,
211214
setHighGain: g => high.gain.value = g,
212215
setPan: p => panNode.pan.value = p,
213216
};

src/components/FolderList.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ul {
1+
ul.folderList {
22
min-width: 600px;
33

44
display: flex;
@@ -11,7 +11,7 @@ ul {
1111
border-radius: 3px;
1212
}
1313

14-
li {
14+
.folderList li {
1515
color: rgba(255, 255, 255, 0.87);
1616
list-style-type: none;
1717
background-color: #1A67AB;
@@ -26,7 +26,7 @@ li {
2626
box-shadow: 5px 5px 10px 0px rgba(0,0,0,0.3);
2727
}
2828

29-
li:hover {
29+
.folderList li:hover {
3030
border: 1px solid #76a4cd;
3131
box-shadow: 5px 5px 10px 0px rgba(0,0,0,0.5);
3232
}

src/components/FolderList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export function FolderList(props: FolderListProps) {
3232
);
3333

3434
return (
35-
<ul>
35+
<ul className="folderList">
3636
{dirlis}
3737
</ul>
3838
);

src/components/Player.css

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
.player {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 20px;
5+
}
6+
7+
.transport {
8+
min-width: 400px;
9+
max-width: 400px;
10+
11+
border-radius: 3px;
12+
border: 1px solid #aaa;
13+
background-color: #111;
14+
padding: 10px;
15+
16+
display: flex;
17+
justify-content: space-between;
18+
flex-direction: column;
19+
gap: 10px;
20+
}
21+
22+
.transport .screen {
23+
background-color: #baddde;
24+
color: #222;
25+
border-radius: 20px;
26+
box-shadow: inset 0 0 10px #222;
27+
border: 1px solid #111;
28+
29+
box-sizing: border-box;
30+
}
31+
32+
.transport span {
33+
font-family: monospace;
34+
font-size: 36px;
35+
padding: 3px;
36+
}
37+
38+
.transport span.inverted {
39+
background-color: #222;
40+
color: #baddde;
41+
}
42+
43+
.markerList {
44+
overflow-y: scroll;
45+
padding-right: 10px;
46+
}
47+
/*
48+
.markerList::-webkit-scrollbar {
49+
display: none;
50+
}
51+
*/
52+
53+
.markerList ul {
54+
display: flex;
55+
flex-direction: column;
56+
gap: 5px;
57+
58+
padding-top: 10px;
59+
padding-left: 0;
60+
padding-bottom: 10px;
61+
62+
background: linear-gradient(90deg, #111 0%, #111 9%, #ddd 9%, #ddd 11%, #111 11%, #111 100%);
63+
}
64+
65+
.markerList li {
66+
display: grid;
67+
grid-template-columns: 20% 80%;
68+
justify-items: center;
69+
align-items: center;
70+
71+
cursor: pointer;
72+
height: 40px;
73+
list-style-type: none;
74+
border-radius: 3px;
75+
border: 1px solid #aaa;
76+
box-sizing: border-box;
77+
}
78+
79+
80+
.markerList li .dot {
81+
display: inline-block;
82+
width: 30px;
83+
height: 30px;
84+
85+
border-radius: 15px;
86+
87+
background-color: #4ec144;
88+
border: 3px solid #276122;
89+
box-sizing: border-box;
90+
}

src/components/Player.tsx

Lines changed: 67 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
import { useState, useEffect, useCallback } from 'react'
1+
import { useState, useEffect, useCallback, useLayoutEffect } from 'react'
22
import { AudioChannel } from './AudioChannel.tsx'
33
import { MasterChannel } from './MasterChannel.tsx'
44
import { FxChannel } from './FxChannel.tsx'
55
import { Transport } from './Transport.tsx'
6+
import { Timeline } from './Timeline.tsx'
67

78
import { AudioSystem } from '../audio'
8-
import { makeUrl, getJsonFile } from '../filebrowser'
9+
import { makeUrl, getJsonFile, getFile } from '../filebrowser'
910
import { floatToTimestring } from '../util'
11+
import { formatProjectTime } from '../zoom/formatProjectTime'
12+
13+
import './Player.css'
14+
15+
import { ZoomProjectData, binaryZdtToProjectData, zoomMarkerToTime, ProjectTimeSeconds } from '../zoom/zoom_l12.ts'
1016

1117
export type PlayerProps = {
1218
token: string,
@@ -28,23 +34,25 @@ const DEFAULT_TRACK_LIST = [
2834
{ url: 'TRACK09_10.m4a', name: "Keys" },
2935
];
3036

31-
export function Player(props: PlayerProps) {
32-
const [tracks, setTracks] = useState<TrackMeta[]|null>(null);
37+
async function getZoomProjectData(token: string, folder: string): Promise<ZoomProjectData> {
38+
const zoomProjectDataFetch = await getFile(token, folder, 'PRJDATA.ZDT');
39+
const blob = await zoomProjectDataFetch.blob();
40+
const buffer = await blob.arrayBuffer();
41+
const view = new DataView(buffer);
3342

34-
const updatePlaybackPosition = useCallback(() => {
35-
const playbackPos = document.getElementById('playbackPosition');
36-
if (!playbackPos) {
37-
requestAnimationFrame(updatePlaybackPosition);
38-
return;
39-
}
43+
const data = binaryZdtToProjectData(view);
44+
return data;
45+
}
4046

41-
const { position } = props.audioSystem.query();
42-
playbackPos.innerText = floatToTimestring(position);
43-
requestAnimationFrame(updatePlaybackPosition);
44-
}, [props.audioSystem]);
47+
export function Player(props: PlayerProps) {
48+
const [tracks, setTracks] = useState<TrackMeta[]|null>(null);
49+
const [displayedProjectTime, setDisplayedProjectTime] = useState<ProjectTimeSeconds>(0);
50+
const [markers, setMarkers] = useState<ProjectTimeSeconds[]>([]);
4551

46-
const setup = async () => {
52+
const setup = useCallback(async () => {
4753
const trackListInFolder = await getJsonFile(props.token, props.folder, 'tracks.json');
54+
const zoomProjectData = await getZoomProjectData(props.token, props.folder);
55+
setMarkers(zoomProjectData.markers.map(zoomMarkerToTime));
4856

4957
// no tracklist on the server, use default one
5058
const trackList = trackListInFolder ?? DEFAULT_TRACK_LIST;
@@ -54,42 +62,70 @@ export function Player(props: PlayerProps) {
5462
});
5563
setTracks(trackListWithAuth);
5664

57-
updatePlaybackPosition();
58-
}
65+
}, [props.token, props.folder]);
5966

6067
useEffect(() => {
6168
setup();
6269

6370
return () => { };
64-
}, [props.folder, props.token, props.audioSystem]);
71+
}, [props.folder, props.token, props.audioSystem, setup]);
72+
73+
// TODO - useRafLoop
74+
useLayoutEffect(() => {
75+
const i = setInterval(() => {
76+
const { position } = props.audioSystem.query();
77+
setDisplayedProjectTime(position);
78+
}, 100);
79+
return () => clearInterval(i);
80+
}, [props.audioSystem]);
6581

6682
if (!tracks) {
6783
return <span>Loading tracks...</span>;
6884
}
6985

70-
const channels = tracks.map((t: TrackMeta) =>
86+
const channels = tracks.map((t: TrackMeta) =>
7187
<AudioChannel audioSystem={props.audioSystem} name={t.name} url={t.url} key={t.name} />
7288
);
7389

7490
const masterChannelController = props.audioSystem.getMasterChannelController();
7591
const fxChannelController = props.audioSystem.getFxChannelController();
7692

93+
const setProjectTime = (t: ProjectTimeSeconds) => props.audioSystem.update({ position: t});
94+
7795
return (
7896
<div className="player">
79-
<div className="channels">
80-
{channels}
81-
<FxChannel controller={fxChannelController} />
82-
<MasterChannel controller={masterChannelController} />
83-
</div>
97+
<div style={{display:'flex', height: "780px"}}>
98+
<div className="channels">
99+
{channels}
100+
<FxChannel controller={fxChannelController} />
101+
<MasterChannel controller={masterChannelController} />
102+
</div>
84103

85-
<div className="transport">
86-
<div className="screen">
87-
<span className="inverted">{props.folder}</span>
88-
<br />
89-
<span id="playbackPosition"></span>
104+
<div className="transport">
105+
<div className="screen">
106+
<span className="inverted">{props.folder}</span>
107+
<br />
108+
<span id="playbackPosition">{floatToTimestring(displayedProjectTime)}</span>
109+
</div>
110+
<Transport audioSystem={props.audioSystem} />
111+
<div className="markerList" style={{flexGrow: 1}}>
112+
<ul>
113+
{markers.map(m =>
114+
<li key={m} onClick={() => setProjectTime(m)}>
115+
<div className="dot"/>{formatProjectTime(m)}
116+
</li>
117+
)}
118+
</ul>
119+
</div>
90120
</div>
91-
<Transport audioSystem={props.audioSystem} />
92121
</div>
122+
123+
<Timeline
124+
markers={markers}
125+
projectTime={displayedProjectTime}
126+
projectLength={2 * 60 * 60}
127+
setProjectTime={setProjectTime}
128+
/>
93129
</div>
94130
);
95-
}
131+
}

0 commit comments

Comments
 (0)