Skip to content

Commit 3106240

Browse files
committed
Resolve PR comments
1 parent 1cdff1b commit 3106240

File tree

6 files changed

+375
-405
lines changed

6 files changed

+375
-405
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ TidalCycles needs to be configured to send editor highlight events. This is usua
100100
let editorTarget = Target {oName = "editor", oAddress = "127.0.0.1", oPort = 6013, oLatency = 0.2, oSchedule = Pre BundleStamp, oWindow = Nothing, oHandshake = False, oBusPort = Nothing }
101101
let editorShape = OSCContext "/editor/highlights"
102102

103-
tidal <- startStream (defaultConfig {cFrameTimespan = 1/30, , cProcessAhead = (1/20)}) [(superdirtTarget {oLatency = 0.02}, [superdirtShape]), (editorTarget, [editorShape])]
103+
tidal <- startStream (defaultConfig {cFrameTimespan = 1/50, cProcessAhead = (1/20)}) [(superdirtTarget {oLatency = 0.02}, [superdirtShape]), (editorTarget, [editorShape])]
104104
```
105105

106106
The path to the `BootTidal.hs` file can be found in the TidalCycles output console after TidalCycles has been booted in the editor.

lib/event-highlighter.js

Lines changed: 57 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@
33
import OscServer from './osc-server';
44
import LineProcessor from './line-processor';
55

6-
if (!Set.prototype.union) {
7-
Set.prototype.union = function (otherSet) {
8-
return new Set([...this, ...otherSet])
9-
}
10-
}
11-
126
const CLASS = Object.freeze({
137
base: "event-highlight",
148
idPrefix: "event-highlight-",
@@ -60,7 +54,6 @@ export default class EventHighlighter {
6054
const elapsed = now - this.then;
6155

6256
const configFPS = atom.config.get('tidalcycles.eventHighlighting.fps');
63-
const missThreshold = atom.config.get('tidalcycles.eventHighlighting.missThreshold');
6457
const delay = atom.config.get('tidalcycles.eventHighlighting.delay');
6558

6659
const fpsInterval = 1000 / configFPS;
@@ -72,9 +65,9 @@ export default class EventHighlighter {
7265
[...this.messageBuffer.entries()]
7366
.filter(([ts]) => (ts + (delay * -1)) < this.then)
7467
.forEach(([ts, event]) => {
75-
activeThisFrame = activeThisFrame.union(event);
76-
this.messageBuffer.delete(ts);
77-
}
68+
activeThisFrame = new Set([...activeThisFrame, ...event]);
69+
this.messageBuffer.delete(ts);
70+
}
7871
);
7972

8073
const { active, added, removed } = this.#diffEventMaps(
@@ -140,25 +133,22 @@ export default class EventHighlighter {
140133

141134
/** Handle OSC message describing a highlight event */
142135
oscHighlightSubscriber() {
143-
return (args: {}): void => {
144-
const message = OscServer.asDictionary(this.highlightTransformer(args));
145-
this.#queueEvent(message);
146-
}
147-
}
136+
return (args, time) => {
148137

138+
const transformedArgs = [
139+
{ value: "time" }, { value: time },
140+
{ value: "id" }, args[0],
141+
{ value: "duration" }, args[1],
142+
{ value: "cycle" }, args[2],
143+
{ value: "colStart" }, args[3],
144+
{ value: "eventId" }, { value: args[4].value - 1 },
145+
{ value: "colEnd" }, args[5],
146+
];
149147

150-
highlightTransformer(args) {
151-
const result = [
152-
{value: "time"}, {value: args[0]},
153-
{value: "id"}, args[1],
154-
{value: "duration"}, args[2],
155-
{value: "cycle"}, args[3],
156-
{value: "colStart"}, args[4],
157-
{value: "eventId"}, {value: args[5].value - 1},
158-
{value: "colEnd"}, args[6],
159-
];
148+
const message = OscServer.asDictionary(transformedArgs);
160149

161-
return result;
150+
this.#queueEvent(message);
151+
}
162152
}
163153

164154
// ----------------------------------------------------------------------
@@ -190,21 +180,21 @@ export default class EventHighlighter {
190180
const highlightEvent = ensureNestedMap(this.highlights, eventId);
191181

192182
editors.forEach(editor => {
193-
const textEditorEvent = ensureNestedMap(highlightEvent, editor.id);
183+
const textEditorEvent = ensureNestedMap(highlightEvent, editor.id);
194184

195-
if (textEditorEvent.has(colStart)) return; // already highlighted
185+
if (textEditorEvent.has(colStart)) return; // already highlighted
196186

197-
const marker = editor.markBufferRange(baseMarker.getBufferRange(), {
198-
invalidate: "inside",
199-
});
187+
const marker = editor.markBufferRange(baseMarker.getBufferRange(), {
188+
invalidate: "inside",
189+
});
200190

201-
// Base style
202-
editor.decorateMarker(marker, { type: "text", class: CLASS.base });
191+
// Base style
192+
editor.decorateMarker(marker, { type: "text", class: CLASS.base });
203193

204-
// Style by numeric id
205-
editor.decorateMarker(marker, { type: "text", class: `${CLASS.idPrefix}${id}` });
194+
// Style by numeric id
195+
editor.decorateMarker(marker, { type: "text", class: `${CLASS.idPrefix}${id}` });
206196

207-
textEditorEvent.set(colStart, marker);
197+
textEditorEvent.set(colStart, marker);
208198
});
209199
}
210200

@@ -214,7 +204,7 @@ export default class EventHighlighter {
214204

215205
if (!highlightEvents || !highlightEvents.size) return;
216206

217-
highlightEvents.forEach(textEditorIdEvent => {
207+
highlightEvents.forEach(textEditorIdEvent => {
218208
const marker = textEditorIdEvent.get(colStart);
219209
textEditorIdEvent.delete(colStart);
220210

@@ -237,9 +227,9 @@ export default class EventHighlighter {
237227
const rowMarkers = ensureNestedMap(textBufferIdMarkers, lineNumber);
238228

239229
LineProcessor.findTidalWordRanges(line, (range) => {
240-
const bufferRange = [[lineNumber, range.start], [lineNumber, range.end + 1]];
241-
const marker = currentEditor.markBufferRange(bufferRange, { invalidate: "inside" });
242-
rowMarkers.set(range.start, marker);
230+
const bufferRange = [[lineNumber, range.start], [lineNumber, range.end + 1]];
231+
const marker = currentEditor.markBufferRange(bufferRange, { invalidate: "inside" });
232+
rowMarkers.set(range.start, marker);
243233
});
244234
}
245235

@@ -254,41 +244,41 @@ export default class EventHighlighter {
254244
}
255245

256246
#diffEventMaps(prevEvents, currentEvents) {
257-
const removed = new Set();
258-
const added = new Set();
259-
const active = new Set();
260-
261-
for (const [event, prevCols] of prevEvents) {
262-
const currCols = currentEvents.get(event);
263-
if (!currCols) {
264-
for (const [, prevEvt] of prevCols) removed.add(prevEvt);
265-
continue;
266-
}
247+
const removed = new Set();
248+
const added = new Set();
249+
const active = new Set();
250+
251+
for (const [event, prevCols] of prevEvents) {
252+
const currCols = currentEvents.get(event);
253+
if (!currCols) {
254+
for (const [, prevEvt] of prevCols) removed.add(prevEvt);
255+
continue;
256+
}
267257

268-
for (const [col, prevEvt] of prevCols) {
269-
if (!currCols.has(col)) {
270-
removed.add(prevEvt);
271-
} else {
272-
active.add(prevEvt);
273-
}
258+
for (const [col, prevEvt] of prevCols) {
259+
if (!currCols.has(col)) {
260+
removed.add(prevEvt);
261+
} else {
262+
active.add(prevEvt);
274263
}
275264
}
265+
}
276266

277-
for (const [event, currCols] of currentEvents) {
278-
const prevCols = prevEvents.get(event);
279-
if (!prevCols) {
280-
for (const [, currEvt] of currCols) added.add(currEvt);
281-
continue;
282-
}
267+
for (const [event, currCols] of currentEvents) {
268+
const prevCols = prevEvents.get(event);
269+
if (!prevCols) {
270+
for (const [, currEvt] of currCols) added.add(currEvt);
271+
continue;
272+
}
283273

284-
for (const [col, currEvt] of currCols) {
285-
if (!prevCols.has(col)) {
286-
added.add(currEvt);
287-
}
274+
for (const [col, currEvt] of currCols) {
275+
if (!prevCols.has(col)) {
276+
added.add(currEvt);
288277
}
289278
}
279+
}
290280

291-
return { removed, added, active };
281+
return { removed, added, active };
292282
}
293283

294284
#transformedEvents(events) {

lib/osc-server.js

Lines changed: 84 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -5,100 +5,94 @@ const osc = require('osc-min');
55

66
export default class OscServer {
77

8-
port = null;
9-
ip = null;
10-
sock = null;
11-
consoleView = null;
12-
subscribers: Map<string, Function> = new Map();
13-
transformers: Map<string, Function> = new Map();
14-
15-
constructor(consoleView, ip, port) {
16-
this.ip = ip;
17-
this.port = port;
18-
this.consoleView = consoleView;
19-
this.sock = dgram.createSocket('udp4');
20-
}
21-
22-
start(): Promise<void> {
23-
let promise = new Promise((resolve, reject) => {
24-
this.sock.on('listening', () => {
25-
resolve()
26-
});
27-
28-
this.sock.on('error', (err) => {
29-
reject(err);
30-
});
31-
});
32-
33-
this.sock.bind(this.port, this.ip);
34-
35-
this.sock.on('message', (message) => {
36-
let oscMessage = osc.fromBuffer(message);
37-
const timeTag = oscMessage.timetag;
38-
39-
if (oscMessage.oscType === "bundle") {
40-
oscMessage.elements.forEach(element => {
41-
if (oscMessage.timetag) {
42-
element.time = OscServer.fromNTPTime(oscMessage.timetag);
43-
this.handleOscMessage(element.address, [element.time, ...element.args]);
44-
} else {
45-
this.handleOscMessage(element.address, element.args);
46-
}
47-
}
48-
);
49-
} else {
50-
this.handleOscMessage(oscMessage.address, oscMessage.args);
51-
}
8+
port = null;
9+
ip = null;
10+
sock = null;
11+
consoleView = null;
12+
subscribers: Map<string, Function> = new Map();
13+
transformers: Map<string, Function> = new Map();
14+
15+
constructor(consoleView, ip, port) {
16+
this.ip = ip;
17+
this.port = port;
18+
this.consoleView = consoleView;
19+
this.sock = dgram.createSocket('udp4');
20+
}
21+
22+
start(): Promise<void> {
23+
let promise = new Promise((resolve, reject) => {
24+
this.sock.on('listening', () => {
25+
resolve()
26+
});
27+
28+
this.sock.on('error', (err) => {
29+
reject(err);
30+
});
31+
});
32+
33+
this.sock.bind(this.port, this.ip);
34+
35+
this.sock.on('message', (message) => {
36+
let oscMessage = osc.fromBuffer(message);
37+
38+
if (oscMessage.oscType === "bundle") {
39+
oscMessage.elements.forEach(element => {
40+
element.time = OscServer.fromNTPTime(oscMessage.timetag);
41+
this.handleOscMessage(element.address, element.args, element.time);
5242
});
53-
54-
return promise
55-
.then(() => {
56-
this.consoleView.logStdout(`Listening for external osc messages on ${this.ip}:${this.port}`)
57-
})
58-
.catch(err => {
59-
this.consoleView.logStderr(`OSC server error: \n${err.stack}`)
60-
this.sock.close();
61-
});
62-
}
63-
64-
handleOscMessage(address, args) {
65-
let subscriber = this.subscribers.get(address);
66-
67-
if (subscriber) {
68-
subscriber(args);
69-
} else {
70-
this.consoleView.logStderr(`Received OSC message on unsupported ${address} address`);
71-
}
72-
}
73-
74-
stop() {
75-
if (this.sock) {
76-
this.sock.close();
77-
}
78-
}
79-
80-
destroy() {
81-
this.stop();
82-
}
83-
84-
register(address: string, listener: Function) {
85-
this.subscribers.set(address, listener)
43+
} else {
44+
this.handleOscMessage(oscMessage.address, oscMessage.args);
45+
}
46+
});
47+
48+
return promise
49+
.then(() => {
50+
this.consoleView.logStdout(`Listening for external osc messages on ${this.ip}:${this.port}`)
51+
})
52+
.catch(err => {
53+
this.consoleView.logStderr(`OSC server error: \n${err.stack}`)
54+
this.sock.close();
55+
});
56+
}
57+
58+
handleOscMessage(address, args, time) {
59+
let subscriber = this.subscribers.get(address);
60+
61+
if (subscriber) {
62+
subscriber(args, time);
63+
} else {
64+
this.consoleView.logStderr(`Received OSC message on unsupported ${address} address`);
8665
}
66+
}
8767

88-
static fromNTPTime([seconds, fractional]) {
89-
return (
90-
(seconds - 2208988800 + fractional / 4294967295) * // NTP Epoch to Unix Seconds
91-
1000 - // In milliseconds
92-
performance.timeOrigin // Offset by timeOrigin
93-
);
68+
stop() {
69+
if (this.sock) {
70+
this.sock.close();
9471
}
95-
96-
static asDictionary (oscMap): {} {
97-
let dictionary = {}
98-
for (let i = 0; i < oscMap.length; i += 2) {
99-
dictionary[oscMap[i].value] = oscMap[i+1].value
100-
}
101-
return dictionary
72+
}
73+
74+
destroy() {
75+
this.stop();
76+
}
77+
78+
register(address: string, listener: Function) {
79+
this.subscribers.set(address, listener)
80+
}
81+
82+
static fromNTPTime([seconds, fractional]) {
83+
return (
84+
(seconds - 2208988800 + fractional / 4294967295) * // NTP Epoch to Unix Seconds
85+
1000 - // In milliseconds
86+
performance.timeOrigin // Offset by timeOrigin
87+
);
88+
}
89+
90+
static asDictionary(oscMap): {} {
91+
let dictionary = {}
92+
for (let i = 0; i < oscMap.length; i += 2) {
93+
dictionary[oscMap[i].value] = oscMap[i + 1].value
10294
}
95+
return dictionary
96+
}
10397

10498
}

0 commit comments

Comments
 (0)