1 import * as Channel from 'jschannel'
2 import { EventRegistrar } from './events'
3 import { EventHandler, PlayerEventType, PeerTubeResolution } from './definitions'
5 const PASSTHROUGH_EVENTS = [
7 'playbackStatusUpdate',
8 'playbackStatusChange',
13 * Allows for programmatic control of a PeerTube embed running in an <iframe>
16 export class PeerTubePlayer {
18 * Construct a new PeerTubePlayer for the given PeerTube embed iframe.
19 * Optionally provide a `scope` to ensure that messages are not crossed
20 * between multiple PeerTube embeds. The string passed here must match the
21 * `scope=` query parameter on the embed URL.
27 private embedElement : HTMLIFrameElement,
28 private scope? : string
30 this.eventRegistrar.registerTypes(PASSTHROUGH_EVENTS)
32 this.constructChannel()
33 this.prepareToBeReady()
36 private eventRegistrar : EventRegistrar = new EventRegistrar()
37 private channel : Channel.MessagingChannel
38 private readyPromise : Promise<void>
41 * Destroy the player object and remove the associated player from the DOM.
44 this.embedElement.remove()
48 * Listen to an event emitted by this player.
50 * @param event One of the supported event types
51 * @param handler A handler which will be passed an event object (or undefined if no event object is included)
53 addEventListener(event : PlayerEventType, handler : EventHandler<any>): boolean {
54 return this.eventRegistrar.addListener(event, handler)
58 * Remove an event listener previously added with addEventListener().
60 * @param event The name of the event previously listened to
63 removeEventListener(event : PlayerEventType, handler : EventHandler<any>): boolean {
64 return this.eventRegistrar.removeListener(event, handler)
68 * Promise resolves when the player is ready.
70 get ready(): Promise<void> {
71 return this.readyPromise
75 * Tell the embed to start/resume playback
78 await this.sendMessage('play')
82 * Tell the embed to pause playback.
85 await this.sendMessage('pause')
89 * Tell the embed to change the audio volume
90 * @param value A number from 0 to 1
92 async setVolume(value : number) {
93 await this.sendMessage('setVolume', value)
97 * Get the current volume level in the embed.
98 * @param value A number from 0 to 1
100 async getVolume(): Promise<number> {
101 return await this.sendMessage<void, number>('setVolume')
105 * Tell the embed to seek to a specific position (in seconds)
108 async seek(seconds : number) {
109 await this.sendMessage('seek', seconds)
113 * Tell the embed to switch resolutions to the resolution identified
116 * @param resolutionId The ID of the resolution as found with getResolutions()
118 async setResolution(resolutionId : any) {
119 await this.sendMessage('setResolution', resolutionId)
123 * Retrieve a list of the available resolutions. This may change later, listen to the
124 * `resolutionUpdate` event with `addEventListener` in order to be updated as the available
125 * resolutions change.
127 async getResolutions(): Promise<PeerTubeResolution[]> {
128 return await this.sendMessage<void, PeerTubeResolution[]>('getResolutions')
132 * Retrieve a list of available playback rates.
134 async getPlaybackRates() : Promise<number[]> {
135 return await this.sendMessage<void, number[]>('getPlaybackRates')
139 * Get the current playback rate. Defaults to 1 (1x playback rate).
141 async getPlaybackRate() : Promise<number> {
142 return await this.sendMessage<void, number>('getPlaybackRate')
146 * Set the playback rate. Should be one of the options returned by getPlaybackRates().
147 * Passing 0.5 means half speed, 1 means normal, 2 means 2x speed, etc.
151 async setPlaybackRate(rate : number) {
152 await this.sendMessage('setPlaybackRate', rate)
155 private constructChannel() {
156 this.channel = Channel.build({
157 window: this.embedElement.contentWindow,
159 scope: this.scope || 'peertube'
161 this.eventRegistrar.bindToChannel(this.channel)
164 private prepareToBeReady() {
165 let readyResolve, readyReject
166 this.readyPromise = new Promise<void>((res, rej) => {
171 this.channel.bind('ready', success => success ? readyResolve() : readyReject())
174 success: isReady => isReady ? readyResolve() : null
178 private sendMessage<TIn, TOut>(method : string, params? : TIn): Promise<TOut> {
179 return new Promise<TOut>((resolve, reject) => {
182 success: result => resolve(result),
183 error: error => reject(error)
189 // put it on the window as well as the export
190 window['PeerTubePlayer'] = PeerTubePlayer