Skip to content

Commit

Permalink
✨ Add event constants
Browse files Browse the repository at this point in the history
It is better practice to identify events with constants instead of
string literals.
  • Loading branch information
clabe45 committed Jan 6, 2023
1 parent 3e6fa59 commit 6ac91e1
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 37 deletions.
11 changes: 6 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added
- `Movie#stream()` to start streaming the movie to a `MediaStream`.
- `Movie#getStream()` to get the current `MediaStream`.
- Event constants (e.g. `Movie.Event.PLAY`).
- Image and video layers' `source` properties now accept urls ([#153](https://github.com/etro-js/etro/pull/153)).
- Movies, layers and effects have a new `ready` getter, indicating if they are ready to play.
- `'ready'` event, published when the movie, layer or effect is ready to play.
- `once` option for `subscribe`.

### Changed
- Events are no longer prefixed with `'movie.'`, `'layer.'` or `'effect.'`.
- `'pause'` event is now published every time playback stops, regardless of the reason.
- `Movie.Event.PAUSE` is now published every time playback stops, regardless of the reason.

### Deprecated
- `etro.applyOptions()` and `EtroObject#getDefaultOptions()` are deprecated. Instead, set each option in the constructor ([#131](https://github.com/etro-js/etro/issues/131)).
- Events starting with `'movie.'`, `'layer.'` or `'effect.'` are deprecated. Use the unprefixed events instead.
- The `'movie.loadeddata'` event is deprecated. Consider using `'ready'` instead.
- `'movie.record'` and `'movie.recordended'` events are deprecated. Use `'play'` and `'pause'` instead.
- The `'movie.ended'` event is deprecated. Use `'end'` instead.
- Events starting with `'movie.'`, `'layer.'` or `'effect.'` are deprecated. Use the unprefixed event names or the new event constants instead.
- The `'movie.loadeddata'` event is deprecated. Consider using `Movie.Event.READY` instead.
- `'movie.record'` and `'movie.recordended'` events are deprecated. Use `Movie.Event.PLAY` and `Movie.Event.PAUSE` instead.
- The `'movie.ended'` event is deprecated. Use `Movie.Event.END` instead.

### Removed
- `Movie#autoRefresh` (see [#130](https://github.com/etro-js/etro/issues/130)).
Expand Down
9 changes: 9 additions & 0 deletions src/effect/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import BaseObject from '../object'
* @deprecated All visual effects now inherit from `Visual` instead
*/
export class Base implements BaseObject {
static readonly Event = {
/**
* Fired when the effect is ready to be applied
*
* @event
*/
READY: 'ready'
}

type: string
publicExcludes: string[]
propertyFilters: Record<string, <T>(value: T) => T>
Expand Down
4 changes: 2 additions & 2 deletions src/layer/audio-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ class AudioSource extends Base {
attach (movie: Movie) {
super.attach(movie)

subscribe(movie, 'seek', () => {
subscribe(movie, Movie.Event.SEEK, () => {
if (this.currentTime < 0 || this.currentTime >= this.duration)
return

this.source.currentTime = this.currentTime + this.sourceStartTime
})

// TODO: on unattach?
subscribe(movie, 'audiodestinationupdate', event => {
subscribe(movie, Movie.Event.AUDIO_DESTINATION_UPDATE, event => {
// Connect to new destination if immediately connected to the existing
// destination.
if (this._connectedToDestination) {
Expand Down
2 changes: 1 addition & 1 deletion src/layer/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Audio extends AudioSource {
this.source.addEventListener('loadeddata', () => {
// Make sure all superclasses are ready
if (this.ready)
publish(this, 'ready', {})
publish(this, Audio.Event.READY, {})
})

if (this.duration === undefined)
Expand Down
9 changes: 9 additions & 0 deletions src/layer/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ interface BaseOptions {
* A layer outputs content for the movie
*/
class Base implements EtroObject {
static readonly Event = {
/**
* Fired when the layer is ready to render
*
* @event
*/
READY: 'ready'
}

type: string
publicExcludes: string[]
propertyFilters: Record<string, <T>(value: T) => T>
Expand Down
2 changes: 1 addition & 1 deletion src/layer/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Image extends VisualSource {
this.source.addEventListener('load', () => {
// Make sure all superclasses are ready
if (this.ready)
publish(this, 'ready', {})
publish(this, Image.Event.READY, {})
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/layer/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Video extends Mixin(VisualSource, AudioSource) {
this.source.addEventListener('loadeddata', () => {
// Make sure all superclasses are ready
if (this.ready)
publish(this, 'ready', {})
publish(this, Video.Event.READY, {})
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/layer/visual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class VisualEffectsListener extends CustomArrayListener<VisualEffect> {

// Emit a layer.ready event whenever the effect is ready (as long as the
// layer is too).
subscribe(effect, 'ready', () => {
subscribe(effect, VisualEffect.Event.READY, () => {
this._checkReady()
})
}
Expand Down Expand Up @@ -174,7 +174,7 @@ class Visual extends Base {

private _checkReady () {
if (this.ready && this.publishReadyEvent) {
publish(this, 'ready', {})
publish(this, Visual.Event.READY, {})
this.publishReadyEvent = false
} else if (!this.ready) {
this.publishReadyEvent = true
Expand Down
2 changes: 1 addition & 1 deletion src/movie/effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class MovieEffectsListener extends CustomArrayListener<VisualEffect> {

// Emit a movie.ready event whenever the effect is ready (as long as the
// movie is too).
subscribe(effect, 'ready', () => {
subscribe(effect, VisualEffect.Event.READY, () => {
if (effect.parent !== this._movie)
return

Expand Down
2 changes: 1 addition & 1 deletion src/movie/layers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class MovieLayersListener extends CustomArrayListener<BaseLayer> {
this._checkReady()

// Update internal ready state when the layer is ready
subscribe(layer, 'ready', () => {
subscribe(layer, BaseLayer.Event.READY, () => {
if (layer.parent !== this._movie)
return

Expand Down
97 changes: 74 additions & 23 deletions src/movie/movie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@ declare global {
}
}

deprecate('movie.ended', 'end')
deprecate('movie.loadeddata', undefined, "Consider using the `'ready'` event instead.")
deprecate('movie.pause', 'pause')
deprecate('movie.play', 'play')
deprecate('movie.record', undefined, "Consider using the `'play'` event instead.")
deprecate('movie.recordended', undefined, "Consider using the `'pause'` event instead.")
deprecate('movie.seek', 'seek')
deprecate('movie.timeupdate', 'timeupdate')

export class MovieOptions {
/** The html canvas element to use for playback */
canvas: HTMLCanvasElement
Expand All @@ -49,6 +40,57 @@ export class MovieOptions {
// it's recording
// TODO: rename renderingFrame -> refreshing
export class Movie {
static readonly Event = {
/**
* Fired when `currentTime` skips to a new position.
*
* @event
*/
SEEK: 'seek',

/**
* Fired when `currentTime` changes due to playback.
*
* @event
*/
TIME_UPDATE: 'timeupdate',

/**
* Fired when the movie is ready to play.
*
* @event
*/
READY: 'ready',

/**
* Fired when the movie is played.
*
* @event
*/
PLAY: 'play',

/**
* Fired when the movie is paused.
*
* @event
*/
PAUSE: 'pause',

/**
* Fired when the end of the movie is reached.
*
* @event
*/
END: 'end',

/**
* Fired when the destination of `actx` is changed.
*
* @event
*/
AUDIO_DESTINATION_UPDATE: 'audiodestinationupdate'
}

type: string
/**
* @deprecated Auto-refresh will be removed in the future. If you want to
Expand Down Expand Up @@ -129,7 +171,7 @@ export class Movie {
// this._lastUpdate = -1;

// Stop recording when the movie is paused
subscribe(this, 'pause', () => {
subscribe(this, Movie.Event.PAUSE, () => {
if (this.recording) {
this._mediaRecorder.requestData()
this._mediaRecorder.stop()
Expand All @@ -142,7 +184,7 @@ export class Movie {
if (this.ready)
resolve()
else
subscribe(this, 'ready', () => {
subscribe(this, Movie.Event.READY, () => {
resolve()
}, { once: true })
})
Expand All @@ -162,7 +204,7 @@ export class Movie {
this._lastPlayed = performance.now()
this._lastPlayedOffset = this.currentTime

publish(this, 'play', {})
publish(this, Movie.Event.PLAY, {})

await new Promise<void>(resolve => {
if (!this.renderingFrame)
Expand All @@ -183,7 +225,7 @@ export class Movie {
this._canvas = this._visibleCanvas
this._cctx = this.canvas.getContext('2d')

publish(this, 'audiodestinationupdate',
publish(this, Movie.Event.AUDIO_DESTINATION_UPDATE,
{ movie: this, destination: this.actx.destination }
)
}
Expand Down Expand Up @@ -244,7 +286,7 @@ export class Movie {
tracks = tracks.concat(audioStream.getTracks())

// Notify layers and any other listeners of the new audio destination
publish(this, 'audiodestinationupdate',
publish(this, Movie.Event.AUDIO_DESTINATION_UPDATE,
{ movie: this, destination: audioDestination }
)
}
Expand Down Expand Up @@ -279,7 +321,7 @@ export class Movie {

// Wait for playback to start. The stream will be available then.
return await new Promise(resolve => {
subscribe(this, 'play', () => {
subscribe(this, Movie.Event.PLAY, () => {
resolve(this._currentStream)
}, { once: true })
})
Expand Down Expand Up @@ -376,7 +418,7 @@ export class Movie {
layer.active = false
}

publish(this, 'pause', {})
publish(this, Movie.Event.PAUSE, {})
return this
}

Expand Down Expand Up @@ -424,13 +466,13 @@ export class Movie {
publish(this, 'recordended', { movie: this })

if (this.currentTime === this.duration)
publish(this, 'end', { movie: this, repeat: this.repeat })
publish(this, Movie.Event.END, { movie: this, repeat: this.repeat })

if (this.repeat) {
// Don't use setter, which publishes 'seek'. Instead, update the
// value and publish a 'imeupdate' event.
this._currentTime = 0
publish(this, 'timeupdate', { movie: this })
publish(this, Movie.Event.TIME_UPDATE, { movie: this })
}

this._lastPlayed = performance.now()
Expand All @@ -455,7 +497,7 @@ export class Movie {
layer.active = false
}

publish(this, 'pause', {})
publish(this, Movie.Event.PAUSE, {})

if (done)
done()
Expand Down Expand Up @@ -501,7 +543,7 @@ export class Movie {
const currentTime = this._lastPlayedOffset + sinceLastPlayed // don't use setter
if (this.currentTime !== currentTime) {
this._currentTime = currentTime
publish(this, 'timeupdate', { movie: this })
publish(this, Movie.Event.TIME_UPDATE, { movie: this })
}
// this._lastUpdate = timestamp;
// }
Expand Down Expand Up @@ -684,7 +726,7 @@ export class Movie {
*/
set currentTime (time: number) {
this._currentTime = time
publish(this, 'seek', {})
publish(this, Movie.Event.SEEK, {})
}

/**
Expand All @@ -700,7 +742,7 @@ export class Movie {
setCurrentTime (time: number, refresh = true): Promise<void> {
return new Promise((resolve, reject) => {
this._currentTime = time
publish(this, 'seek', {})
publish(this, Movie.Event.SEEK, {})
if (refresh)
// Pass promise callbacks to `refresh`
this.refresh().then(resolve).catch(reject)
Expand All @@ -711,7 +753,7 @@ export class Movie {

private _checkReady () {
if (this.ready && this._publishReadyEvent) {
publish(this, 'ready', {})
publish(this, Movie.Event.READY, {})
this._publishReadyEvent = false
} else if (!this.ready) {
this._publishReadyEvent = true
Expand Down Expand Up @@ -792,3 +834,12 @@ export class Movie {
// Id for events
Movie.prototype.type = 'movie'
Movie.prototype.propertyFilters = {}

deprecate('movie.ended', Movie.Event.END)
deprecate('movie.loadeddata', undefined, 'Consider using `Movie.Events.READY` instead.')
deprecate('movie.pause', Movie.Event.PAUSE)
deprecate('movie.play', Movie.Event.PLAY)
deprecate('movie.record', undefined, 'Consider using `Movie.Events.PLAY` instead.')
deprecate('movie.recordended', undefined, 'Consider using `Movie.Events.PAUSE` instead.')
deprecate('movie.seek', Movie.Event.SEEK)
deprecate('movie.timeupdate', Movie.Event.TIME_UPDATE)

0 comments on commit 6ac91e1

Please sign in to comment.