diff --git a/packages/app/example-import-sample/.eslintrc.cjs b/packages/app/example-import-sample/.eslintrc.cjs index 02c4f0b2..e40c1bad 100644 --- a/packages/app/example-import-sample/.eslintrc.cjs +++ b/packages/app/example-import-sample/.eslintrc.cjs @@ -1,5 +1,5 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - extends: ["@opendaw/eslint-config/index.js"], + root: true, + extends: ["@opendaw/eslint-config/index.js"], }; diff --git a/packages/app/headless/.eslintrc.cjs b/packages/app/headless/.eslintrc.cjs index 02c4f0b2..e40c1bad 100644 --- a/packages/app/headless/.eslintrc.cjs +++ b/packages/app/headless/.eslintrc.cjs @@ -1,5 +1,5 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - extends: ["@opendaw/eslint-config/index.js"], + root: true, + extends: ["@opendaw/eslint-config/index.js"], }; diff --git a/packages/app/soundfont/.eslintrc.cjs b/packages/app/soundfont/.eslintrc.cjs index 02c4f0b2..e40c1bad 100644 --- a/packages/app/soundfont/.eslintrc.cjs +++ b/packages/app/soundfont/.eslintrc.cjs @@ -1,5 +1,5 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - extends: ["@opendaw/eslint-config/index.js"], + root: true, + extends: ["@opendaw/eslint-config/index.js"], }; diff --git a/packages/app/studio/.eslintrc.cjs b/packages/app/studio/.eslintrc.cjs index 02c4f0b2..e40c1bad 100644 --- a/packages/app/studio/.eslintrc.cjs +++ b/packages/app/studio/.eslintrc.cjs @@ -1,5 +1,5 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - extends: ["@opendaw/eslint-config/index.js"], + root: true, + extends: ["@opendaw/eslint-config/index.js"], }; diff --git a/packages/app/studio/index.html b/packages/app/studio/index.html index c5070ae9..d40d5724 100644 --- a/packages/app/studio/index.html +++ b/packages/app/studio/index.html @@ -1,88 +1,88 @@ - - - - - - - - - - - - - - - - - - - - - - - - - 🎧openDAW.studio - - + @keyframes mulShdSpin { + 0%, + 100% { + box-shadow: 0em -2.6em 0em 0em #ffffff, 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.5), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7); + } + 12.5% { + box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.7), 1.8em -1.8em 0 0em #ffffff, 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5); + } + 25% { + box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.5), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7), 2.5em 0em 0 0em #ffffff, 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2); + } + 37.5% { + box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5), 2.5em 0em 0 0em rgba(255, 255, 255, 0.7), 1.75em 1.75em 0 0em #ffffff, 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2); + } + 50% { + box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.5), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.7), 0em 2.5em 0 0em #ffffff, -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2); + } + 62.5% { + box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.5), 0em 2.5em 0 0em rgba(255, 255, 255, 0.7), -1.8em 1.8em 0 0em #ffffff, -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2); + } + 75% { + box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.5), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.7), -2.6em 0em 0 0em #ffffff, -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2); + } + 87.5% { + box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.5), -2.6em 0em 0 0em rgba(255, 255, 255, 0.7), -1.8em -1.8em 0 0em #ffffff; + } + } + + diff --git a/packages/app/studio/public/manuals/browser-support.md b/packages/app/studio/public/manuals/browser-support.md index 91a60269..6a9a6963 100644 --- a/packages/app/studio/public/manuals/browser-support.md +++ b/packages/app/studio/public/manuals/browser-support.md @@ -13,5 +13,6 @@ However, there are differences in which web APIs are supported by each browser. ## Legend ### ⚠️ Workaround + This symbol indicates a temporary solution or alternative approach to bypass a limitation, bug, or missing feature. It is not a permanent fix but allows functionality until an official resolution is available. \ No newline at end of file diff --git a/packages/app/studio/public/manuals/dev-log.md b/packages/app/studio/public/manuals/dev-log.md index 1c498c07..dfa774fd 100644 --- a/packages/app/studio/public/manuals/dev-log.md +++ b/packages/app/studio/public/manuals/dev-log.md @@ -13,8 +13,8 @@ * ~~If MIDI, select all channels or specific channel~~ * ~~Arm buttons default behavior should be radio group (shift to add)~~ * ~~Capture audio~~ - * layout channels - * adjust pre-gain? + * layout channels + * adjust pre-gain? * ~~MIDI Controller (values)~~ * ~~Put Recording.start into class Project~~ * ~~Stop (~~start~~) recording at quantized positions~~ diff --git a/packages/app/studio/public/manuals/permissions.md b/packages/app/studio/public/manuals/permissions.md index 6f307e8e..af857f61 100644 --- a/packages/app/studio/public/manuals/permissions.md +++ b/packages/app/studio/public/manuals/permissions.md @@ -8,7 +8,8 @@ as it makes working with openDAW much smoother. ## More Info -In all modern browsers, `navigator.mediaDevices.enumerateDevices()` will only list audio and video devices after the user +In all modern browsers, `navigator.mediaDevices.enumerateDevices()` will only list audio and video devices after the +user grants permission—typically via a getUserMedia() call. Chrome, Safari, and Firefox have all adopted this behavior to protect user privacy and reduce fingerprinting risks. Without permission, device names, IDs, or availability remain hidden. This is how browsers are designed. Granting microphone access ensures openDAW can list diff --git a/packages/app/studio/public/manuals/private-file-system.md b/packages/app/studio/public/manuals/private-file-system.md index 853ce770..4de5e79a 100644 --- a/packages/app/studio/public/manuals/private-file-system.md +++ b/packages/app/studio/public/manuals/private-file-system.md @@ -13,7 +13,10 @@ access to user samples, openDAW copies every imported sample into OPFS, allowing these files securely without relying on external file paths. ## Granting OPFS Storage Permission in Firefox -In Firefox, storing data in OPFS requires explicit user approval due to its privacy settings. Without permission, openDAW may not be able to retain imported samples across sessions. To allow persistent storage for openDAW in Firefox, follow these steps: + +In Firefox, storing data in OPFS requires explicit user approval due to its privacy settings. Without permission, +openDAW may not be able to retain imported samples across sessions. To allow persistent storage for openDAW in Firefox, +follow these steps: * Open Firefox Settings * Navigate to Privacy & Security diff --git a/packages/app/studio/public/manuals/tech-stack.md b/packages/app/studio/public/manuals/tech-stack.md index 3d790855..eb288bd9 100644 --- a/packages/app/studio/public/manuals/tech-stack.md +++ b/packages/app/studio/public/manuals/tech-stack.md @@ -71,4 +71,5 @@ Each in-house library has a clear, focused purpose. * [jszip](https://www.npmjs.com/package/jszip) (Pack & Unpack Zip-Files) * [markdown-it](https://www.npmjs.com/package/markdown-it) + markdown-it-table (Markdown parsing/rendering) -* [d3-force](https://github.com/d3/d3-force) and [force-graph](https://github.com/vasturiano/force-graph) (graph/layout) < dynamic import \ No newline at end of file +* [d3-force](https://github.com/d3/d3-force) and [force-graph](https://github.com/vasturiano/force-graph) ( + graph/layout) < dynamic import \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/01.svg b/packages/app/studio/public/viscious-speed/01.svg index 548eda6f..32838337 100644 --- a/packages/app/studio/public/viscious-speed/01.svg +++ b/packages/app/studio/public/viscious-speed/01.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/02.svg b/packages/app/studio/public/viscious-speed/02.svg index 84b3cc02..de171404 100644 --- a/packages/app/studio/public/viscious-speed/02.svg +++ b/packages/app/studio/public/viscious-speed/02.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/03.svg b/packages/app/studio/public/viscious-speed/03.svg index f70fb952..d4819dbe 100644 --- a/packages/app/studio/public/viscious-speed/03.svg +++ b/packages/app/studio/public/viscious-speed/03.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/04.svg b/packages/app/studio/public/viscious-speed/04.svg index 339973c3..87534cfd 100644 --- a/packages/app/studio/public/viscious-speed/04.svg +++ b/packages/app/studio/public/viscious-speed/04.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/05.svg b/packages/app/studio/public/viscious-speed/05.svg index 8bd91766..6a29ee43 100644 --- a/packages/app/studio/public/viscious-speed/05.svg +++ b/packages/app/studio/public/viscious-speed/05.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/06.svg b/packages/app/studio/public/viscious-speed/06.svg index 58249328..f6a6d3aa 100644 --- a/packages/app/studio/public/viscious-speed/06.svg +++ b/packages/app/studio/public/viscious-speed/06.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/07.svg b/packages/app/studio/public/viscious-speed/07.svg index 4163dfd8..35574a73 100644 --- a/packages/app/studio/public/viscious-speed/07.svg +++ b/packages/app/studio/public/viscious-speed/07.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/08.svg b/packages/app/studio/public/viscious-speed/08.svg index 9de373c7..f9abc2e4 100644 --- a/packages/app/studio/public/viscious-speed/08.svg +++ b/packages/app/studio/public/viscious-speed/08.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/09.svg b/packages/app/studio/public/viscious-speed/09.svg index 5c7eef2f..f03353e9 100644 --- a/packages/app/studio/public/viscious-speed/09.svg +++ b/packages/app/studio/public/viscious-speed/09.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/10.svg b/packages/app/studio/public/viscious-speed/10.svg index 36660395..86c64fbc 100644 --- a/packages/app/studio/public/viscious-speed/10.svg +++ b/packages/app/studio/public/viscious-speed/10.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/11.svg b/packages/app/studio/public/viscious-speed/11.svg index c5d4164f..8ea89117 100644 --- a/packages/app/studio/public/viscious-speed/11.svg +++ b/packages/app/studio/public/viscious-speed/11.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/12.svg b/packages/app/studio/public/viscious-speed/12.svg index ae61e361..311859c4 100644 --- a/packages/app/studio/public/viscious-speed/12.svg +++ b/packages/app/studio/public/viscious-speed/12.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/13.svg b/packages/app/studio/public/viscious-speed/13.svg index 564093ba..91ac9c44 100644 --- a/packages/app/studio/public/viscious-speed/13.svg +++ b/packages/app/studio/public/viscious-speed/13.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/14.svg b/packages/app/studio/public/viscious-speed/14.svg index bc5abb42..9b05bd71 100644 --- a/packages/app/studio/public/viscious-speed/14.svg +++ b/packages/app/studio/public/viscious-speed/14.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/15.svg b/packages/app/studio/public/viscious-speed/15.svg index a11465ef..a34c6bde 100644 --- a/packages/app/studio/public/viscious-speed/15.svg +++ b/packages/app/studio/public/viscious-speed/15.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/16.svg b/packages/app/studio/public/viscious-speed/16.svg index 08070265..87febee1 100644 --- a/packages/app/studio/public/viscious-speed/16.svg +++ b/packages/app/studio/public/viscious-speed/16.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/17.svg b/packages/app/studio/public/viscious-speed/17.svg index e1ac9390..44410a85 100644 --- a/packages/app/studio/public/viscious-speed/17.svg +++ b/packages/app/studio/public/viscious-speed/17.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/18.svg b/packages/app/studio/public/viscious-speed/18.svg index 18a11285..c0d20f4c 100644 --- a/packages/app/studio/public/viscious-speed/18.svg +++ b/packages/app/studio/public/viscious-speed/18.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/19.svg b/packages/app/studio/public/viscious-speed/19.svg index a5965d26..624d84b9 100644 --- a/packages/app/studio/public/viscious-speed/19.svg +++ b/packages/app/studio/public/viscious-speed/19.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/public/viscious-speed/20.svg b/packages/app/studio/public/viscious-speed/20.svg index e8fe525a..db90483f 100644 --- a/packages/app/studio/public/viscious-speed/20.svg +++ b/packages/app/studio/public/viscious-speed/20.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/app/studio/src/errors/ErrorHandler.ts b/packages/app/studio/src/errors/ErrorHandler.ts index 2f0c18da..b414f6df 100644 --- a/packages/app/studio/src/errors/ErrorHandler.ts +++ b/packages/app/studio/src/errors/ErrorHandler.ts @@ -30,9 +30,12 @@ export class ErrorHandler { Dialogs.info({headline: "Warning", message: reason.message}).then(EmptyExec) return false } - if(error.message?.includes("script-src blocked eval")) { + if (error.message?.includes("script-src blocked eval")) { event.preventDefault() - Dialogs.info({headline: "Warning", message: "One of your browser extensions caused an error. Please disable extensions for a more stable experience."}).then(EmptyExec) + Dialogs.info({ + headline: "Warning", + message: "One of your browser extensions caused an error. Please disable extensions for a more stable experience." + }).then(EmptyExec) return false } } diff --git a/packages/lib/box-forge/.eslintrc.cjs b/packages/lib/box-forge/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/box-forge/.eslintrc.cjs +++ b/packages/lib/box-forge/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/box-forge/src/forge.ts b/packages/lib/box-forge/src/forge.ts index 5d825d8a..b90048b7 100644 --- a/packages/lib/box-forge/src/forge.ts +++ b/packages/lib/box-forge/src/forge.ts @@ -5,8 +5,8 @@ import { asValidIdentifier, isDefined, isValidIdentifier, - Nullable, Maybe, + Nullable, panic, SetMultimap, Strings, diff --git a/packages/lib/box/.eslintrc.cjs b/packages/lib/box/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/box/.eslintrc.cjs +++ b/packages/lib/box/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/dawproject/.eslintrc.cjs b/packages/lib/dawproject/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/dawproject/.eslintrc.cjs +++ b/packages/lib/dawproject/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/dawproject/vite-env.d.ts b/packages/lib/dawproject/vite-env.d.ts index 99cb38e7..140899a8 100644 --- a/packages/lib/dawproject/vite-env.d.ts +++ b/packages/lib/dawproject/vite-env.d.ts @@ -1,4 +1,4 @@ -declare module '*.xml?raw' { +declare module "*.xml?raw" { const content: string export default content } \ No newline at end of file diff --git a/packages/lib/dom/.eslintrc.cjs b/packages/lib/dom/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/dom/.eslintrc.cjs +++ b/packages/lib/dom/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/dsp/.eslintrc.cjs b/packages/lib/dsp/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/dsp/.eslintrc.cjs +++ b/packages/lib/dsp/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/fusion/.eslintrc.cjs b/packages/lib/fusion/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/fusion/.eslintrc.cjs +++ b/packages/lib/fusion/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/fusion/src/index.ts b/packages/lib/fusion/src/index.ts index 285eaa0f..ac839bb3 100644 --- a/packages/lib/fusion/src/index.ts +++ b/packages/lib/fusion/src/index.ts @@ -7,7 +7,7 @@ if ((globalThis as any)[key]) { console.debug(`%c${key.description}%c is now available in ${globalThis.constructor.name}.`, "color: hsl(200, 83%, 60%)", "color: inherit") } -import './types' +import "./types" export * from "./live-stream/LiveStreamReceiver" export * from "./live-stream/LiveStreamBroadcaster" diff --git a/packages/lib/jsx/.eslintrc.cjs b/packages/lib/jsx/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/jsx/.eslintrc.cjs +++ b/packages/lib/jsx/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/midi/.eslintrc.cjs b/packages/lib/midi/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/midi/.eslintrc.cjs +++ b/packages/lib/midi/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/runtime/.eslintrc.cjs b/packages/lib/runtime/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/runtime/.eslintrc.cjs +++ b/packages/lib/runtime/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/std/.eslintrc.cjs b/packages/lib/std/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/std/.eslintrc.cjs +++ b/packages/lib/std/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/std/src/color.test.ts b/packages/lib/std/src/color.test.ts index 08ede988..c9a8b6b3 100644 --- a/packages/lib/std/src/color.test.ts +++ b/packages/lib/std/src/color.test.ts @@ -40,14 +40,14 @@ describe("color", () => { }) it("should convert HEX to HSL correctly (approximate)", () => { - const { h, s, l } = hexToHsl("#e6bf99") + const {h, s, l} = hexToHsl("#e6bf99") expect(h).toBeCloseTo(30, 0) expect(s).toBeCloseTo(0.6, 1) expect(l).toBeCloseTo(0.75, 2) }) it("should work without leading # in hex", () => { - const { h, s, l } = hexToHsl("e6bf99") + const {h, s, l} = hexToHsl("e6bf99") expect(h).toBeCloseTo(30, 0) expect(s).toBeCloseTo(0.6, 1) expect(l).toBeCloseTo(0.75, 2) @@ -55,11 +55,11 @@ describe("color", () => { it("should round-trip between HSL and HEX", () => { const colors = [ - { h: 0, s: 1, l: 0.5 }, - { h: 120, s: 1, l: 0.5 }, - { h: 240, s: 1, l: 0.5 }, - { h: 30, s: 0.6, l: 0.75 }, - { h: 200, s: 0.4, l: 0.3 } + {h: 0, s: 1, l: 0.5}, + {h: 120, s: 1, l: 0.5}, + {h: 240, s: 1, l: 0.5}, + {h: 30, s: 0.6, l: 0.75}, + {h: 200, s: 0.4, l: 0.3} ] for (const c of colors) { diff --git a/packages/lib/std/src/iterables.ts b/packages/lib/std/src/iterables.ts index 217fca9d..42094bbf 100644 --- a/packages/lib/std/src/iterables.ts +++ b/packages/lib/std/src/iterables.ts @@ -1,4 +1,4 @@ -import {Func, int, isDefined, Nullable, Maybe, Predicate, Procedure} from "./lang" +import {Func, int, isDefined, Maybe, Nullable, Predicate, Procedure} from "./lang" export class Iterables { static* empty(): Iterable {} diff --git a/packages/lib/std/src/multimap.ts b/packages/lib/std/src/multimap.ts index 54041039..41e210f2 100644 --- a/packages/lib/std/src/multimap.ts +++ b/packages/lib/std/src/multimap.ts @@ -1,5 +1,5 @@ import {Arrays} from "./arrays" -import {Comparator, int, Nullable, Maybe, Predicate} from "./lang" +import {Comparator, int, Maybe, Nullable, Predicate} from "./lang" import {Sets} from "./sets" import {Iterables} from "./iterables" import {Maps} from "./maps" diff --git a/packages/lib/std/src/sorted-set.ts b/packages/lib/std/src/sorted-set.ts index 9b65b099..f836c002 100644 --- a/packages/lib/std/src/sorted-set.ts +++ b/packages/lib/std/src/sorted-set.ts @@ -4,8 +4,8 @@ import { Func, int, isDefined, - Nullable, Maybe, + Nullable, panic, Predicate, Procedure, diff --git a/packages/lib/xml/.eslintrc.cjs b/packages/lib/xml/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/lib/xml/.eslintrc.cjs +++ b/packages/lib/xml/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/lib/xml/src/test.xml b/packages/lib/xml/src/test.xml index 16d18923..4bc970e8 100644 --- a/packages/lib/xml/src/test.xml +++ b/packages/lib/xml/src/test.xml @@ -10,11 +10,11 @@ Dark fantasy masterpiece. - +
- +
diff --git a/packages/server/yjs-server/callback.js b/packages/server/yjs-server/callback.js index f3002bf9..e0e1c294 100644 --- a/packages/server/yjs-server/callback.js +++ b/packages/server/yjs-server/callback.js @@ -11,20 +11,20 @@ export const isCallbackSet = !!CALLBACK_URL * @param {import('./utils.js').WSSharedDoc} doc */ export const callbackHandler = (doc) => { - const room = doc.name - const dataToSend = { - room, - data: {} - } - const sharedObjectList = Object.keys(CALLBACK_OBJECTS) - sharedObjectList.forEach(sharedObjectName => { - const sharedObjectType = CALLBACK_OBJECTS[sharedObjectName] - dataToSend.data[sharedObjectName] = { - type: sharedObjectType, - content: getContent(sharedObjectName, sharedObjectType, doc).toJSON() + const room = doc.name + const dataToSend = { + room, + data: {} } - }) - CALLBACK_URL && callbackRequest(CALLBACK_URL, CALLBACK_TIMEOUT, dataToSend) + const sharedObjectList = Object.keys(CALLBACK_OBJECTS) + sharedObjectList.forEach(sharedObjectName => { + const sharedObjectType = CALLBACK_OBJECTS[sharedObjectName] + dataToSend.data[sharedObjectName] = { + type: sharedObjectType, + content: getContent(sharedObjectName, sharedObjectType, doc).toJSON() + } + }) + CALLBACK_URL && callbackRequest(CALLBACK_URL, CALLBACK_TIMEOUT, dataToSend) } /** @@ -33,29 +33,29 @@ export const callbackHandler = (doc) => { * @param {Object} data */ const callbackRequest = (url, timeout, data) => { - data = JSON.stringify(data) - const options = { - hostname: url.hostname, - port: url.port, - path: url.pathname, - timeout, - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Content-Length': Buffer.byteLength(data) + data = JSON.stringify(data) + const options = { + hostname: url.hostname, + port: url.port, + path: url.pathname, + timeout, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(data) + } } - } - const req = http.request(options) - req.on('timeout', () => { - console.warn('Callback request timed out.') - req.abort() - }) - req.on('error', (e) => { - console.error('Callback request error.', e) - req.abort() - }) - req.write(data) - req.end() + const req = http.request(options) + req.on('timeout', () => { + console.warn('Callback request timed out.') + req.abort() + }) + req.on('error', (e) => { + console.error('Callback request error.', e) + req.abort() + }) + req.write(data) + req.end() } /** @@ -64,12 +64,18 @@ const callbackRequest = (url, timeout, data) => { * @param {import('./utils.js').WSSharedDoc} doc */ const getContent = (objName, objType, doc) => { - switch (objType) { - case 'Array': return doc.getArray(objName) - case 'Map': return doc.getMap(objName) - case 'Text': return doc.getText(objName) - case 'XmlFragment': return doc.getXmlFragment(objName) - case 'XmlElement': return doc.getXmlElement(objName) - default : return {} - } + switch (objType) { + case 'Array': + return doc.getArray(objName) + case 'Map': + return doc.getMap(objName) + case 'Text': + return doc.getText(objName) + case 'XmlFragment': + return doc.getXmlFragment(objName) + case 'XmlElement': + return doc.getXmlElement(objName) + default : + return {} + } } \ No newline at end of file diff --git a/packages/server/yjs-server/utils.js b/packages/server/yjs-server/utils.js index 64e3c547..b85fb139 100644 --- a/packages/server/yjs-server/utils.js +++ b/packages/server/yjs-server/utils.js @@ -8,7 +8,7 @@ import * as map from 'lib0/map' import * as eventloop from 'lib0/eventloop' -import { callbackHandler, isCallbackSet } from './callback.js' +import {callbackHandler, isCallbackSet} from './callback.js' const CALLBACK_DEBOUNCE_WAIT = parseInt(process.env.CALLBACK_DEBOUNCE_WAIT || '2000') const CALLBACK_DEBOUNCE_MAXWAIT = parseInt(process.env.CALLBACK_DEBOUNCE_MAXWAIT || '10000') @@ -33,13 +33,13 @@ let persistence = null * writeState:function(string,WSSharedDoc):Promise,provider:any}|null} persistence_ */ export const setPersistence = persistence_ => { - persistence = persistence_ + persistence = persistence_ } /** * @return {null|{bindState: function(string,WSSharedDoc):void, - * writeState:function(string,WSSharedDoc):Promise}|null} used persistence layer - */ + * writeState:function(string,WSSharedDoc):Promise}|null} used persistence layer + */ export const getPersistence = () => persistence /** @@ -58,11 +58,11 @@ const messageAwareness = 1 * @param {any} _tr */ const updateHandler = (update, _origin, doc, _tr) => { - const encoder = encoding.createEncoder() - encoding.writeVarUint(encoder, messageSync) - syncProtocol.writeUpdate(encoder, update) - const message = encoding.toUint8Array(encoder) - doc.conns.forEach((_, conn) => send(doc, conn, message)) + const encoder = encoding.createEncoder() + encoding.writeVarUint(encoder, messageSync) + syncProtocol.writeUpdate(encoder, update) + const message = encoding.toUint8Array(encoder) + doc.conns.forEach((_, conn) => send(doc, conn, message)) } /** @@ -77,57 +77,61 @@ let contentInitializor = _ydoc => Promise.resolve() * @param {(ydoc: Y.Doc) => Promise} f */ export const setContentInitializor = (f) => { - contentInitializor = f + contentInitializor = f } export class WSSharedDoc extends Y.Doc { - /** - * @param {string} name - */ - constructor (name) { - super({ gc: gcEnabled }) - this.name = name /** - * Maps from conn to set of controlled user ids. Delete all user ids from awareness when this conn is closed - * @type {Map>} + * @param {string} name */ - this.conns = new Map() - /** - * @type {awarenessProtocol.Awareness} - */ - this.awareness = new awarenessProtocol.Awareness(this) - this.awareness.setLocalState(null) - /** - * @param {{ added: Array, updated: Array, removed: Array }} changes - * @param {Object | null} conn Origin is the connection that made the change - */ - const awarenessChangeHandler = ({ added, updated, removed }, conn) => { - const changedClients = added.concat(updated, removed) - if (conn !== null) { - const connControlledIDs = /** @type {Set} */ (this.conns.get(conn)) - if (connControlledIDs !== undefined) { - added.forEach(clientID => { connControlledIDs.add(clientID) }) - removed.forEach(clientID => { connControlledIDs.delete(clientID) }) + constructor(name) { + super({gc: gcEnabled}) + this.name = name + /** + * Maps from conn to set of controlled user ids. Delete all user ids from awareness when this conn is closed + * @type {Map>} + */ + this.conns = new Map() + /** + * @type {awarenessProtocol.Awareness} + */ + this.awareness = new awarenessProtocol.Awareness(this) + this.awareness.setLocalState(null) + /** + * @param {{ added: Array, updated: Array, removed: Array }} changes + * @param {Object | null} conn Origin is the connection that made the change + */ + const awarenessChangeHandler = ({added, updated, removed}, conn) => { + const changedClients = added.concat(updated, removed) + if (conn !== null) { + const connControlledIDs = /** @type {Set} */ (this.conns.get(conn)) + if (connControlledIDs !== undefined) { + added.forEach(clientID => { + connControlledIDs.add(clientID) + }) + removed.forEach(clientID => { + connControlledIDs.delete(clientID) + }) + } + } + // broadcast awareness update + const encoder = encoding.createEncoder() + encoding.writeVarUint(encoder, messageAwareness) + encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(this.awareness, changedClients)) + const buff = encoding.toUint8Array(encoder) + this.conns.forEach((_, c) => { + send(this, c, buff) + }) } - } - // broadcast awareness update - const encoder = encoding.createEncoder() - encoding.writeVarUint(encoder, messageAwareness) - encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(this.awareness, changedClients)) - const buff = encoding.toUint8Array(encoder) - this.conns.forEach((_, c) => { - send(this, c, buff) - }) + this.awareness.on('update', awarenessChangeHandler) + this.on('update', /** @type {any} */ (updateHandler)) + if (isCallbackSet) { + this.on('update', (_update, _origin, doc) => { + debouncer(() => callbackHandler(/** @type {WSSharedDoc} */ (doc))) + }) + } + this.whenInitialized = contentInitializor(this) } - this.awareness.on('update', awarenessChangeHandler) - this.on('update', /** @type {any} */ (updateHandler)) - if (isCallbackSet) { - this.on('update', (_update, _origin, doc) => { - debouncer(() => callbackHandler(/** @type {WSSharedDoc} */ (doc))) - }) - } - this.whenInitialized = contentInitializor(this) - } } /** @@ -138,13 +142,13 @@ export class WSSharedDoc extends Y.Doc { * @return {WSSharedDoc} */ export const getYDoc = (docname, gc = true) => map.setIfUndefined(docs, docname, () => { - const doc = new WSSharedDoc(docname) - doc.gc = gc - if (persistence !== null) { - persistence.bindState(docname, doc) - } - docs.set(docname, doc) - return doc + const doc = new WSSharedDoc(docname) + doc.gc = gc + if (persistence !== null) { + persistence.bindState(docname, doc) + } + docs.set(docname, doc) + return doc }) /** @@ -153,32 +157,32 @@ export const getYDoc = (docname, gc = true) => map.setIfUndefined(docs, docname, * @param {Uint8Array} message */ const messageListener = (conn, doc, message) => { - try { - const encoder = encoding.createEncoder() - const decoder = decoding.createDecoder(message) - const messageType = decoding.readVarUint(decoder) - switch (messageType) { - case messageSync: - encoding.writeVarUint(encoder, messageSync) - syncProtocol.readSyncMessage(decoder, encoder, doc, conn) + try { + const encoder = encoding.createEncoder() + const decoder = decoding.createDecoder(message) + const messageType = decoding.readVarUint(decoder) + switch (messageType) { + case messageSync: + encoding.writeVarUint(encoder, messageSync) + syncProtocol.readSyncMessage(decoder, encoder, doc, conn) - // If the `encoder` only contains the type of reply message and no - // message, there is no need to send the message. When `encoder` only - // contains the type of reply, its length is 1. - if (encoding.length(encoder) > 1) { - send(doc, conn, encoding.toUint8Array(encoder)) + // If the `encoder` only contains the type of reply message and no + // message, there is no need to send the message. When `encoder` only + // contains the type of reply, its length is 1. + if (encoding.length(encoder) > 1) { + send(doc, conn, encoding.toUint8Array(encoder)) + } + break + case messageAwareness: { + awarenessProtocol.applyAwarenessUpdate(doc.awareness, decoding.readVarUint8Array(decoder), conn) + break + } } - break - case messageAwareness: { - awarenessProtocol.applyAwarenessUpdate(doc.awareness, decoding.readVarUint8Array(decoder), conn) - break - } + } catch (err) { + console.error(err) + // @ts-ignore + doc.emit('error', [err]) } - } catch (err) { - console.error(err) - // @ts-ignore - doc.emit('error', [err]) - } } /** @@ -186,23 +190,23 @@ const messageListener = (conn, doc, message) => { * @param {any} conn */ const closeConn = (doc, conn) => { - if (doc.conns.has(conn)) { - /** - * @type {Set} - */ - // @ts-ignore - const controlledIds = doc.conns.get(conn) - doc.conns.delete(conn) - awarenessProtocol.removeAwarenessStates(doc.awareness, Array.from(controlledIds), null) - if (doc.conns.size === 0 && persistence !== null) { - // if persisted, we store state and destroy ydocument - persistence.writeState(doc.name, doc).then(() => { - doc.destroy() - }) - docs.delete(doc.name) + if (doc.conns.has(conn)) { + /** + * @type {Set} + */ + // @ts-ignore + const controlledIds = doc.conns.get(conn) + doc.conns.delete(conn) + awarenessProtocol.removeAwarenessStates(doc.awareness, Array.from(controlledIds), null) + if (doc.conns.size === 0 && persistence !== null) { + // if persisted, we store state and destroy ydocument + persistence.writeState(doc.name, doc).then(() => { + doc.destroy() + }) + docs.delete(doc.name) + } } - } - conn.close() + conn.close() } /** @@ -211,14 +215,16 @@ const closeConn = (doc, conn) => { * @param {Uint8Array} m */ const send = (doc, conn, m) => { - if (conn.readyState !== wsReadyStateConnecting && conn.readyState !== wsReadyStateOpen) { - closeConn(doc, conn) - } - try { - conn.send(m, {}, err => { err != null && closeConn(doc, conn) }) - } catch (e) { - closeConn(doc, conn) - } + if (conn.readyState !== wsReadyStateConnecting && conn.readyState !== wsReadyStateOpen) { + closeConn(doc, conn) + } + try { + conn.send(m, {}, err => { + err != null && closeConn(doc, conn) + }) + } catch (e) { + closeConn(doc, conn) + } } const pingTimeout = 30000 @@ -228,68 +234,68 @@ const pingTimeout = 30000 * @param {import('http').IncomingMessage} req * @param {any} opts */ -export const setupWSConnection = (conn, req, { docName = (req.url || '').slice(1).split('?')[0], gc = true } = {}) => { - console.log("Incoming WS from origin:", req.headers.origin) +export const setupWSConnection = (conn, req, {docName = (req.url || '').slice(1).split('?')[0], gc = true} = {}) => { + console.log("Incoming WS from origin:", req.headers.origin) - // ✅ Allow only specific origins - const allowedOrigins = [ - 'https://opendaw.studio', - 'https://live.opendaw.studio', - 'https://localhost:8080', - 'https://inspector.yjs.dev' - ] - const origin = req.headers.origin - if (origin && !allowedOrigins.includes(origin)) { - console.warn('Rejected WS connection from origin:', origin) - conn.close() - return - } - conn.binaryType = 'arraybuffer' - // get doc, initialize if it does not exist yet - const doc = getYDoc(docName, gc) - doc.conns.set(conn, new Set()) - // listen and reply to events - conn.on('message', /** @param {ArrayBuffer} message */ message => messageListener(conn, doc, new Uint8Array(message))) + // ✅ Allow only specific origins + const allowedOrigins = [ + 'https://opendaw.studio', + 'https://live.opendaw.studio', + 'https://localhost:8080', + 'https://inspector.yjs.dev' + ] + const origin = req.headers.origin + if (origin && !allowedOrigins.includes(origin)) { + console.warn('Rejected WS connection from origin:', origin) + conn.close() + return + } + conn.binaryType = 'arraybuffer' + // get doc, initialize if it does not exist yet + const doc = getYDoc(docName, gc) + doc.conns.set(conn, new Set()) + // listen and reply to events + conn.on('message', /** @param {ArrayBuffer} message */message => messageListener(conn, doc, new Uint8Array(message))) - // Check if connection is still alive - let pongReceived = true - const pingInterval = setInterval(() => { - if (!pongReceived) { - if (doc.conns.has(conn)) { - closeConn(doc, conn) - } - clearInterval(pingInterval) - } else if (doc.conns.has(conn)) { - pongReceived = false - try { - conn.ping() - } catch (e) { + // Check if connection is still alive + let pongReceived = true + const pingInterval = setInterval(() => { + if (!pongReceived) { + if (doc.conns.has(conn)) { + closeConn(doc, conn) + } + clearInterval(pingInterval) + } else if (doc.conns.has(conn)) { + pongReceived = false + try { + conn.ping() + } catch (e) { + closeConn(doc, conn) + clearInterval(pingInterval) + } + } + }, pingTimeout) + conn.on('close', () => { closeConn(doc, conn) clearInterval(pingInterval) - } + }) + conn.on('pong', () => { + pongReceived = true + }) + // put the following in a variables in a block so the interval handlers don't keep in in + // scope + { + // send sync step 1 + const encoder = encoding.createEncoder() + encoding.writeVarUint(encoder, messageSync) + syncProtocol.writeSyncStep1(encoder, doc) + send(doc, conn, encoding.toUint8Array(encoder)) + const awarenessStates = doc.awareness.getStates() + if (awarenessStates.size > 0) { + const encoder = encoding.createEncoder() + encoding.writeVarUint(encoder, messageAwareness) + encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(doc.awareness, Array.from(awarenessStates.keys()))) + send(doc, conn, encoding.toUint8Array(encoder)) + } } - }, pingTimeout) - conn.on('close', () => { - closeConn(doc, conn) - clearInterval(pingInterval) - }) - conn.on('pong', () => { - pongReceived = true - }) - // put the following in a variables in a block so the interval handlers don't keep in in - // scope - { - // send sync step 1 - const encoder = encoding.createEncoder() - encoding.writeVarUint(encoder, messageSync) - syncProtocol.writeSyncStep1(encoder, doc) - send(doc, conn, encoding.toUint8Array(encoder)) - const awarenessStates = doc.awareness.getStates() - if (awarenessStates.size > 0) { - const encoder = encoding.createEncoder() - encoding.writeVarUint(encoder, messageAwareness) - encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(doc.awareness, Array.from(awarenessStates.keys()))) - send(doc, conn, encoding.toUint8Array(encoder)) - } - } } \ No newline at end of file diff --git a/packages/studio/adapters/.eslintrc.cjs b/packages/studio/adapters/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/studio/adapters/.eslintrc.cjs +++ b/packages/studio/adapters/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/studio/adapters/generate-exports.mjs b/packages/studio/adapters/generate-exports.mjs index 920df321..715e471c 100644 --- a/packages/studio/adapters/generate-exports.mjs +++ b/packages/studio/adapters/generate-exports.mjs @@ -2,49 +2,49 @@ import fs from 'fs'; import path from 'path'; -import { fileURLToPath } from 'url'; +import {fileURLToPath} from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Function to recursively find all TypeScript files function findTsFiles(dir, baseDir = dir) { - const files = []; - const items = fs.readdirSync(dir); - - for (const item of items) { - const fullPath = path.join(dir, item); - const stat = fs.statSync(fullPath); - - if (stat.isDirectory()) { - files.push(...findTsFiles(fullPath, baseDir)); - } else if (item.endsWith('.ts') && !item.endsWith('.d.ts') && item !== 'index.ts') { - const relativePath = path.relative(baseDir, fullPath).replace(/\\/g, '/').replace('.ts', ''); - files.push(relativePath); + const files = []; + const items = fs.readdirSync(dir); + + for (const item of items) { + const fullPath = path.join(dir, item); + const stat = fs.statSync(fullPath); + + if (stat.isDirectory()) { + files.push(...findTsFiles(fullPath, baseDir)); + } else if (item.endsWith('.ts') && !item.endsWith('.d.ts') && item !== 'index.ts') { + const relativePath = path.relative(baseDir, fullPath).replace(/\\/g, '/').replace('.ts', ''); + files.push(relativePath); + } } - } - - return files; + + return files; } // Generate the index.ts content function generateIndex() { - const srcDir = path.join(__dirname, 'src'); - const files = findTsFiles(srcDir); - - const exports = files - .sort() - .map(file => `export * from "./${file}"`) - .join('\n'); - - const content = `// Auto-generated exports - do not edit manually + const srcDir = path.join(__dirname, 'src'); + const files = findTsFiles(srcDir); + + const exports = files + .sort() + .map(file => `export * from "./${file}"`) + .join('\n'); + + const content = `// Auto-generated exports - do not edit manually // Run: node generate-exports.js to regenerate ${exports} `; - fs.writeFileSync(path.join(srcDir, 'index.ts'), content); - console.log(`Generated ${files.length} exports in index.ts`); + fs.writeFileSync(path.join(srcDir, 'index.ts'), content); + console.log(`Generated ${files.length} exports in index.ts`); } generateIndex(); \ No newline at end of file diff --git a/packages/studio/adapters/src/ParameterAdapterSet.ts b/packages/studio/adapters/src/ParameterAdapterSet.ts index f149f9f0..4e772d61 100644 --- a/packages/studio/adapters/src/ParameterAdapterSet.ts +++ b/packages/studio/adapters/src/ParameterAdapterSet.ts @@ -1,5 +1,13 @@ import {FieldKeys, PointerTypes, PrimitiveField, PrimitiveValues} from "@opendaw/lib-box" -import {assert, NumberArrayComparator, SortedSet, StringMapping, Terminable, unitValue, ValueMapping} from "@opendaw/lib-std" +import { + assert, + NumberArrayComparator, + SortedSet, + StringMapping, + Terminable, + unitValue, + ValueMapping +} from "@opendaw/lib-std" import {AutomatableParameterFieldAdapter} from "./AutomatableParameterFieldAdapter" import {BoxAdaptersContext} from "./BoxAdaptersContext" diff --git a/packages/studio/adapters/src/devices/audio-effects/ModularDeviceBoxAdapter.ts b/packages/studio/adapters/src/devices/audio-effects/ModularDeviceBoxAdapter.ts index 59cdf740..230c205a 100644 --- a/packages/studio/adapters/src/devices/audio-effects/ModularDeviceBoxAdapter.ts +++ b/packages/studio/adapters/src/devices/audio-effects/ModularDeviceBoxAdapter.ts @@ -9,7 +9,6 @@ import {AudioUnitBoxAdapter} from "../../audio-unit/AudioUnitBoxAdapter" import {ModularAdapter} from "../../modular/modular" import {DeviceInterfaceKnobAdapter} from "../../modular/user-interface" - export class ModularDeviceBoxAdapter implements AudioEffectDeviceAdapter { readonly type = "audio-effect" readonly accepts = "audio" diff --git a/packages/studio/adapters/src/devices/instruments/Playfield/PlayfieldSampleBoxAdapter.ts b/packages/studio/adapters/src/devices/instruments/Playfield/PlayfieldSampleBoxAdapter.ts index 9c886139..dc004a0a 100644 --- a/packages/studio/adapters/src/devices/instruments/Playfield/PlayfieldSampleBoxAdapter.ts +++ b/packages/studio/adapters/src/devices/instruments/Playfield/PlayfieldSampleBoxAdapter.ts @@ -5,7 +5,8 @@ import {Address, BooleanField, Field, Int32Field, StringField} from "@opendaw/li import { AudioEffectDeviceAdapter, DeviceAccepts, - DeviceHost, Devices, + DeviceHost, + Devices, InstrumentDeviceBoxAdapter, MidiEffectDeviceAdapter } from "../../../DeviceAdapter" diff --git a/packages/studio/adapters/src/devices/midi-effects/PitchDeviceBoxAdapter.ts b/packages/studio/adapters/src/devices/midi-effects/PitchDeviceBoxAdapter.ts index ce2f2f2e..b3323835 100644 --- a/packages/studio/adapters/src/devices/midi-effects/PitchDeviceBoxAdapter.ts +++ b/packages/studio/adapters/src/devices/midi-effects/PitchDeviceBoxAdapter.ts @@ -6,7 +6,7 @@ import {DeviceHost, Devices, MidiEffectDeviceAdapter} from "../../DeviceAdapter" import {BoxAdaptersContext} from "../../BoxAdaptersContext" import {ParameterAdapterSet} from "../../ParameterAdapterSet" import {AudioUnitBoxAdapter} from "../../audio-unit/AudioUnitBoxAdapter" -import { AutomatableParameterFieldAdapter } from "../../AutomatableParameterFieldAdapter" +import {AutomatableParameterFieldAdapter} from "../../AutomatableParameterFieldAdapter" export class PitchDeviceBoxAdapter implements MidiEffectDeviceAdapter { readonly type = "midi-effect" diff --git a/packages/studio/adapters/src/modular/module.ts b/packages/studio/adapters/src/modular/module.ts index 3f682201..12e1c0e1 100644 --- a/packages/studio/adapters/src/modular/module.ts +++ b/packages/studio/adapters/src/modular/module.ts @@ -2,7 +2,8 @@ import {Box, Vertex} from "@opendaw/lib-box" import { BoxVisitor, ModularAudioInputBox, - ModularAudioOutputBox, ModuleAttributes, + ModularAudioOutputBox, + ModuleAttributes, ModuleDelayBox, ModuleGainBox, ModuleMultiplierBox diff --git a/packages/studio/adapters/src/selection/VertexSelection.ts b/packages/studio/adapters/src/selection/VertexSelection.ts index ff2576c6..507b6f4b 100644 --- a/packages/studio/adapters/src/selection/VertexSelection.ts +++ b/packages/studio/adapters/src/selection/VertexSelection.ts @@ -13,7 +13,7 @@ import { Terminator, UUID } from "@opendaw/lib-std" -import {Address, Addressable, BoxGraph, Editing, Field, PointerField, PointerListener} from "@opendaw/lib-box" +import {Address, Addressable, BoxGraph, Editing, Field, PointerField} from "@opendaw/lib-box" import {Pointers} from "@opendaw/studio-enums" import {SelectionBox} from "@opendaw/studio-boxes" import {SelectableVertex} from "./SelectableVertex" diff --git a/packages/studio/adapters/src/timeline/clip/AudioClipBoxAdapter.ts b/packages/studio/adapters/src/timeline/clip/AudioClipBoxAdapter.ts index 21dea1a4..a6dd2cb0 100644 --- a/packages/studio/adapters/src/timeline/clip/AudioClipBoxAdapter.ts +++ b/packages/studio/adapters/src/timeline/clip/AudioClipBoxAdapter.ts @@ -2,8 +2,8 @@ import {ppqn, PPQN} from "@opendaw/lib-dsp" import { DefaultObservableValue, int, - Notifier, Maybe, + Notifier, ObservableValue, Observer, Option, diff --git a/packages/studio/adapters/src/timeline/clip/NoteClipBoxAdapter.ts b/packages/studio/adapters/src/timeline/clip/NoteClipBoxAdapter.ts index 7d4c5b69..d88dfbfd 100644 --- a/packages/studio/adapters/src/timeline/clip/NoteClipBoxAdapter.ts +++ b/packages/studio/adapters/src/timeline/clip/NoteClipBoxAdapter.ts @@ -1,8 +1,8 @@ import { DefaultObservableValue, int, - Notifier, Maybe, + Notifier, ObservableValue, Observer, Option, diff --git a/packages/studio/adapters/src/timeline/clip/ValueClipBoxAdapter.ts b/packages/studio/adapters/src/timeline/clip/ValueClipBoxAdapter.ts index 9e64d55b..2f4a9906 100644 --- a/packages/studio/adapters/src/timeline/clip/ValueClipBoxAdapter.ts +++ b/packages/studio/adapters/src/timeline/clip/ValueClipBoxAdapter.ts @@ -2,8 +2,8 @@ import {EventCollection, ppqn, PPQN} from "@opendaw/lib-dsp" import { DefaultObservableValue, int, - Notifier, Maybe, + Notifier, ObservableValue, Observer, Option, diff --git a/packages/studio/adapters/src/timeline/region/NoteRegionBoxAdapter.ts b/packages/studio/adapters/src/timeline/region/NoteRegionBoxAdapter.ts index a3be0242..89203d18 100644 --- a/packages/studio/adapters/src/timeline/region/NoteRegionBoxAdapter.ts +++ b/packages/studio/adapters/src/timeline/region/NoteRegionBoxAdapter.ts @@ -2,8 +2,8 @@ import {LoopableRegion, NoteEvent, ppqn, PPQN, RegionCollection} from "@opendaw/ import { Arrays, int, - Notifier, Maybe, + Notifier, Observer, Option, safeExecute, diff --git a/packages/studio/adapters/src/timeline/region/ValueRegionBoxAdapter.ts b/packages/studio/adapters/src/timeline/region/ValueRegionBoxAdapter.ts index d041bfec..a9e19933 100644 --- a/packages/studio/adapters/src/timeline/region/ValueRegionBoxAdapter.ts +++ b/packages/studio/adapters/src/timeline/region/ValueRegionBoxAdapter.ts @@ -2,8 +2,8 @@ import {EventCollection, LoopableRegion, ppqn, PPQN, RegionCollection} from "@op import { Arrays, int, - Notifier, Maybe, + Notifier, Observer, Option, safeExecute, diff --git a/packages/studio/boxes/.eslintrc.cjs b/packages/studio/boxes/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/studio/boxes/.eslintrc.cjs +++ b/packages/studio/boxes/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/studio/core-processors/.eslintrc.cjs b/packages/studio/core-processors/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/studio/core-processors/.eslintrc.cjs +++ b/packages/studio/core-processors/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/studio/core-processors/src/AudioDeviceChain.ts b/packages/studio/core-processors/src/AudioDeviceChain.ts index 5a3873be..c2b49cb1 100644 --- a/packages/studio/core-processors/src/AudioDeviceChain.ts +++ b/packages/studio/core-processors/src/AudioDeviceChain.ts @@ -1,9 +1,8 @@ import {Arrays, assert, SortedSet, Subscription, Terminator, UUID} from "@opendaw/lib-std" import {AuxSendProcessor} from "./AuxSendProcessor" import {ChannelStripProcessor} from "./ChannelStripProcessor" -import {AudioEffectDeviceAdapter} from "@opendaw/studio-adapters" +import {AudioEffectDeviceAdapter, AuxSendBoxAdapter} from "@opendaw/studio-adapters" import {AudioEffectDeviceProcessorFactory} from "./DeviceProcessorFactory" -import {AuxSendBoxAdapter} from "@opendaw/studio-adapters" import {ProcessPhase} from "./processing" import {AudioUnit} from "./AudioUnit" import {DeviceChain} from "./DeviceChain" diff --git a/packages/studio/core-processors/src/AutomatableParameter.ts b/packages/studio/core-processors/src/AutomatableParameter.ts index 7b5c3f10..546c0e58 100644 --- a/packages/studio/core-processors/src/AutomatableParameter.ts +++ b/packages/studio/core-processors/src/AutomatableParameter.ts @@ -1,6 +1,16 @@ import {PrimitiveValues} from "@opendaw/lib-box" import {AutomatableParameterFieldAdapter} from "@opendaw/studio-adapters" -import {assert, Notifier, Observer, Option, Subscription, Terminable, TerminableOwner, Terminator, unitValue} from "@opendaw/lib-std" +import { + assert, + Notifier, + Observer, + Option, + Subscription, + Terminable, + TerminableOwner, + Terminator, + unitValue +} from "@opendaw/lib-std" import {ppqn} from "@opendaw/lib-dsp" import {EngineContext} from "./EngineContext" diff --git a/packages/studio/core-processors/src/ClipSequencingAudioContext.ts b/packages/studio/core-processors/src/ClipSequencingAudioContext.ts index 2b8a1924..c5de664c 100644 --- a/packages/studio/core-processors/src/ClipSequencingAudioContext.ts +++ b/packages/studio/core-processors/src/ClipSequencingAudioContext.ts @@ -1,10 +1,13 @@ -import {AnyClipBoxAdapter} from "@opendaw/studio-adapters" +import { + AnyClipBoxAdapter, + ClipSequencing, + ClipSequencingUpdates, + Section, + TrackBoxAdapter +} from "@opendaw/studio-adapters" import {Arrays, identity, Option, quantizeFloor, SortedSet, UUID} from "@opendaw/lib-std" import {ppqn, PPQN} from "@opendaw/lib-dsp" -import {TrackBoxAdapter} from "@opendaw/studio-adapters" import {BoxGraph, Update} from "@opendaw/lib-box" -import {ClipSequencing, Section} from "@opendaw/studio-adapters" -import {ClipSequencingUpdates} from "@opendaw/studio-adapters" // Just convenient to identify which UUID is for which type type ClipKey = UUID.Bytes diff --git a/packages/studio/core-processors/src/InsertReturnAudioChain.ts b/packages/studio/core-processors/src/InsertReturnAudioChain.ts index 0704c322..101673fc 100644 --- a/packages/studio/core-processors/src/InsertReturnAudioChain.ts +++ b/packages/studio/core-processors/src/InsertReturnAudioChain.ts @@ -1,10 +1,9 @@ import {Arrays, assert, SortedSet, Subscription, Terminator, UUID} from "@opendaw/lib-std" -import {AudioEffectDeviceAdapter} from "@opendaw/studio-adapters" +import {AudioEffectDeviceAdapter, IndexedBoxAdapterCollection} from "@opendaw/studio-adapters" import {AudioEffectDeviceProcessorFactory} from "./DeviceProcessorFactory" import {AudioInput, ProcessPhase} from "./processing" import {DeviceChain} from "./DeviceChain" import {EngineContext} from "./EngineContext" -import {IndexedBoxAdapterCollection} from "@opendaw/studio-adapters" import {Pointers} from "@opendaw/studio-enums" import {DeviceProcessor} from "./DeviceProcessor" import {AudioDeviceProcessor} from "./AudioDeviceProcessor" diff --git a/packages/studio/core-processors/src/SampleManagerWorklet.ts b/packages/studio/core-processors/src/SampleManagerWorklet.ts index 440393d6..47771d85 100644 --- a/packages/studio/core-processors/src/SampleManagerWorklet.ts +++ b/packages/studio/core-processors/src/SampleManagerWorklet.ts @@ -1,5 +1,5 @@ import {Peaks} from "@opendaw/lib-fusion" -import {AudioData, EngineToClient, SampleLoader, SampleLoaderState, SampleLoaderManager} from "@opendaw/studio-adapters" +import {AudioData, EngineToClient, SampleLoader, SampleLoaderManager, SampleLoaderState} from "@opendaw/studio-adapters" import {Observer, Option, SortedSet, Subscription, Terminable, UUID} from "@opendaw/lib-std" class AudioLoaderWorklet implements SampleLoader { diff --git a/packages/studio/core-processors/src/UpdateClock.ts b/packages/studio/core-processors/src/UpdateClock.ts index dcbc4c01..f3575268 100644 --- a/packages/studio/core-processors/src/UpdateClock.ts +++ b/packages/studio/core-processors/src/UpdateClock.ts @@ -1,10 +1,9 @@ import {BlockFlag, ProcessInfo} from "./processing" -import {Event} from "@opendaw/lib-dsp" +import {Event, Fragmentor} from "@opendaw/lib-dsp" import {EngineContext} from "./EngineContext" import {Arrays, Bits, int, Terminable} from "@opendaw/lib-std" import {AbstractProcessor} from "./AbstractProcessor" import {EventBuffer} from "./EventBuffer" -import {Fragmentor} from "@opendaw/lib-dsp" import {UpdateClockRate} from "@opendaw/studio-adapters" export interface UpdateEvent extends Event {type: "update-event"} diff --git a/packages/studio/core-workers/.eslintrc.cjs b/packages/studio/core-workers/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/studio/core-workers/.eslintrc.cjs +++ b/packages/studio/core-workers/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/studio/core/.eslintrc.cjs b/packages/studio/core/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/studio/core/.eslintrc.cjs +++ b/packages/studio/core/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/studio/core/src/dawproject/todo.md b/packages/studio/core/src/dawproject/todo.md index da1b0837..f12b62d8 100644 --- a/packages/studio/core/src/dawproject/todo.md +++ b/packages/studio/core/src/dawproject/todo.md @@ -22,7 +22,7 @@ * ~~Map to new uuids (not when exporting)~~ * ~~Create the openDAW device if found~~ - * ~~Read preset~~ + * ~~Read preset~~ * Create automation * Read event-offset and import loop settings * ~~Auto-select the first audio-unit~~ \ No newline at end of file diff --git a/packages/studio/core/src/project/Project.md b/packages/studio/core/src/project/Project.md index bd86f64a..8e3827c7 100644 --- a/packages/studio/core/src/project/Project.md +++ b/packages/studio/core/src/project/Project.md @@ -14,8 +14,8 @@ - list used samples - SampleStorage - - list/store/load/delete samples - - per-sample files in OPFS + - list/store/load/delete samples + - per-sample files in OPFS - ProjectBundle (bundles metadata and samples) - encode/decode bundled projects diff --git a/packages/studio/core/vite-env.d.ts b/packages/studio/core/vite-env.d.ts index 1cf8f592..ac8ebb09 100644 --- a/packages/studio/core/vite-env.d.ts +++ b/packages/studio/core/vite-env.d.ts @@ -1,6 +1,6 @@ /// -declare module '*?url' { +declare module "*?url" { const url: string export default url } diff --git a/packages/studio/enums/.eslintrc.cjs b/packages/studio/enums/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/studio/enums/.eslintrc.cjs +++ b/packages/studio/enums/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/studio/forge-boxes/.eslintrc.cjs b/packages/studio/forge-boxes/.eslintrc.cjs index 471629b0..b05ce46b 100644 --- a/packages/studio/forge-boxes/.eslintrc.cjs +++ b/packages/studio/forge-boxes/.eslintrc.cjs @@ -1,10 +1,10 @@ /** @type {import("eslint").Linter.Config} */ module.exports = { - root: true, - ignorePatterns: [".eslintrc.cjs"], - extends: ["@opendaw/eslint-config/index.js"], - parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, + root: true, + ignorePatterns: [".eslintrc.cjs"], + extends: ["@opendaw/eslint-config/index.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, }; diff --git a/packages/studio/sdk/README.md b/packages/studio/sdk/README.md index cf8f163e..6ae66a5d 100644 --- a/packages/studio/sdk/README.md +++ b/packages/studio/sdk/README.md @@ -21,15 +21,16 @@ openDAW is available **under two alternative license terms**: -| Option | When to choose it | Obligations | -|-----------------------------|----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **A. AGPL v3 (or later)** | You are happy for the entire work that includes openDAW to be released under AGPL-compatible open-source terms. | – Must distribute complete corresponding source code under AGPL.
– Must keep copyright & licence notices.
– Applies both to distribution **and** to public use via network/SaaS (§13).
– May run openDAW privately in any software, open or closed (§0). | -| **B. Commercial Licence** | You wish to incorporate openDAW into **closed-source** or otherwise licence-incompatible software or SaaS offerings. | – Pay the agreed fee.
– No copyleft requirement for your own source code.
– Other terms as per the signed agreement. | +| Option | When to choose it | Obligations | +|---------------------------|----------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **A. AGPL v3 (or later)** | You are happy for the entire work that includes openDAW to be released under AGPL-compatible open-source terms. | – Must distribute complete corresponding source code under AGPL.
– Must keep copyright & licence notices.
– Applies both to distribution **and** to public use via network/SaaS (§13).
– May run openDAW privately in any software, open or closed (§0). | +| **B. Commercial Licence** | You wish to incorporate openDAW into **closed-source** or otherwise licence-incompatible software or SaaS offerings. | – Pay the agreed fee.
– No copyleft requirement for your own source code.
– Other terms as per the signed agreement. | > **How to obtain the Commercial License** > Email `andre.michelle@opendaw.org` with your company name, product description, and expected distribution volume. -If you redistribute or run modified versions of openDAW for public use **without** a commercial license, the AGPL v3 terms apply automatically. +If you redistribute or run modified versions of openDAW for public use **without** a commercial license, the AGPL v3 +terms apply automatically. ## License