Skip to content

Commit

Permalink
Merge pull request #79 from mindofmatthew/tidal-highlights
Browse files Browse the repository at this point in the history
Tidal mininotation highlights
  • Loading branch information
matthewkaney authored May 11, 2024
2 parents 725206b + 352cb15 commit 5929d6d
Show file tree
Hide file tree
Showing 10 changed files with 371 additions and 13 deletions.
2 changes: 2 additions & 0 deletions app/desktop/src/ipc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { DocumentUpdate, Evaluation, Log } from "@core/api";

import type { SavedStatus } from "./main/filesystem";
import { HighlightEvent } from "@management/lang-tidal";

export type Handler<T> = (event: T) => void;

Expand Down Expand Up @@ -28,4 +29,5 @@ export interface ToRendererChannels {
tidalNow: number;
toggleConsole: undefined;
showAbout: string;
tidalHighlight: HighlightEvent;
}
10 changes: 8 additions & 2 deletions app/desktop/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ fixPath();

import { autoUpdater } from "electron-updater";

import { dialog } from "electron";

// autoUpdater.checkForUpdatesAndNotify();

import { StateManagement } from "@core/state";
Expand Down Expand Up @@ -170,6 +172,12 @@ const createWindow = (
})
);

listeners.push(
tidal.on("highlight", (highlightEvent) => {
send("tidalHighlight", highlightEvent);
})
);

// For now, load a blank document on startup
filesystem.loadDoc();

