Refactoring webplayer
This commit is contained in:
parent
6ad9a47a07
commit
cae29cb634
|
@ -73,9 +73,9 @@
|
|||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.0.tgz",
|
||||
"integrity": "sha512-tgYb3zVApHbLHYOPWtVwg25sBqHhfBXRKeKoTIyoheIxln1nA7oBl7SfHfiTG2GhDPI8EUBkOD/0wJCP/3HN4Q==",
|
||||
"version": "7.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.1.tgz",
|
||||
"integrity": "sha512-nQbbCbQc9u/rpg1XCxoMYQTbSMVZjCDxErQ1ClCn9Pvcmv1lGads19ep0a2VsEiIJeHqjZley6EQGEC3Yo1xMA==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
|
@ -10018,9 +10018,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"url-toolkit": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.1.6.tgz",
|
||||
"integrity": "sha512-UaZ2+50am4HwrV2crR/JAf63Q4VvPYphe63WGeoJxeu8gmOm0qxPt+KsukfakPNrX9aymGNEkkaoICwn+OuvBw=="
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.0.tgz",
|
||||
"integrity": "sha512-Rde0c9S4fJK3FaHim3DSgdQ8IFrSXcZCpAJo9T7/FA+BoQGhK0ow3mpwGQLJCPYsNn6TstpW7/7DzMpSpz9F9w=="
|
||||
},
|
||||
"use": {
|
||||
"version": "3.1.0",
|
||||
|
@ -10300,9 +10300,8 @@
|
|||
"dev": true
|
||||
},
|
||||
"vue-videojs-player": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-videojs-player/-/vue-videojs-player-1.1.2.tgz",
|
||||
"integrity": "sha512-vRBx8BOSOgo3tbYbTGQKzPrdco0jX1kS+lz5iP8F5Fv7CQTJtAuaKYPgu+VsVbFhdTJ5xpi1h4XMlbaeju8CEg==",
|
||||
"version": "file:../vue-videojs-player/vue-videojs-player-2.0.0.tgz",
|
||||
"integrity": "sha512-+fx7Nnu3IYeskmxZ8RYxNs+PE95qBV59FH0d27/NGHK3KzmXAkBgOyodO7UtY5xg7LOjBXALOZDQOFhDZ/07HQ==",
|
||||
"requires": {
|
||||
"video.js": "^7.8.2"
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"vue": "^2.6.11",
|
||||
"vue-cookies": "^1.7.0",
|
||||
"vue-router": "^2.3.1",
|
||||
"vue-videojs-player": "^1.1.2",
|
||||
"vue-videojs-player": "file:../vue-videojs-player/vue-videojs-player-2.0.0.tgz",
|
||||
"vuetify": "^1.5.14",
|
||||
"vuex": "^2.3.1",
|
||||
"waterline": "^0.13.6",
|
||||
|
|
|
@ -804,4 +804,4 @@ span {
|
|||
|
||||
.platform-xbox {
|
||||
background-color: #107c10;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<div style="width:100%; position: relative">
|
||||
<div style="position: relative" @mouseover="hovered = true" @mouseout="hovered = false">
|
||||
<videoplayer v-if="playingMetadata && chosenServer && chosenQuality && ready"
|
||||
@playerMounted="playerMounted()"
|
||||
@timelineUpdate="timelineUpdate"
|
||||
@playbackEnded="stopPlayback()"
|
||||
|
||||
|
@ -56,9 +55,11 @@
|
|||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
|
||||
<div class="messages-wrapper" v-if="$vuetify.breakpoint.mdAndDown">
|
||||
<messages></messages>
|
||||
</div>
|
||||
|
||||
<v-dialog v-model="dialog" width="350">
|
||||
<v-card>
|
||||
<v-card-title>Playback Settings </v-card-title>
|
||||
|
@ -108,6 +109,7 @@
|
|||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-layout v-if="playingMetadata && chosenServer" justify-center row class="pa-3 hidden-sm-and-up">
|
||||
<v-flex xs12>
|
||||
<v-layout row wrap>
|
||||
|
@ -174,7 +176,7 @@ export default {
|
|||
// Check if we have params
|
||||
if (this.$route.query.start) {
|
||||
// We need to auto play
|
||||
const query = this.$route.query;
|
||||
const { query } = this.$route;
|
||||
this.chosenKey = query.key.replace('/library/metadata/', '');
|
||||
this.chosenMediaIndex = query.mediaIndex || 0;
|
||||
this.chosenServer = this.plex.servers[query.chosenServer];
|
||||
|
@ -248,7 +250,6 @@ export default {
|
|||
this.chosenServer = null;
|
||||
this.playerduration = null;
|
||||
this.playertime = 0;
|
||||
this.bufferedTile = null;
|
||||
this.playingMetadata = null;
|
||||
this.$router.push('/browse');
|
||||
return data.callback(true);
|
||||
|
@ -289,7 +290,6 @@ export default {
|
|||
playertime: 0,
|
||||
playerstatus: 'stopped',
|
||||
playerduration: 0,
|
||||
bufferedTill: 0,
|
||||
playerCreatedAt: new Date().getTime(),
|
||||
|
||||
// These are changed by the watched functions
|
||||
|
@ -493,9 +493,6 @@ export default {
|
|||
this.destroyed = true;
|
||||
},
|
||||
methods: {
|
||||
playerMounted() {
|
||||
// console.log('Child player said it is mounted')
|
||||
},
|
||||
getSourceByLabel(label) {
|
||||
for (let i = 0; i < this.sources.length; i++) {
|
||||
const source = this.sources[i];
|
||||
|
@ -674,7 +671,6 @@ export default {
|
|||
timelineUpdate(data) {
|
||||
this.playertime = data.time;
|
||||
this.playerstatus = data.status;
|
||||
this.bufferedTill = data.bufferedTill;
|
||||
this.playerduration = data.duration;
|
||||
|
||||
if (this.lastSentTimeline.state !== data.status || this.chosenKey !== this.lastSentTimeline.key) {
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
<template>
|
||||
<div v-if="source && initReqSent">
|
||||
<div v-if="src" class="ptplayer">
|
||||
<videojs-player
|
||||
ref="videoPlayer"
|
||||
:options="playerOptions"
|
||||
autoplay="true"
|
||||
controls="true"
|
||||
preload="auto"
|
||||
|
||||
@play="onPlayerPlay($event)"
|
||||
@pause="onPlayerPause($event)"
|
||||
@loadeddata="onPlayerLoadeddata($event)"
|
||||
@ended="onPlayerEnded($event)"
|
||||
@waiting="onPlayerWaiting($event)"
|
||||
@playing="onPlayerPlaying($event)"
|
||||
@timeupdate="onPlayerTimeupdate($event)"
|
||||
@canplay.once="onPlayerCanplay($event)"
|
||||
@canplaythrough="onPlayerCanplaythrough($event)"
|
||||
@seeking="onPlayerSeeking($event)"
|
||||
@seeked="onPlayerSeeked($event)"
|
||||
@statechanged="playerStateChanged($event)"
|
||||
@volumechange="volumeChange($event)"
|
||||
:initial-options="initialOptions"
|
||||
:src="[src]"
|
||||
|
||||
@ready="playerReadied($event)"
|
||||
@pause="onPlayerPause"
|
||||
@loadeddata="onPlayerLoadeddata"
|
||||
@ended="onPlayerEnded"
|
||||
@waiting="onPlayerWaiting"
|
||||
@playing="onPlayerPlaying"
|
||||
@timeupdate="sendTimelineUpdateEvent"
|
||||
@seeking="sendTimelineUpdateEvent"
|
||||
@seeked="sendTimelineUpdateEvent"
|
||||
@volumechange="volumeChange"
|
||||
@error="onPlayerError"
|
||||
|
||||
|
||||
@ready="playerReadied"
|
||||
style="background-color:transparent !important;"
|
||||
class="ptplayer"
|
||||
class="video-js"
|
||||
>
|
||||
</videojs-player>
|
||||
<div class="center" v-if="!src">
|
||||
|
@ -30,7 +33,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
const request = require('request');
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
props: ['server', 'metadata', 'initialOffset', 'src', 'initUrl', 'stopUrl', 'params', 'sources'],
|
||||
|
@ -40,122 +43,20 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
eventbus: window.EventBus,
|
||||
|
||||
destroyed: false,
|
||||
offset: this.initialOffset,
|
||||
initReqSent: false,
|
||||
source: null,
|
||||
|
||||
isPlaying: 'buffering',
|
||||
playerState: 'buffering',
|
||||
lastTime: 0,
|
||||
duration: 0,
|
||||
bufferedTill: 0,
|
||||
|
||||
decisionResult: null,
|
||||
blockedSpeedChanges: false,
|
||||
ticker: null,
|
||||
|
||||
playbackRate: 1,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.source = this.src;
|
||||
this.initReqSent = true;
|
||||
this.$emit('playerMounted');
|
||||
|
||||
// Events from the parent component
|
||||
this.eventbus.$on('player-press-pause', (callback) => {
|
||||
if (this.isPlaying === 'paused') {
|
||||
return callback();
|
||||
}
|
||||
if (this.player) {
|
||||
this.player.pause();
|
||||
}
|
||||
return callback();
|
||||
});
|
||||
|
||||
this.eventbus.$on('player-press-play', (callback) => {
|
||||
if (this.isPlaying === 'playing') {
|
||||
return callback();
|
||||
}
|
||||
if (this.player) {
|
||||
this.player.play();
|
||||
}
|
||||
return callback();
|
||||
});
|
||||
|
||||
this.eventbus.$on('player-seek', async (data) => {
|
||||
// Return a promise through the callback
|
||||
data.callback(this.seekMethod(data));
|
||||
});
|
||||
this.eventbus.$on('ptplayer-poll', (callback) => {
|
||||
try {
|
||||
callback(null, this.player.currentTime() * 1000);
|
||||
} catch (e) {
|
||||
return callback(e, -1);
|
||||
}
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.ticker);
|
||||
this.eventbus.$off('player-press-pause');
|
||||
this.eventbus.$off('player-press-play');
|
||||
this.eventbus.$off('player-seek');
|
||||
this.eventbus.$off('ptplayer-poll');
|
||||
|
||||
let query = '';
|
||||
const params = {
|
||||
hasMDE: 1,
|
||||
ratingKey: this.metadata.ratingKey,
|
||||
key: this.metadata.key,
|
||||
state: 'stopped',
|
||||
time: this.lastTime,
|
||||
duration: Math.round(this.player.duration() * 1000),
|
||||
'X-Plex-Product': this.params['X-Plex-Product'],
|
||||
'X-Plex-Version': this.params['X-Plex-Version'],
|
||||
'X-Plex-Client-Identifier': this.params['X-Plex-Client-Identifier'],
|
||||
'X-Plex-Platform': this.params['X-Plex-Platform'],
|
||||
'X-Plex-Platform-Version': this.params['X-Plex-Platform-Version'],
|
||||
'X-Plex-Device': this.params['X-Plex-Device'],
|
||||
'X-Plex-Device-Name': this.params['X-Plex-Device-Name'],
|
||||
'X-Plex-Device-Screen-Resolution': this.params['X-Plex-Device-Screen-Resolution'],
|
||||
'X-Plex-Token': this.params['X-Plex-Token'],
|
||||
'X-Plex-Session-Identifier': this.params['X-Plex-Session-Identifier'],
|
||||
};
|
||||
for (const key in params) {
|
||||
query += `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}&`;
|
||||
}
|
||||
const url = `${this.server.chosenConnection.uri}/:/timeline?${query}`;
|
||||
request(url, (error, response, body) => {
|
||||
if (!error) {
|
||||
// console.log('Succesfully sent Player status to PMS')
|
||||
}
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
player() {
|
||||
if (this.$refs && this.$refs.videoPlayer) {
|
||||
return this.$refs.videoPlayer.player;
|
||||
}
|
||||
},
|
||||
|
||||
playerOptions() {
|
||||
// component options
|
||||
return {
|
||||
playsinline: true,
|
||||
|
||||
// videojs options
|
||||
plugins: {},
|
||||
|
||||
fluid: true,
|
||||
preload: 'auto',
|
||||
aspectRatio: '16:9',
|
||||
autoplay: true,
|
||||
width: '100%',
|
||||
initialOptions: {
|
||||
language: 'en',
|
||||
inactivityTimeout: 2000,
|
||||
fluid: true,
|
||||
aspectRatio: '16:9',
|
||||
|
||||
sources: [
|
||||
this.source,
|
||||
],
|
||||
controlBar: {
|
||||
children: {
|
||||
playToggle: {},
|
||||
|
@ -171,36 +72,121 @@ export default {
|
|||
fullscreenToggle: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Events from the parent component
|
||||
this.eventbus.$on('player-press-pause', (callback) => {
|
||||
if (this.playerState === 'paused') {
|
||||
return callback();
|
||||
}
|
||||
if (this.player) {
|
||||
this.player.pause();
|
||||
}
|
||||
return callback();
|
||||
});
|
||||
|
||||
this.eventbus.$on('player-press-play', (callback) => {
|
||||
if (this.playerState === 'playing') {
|
||||
return callback();
|
||||
}
|
||||
if (this.player) {
|
||||
this.player.play();
|
||||
}
|
||||
return callback();
|
||||
});
|
||||
|
||||
this.eventbus.$on('player-seek', async (data) => {
|
||||
// Return a promise through the callback
|
||||
data.callback(this.seekMethod(data));
|
||||
});
|
||||
this.eventbus.$on('ptplayer-poll', (callback) => {
|
||||
try {
|
||||
return callback(null, this.playerCurrentTime);
|
||||
} catch (e) {
|
||||
return callback(e, -1);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.destroyed = true;
|
||||
clearInterval(this.ticker);
|
||||
this.eventbus.$off('player-press-pause');
|
||||
this.eventbus.$off('player-press-play');
|
||||
this.eventbus.$off('player-seek');
|
||||
this.eventbus.$off('ptplayer-poll');
|
||||
|
||||
const params = {
|
||||
hasMDE: 1,
|
||||
ratingKey: this.metadata.ratingKey,
|
||||
key: this.metadata.key,
|
||||
state: 'stopped',
|
||||
time: this.playerCurrentTime,
|
||||
duration: this.playerDuration,
|
||||
'X-Plex-Product': this.params['X-Plex-Product'],
|
||||
'X-Plex-Version': this.params['X-Plex-Version'],
|
||||
'X-Plex-Client-Identifier': this.params['X-Plex-Client-Identifier'],
|
||||
'X-Plex-Platform': this.params['X-Plex-Platform'],
|
||||
'X-Plex-Platform-Version': this.params['X-Plex-Platform-Version'],
|
||||
'X-Plex-Device': this.params['X-Plex-Device'],
|
||||
'X-Plex-Device-Name': this.params['X-Plex-Device-Name'],
|
||||
'X-Plex-Device-Screen-Resolution': this.params['X-Plex-Device-Screen-Resolution'],
|
||||
'X-Plex-Token': this.params['X-Plex-Token'],
|
||||
'X-Plex-Session-Identifier': this.params['X-Plex-Session-Identifier'],
|
||||
};
|
||||
const query = Object.entries(params)
|
||||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
||||
.join('&');
|
||||
|
||||
const url = `${this.server.chosenConnection.uri}/:/timeline?${query}`;
|
||||
return axios.get(url);
|
||||
},
|
||||
|
||||
computed: {
|
||||
player() {
|
||||
if (this.$refs && this.$refs.videoPlayer) {
|
||||
return this.$refs.videoPlayer.player;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
metadataImage() {
|
||||
const w = Math.round(Math.max(document.documentElement.clientWidth, window.innerWidth || 0));
|
||||
const h = Math.round(Math.max(document.documentElement.clientHeight, window.innerHeight || 0));
|
||||
const w = Math.round(Math.max(
|
||||
document.documentElement.clientWidth,
|
||||
window.innerWidth || 0,
|
||||
));
|
||||
const h = Math.round(Math.max(
|
||||
document.documentElement.clientHeight,
|
||||
window.innerHeight || 0,
|
||||
));
|
||||
|
||||
return this.server.getUrlForLibraryLoc(this.metadata.thumb, w / 12, h / 4);
|
||||
},
|
||||
|
||||
},
|
||||
methods: {
|
||||
playerCurrentTime() {
|
||||
return this.player.currentTime() * 1000;
|
||||
},
|
||||
|
||||
// Player events
|
||||
closingPlayer() {
|
||||
playerDuration() {
|
||||
return this.player.duration() * 1000;
|
||||
},
|
||||
onPlayerPlay(player) {
|
||||
},
|
||||
|
||||
methods: {
|
||||
onPlayerPause() {
|
||||
this.playerState = 'paused';
|
||||
this.sendTimelineUpdateEvent();
|
||||
},
|
||||
onPlayerPause(player) {
|
||||
},
|
||||
onPlayerLoaded(player) {
|
||||
},
|
||||
onPlayerEnded(player) {
|
||||
onPlayerEnded(event) {
|
||||
this.$router.push('/browse');
|
||||
this.$emit('playbackEnded');
|
||||
this.$emit('playbackEnded', event);
|
||||
},
|
||||
onPlayerCanplay(player) {
|
||||
},
|
||||
onPlayerCanplaythrough(player) {
|
||||
},
|
||||
onPlayerTimeupdate(player) {
|
||||
onPlayerError(event) {
|
||||
this.$emit('playerError', event);
|
||||
},
|
||||
seekMethod(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -235,7 +221,7 @@ export default {
|
|||
cancelled = true;
|
||||
});
|
||||
const clicker = setInterval(() => {
|
||||
if (cancelled || !this.player || this.isPlaying === 'paused' || this.isPlaying === 'buffering' || oldSources !== this.player.options_.sources) {
|
||||
if (cancelled || !this.player || this.playerState === 'paused' || this.playerState === 'buffering' || oldSources !== this.player.options_.sources) {
|
||||
clearInterval(clicker);
|
||||
this.player.playbackRate(1.0);
|
||||
return reject(new Error('Slow seek was stop due to buffering or pausing'));
|
||||
|
@ -255,7 +241,7 @@ export default {
|
|||
reject(new Error('Failed to slow seek as the playback rate did not want to change'));
|
||||
return clearInterval(clicker);
|
||||
}
|
||||
if (this.isPlaying === 'paused' || (lastPlayerTime === this.player.currentTime() * 1000)) {
|
||||
if (this.playerState === 'paused' || (lastPlayerTime === this.player.currentTime() * 1000)) {
|
||||
return;
|
||||
}
|
||||
lastPlayerTime = this.player.currentTime * 1000;
|
||||
|
@ -311,123 +297,80 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
onPlayerLoadeddata(player) {
|
||||
const that = this;
|
||||
|
||||
player.on(['pause'], () => {
|
||||
this.isPlaying = 'paused';
|
||||
});
|
||||
player.on(['waiting'], () => {
|
||||
this.isPlaying = 'buffering';
|
||||
});
|
||||
player.on('playing', () => {
|
||||
this.isPlaying = 'playing';
|
||||
});
|
||||
|
||||
// Setup our intervals for pinging the transcoder and timelines
|
||||
function send() {
|
||||
// console.log('Sending timeline')
|
||||
if (!that || !that.player) {
|
||||
return clearInterval(that.ticker);
|
||||
onPlayerLoadeddata() {
|
||||
return this.periodicPlexTimelineUpdate();
|
||||
},
|
||||
async periodicPlexTimelineUpdate() {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
if (this.destroyed) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (!that.player || !that.metadata) {
|
||||
return;
|
||||
}
|
||||
let query = '';
|
||||
const params = {
|
||||
hasMDE: 1,
|
||||
ratingKey: that.metadata.ratingKey,
|
||||
key: that.metadata.key,
|
||||
state: that.isPlaying,
|
||||
time: that.lastTime,
|
||||
duration: Math.round(that.player.duration() * 1000),
|
||||
'X-Plex-Product': that.params['X-Plex-Product'],
|
||||
'X-Plex-Version': that.params['X-Plex-Version'],
|
||||
'X-Plex-Client-Identifier': that.params['X-Plex-Client-Identifier'],
|
||||
'X-Plex-Platform': that.params['X-Plex-Platform'],
|
||||
'X-Plex-Platform-Version': that.params['X-Plex-Platform-Version'],
|
||||
'X-Plex-Device': that.params['X-Plex-Device'],
|
||||
'X-Plex-Device-Name': that.params['X-Plex-Device-Name'],
|
||||
'X-Plex-Device-Screen-Resolution': that.params['X-Plex-Device-Screen-Resolution'],
|
||||
'X-Plex-Token': that.params['X-Plex-Token'],
|
||||
'X-Plex-Session-Identifier': that.params['X-Plex-Session-Identifier'],
|
||||
};
|
||||
for (const key in params) {
|
||||
query += `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}&`;
|
||||
}
|
||||
const url = `${that.server.chosenConnection.uri}/:/timeline?${query}`;
|
||||
request(url, (error, response, body) => {
|
||||
if (!error) {
|
||||
// console.log('Succesfully sent Player status to PMS')
|
||||
}
|
||||
});
|
||||
const delayPromise = this.delay(10000);
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await this.sendPlexTimelineUpdate().catch(e => e);
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await delayPromise;
|
||||
}
|
||||
|
||||
this.ticker = setInterval(() => {
|
||||
// Tell the PMS instance of our status
|
||||
send();
|
||||
}, 10000);
|
||||
send();
|
||||
},
|
||||
onPlayerPlaying(player) {
|
||||
onPlayerPlaying() {
|
||||
this.playerState = 'playing';
|
||||
},
|
||||
onPlayerWaiting(player) {
|
||||
onPlayerWaiting() {
|
||||
this.playerState = 'buffering';
|
||||
this.sendTimelineUpdateEvent();
|
||||
},
|
||||
onPlayerSeeking(player) {
|
||||
this.$emit('timelineUpdate', {
|
||||
time: this.player.currentTime() * 1000,
|
||||
status: this.isPlaying,
|
||||
bufferedTill: this.bufferedTill,
|
||||
duration: this.duration,
|
||||
});
|
||||
},
|
||||
onPlayerSeeked(player) {
|
||||
this.$emit('timelineUpdate', {
|
||||
time: this.player.currentTime() * 1000,
|
||||
status: this.isPlaying,
|
||||
bufferedTill: this.bufferedTill,
|
||||
duration: this.duration,
|
||||
});
|
||||
},
|
||||
volumeChange(event) {
|
||||
// console.log("Setting volume to " + this.player.volume() || 0)
|
||||
volumeChange() {
|
||||
this.$store.commit('setSetting', ['PTPLAYERVOLUME', this.player.volume() || 0]);
|
||||
},
|
||||
playerStateChanged(playerCurrentState) {
|
||||
|
||||
this.bufferedTill = Math.round(this.player.buffered().end(0) * 1000);
|
||||
this.duration = Math.round(this.player.duration() * 1000);
|
||||
this.bufferStart = Math.round(this.player.buffered().start(0) * 1000);
|
||||
this.bufferEnd = Math.round(this.player.buffered().end(0) * 1000);
|
||||
if (this.player.error_) {
|
||||
this.$emit('playerError');
|
||||
}
|
||||
if (playerCurrentState.timeupdate) {
|
||||
this.lastTime = Math.round(playerCurrentState.timeupdate * 1000);
|
||||
}
|
||||
if (playerCurrentState.pause) {
|
||||
this.isPlaying = 'paused';
|
||||
}
|
||||
if (playerCurrentState.playing) {
|
||||
this.isPlaying = 'playing';
|
||||
}
|
||||
this.playbackRate = this.player.playbackRate();
|
||||
this.$emit('timelineUpdate', {
|
||||
time: this.lastTime,
|
||||
status: this.isPlaying,
|
||||
bufferedTill: this.bufferedTill,
|
||||
duration: this.duration,
|
||||
});
|
||||
},
|
||||
playerReadied(player) {
|
||||
// console.log('Setting volume to ' + this.$store.getters.getSettingPTPLAYERVOLUME)
|
||||
playerReadied() {
|
||||
this.player.volume(this.$store.getters.getSettings.PTPLAYERVOLUME || 100);
|
||||
this.player.currentTime(this.initialOffset / 1000);
|
||||
},
|
||||
sendTimelineUpdateEvent() {
|
||||
this.$emit('timelineUpdate', {
|
||||
time: this.playerCurrentTime,
|
||||
duration: this.playerDuration,
|
||||
status: this.playerState,
|
||||
});
|
||||
},
|
||||
|
||||
sendPlexTimelineUpdate() {
|
||||
if (!this || !this.player || !this.metadata) {
|
||||
clearInterval(this.ticker);
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
const params = {
|
||||
hasMDE: 1,
|
||||
ratingKey: this.metadata.ratingKey,
|
||||
key: this.metadata.key,
|
||||
state: this.playerState,
|
||||
time: this.playerCurrentTime,
|
||||
duration: this.playerDuration,
|
||||
'X-Plex-Product': this.params['X-Plex-Product'],
|
||||
'X-Plex-Version': this.params['X-Plex-Version'],
|
||||
'X-Plex-Client-Identifier': this.params['X-Plex-Client-Identifier'],
|
||||
'X-Plex-Platform': this.params['X-Plex-Platform'],
|
||||
'X-Plex-Platform-Version': this.params['X-Plex-Platform-Version'],
|
||||
'X-Plex-Device': this.params['X-Plex-Device'],
|
||||
'X-Plex-Device-Name': this.params['X-Plex-Device-Name'],
|
||||
'X-Plex-Device-Screen-Resolution': this.params['X-Plex-Device-Screen-Resolution'],
|
||||
'X-Plex-Token': this.params['X-Plex-Token'],
|
||||
'X-Plex-Session-Identifier': this.params['X-Plex-Session-Identifier'],
|
||||
};
|
||||
|
||||
const query = Object.entries(params)
|
||||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
||||
.join('&');
|
||||
|
||||
const url = `${this.server.chosenConnection.uri}/:/timeline?${query}`;
|
||||
return axios.get(url, { timeout: 10000 });
|
||||
},
|
||||
delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue