]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/standalone/videos/embed-api.ts
Migrate client to eslint
[github/Chocobozzz/PeerTube.git] / client / src / standalone / videos / embed-api.ts
CommitLineData
5efab546
C
1import './embed.scss'
2
3import * as Channel from 'jschannel'
1151f521 4import { PeerTubeResolution, PeerTubeTextTrack } from '../player/definitions'
5efab546
C
5import { PeerTubeEmbed } from './embed'
6
7/**
8 * Embed API exposes control of the embed player to the outside world via
9 * JSChannels and window.postMessage
10 */
11export class PeerTubeEmbedApi {
12 private channel: Channel.MessagingChannel
13 private isReady = false
6377a9f2 14 private resolutions: PeerTubeResolution[] = []
5efab546 15
9df52d66
C
16 constructor (private readonly embed: PeerTubeEmbed) {
17
5efab546
C
18 }
19
20 initialize () {
21 this.constructChannel()
22 this.setupStateTracking()
23
24 // We're ready!
25
26 this.notifyReady()
27 }
28
29 private get element () {
5abc96fc 30 return this.embed.playerElement
5efab546
C
31 }
32
33 private constructChannel () {
34 const channel = Channel.build({ window: window.parent, origin: '*', scope: this.embed.scope })
35
36 channel.bind('play', (txn, params) => this.embed.player.play())
37 channel.bind('pause', (txn, params) => this.embed.player.pause())
38 channel.bind('seek', (txn, time) => this.embed.player.currentTime(time))
6377a9f2 39
5efab546
C
40 channel.bind('setVolume', (txn, value) => this.embed.player.volume(value))
41 channel.bind('getVolume', (txn, value) => this.embed.player.volume())
6377a9f2 42
5efab546 43 channel.bind('isReady', (txn, params) => this.isReady)
6377a9f2 44
5efab546
C
45 channel.bind('setResolution', (txn, resolutionId) => this.setResolution(resolutionId))
46 channel.bind('getResolutions', (txn, params) => this.resolutions)
6377a9f2 47
1151f521 48 channel.bind('getCaptions', (txn, params) => this.getCaptions())
9df52d66 49 channel.bind('setCaption', (txn, id) => this.setCaption(id))
1151f521 50
5efab546
C
51 channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate))
52 channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate())
6377a9f2 53 channel.bind('getPlaybackRates', (txn, params) => this.embed.player.options_.playbackRates)
9054a8b6
C
54
55 channel.bind('playNextVideo', (txn, params) => this.embed.playNextVideo())
56 channel.bind('playPreviousVideo', (txn, params) => this.embed.playPreviousVideo())
57 channel.bind('getCurrentPosition', (txn, params) => this.embed.getCurrentPosition())
5efab546
C
58 this.channel = channel
59 }
60
61 private setResolution (resolutionId: number) {
6377a9f2
C
62 console.log('set resolution %d', resolutionId)
63
64 if (this.isWebtorrent()) {
65 if (resolutionId === -1 && this.embed.player.webtorrent().isAutoResolutionPossible() === false) return
66
67 // Auto resolution
68 if (resolutionId === -1) {
69 this.embed.player.webtorrent().enableAutoResolution()
70 return
71 }
72
73 this.embed.player.webtorrent().disableAutoResolution()
74 this.embed.player.webtorrent().updateResolution(resolutionId)
5efab546 75
5efab546
C
76 return
77 }
78
6377a9f2 79 this.embed.player.p2pMediaLoader().getHLSJS().nextLevel = resolutionId
5efab546
C
80 }
81
1151f521 82 private getCaptions (): PeerTubeTextTrack[] {
9df52d66
C
83 return this.embed.player.textTracks().tracks_.map(t => ({
84 id: t.id,
85 src: t.src,
86 label: t.label,
87 mode: t.mode
88 }))
1151f521
C
89 }
90
91 private setCaption (id: string) {
92 const tracks = this.embed.player.textTracks().tracks_
93
94 for (const track of tracks) {
95 if (track.id === id) track.mode = 'showing'
96 else track.mode = 'disabled'
97 }
98 }
99
5efab546
C
100 /**
101 * Let the host know that we're ready to go!
102 */
103 private notifyReady () {
104 this.isReady = true
105 this.channel.notify({ method: 'ready', params: true })
106 }
107
108 private setupStateTracking () {
96aae68c 109 let currentState: 'playing' | 'paused' | 'unstarted' | 'ended' = 'unstarted'
5efab546
C
110
111 setInterval(() => {
112 const position = this.element.currentTime
113 const volume = this.element.volume
114
115 this.channel.notify({
116 method: 'playbackStatusUpdate',
117 params: {
118 position,
119 volume,
6ccdf9d5 120 duration: this.embed.player.duration(),
5efab546
C
121 playbackState: currentState
122 }
123 })
124 }, 500)
125
126 this.element.addEventListener('play', ev => {
127 currentState = 'playing'
128 this.channel.notify({ method: 'playbackStatusChange', params: 'playing' })
129 })
130
131 this.element.addEventListener('pause', ev => {
132 currentState = 'paused'
133 this.channel.notify({ method: 'playbackStatusChange', params: 'paused' })
134 })
135
96aae68c
C
136 this.element.addEventListener('ended', ev => {
137 currentState = 'ended'
138 this.channel.notify({ method: 'playbackStatusChange', params: 'ended' })
139 })
140
5efab546 141 // PeerTube specific capabilities
6377a9f2 142 if (this.isWebtorrent()) {
5efab546
C
143 this.embed.player.webtorrent().on('autoResolutionUpdate', () => this.loadWebTorrentResolutions())
144 this.embed.player.webtorrent().on('videoFileUpdate', () => this.loadWebTorrentResolutions())
ffacd78f
C
145
146 this.loadWebTorrentResolutions()
6377a9f2
C
147 } else {
148 this.embed.player.p2pMediaLoader().on('resolutionChange', () => this.loadP2PMediaLoaderResolutions())
ffacd78f 149 this.embed.player.p2pMediaLoader().on('resolutionsLoaded', () => this.loadP2PMediaLoaderResolutions())
5efab546 150 }
6377a9f2
C
151
152 this.embed.player.on('volumechange', () => {
153 this.channel.notify({
154 method: 'volumeChange',
155 params: this.embed.player.volume()
156 })
157 })
5efab546
C
158 }
159
160 private loadWebTorrentResolutions () {
6377a9f2
C
161 this.resolutions = []
162
5efab546
C
163 const currentResolutionId = this.embed.player.webtorrent().getCurrentResolutionId()
164
165 for (const videoFile of this.embed.player.webtorrent().videoFiles) {
166 let label = videoFile.resolution.label
167 if (videoFile.fps && videoFile.fps >= 50) {
168 label += videoFile.fps
169 }
170
6377a9f2 171 this.resolutions.push({
5efab546
C
172 id: videoFile.resolution.id,
173 label,
174 src: videoFile.magnetUri,
6377a9f2
C
175 active: videoFile.resolution.id === currentResolutionId,
176 height: videoFile.resolution.id
5efab546
C
177 })
178 }
179
5efab546
C
180 this.channel.notify({
181 method: 'resolutionUpdate',
182 params: this.resolutions
183 })
184 }
6377a9f2
C
185
186 private loadP2PMediaLoaderResolutions () {
187 this.resolutions = []
188
189 const qualityLevels = this.embed.player.qualityLevels()
190 const currentResolutionId = this.embed.player.qualityLevels().selectedIndex
191
192 for (let i = 0; i < qualityLevels.length; i++) {
193 const level = qualityLevels[i]
194
195 this.resolutions.push({
196 id: level.id,
197 label: level.height + 'p',
198 active: level.id === currentResolutionId,
199 width: level.width,
200 height: level.height
201 })
202 }
203
204 this.channel.notify({
205 method: 'resolutionUpdate',
206 params: this.resolutions
207 })
208 }
209
210 private isWebtorrent () {
ffacd78f 211 return !!this.embed.player.webtorrent
6377a9f2 212 }
5efab546 213}