Expand Down Expand Up @@ -240,8 +248,6 @@ app.whenReady().then(async () => {
// if (process.platform !== "darwindow") app.quit();
// });

import { dialog } from "electron";

menu.on("newFile", newFile);
async function newFile() {
filesystem.loadDoc();
Expand Down
2 changes: 2 additions & 0 deletions app/desktop/src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ const ElectronAPI = {
onTidalVersion: listen("tidalVersion"),

onTidalNow: listen("tidalNow"),

onTidalHighlight: listen("tidalHighlight"),
};

contextBridge.exposeInMainWorld("api", ElectronAPI);
9 changes: 7 additions & 2 deletions app/desktop/src/renderer/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ElectronAPI } from "../preload";

import { Text } from "@codemirror/state";
import { evaluation } from "@management/cm-evaluate";
import { basicSetup } from "@core/extensions/basicSetup";
import { oneDark } from "@core/extensions/theme/theme";
import { tidal } from "@management/lang-tidal/editor";
Expand All @@ -17,6 +16,11 @@ import { fileSync } from "./file";
import { EditorTabView } from "@core/extensions/layout/tabs/editor";
import { AboutTabView } from "@core/extensions/layout/tabs/about";

import {
evaluationWithHighlights,
highlighter,
} from "@management/lang-tidal/highlights";

window.addEventListener("load", () => {
const parent = document.body.appendChild(document.createElement("section"));
parent.id = "editor";
Expand Down Expand Up @@ -76,7 +80,8 @@ export class Editor {
doc,
extensions: [
languageMode,
evaluation(api.evaluate),
evaluationWithHighlights(api.evaluate),
highlighter(api),
basicSetup,
oneDark,
fileSync(
Expand Down
19 changes: 16 additions & 3 deletions core/osc/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
/**
* An object representing any sort of OSC packet.
*/
export type OSCPacket = OSCBundle | OSCMessage;

/**
* An object representing a complete OSC bundle.
*/
export interface OSCBundle {
time: number;
ntpTime: [number, number];
packets: (OSCBundle | OSCMessage)[];
ntpTime: NTPTime;
packets: OSCPacket[];
}

/**
Expand All @@ -14,8 +19,16 @@ export interface OSCMessage {
address: string;
args: OSCArgumentValueList;
argTypes: OSCArgumentTagList;
ntpTime?: NTPTime;
}

export type OSCMessageWithTime = Required<OSCMessage>;

/**
* A representation of an NTP timestamp.
*/
export type NTPTime = [number, number];

/**
* The possible types that an individual OSC argument may have.
*/
Expand Down Expand Up @@ -59,7 +72,7 @@ const OSCArgumentTags = [
/**
* Any one of those type strings.
*/
export type OSCArgumentTag = typeof OSCArgumentTags[number];
export type OSCArgumentTag = (typeof OSCArgumentTags)[number];

/**
* The list of type strings for the arguments of an OSC message. An argument
Expand Down
25 changes: 25 additions & 0 deletions core/osc/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { OSCPacket, OSCMessageWithTime, NTPTime } from "./types";

export function asMessages(packet: OSCPacket) {
return asMessagesAtTime(packet, [0, 0]);
}

function asMessagesAtTime(
packet: OSCPacket,
ntpTime: NTPTime
): OSCMessageWithTime[] {
if ("address" in packet) {
return [{ ...packet, ntpTime }];
} else {
let { ntpTime: newTime, packets } = packet;
return packets.flatMap((newPacket) => asMessagesAtTime(newPacket, newTime));
}
}

export function fromNTPTime([seconds, fractional]: NTPTime) {
return (
(seconds - 2208988800 + fractional / 4294967295) * // NTP Epoch to Unix Seconds
1000 - // In milliseconds
performance.timeOrigin // Offset by timeOrigin
);
}
15 changes: 14 additions & 1 deletion packages/languages/tidal/editor-integration/TidalSetup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,23 @@ import Control.Concurrent
import Sound.Tidal.Context hiding (startStream, startTidal)
import qualified Sound.Tidal.Stream as Stream

:{
highlightTarget :: Target
highlightTarget = Target {oName = "Text Management Highlights",
oAddress = "127.0.0.1",
oPort = editorPort,
oBusPort = Nothing,
oLatency = 0.02,
oWindow = Nothing,
oSchedule = Pre BundleStamp,
oHandshake = False
}
:}

:{
startStream :: Config -> [(Target, [OSC])] -> IO Stream
startStream config oscmap
= do tidal <- Stream.startStream config oscmap
= do tidal <- Stream.startStream config (oscmap ++ [(highlightTarget, [OSCContext "/highlight"])])
watchClock tidal
return tidal
where
Expand Down
35 changes: 30 additions & 5 deletions packages/languages/tidal/ghci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,23 @@ export { TidalSettingsSchema } from "./settings";
import { TidalSettingsSchema } from "./settings";

import { generateIntegrationCode } from "./editor-integration";
import { NTPTime } from "@core/osc/types";
import { EventEmitter } from "@core/events";

export interface HighlightEvent {
miniID: number;
from: number;
to: number;
onset: NTPTime;
cycle: number;
duration: number;
}

interface GHCIEvents {
message: Evaluation | Log;
now: number;
openSettings: string;
highlight: HighlightEvent;
}

export class GHCI extends Engine<GHCIEvents> {
Expand Down Expand Up @@ -56,11 +67,24 @@ export class GHCI extends Engine<GHCIEvents> {
});

socket.on("message", (data) => {
let message = parse(data);

if ("address" in message && message.address === "/now") {
if (typeof message.args[0] === "number") {
this.emit("now", message.args[0]);
let packet = parse(data);

for (let message of asMessages(packet)) {
if (message.address === "/now") {
if (typeof message.args[0] === "number") {
this.emit("now", message.args[0]);
}
} else if (message.address === "/highlight") {
let [_orbit, duration, cycle, from, miniID, to] =
message.args as number[];
this.emit("highlight", {
miniID: miniID - 1,
from,
to,
onset: message.ntpTime,
cycle,
duration: duration / 1000, // Convert from microseconds
});
}
}
});
Expand Down Expand Up @@ -215,6 +239,7 @@ export class GHCI extends Engine<GHCIEvents> {

import { extractStatements } from "./parse";
import { EOL } from "os";
import { asMessages } from "@core/osc/utils";

interface ProcessWrapperEvents {
prologue: string;
Expand Down
Loading

0 comments on commit 5929d6d

Please sign in to comment.