From 7820d85b4076c8d423f8f45b2b88ea923afcc899 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 10 Nov 2023 12:08:29 +0100 Subject: [PATCH] minor changes --- dev-dist/sw.js | 2 +- dev-dist/sw.js.map | 2 +- src/API.ts | 240 ++++++++++++++++---------------- src/classes/SoundEvent.ts | 1 - src/documentation/inlineHelp.ts | 34 +++-- 5 files changed, 142 insertions(+), 137 deletions(-) diff --git a/dev-dist/sw.js b/dev-dist/sw.js index 84a2f05..4bf24cf 100644 --- a/dev-dist/sw.js +++ b/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-5357ef54'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.7orc2ranod8" + "revision": "0.juov83h1sno" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/dev-dist/sw.js.map b/dev-dist/sw.js.map index 61046c0..62eb1b9 100644 --- a/dev-dist/sw.js.map +++ b/dev-dist/sw.js.map @@ -1 +1 @@ -{"version":3,"file":"sw.js","sources":["../../../private/var/folders/zq/nwpwzg_s2rq87xq7zggqfvhw0000gn/T/73355ed5d4866d2eda465e26f727db67/sw.js"],"sourcesContent":["import {clientsClaim as workbox_core_clientsClaim} from '/Users/bubo/Topos/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/Users/bubo/Topos/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/Users/bubo/Topos/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {registerRoute as workbox_routing_registerRoute} from '/Users/bubo/Topos/node_modules/workbox-routing/registerRoute.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/Users/bubo/Topos/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/Users/bubo/Topos/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"registerSW.js\",\n \"revision\": \"3ca0b8505b4bec776b69afdba2768812\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"0.7orc2ranod8\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();\nworkbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"index.html\"), {\n allowlist: [/^\\/$/],\n \n}));\n\n\n\n\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL","allowlist"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"sw.js","sources":["../../../private/var/folders/zq/nwpwzg_s2rq87xq7zggqfvhw0000gn/T/785e34b954b8574748801e9e083e93e0/sw.js"],"sourcesContent":["import {clientsClaim as workbox_core_clientsClaim} from '/Users/bubo/Topos/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/Users/bubo/Topos/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/Users/bubo/Topos/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {registerRoute as workbox_routing_registerRoute} from '/Users/bubo/Topos/node_modules/workbox-routing/registerRoute.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/Users/bubo/Topos/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/Users/bubo/Topos/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"registerSW.js\",\n \"revision\": \"3ca0b8505b4bec776b69afdba2768812\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"0.juov83h1sno\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();\nworkbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"index.html\"), {\n allowlist: [/^\\/$/],\n \n}));\n\n\n\n\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL","allowlist"],"mappings":"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"} \ No newline at end of file diff --git a/src/API.ts b/src/API.ts index eb05683..ad8d2af 100644 --- a/src/API.ts +++ b/src/API.ts @@ -1,4 +1,4 @@ -import { EditorView } from '@codemirror/view'; +import { EditorView } from "@codemirror/view"; import { getAllScaleNotes, seededRandom } from "zifferjs"; import { MidiCCEvent, @@ -28,7 +28,7 @@ import { import { Speaker } from "./StringExtensions"; import { getScaleNotes } from "zifferjs"; import { OscilloscopeConfig, blinkScript } from "./AudioVisualisation"; -import { SkipEvent } from './classes/SkipEvent'; +import { SkipEvent } from "./classes/SkipEvent"; interface ControlChange { channel: number; @@ -151,9 +151,13 @@ export class UserAPI { const stackLines = error.stack?.split("\n"); if (stackLines) { for (const line of stackLines) { - if (line.includes('')) { + if (line.includes("")) { const match = line.match(/:(\d+):(\d+)/); - if (match) return { line: parseInt(match[1], 10), column: parseInt(match[2], 10) }; + if (match) + return { + line: parseInt(match[1], 10), + column: parseInt(match[2], 10), + }; } } } @@ -161,10 +165,10 @@ export class UserAPI { }; const { line, column } = extractLineAndColumn(error); - const errorMessage = line && column - ? `${error.message} (Line: ${line - 2}, Column: ${column})` - : error.message; - + const errorMessage = + line && column + ? `${error.message} (Line: ${line - 2}, Column: ${column})` + : error.message; clearTimeout(this.errorTimeoutID); clearTimeout(this.printTimeoutID); @@ -406,7 +410,7 @@ export class UserAPI { * { channel: 0, velocity: 100, duration: 0.5 } */ - const event = { note: value, velocity, channel, port } as MidiParams + const event = { note: value, velocity, channel, port } as MidiParams; return new MidiEvent(event, this.app); }; @@ -675,7 +679,7 @@ export class UserAPI { public resetAllFromCache = (): void => { this.patternCache.forEach((player) => (player as Player).reset()); - } + }; public z = ( input: string, @@ -1005,74 +1009,6 @@ export class UserAPI { }; cmp = this.clamp; - // ============================================================= - // Transport functions - // ============================================================= - - public nudge = (nudge?: number): number => { - /** - * Sets or returns the current clock nudge. - * - * @param nudge - [optional] the nudge to set - * @returns The current nudge - */ - if (nudge) { - this.app.clock.nudge = nudge; - } - return this.app.clock.nudge; - }; - - public bpm = (n?: number): number => { - /** - * Sets or returns the current bpm. - * - * @param bpm - [optional] The bpm to set - * @returns The current bpm - */ - if (n === undefined) return this.app.clock.bpm; - - if (n < 1 || n > 500) console.log(`Setting bpm to ${n}`); - this.app.clock.bpm = n; - return n; - }; - tempo = this.bpm; - - public bpb = (n?: number): number => { - /** - * Sets or returns the number of beats per bar. - * - * @param bpb - [optional] The number of beats per bar to set - * @returns The current bpb - */ - if (n === undefined) return this.app.clock.time_signature[0]; - - if (n < 1) console.log(`Setting bpb to ${n}`); - this.app.clock.time_signature[0] = n; - return n; - }; - - public ppqn = (n?: number) => { - /** - * Sets or returns the number of pulses per quarter note. - */ - if (n === undefined) return this.app.clock.ppqn; - - if (n < 1) console.log(`Setting ppqn to ${n}`); - this.app.clock.ppqn = n; - return n; - }; - - public time_signature = (numerator: number, denominator: number): void => { - /** - * Sets the time signature. - * - * @param numerator - The numerator of the time signature - * @param denominator - The denominator of the time signature - * @returns The current time signature - */ - this.app.clock.time_signature = [numerator, denominator]; - }; - // ============================================================= // Probability functions // ============================================================= @@ -1293,30 +1229,29 @@ export class UserAPI { // ============================================================= public fullseq = (sequence: string, duration: number) => { - if (sequence.split('').every(c => c === 'x' || c === 'o')) { - return [...sequence].map(c => c === 'x').beat(duration); + if (sequence.split("").every((c) => c === "x" || c === "o")) { + return [...sequence].map((c) => c === "x").beat(duration); } else { - return false + return false; } - } + }; public seq = (expr: string, duration: number = 0.5): boolean => { - let len = expr.length * duration + let len = expr.length * duration; let output: number[] = []; for (let i = 1; i <= len + 1; i += duration) { output.push(Math.floor(i * 10) / 10); } - output.pop() + output.pop(); output = output.filter((_, idx) => { const exprIdx = idx % expr.length; - return expr[exprIdx] === 'x'; + return expr[exprIdx] === "x"; }); - return this.oncount(output, len) - } - + return this.oncount(output, len); + }; public beat = (n: number | number[] = 1, nudge: number = 0): boolean => { /** @@ -1329,7 +1264,7 @@ export class UserAPI { const results: boolean[] = nArray.map( (value) => (this.app.clock.pulses_since_origin - Math.floor(nudge * this.ppqn())) % - Math.floor(value * this.ppqn()) === + Math.floor(value * this.ppqn()) === 0 ); return results.some((value) => value === true); @@ -1349,7 +1284,7 @@ export class UserAPI { const results: boolean[] = nArray.map( (value) => (this.app.clock.pulses_since_origin - nudgeInPulses) % - Math.floor(value * barLength) === + Math.floor(value * barLength) === 0 ); return results.some((value) => value === true); @@ -2032,7 +1967,7 @@ export class UserAPI { effects: this.app.fontSize.reconfigure( EditorView.theme({ "&": { fontFamily: mainFont }, - ".cm-gutters": { fontFamily: mainFont, }, + ".cm-gutters": { fontFamily: mainFont }, ".cm-content": { fontFamily: mainFont, }, @@ -2042,8 +1977,7 @@ export class UserAPI { }) ), }); - } - + }; // ============================================================= // Resolution @@ -2051,56 +1985,57 @@ export class UserAPI { public gif = (options: any) => { /** - * Displays a GIF on the webpage with customizable options including rotation and timed fade-out. - * @param {Object} options - The configuration object for displaying the GIF. - * @param {string} options.url - The URL of the GIF to display. - * @param {number} [options.posX=0] - The X-coordinate to place the GIF at. - * @param {number} [options.posY=0] - The Y-coordinate to place the GIF at. - * @param {number} [options.opacity=1] - The initial opacity level of the GIF. - * @param {string} [options.size='auto'] - The size of the GIF (can be 'cover', 'contain', or specific dimensions). - * @param {boolean} [options.center=false] - Whether to center the GIF in the window. - * @param {number} [options.rotation=0] - The rotation angle of the GIF in degrees. - * @param {string} [options.filter='none'] - The CSS filter function to apply for color alterations. - * @param {number} [options.duration=10] - The total duration the GIF is displayed, in pulses. - */ + * Displays a GIF on the webpage with customizable options including rotation and timed fade-out. + * @param {Object} options - The configuration object for displaying the GIF. + * @param {string} options.url - The URL of the GIF to display. + * @param {number} [options.posX=0] - The X-coordinate to place the GIF at. + * @param {number} [options.posY=0] - The Y-coordinate to place the GIF at. + * @param {number} [options.opacity=1] - The initial opacity level of the GIF. + * @param {string} [options.size='auto'] - The size of the GIF (can be 'cover', 'contain', or specific dimensions). + * @param {boolean} [options.center=false] - Whether to center the GIF in the window. + * @param {number} [options.rotation=0] - The rotation angle of the GIF in degrees. + * @param {string} [options.filter='none'] - The CSS filter function to apply for color alterations. + * @param {number} [options.duration=10] - The total duration the GIF is displayed, in pulses. + */ const { url, posX = 0, posY = 0, opacity = 1, - size = 'auto', + size = "auto", center = false, rotation = 0, - filter = 'none', - dur = 1 + filter = "none", + dur = 1, } = options; - let real_duration = dur * this.app.clock.pulse_duration * this.app.clock.ppqn; + let real_duration = + dur * this.app.clock.pulse_duration * this.app.clock.ppqn; let fadeOutDuration = real_duration * 0.1; let visibilityDuration = real_duration - fadeOutDuration; - const gifElement = document.createElement('img'); + const gifElement = document.createElement("img"); gifElement.src = url; - gifElement.style.position = 'fixed'; - gifElement.style.left = center ? '50%' : `${posX}px`; - gifElement.style.top = center ? '50%' : `${posY}px`; + gifElement.style.position = "fixed"; + gifElement.style.left = center ? "50%" : `${posX}px`; + gifElement.style.top = center ? "50%" : `${posY}px`; gifElement.style.opacity = `${opacity}`; - gifElement.style.zIndex = '-1'; - if (size !== 'auto') { + gifElement.style.zIndex = "-1"; + if (size !== "auto") { gifElement.style.width = size; gifElement.style.height = size; } const transformRules = [`rotate(${rotation}deg)`]; if (center) { - transformRules.unshift('translate(-50%, -50%)'); + transformRules.unshift("translate(-50%, -50%)"); } - gifElement.style.transform = transformRules.join(' '); + gifElement.style.transform = transformRules.join(" "); gifElement.style.filter = filter; gifElement.style.transition = `opacity ${fadeOutDuration}s ease`; document.body.appendChild(gifElement); // Start the fade-out at the end of the visibility duration setTimeout(() => { - gifElement.style.opacity = '0'; + gifElement.style.opacity = "0"; }, visibilityDuration * 1000); // Remove the GIF from the DOM after the fade-out duration @@ -2109,6 +2044,73 @@ export class UserAPI { document.body.removeChild(gifElement); } }, real_duration * 1000); - } + }; + // ============================================================= + // Transport functions + // ============================================================= + + public nudge = (nudge?: number): number => { + /** + * Sets or returns the current clock nudge. + * + * @param nudge - [optional] the nudge to set + * @returns The current nudge + */ + if (nudge) { + this.app.clock.nudge = nudge; + } + return this.app.clock.nudge; + }; + + public bpm = (n?: number): number => { + /** + * Sets or returns the current bpm. + * + * @param bpm - [optional] The bpm to set + * @returns The current bpm + */ + if (n === undefined) return this.app.clock.bpm; + + if (n < 1 || n > 500) console.log(`Setting bpm to ${n}`); + this.app.clock.bpm = n; + return n; + }; + tempo = this.bpm; + + public bpb = (n?: number): number => { + /** + * Sets or returns the number of beats per bar. + * + * @param bpb - [optional] The number of beats per bar to set + * @returns The current bpb + */ + if (n === undefined) return this.app.clock.time_signature[0]; + + if (n < 1) console.log(`Setting bpb to ${n}`); + this.app.clock.time_signature[0] = n; + return n; + }; + + public ppqn = (n?: number) => { + /** + * Sets or returns the number of pulses per quarter note. + */ + if (n === undefined) return this.app.clock.ppqn; + + if (n < 1) console.log(`Setting ppqn to ${n}`); + this.app.clock.ppqn = n; + return n; + }; + + public time_signature = (numerator: number, denominator: number): void => { + /** + * Sets the time signature. + * + * @param numerator - The numerator of the time signature + * @param denominator - The denominator of the time signature + * @returns The current time signature + */ + this.app.clock.time_signature = [numerator, denominator]; + }; } diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 16f6d09..37e7579 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -432,7 +432,6 @@ export class SoundEvent extends AudibleEvent { }; out = (): void => { - console.log(this.app.clock.time_position.pulse) const events = objectWithArraysToArrayOfObjects(this.values, [ "parsedScale", ]); diff --git a/src/documentation/inlineHelp.ts b/src/documentation/inlineHelp.ts index 5290296..d5985d7 100644 --- a/src/documentation/inlineHelp.ts +++ b/src/documentation/inlineHelp.ts @@ -1,10 +1,9 @@ import { hoverTooltip } from "@codemirror/view"; import { type EditorView } from "@codemirror/view"; -import { CompletionContext } from "@codemirror/autocomplete" +import { CompletionContext } from "@codemirror/autocomplete"; // @ts-ignore import { soundMap } from "superdough"; - interface InlineCompletion { name: string; category: string; @@ -562,6 +561,13 @@ const completionDatabase: CompletionDatabase = { description: "Get or set the current beats per minute.", example: "bpm(135) // set the bpm to 135", }, + tempo: { + name: "tempo", + category: "time", + description: "Get or set the current beats per minute.", + example: "tempo(135) // set the bpm to 135", + }, + out: { name: "out", category: "audio", @@ -974,30 +980,28 @@ export const inlineHoveringTips = hoverTooltip( ); export const toposCompletions = (context: CompletionContext) => { - let word = context.matchBefore(/\w*/) + let word = context.matchBefore(/\w*/); if (word) { - if (word.from == word.to && !context.explicit) - return null + if (word.from == word.to && !context.explicit) return null; return { from: word.from, options: Object.keys(completionDatabase).map((key) => ({ label: key, type: completionDatabase[key].category, info: () => { - let div = document.createElement('div'); + let div = document.createElement("div"); div.innerHTML = `

${completionDatabase[key].name} [${completionDatabase[key].category}]

${completionDatabase[key].description}

${completionDatabase[key].example}
- ` + `; div.classList.add("px-4", "py-2", "rounded-lg", "w-92"); - return div - } - })) - } + return div; + }, + })), + }; } -} - +}; export const soundCompletions = (context: CompletionContext) => { let map = soundMap.get(); @@ -1007,10 +1011,10 @@ export const soundCompletions = (context: CompletionContext) => { let from = match.from + "sound(".length; return { from, - options: Object.keys(map).map(key => ({ + options: Object.keys(map).map((key) => ({ label: key, type: map[key].data.type, - apply: `"${key}"` + apply: `"${key}"`, })), }; }