Skip to content

Commit

Permalink
Merge branch 'tidalcycles:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
edcrub authored Jan 27, 2025
2 parents a3af3d5 + 77267a8 commit 8579909
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 35 deletions.
78 changes: 44 additions & 34 deletions packages/draw/pianoroll.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { Pattern, noteToMidi, freqToMidi } from '@strudel/core';
import { Pattern, noteToMidi, freqToMidi, isPattern } from '@strudel/core';
import { getTheme, getDrawContext } from './draw.mjs';

const scale = (normalized, min, max) => normalized * (max - min) + min;
Expand Down Expand Up @@ -36,35 +36,9 @@ const getValue = (e) => {
return value;
};

Pattern.prototype.pianoroll = function (options = {}) {
let { cycles = 4, playhead = 0.5, overscan = 0, hideNegative = false, ctx = getDrawContext(), id = 1 } = options;

let from = -cycles * playhead;
let to = cycles * (1 - playhead);
const inFrame = (hap, t) => (!hideNegative || hap.whole.begin >= 0) && hap.isWithinTime(t + from, t + to);
this.draw(
(haps, time) => {
pianoroll({
...options,
time,
ctx,
haps: haps.filter((hap) => inFrame(hap, time)),
});
},
{
lookbehind: from - overscan,
lookahead: to + overscan,
id,
},
);
return this;
};

// this function allows drawing a pianoroll without ties to Pattern.prototype
// it will probably replace the above in the future

/**
* Displays a midi-style piano roll
* Visualises a pattern as a scrolling 'pianoroll', displayed in the background of the editor. To show a pianoroll for all running patterns, use `all(pianoroll)`. To have a pianoroll appear below
* a pattern instead, prefix with `_`, e.g.: `sound("bd sd")._pianoroll()`.
*
* @name pianoroll
* @synonyms punchcard
Expand Down Expand Up @@ -93,15 +67,51 @@ Pattern.prototype.pianoroll = function (options = {}) {
* @param {integer} minMidi minimum note value to display on the value axis - defaults to 10
* @param {integer} maxMidi maximum note value to display on the value axis - defaults to 90
* @param {boolean} autorange automatically calculate the minMidi and maxMidi parameters - 0 by default
*
* @see _pianoroll
* @example
* note("c2 a2 eb2")
* .euclid(5,8)
* .s('sawtooth')
* .lpenv(4).lpf(300)
* ._pianoroll({ labels: 1 })
* .pianoroll({ labels: 1 })
*/
export function pianoroll({

Pattern.prototype.pianoroll = function (options = {}) {
let { cycles = 4, playhead = 0.5, overscan = 0, hideNegative = false, ctx = getDrawContext(), id = 1 } = options;

let from = -cycles * playhead;
let to = cycles * (1 - playhead);
const inFrame = (hap, t) => (!hideNegative || hap.whole.begin >= 0) && hap.isWithinTime(t + from, t + to);
this.draw(
(haps, time) => {
__pianoroll({
...options,
time,
ctx,
haps: haps.filter((hap) => inFrame(hap, time)),
});
},
{
lookbehind: from - overscan,
lookahead: to + overscan,
id,
},
);
return this;
};

export function pianoroll(arg) {
if (isPattern(arg)) {
// Single argument as a pattern
// (to support `all(pianoroll)`)
return arg.pianoroll();
}
// Single argument with option - return function to get the pattern
// (to support `all(pianoroll(options))`)
return (pat) => pat.pianoroll(arg);
}

export function __pianoroll({
time,
haps,
cycles = 4,
Expand Down Expand Up @@ -278,7 +288,7 @@ export function getDrawOptions(drawTime, options = {}) {
export const getPunchcardPainter =
(options = {}) =>
(ctx, time, haps, drawTime) =>
pianoroll({ ctx, time, haps, ...getDrawOptions(drawTime, options) });
__pianoroll({ ctx, time, haps, ...getDrawOptions(drawTime, options) });

Pattern.prototype.punchcard = function (options) {
return this.onPaint(getPunchcardPainter(options));
Expand All @@ -302,5 +312,5 @@ Pattern.prototype.wordfall = function (options) {

export function drawPianoroll(options) {
const { drawTime, ...rest } = options;
pianoroll({ ...getDrawOptions(drawTime), ...rest });
__pianoroll({ ...getDrawOptions(drawTime), ...rest });
}
19 changes: 19 additions & 0 deletions packages/mqtt/mqtt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ function onMessageArrived(message) {

function onFailure(err) {
console.error('Connection failed: ', err);
if (typeof window !== 'undefined') {
document.cookie = 'mqtt_pass=';
}
}

Pattern.prototype.mqtt = function (
Expand All @@ -35,12 +38,17 @@ Pattern.prototype.mqtt = function (
) {
const key = host + '-' + client;
let connected = false;
let password_entered = false;

if (!client) {
client = 'strudel-' + String(Math.floor(Math.random() * 1000000));
}
function onConnect() {
console.log('Connected to mqtt broker');
connected = true;
if (password_entered) {
document.cookie = 'mqtt_pass=' + password;
}
}

let cx;
Expand All @@ -58,6 +66,17 @@ Pattern.prototype.mqtt = function (

if (username) {
props.userName = username;
if (typeof password === 'undefined' && typeof window !== 'undefined') {
const cookie = /mqtt_pass=(\w+)/.exec(window.document.cookie);
if (cookie) {
password = cookie[1];
}
if (typeof password === 'undefined') {
password = prompt('Please enter MQTT server password');
password_entered = true;
}
}

props.password = password;
}
cx.connect(props);
Expand Down
8 changes: 8 additions & 0 deletions packages/reference/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# @strudel/reference

this package contains metadata for all documented strudel functions, useful to implement a reference.

```js
import { reference } from '@strudel/reference';
console.log(reference)
```
2 changes: 2 additions & 0 deletions packages/reference/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import jsdoc from '../../doc.json';
export const reference = jsdoc;
39 changes: 39 additions & 0 deletions packages/reference/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "@strudel/reference",
"version": "1.1.0",
"description": "Headless reference of all strudel functions",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
"prepublishOnly": "npm run build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/tidalcycles/strudel.git"
},
"keywords": [
"tidalcycles",
"strudel",
"pattern",
"livecoding",
"algorave"
],
"author": "Felix Roos <[email protected]>",
"contributors": [
"Alex McLean <[email protected]>"
],
"license": "AGPL-3.0-or-later",
"bugs": {
"url": "https://github.com/tidalcycles/strudel/issues"
},
"homepage": "https://github.com/tidalcycles/strudel#readme",
"dependencies": {
},
"devDependencies": {
"vite": "^5.0.10"
}
}
19 changes: 19 additions & 0 deletions packages/reference/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineConfig } from 'vite';
import { dependencies } from './package.json';
import { resolve } from 'path';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [],
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
},
target: 'esnext',
},
});
7 changes: 6 additions & 1 deletion pnpm-lock.yaml

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

0 comments on commit 8579909

Please sign in to comment.