diff --git a/package.json b/package.json index 60cf6e388..3f8b2bc94 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "eslint-plugin-prettier": "^4.2.1", "prettier": "^2.8.7", "rollup": "^3.26.2", + "rollup-plugin-dts": "^6.1.0", "typescript": "^5.0.4" } } diff --git a/rollup.config.js b/rollup.config.js index 8c0d9898d..66b725797 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,7 @@ import glob from 'glob' import typescript from '@rollup/plugin-typescript' import terser from '@rollup/plugin-terser' +import dts from 'rollup-plugin-dts' const plugins = [typescript(), terser()] @@ -36,6 +37,13 @@ export default [ plugins, }, + // Compiled type definitions + { + input: './dist/wavesurfer.d.ts', + output: [{ file: 'dist/types.d.ts', format: 'es' }], + plugins: [dts()], + }, + // Wavesurfer plugins ...glob .sync('src/plugins/*.ts') diff --git a/src/base-plugin.ts b/src/base-plugin.ts index c0414a40e..22762762f 100644 --- a/src/base-plugin.ts +++ b/src/base-plugin.ts @@ -7,27 +7,31 @@ export type BasePluginEvents = { export type GenericPlugin = BasePlugin +/** Base class for wavesurfer plugins */ export class BasePlugin extends EventEmitter { protected wavesurfer?: WaveSurfer protected subscriptions: (() => void)[] = [] protected options: Options + /** Create a plugin instance */ constructor(options: Options) { super() this.options = options } - onInit() { - // Overridden in plugin definition + /** Called after this.wavesurfer is available */ + protected onInit() { return } - init(wavesurfer: WaveSurfer) { + /** Do not call directly, only called by WavesSurfer internally */ + public _init(wavesurfer: WaveSurfer) { this.wavesurfer = wavesurfer this.onInit() } - destroy() { + /** Destroy the plugin and unsubscribe from all events */ + public destroy() { this.emit('destroy') this.subscriptions.forEach((unsubscribe) => unsubscribe()) } diff --git a/src/event-emitter.ts b/src/event-emitter.ts index f3ab3d820..f148dfd43 100644 --- a/src/event-emitter.ts +++ b/src/event-emitter.ts @@ -16,8 +16,8 @@ type EventMap = { class EventEmitter { private listeners = {} as EventMap - /** Add an event listener */ - public addEventListener( + /** Subscribe to an event. Returns an unsubscribe function. */ + public on( event: EventName, listener: EventListener, options?: { once?: boolean }, @@ -29,29 +29,24 @@ class EventEmitter { if (options?.once) { const unsubscribeOnce = () => { - this.removeEventListener(event, unsubscribeOnce) - this.removeEventListener(event, listener) + this.un(event, unsubscribeOnce) + this.un(event, listener) } - this.addEventListener(event, unsubscribeOnce) + this.on(event, unsubscribeOnce) return unsubscribeOnce } - return () => this.removeEventListener(event, listener) + return () => this.un(event, listener) } - public removeEventListener( + /** Unsubscribe from an event */ + public un( event: EventName, listener: EventListener, ): void { this.listeners[event]?.delete(listener) } - /** Subscribe to an event. Returns an unsubscribe function. */ - public on = this.addEventListener - - /** Unsubscribe from an event */ - public un = this.removeEventListener - /** Subscribe to an event only once */ public once( event: EventName, diff --git a/src/wavesurfer.ts b/src/wavesurfer.ts index 4d8368c37..6e660f05d 100644 --- a/src/wavesurfer.ts +++ b/src/wavesurfer.ts @@ -304,7 +304,7 @@ class WaveSurfer extends Player { /** Register a wavesurfer.js plugin */ public registerPlugin(plugin: T): T { - plugin.init(this) + plugin._init(this) this.plugins.push(plugin) // Unregister plugin on destroy diff --git a/src/webaudio.ts b/src/webaudio.ts index ad9bb71a8..2b807b47d 100644 --- a/src/webaudio.ts +++ b/src/webaudio.ts @@ -35,6 +35,12 @@ class WebAudioPlayer extends EventEmitter { this.gainNode.connect(this.audioContext.destination) } + /** Subscribe to an event. Returns an unsubscribe function. */ + addEventListener = this.on + + /** Unsubscribe from an event */ + removeEventListener = this.un + async load() { return } @@ -175,6 +181,17 @@ class WebAudioPlayer extends EventEmitter { public getGainNode(): GainNode { return this.gainNode } + + /** Get decoded audio */ + public getChannelData(): Float32Array[] { + const channels: Float32Array[] = [] + if (!this.buffer) return channels + const numChannels = this.buffer.numberOfChannels + for (let i = 0; i < numChannels; i++) { + channels.push(this.buffer.getChannelData(i)) + } + return channels + } } export default WebAudioPlayer diff --git a/yarn.lock b/yarn.lock index 1fad7d9ae..50f30c627 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,28 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== +"@babel/code-frame@^7.22.13": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -122,7 +144,7 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -548,7 +570,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.4.1: +chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1492,6 +1514,11 @@ jest-image-snapshot@4.2.0: rimraf "^2.6.2" ssim.js "^3.1.1" +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -1644,6 +1671,13 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +magic-string@^0.30.4: + version "0.30.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" + integrity sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -2045,6 +2079,15 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup-plugin-dts@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-6.1.0.tgz#56e9c5548dac717213c6a4aa9df523faf04f75ae" + integrity sha512-ijSCPICkRMDKDLBK9torss07+8dl9UpY9z1N/zTeA1cIqdzMlpkV3MOOC7zukyvQfDyxa1s3Dl2+DeiP/G6DOw== + dependencies: + magic-string "^0.30.4" + optionalDependencies: + "@babel/code-frame" "^7.22.13" + rollup@^3.26.2: version "3.29.4" resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981"