diff --git a/packages/webamp-docs/docs/06_API/00_entrypoints.md b/packages/webamp-docs/docs/06_API/00_entrypoints.md index 697f9491..aacf7f7e 100644 --- a/packages/webamp-docs/docs/06_API/00_entrypoints.md +++ b/packages/webamp-docs/docs/06_API/00_entrypoints.md @@ -6,7 +6,7 @@ All bundles are minified ES modules with provided TypeScript types. For examples The main bundles are exposed as the following [package entrypoints](https://nodejs.org/api/packages.html#package-entry-points): -# `webamp/butterchurn` +## `webamp/butterchurn` **Since** [v2.2.0](../12_changelog.md#220) @@ -20,7 +20,7 @@ This all-inclusive minified bundle has everything you need to enable all Webamp import Webamp from "webamp/butterchurn"; ``` -# `webamp/lazy` +## `webamp/lazy` :::warning Using this entrypoint requires that you have a rather sophisticated bundler setup. @@ -38,7 +38,7 @@ import Webamp from "webamp/lazy"; For instructions on how to use this entrypoint, see the [Bundle Size Guide](../07_guides/03_bundle-size.md). -# `webamp` +## `webamp` :::warning In a future version of Webamp, this entrypoint will become an alias of `webamp/butterchurn`. diff --git a/packages/webamp-docs/docs/06_API/02_webamp-constructor.md b/packages/webamp-docs/docs/06_API/02_webamp-constructor.md index 9c082ceb..23d15adb 100644 --- a/packages/webamp-docs/docs/06_API/02_webamp-constructor.md +++ b/packages/webamp-docs/docs/06_API/02_webamp-constructor.md @@ -254,3 +254,15 @@ const webamp = new Webamp({ // ...other config options }); ``` + +### `requireButterchurnPresets?: () => Promise` + +**Since** [unreleased](../12_changelog.md#unreleased) + +Milkdrop (Butterchurn) presets to be used. If not specified, the default presets +included in the bundle will be used. + +Presets are expected to be in Butterchurn's JSON format. You can find these `.json` files in: + +- The [Milkdrop Presets Collection](https://archive.org/details/milkdrops) at the Internet Archive. +- The [`butterchurn-presets@3.0.0-beta.4`](https://www.npmjs.com/package/butterchurn-presets/v/3.0.0-beta.4) NPM package diff --git a/packages/webamp-docs/docs/12_changelog.md b/packages/webamp-docs/docs/12_changelog.md index 7f9d31de..bacb1d55 100644 --- a/packages/webamp-docs/docs/12_changelog.md +++ b/packages/webamp-docs/docs/12_changelog.md @@ -1,12 +1,16 @@ # Changelog - +::: + +### Improvements + +- Added new [`requireButterchurnPresets`](./06_API/02_webamp-constructor.md#requirebutterchurnpresets---promisepreset) option when constructing a Webamp instance. This allows you to specify which Butterchurn presets to use for the Milkdrop visualizer. If you don't specify this option, Webamp will use the default Butterchurn presets. ## 2.2.0 diff --git a/packages/webamp/js/types.ts b/packages/webamp/js/types.ts index 802becc6..03f77d15 100644 --- a/packages/webamp/js/types.ts +++ b/packages/webamp/js/types.ts @@ -741,6 +741,18 @@ export interface Options { * https://developer.mozilla.org/en-US/docs/Web/API/Media_Session_API */ enableMediaSession?: boolean; + + /** + * Milkdrop (Butterchurn) presets to be used. If not specified, the default presets + * included in the bundle will be used. + * + * Presets are expected to be in Butterchurn's JSON format. You can find these + * `.json` files in: + * + * * The [Milkdrop Presets Collection](https://archive.org/details/milkdrops) at the Internet Archive. + * * The `butterchurn-presets@3.0.0-beta.4` NPM package + */ + requireButterchurnPresets?: () => Promise; } /** diff --git a/packages/webamp/js/webampLazy.tsx b/packages/webamp/js/webampLazy.tsx index 81ce91ec..2078e514 100644 --- a/packages/webamp/js/webampLazy.tsx +++ b/packages/webamp/js/webampLazy.tsx @@ -16,6 +16,7 @@ import { PlaylistTrack, PlayerMediaStatus, IMetadataApi, + Preset, } from "./types"; import getStore from "./store"; import App from "./components/App"; @@ -44,6 +45,7 @@ export interface PrivateOptions { export interface InjectableDependencies { requireJSZip: () => Promise; requireMusicMetadata: () => Promise; + requireButterchurnPresets?: () => Promise; } class Webamp { @@ -51,7 +53,9 @@ class Webamp { _actionEmitter: Emitter; _root: ReactDOM.Root | null; _disposable: Disposable; - options: Options & PrivateOptions & InjectableDependencies; // TODO: Make this _private + // TODO: Make this _private + options: Options & PrivateOptions & InjectableDependencies; + media: IMedia; // TODO: Make this _private store: Store; // TODO: Make this _private @@ -84,6 +88,7 @@ class Webamp { zIndex, requireJSZip, requireMusicMetadata, + requireButterchurnPresets, handleTrackDropEvent, handleAddUrlEvent, handleLoadListEvent, @@ -93,11 +98,22 @@ class Webamp { __customMediaClass, } = this.options; + const butterchurnOptions = __butterchurnOptions; + + if (requireButterchurnPresets != null) { + if (butterchurnOptions == null) { + throw new Error( + "You must pass `__butterchurnOptions` if you are using `requireButterchurnPresets`." + ); + } + butterchurnOptions.getPresets = requireButterchurnPresets; + } + // TODO: Make this much cleaner. let convertPreset = null; - if (__butterchurnOptions != null) { + if (butterchurnOptions != null) { const { importConvertPreset, presetConverterEndpoint } = - __butterchurnOptions; + butterchurnOptions; if (importConvertPreset != null && presetConverterEndpoint != null) { convertPreset = async (file: File): Promise => { @@ -148,14 +164,12 @@ class Webamp { this.store.dispatch({ type: "SET_Z_INDEX", zIndex }); } - if (options.__butterchurnOptions) { + if (butterchurnOptions) { this.store.dispatch({ type: "ENABLE_MILKDROP", - open: options.__butterchurnOptions.butterchurnOpen, + open: butterchurnOptions.butterchurnOpen, }); - this.store.dispatch( - Actions.initializePresets(options.__butterchurnOptions) - ); + this.store.dispatch(Actions.initializePresets(butterchurnOptions)); } const handleOnline = () => diff --git a/packages/webamp/js/webampWithButterchurn.ts b/packages/webamp/js/webampWithButterchurn.ts index a327a094..10ef253e 100644 --- a/packages/webamp/js/webampWithButterchurn.ts +++ b/packages/webamp/js/webampWithButterchurn.ts @@ -1,4 +1,4 @@ -import { Options } from "./types"; +import { Options, Preset } from "./types"; import { PrivateOptions } from "./webampLazy"; import Webamp from "./webamp"; // @ts-ignore @@ -19,18 +19,23 @@ const DEFAULT_BUTTERCHURN_WINDOW_LAYOUT = { }, }; +const DEFAULT_REQUIRE_BUTTERCHURN_PRESETS = async () => + Object.entries(butterchurnPresets).map(([name, preset]) => { + return { name, butterchurnPresetObject: preset as Object }; + }); + export default class WebampWithButterchurn extends Webamp { constructor(options: Options & PrivateOptions) { + const requireButterchurnPresets = + options.requireButterchurnPresets ?? DEFAULT_REQUIRE_BUTTERCHURN_PRESETS; super({ ...options, + requireButterchurnPresets, __butterchurnOptions: { importButterchurn: () => Promise.resolve(butterchurn), - // @ts-ignore - getPresets: () => { - return Object.entries(butterchurnPresets).map(([name, preset]) => { - return { name, butterchurnPresetObject: preset }; - }); - }, + // This should be considered deprecated, and users should instead supply + // the top level `requireButterchurnPresets` option. + getPresets: requireButterchurnPresets, butterchurnOpen: true, }, windowLayout: options.windowLayout ?? DEFAULT_BUTTERCHURN_WINDOW_LAYOUT,