Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ableton link integration #719

Draft
wants to merge 21 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/core/repl.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ export function repl({
transpiler,
onToggle,
editPattern,
createCyclist,
}) {
const scheduler = new Cyclist({
const cyclistParams = {
interval,
onTrigger: getTrigger({ defaultOutput, getTime }),
onError: onSchedulerError,
getTime,
onToggle,
});
};
const scheduler = createCyclist?.(cyclistParams) || new Cyclist(cyclistParams);

const setPattern = (pattern, autostart = true) => {
pattern = editPattern?.(pattern) || pattern;
scheduler.setPattern(pattern, autostart);
Expand Down
3 changes: 2 additions & 1 deletion packages/core/zyklus.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ function createClock(
clear();
};
const getPhase = () => phase;
const setPhase = (_phase) => (phase = _phase);
// setCallback
return { setDuration, start, stop, pause, duration, interval, getPhase, minLatency };
return { setDuration, start, stop, pause, duration, interval, getPhase, setPhase, minLatency };
}
export default createClock;
77 changes: 77 additions & 0 deletions packages/desktopbridge/cyclistbridge.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Cyclist } from '@strudel.cycles/core';
import { logger } from '../core/logger.mjs';
import { Invoke } from '../../website/src/tauri.mjs';
import { listen } from '@tauri-apps/api/event';

export class CyclistBridge extends Cyclist {
constructor(params) {
super(params);
this.start_timer;
this.abeLinkListener = listen('abelink-event', async (e) => {
const payload = e?.payload;
if (payload == null) {
return;
}
const { started, cps, phase, timestamp } = payload;

if (cps !== this.cps) {
this.setCps(cps);
}

// TODO: I'm not sure how to hook this up this phase adjustment in Strudel
// a phase adjustment message is sent every 30 seconds from backend to keep clocks in sync
const phaseDiff = Math.abs(phase - this.clock.getPhase());
if (phaseDiff > 0.1) {
console.log('set phase from', this.clock.getPhase(), 'to', phase);
// hmmm this seems wrong...
//this.clock.setPhase(phase);
}

if (this.started !== started && started != null) {
if (started) {
// the time delay in ms that seems to occur when starting the clock. Unsure if this is standard across all clients
const evaluationTime = 140;

// when start message comes from abelink, delay starting cyclist clock until the start of the next abelink phase
this.start_timer = window.setTimeout(() => {
// TODO: evaluate the code so if another source triggers the play there will not be an error

logger('[cyclist] start');
this.clock.start();
this.setStarted(true);
}, timestamp - Date.now() - evaluationTime);
} else {
this.stop();
}
}
});
}

start() {
if (!this.pattern) {
throw new Error('Scheduler: no pattern set! call .setPattern first.');
}
const linkmsg = {
cps: this.cps,
started: true,
timestamp: Date.now(),
phase: this.clock.getPhase(),
};
Invoke('sendabelinkmsg', { linkmsg });
}

stop() {
logger('[cyclist] stop');
this.clock.stop();
this.lastEnd = 0;
this.setStarted(false);
const linkmsg = {
// TODO: change this to value of "main" clock cps
cps: 0,
started: false,
timestamp: Date.now(),
phase: this.clock.getPhase(),
};
Invoke('sendabelinkmsg', { linkmsg });
}
}
1 change: 1 addition & 0 deletions packages/desktopbridge/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ This program is free software: you can redistribute it and/or modify it under th
export * from './midibridge.mjs';
export * from './utils.mjs';
export * from './oscbridge.mjs';
export * from './cyclistbridge.mjs';
2 changes: 2 additions & 0 deletions packages/react/src/hooks/useStrudel.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function useStrudel({
drawContext,
drawTime = [-2, 2],
paintOptions = {},
createCyclist, // (params) => Cyclist
}) {
const id = useMemo(() => s4(), []);
canvasId = canvasId || `canvas-${id}`;
Expand All @@ -45,6 +46,7 @@ function useStrudel({
onEvalError?.(err);
},
getTime,
createCyclist,
drawContext,
transpiler,
editPattern,
Expand Down
113 changes: 113 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ tauri = { version = "1.4.0", features = ["fs-all"] }
midir = "0.9.1"
tokio = { version = "1.29.0", features = ["full"] }
rosc = "0.10.1"
rusty_link = "0.3.6"

[features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Rust source files for building native desktop apps using Tauri

## Usage

Install [Rust](https://rustup.rs/) on your system.
- Install [Rust](https://rustup.rs/) on your system.
- Install `cmake` on your system. OSX: `brew install cmake`, Linux: `sudo apt-get install cmake`

From the project root:

Expand Down
Loading
Loading