All lint fixes
This commit is contained in:
parent
f728d67af3
commit
a396588322
|
@ -1221,12 +1221,6 @@
|
|||
"integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/json5": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
||||
|
@ -5326,24 +5320,23 @@
|
|||
}
|
||||
},
|
||||
"eslint-plugin-import": {
|
||||
"version": "2.21.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.21.0.tgz",
|
||||
"integrity": "sha512-fbbjKv3jv23WZ1+uCyYOGx+J8H4vAVlVcc9YLHRCycDry1LdgjdSvt7O0dQS1PwOUu/s0QWfR1xE7mq0GuqYnA==",
|
||||
"version": "2.20.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz",
|
||||
"integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-includes": "^3.1.1",
|
||||
"array.prototype.flat": "^1.2.3",
|
||||
"array-includes": "^3.0.3",
|
||||
"array.prototype.flat": "^1.2.1",
|
||||
"contains-path": "^0.1.0",
|
||||
"debug": "^2.6.9",
|
||||
"doctrine": "1.5.0",
|
||||
"eslint-import-resolver-node": "^0.3.3",
|
||||
"eslint-module-utils": "^2.6.0",
|
||||
"eslint-import-resolver-node": "^0.3.2",
|
||||
"eslint-module-utils": "^2.4.1",
|
||||
"has": "^1.0.3",
|
||||
"minimatch": "^3.0.4",
|
||||
"object.values": "^1.1.1",
|
||||
"object.values": "^1.1.0",
|
||||
"read-pkg-up": "^2.0.0",
|
||||
"resolve": "^1.17.0",
|
||||
"tsconfig-paths": "^3.9.0"
|
||||
"resolve": "^1.12.0"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-vue": {
|
||||
|
@ -5958,6 +5951,12 @@
|
|||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-xml-parser": {
|
||||
"version": "3.17.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.17.3.tgz",
|
||||
"integrity": "sha512-g3OSnHBWq5hrpS4LUgFWOS87F7B6UDklkI6v2VLC/89Ech00fabXleKEHTVXQBkKyVsfOxD+1QY6fkoIZMIO/Q==",
|
||||
"dev": true
|
||||
},
|
||||
"faye-websocket": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
|
||||
|
@ -12637,29 +12636,6 @@
|
|||
"integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==",
|
||||
"dev": true
|
||||
},
|
||||
"tsconfig-paths": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
|
||||
"integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json5": "^0.0.29",
|
||||
"json5": "^1.0.1",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-bom": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"json5": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"fast-xml-parser": "^3.17.3",
|
||||
"fscreen": "^1.0.2",
|
||||
"humanize-duration": "^3.23.0",
|
||||
"moment": "^2.26.0",
|
||||
|
@ -67,4 +68,4 @@
|
|||
"vuex-persistedstate": "^3.0.1",
|
||||
"vuex-router-sync": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
:value="GET_CLIENTPOLLINTERVAL"
|
||||
:min="100"
|
||||
:max="10000"
|
||||
hint="Sets how frequently SyncLounge will poll external plex clients for new information in milliseconds. Default is 1000ms (1 second)"
|
||||
hint="Sets how frequently SyncLounge will poll plex clients for new information in
|
||||
milliseconds.Default is 1000ms (1 second)"
|
||||
persistent-hint
|
||||
@change="SET_CLIENTPOLLINTERVAL"
|
||||
/>
|
||||
|
@ -29,7 +30,8 @@
|
|||
:value="GET_SYNCFLEXIBILITY"
|
||||
:min="0"
|
||||
:max="10000"
|
||||
hint="Sets the acceptable distance away from the host in milliseconds. Default is 3000ms (3 seconds)."
|
||||
hint="Sets the acceptable distance away from the host in milliseconds.
|
||||
Default is 3000ms (3 seconds)."
|
||||
persistent-hint
|
||||
@change="SET_SYNCFLEXIBILITY"
|
||||
/>
|
||||
|
@ -66,7 +68,8 @@
|
|||
</h4>
|
||||
<v-switch
|
||||
label="Enabled"
|
||||
hint="If enabled SyncLounge will attempt to automatically play the same content as the host."
|
||||
hint="If enabled SyncLounge will attempt to automatically play the
|
||||
same content as the host."
|
||||
:input-value="GET_AUTOPLAY"
|
||||
@change="SET_AUTOPLAY"
|
||||
/>
|
||||
|
|
|
@ -25,7 +25,7 @@ export default {
|
|||
this.$store.state.plex = null;
|
||||
this.$store.state.signedin = 'notsignedin';
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
window.location.reload();
|
||||
}, 2500);
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
Now Playing
|
||||
</div>
|
||||
<div><small><b>{{ getTitle }}</b> - {{ getUnder }}</small></div>
|
||||
<!-- <div class="hidden-xs-only soft-text" style="font-size: 12px">Click for more info</div> -->
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-card>
|
||||
|
@ -127,14 +126,5 @@ export default {
|
|||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
async mounted() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line max-classes-per-file
|
||||
import shaka from 'shaka-player/dist/shaka-player.ui.debug';
|
||||
import ShakaUtils from '@/player/ui/utils';
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line max-classes-per-file
|
||||
import shaka from 'shaka-player/dist/shaka-player.ui.debug';
|
||||
import ShakaUtils from '@/player/ui/utils';
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line max-classes-per-file
|
||||
import shaka from 'shaka-player/dist/shaka-player.ui.debug';
|
||||
|
||||
class CloseButton extends shaka.ui.Element {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line max-classes-per-file
|
||||
import shaka from 'shaka-player/dist/shaka-player.ui.debug';
|
||||
|
||||
class Forward30Button extends shaka.ui.Element {
|
||||
|
@ -23,7 +24,7 @@ class Forward30Button extends shaka.ui.Element {
|
|||
}
|
||||
|
||||
onButtonClicked() {
|
||||
this.video.currentTime = this.video.currentTime + 30;
|
||||
this.video.currentTime += 30;
|
||||
}
|
||||
|
||||
// Updates whether this should be enabled or disabled depending on
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line max-classes-per-file
|
||||
import shaka from 'shaka-player/dist/shaka-player.ui.debug';
|
||||
import ShakaUtils from '@/player/ui/utils';
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line max-classes-per-file
|
||||
import shaka from 'shaka-player/dist/shaka-player.ui.debug';
|
||||
|
||||
class Replay10Button extends shaka.ui.Element {
|
||||
|
@ -23,7 +24,7 @@ class Replay10Button extends shaka.ui.Element {
|
|||
}
|
||||
|
||||
onButtonClicked() {
|
||||
this.video.currentTime = this.video.currentTime - 10;
|
||||
this.video.currentTime -= 10;
|
||||
}
|
||||
|
||||
// Updates whether this should be enabled or disabled depending on
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line max-classes-per-file
|
||||
import shaka from 'shaka-player/dist/shaka-player.ui.debug';
|
||||
import ShakaUtils from '@/player/ui/utils';
|
||||
|
||||
|
|
|
@ -7,13 +7,13 @@ Vue.use(Router);
|
|||
// Good guide: https://blog.sqreen.com/authentication-best-practices-vue/
|
||||
|
||||
|
||||
const ifNotAuthenticated = (to, from, next) => {
|
||||
if (!store.getters.IS_AUTHENTICATED) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
next('/');
|
||||
};
|
||||
// const ifNotAuthenticated = (to, from, next) => {
|
||||
// if (!store.getters.IS_AUTHENTICATED) {
|
||||
// next();
|
||||
// return;
|
||||
// }
|
||||
// next('/');
|
||||
// };
|
||||
|
||||
const ifAuthenticated = (to, from, next) => {
|
||||
if (store.getters.IS_AUTHENTICATED) {
|
||||
|
|
|
@ -75,11 +75,13 @@ export default {
|
|||
&& metadata.type === 'episode'
|
||||
) {
|
||||
if (!getters.GET_UP_NEXT_TRIGGERED) {
|
||||
state.plex.servers[timeline.machineIdentifier].getPostplay(timeline.ratingKey).then((data) => {
|
||||
if (data.MediaContainer.Hub[0].Metadata[0].grandparentTitle === metadata.grandparentTitle) {
|
||||
commit('SET_UP_NEXT_POST_PLAY_DATA', data);
|
||||
}
|
||||
});
|
||||
state.plex.servers[timeline.machineIdentifier]
|
||||
.getPostplay(timeline.ratingKey).then((data) => {
|
||||
if (data.MediaContainer.Hub[0].Metadata[0].grandparentTitle
|
||||
=== metadata.grandparentTitle) {
|
||||
commit('SET_UP_NEXT_POST_PLAY_DATA', data);
|
||||
}
|
||||
});
|
||||
|
||||
commit('SET_UP_NEXT_TRIGGERED', true);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import axios from 'axios';
|
||||
|
||||
import plexauth from './helpers/PlexAuth';
|
||||
import PlexServer from './helpers/PlexServer';
|
||||
import PlexClient from './helpers/PlexClient';
|
||||
|
||||
|
|
|
@ -11,8 +11,7 @@ export default {
|
|||
getItemCache: (state) => state.itemCache,
|
||||
getLibraryCache: (state) => state.libraryCache,
|
||||
recentClients: (state) => {
|
||||
let clients = [];
|
||||
for (const client in state.clients) clients.push(state.clients[client]);
|
||||
let clients = Object.values(state.clients);
|
||||
clients = clients.sort((a, b) => parseInt(b.lastSeenAt, 10) - parseInt(a.lastSeenAt, 10));
|
||||
return clients;
|
||||
},
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import axios from 'axios';
|
||||
import parser from 'fast-xml-parser';
|
||||
import xmlutils from '@/utils/xmlutils';
|
||||
import { encodeUrlParams } from '@/utils/encoder';
|
||||
import delay from '@/utils/delay';
|
||||
import plexauth from './PlexAuth';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
|
@ -68,9 +70,10 @@ class PlexClient {
|
|||
return `${s4() + s4()}-${s4()}`;
|
||||
}
|
||||
|
||||
async hitApi(command, params, connection, needResponse, dontSub) {
|
||||
async hitApi(command, params, con) {
|
||||
let connection = con;
|
||||
if (this.clientIdentifier === 'PTPLAYER9PLUS10') {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
return new Promise((resolve) => {
|
||||
// We are using the SyncLounge Player
|
||||
const data = {
|
||||
command,
|
||||
|
@ -89,47 +92,40 @@ class PlexClient {
|
|||
if (!connection) {
|
||||
throw new Error('No connection specified');
|
||||
}
|
||||
let query = '';
|
||||
|
||||
Object.assign(params, {
|
||||
type: 'video',
|
||||
commandID: this.commandId,
|
||||
});
|
||||
for (const key in params) {
|
||||
query += `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}&`;
|
||||
}
|
||||
query = query.substring(0, query.length - 1);
|
||||
|
||||
const query = encodeUrlParams(params);
|
||||
|
||||
if (connection.uri.charAt(connection.uri.length - 1) === '/') {
|
||||
// Remove a trailing / that some clients broadcast
|
||||
connection.uri = connection.uri.slice(0, connection.uri.length - 1);
|
||||
}
|
||||
const _url = `${connection.uri + command}?${query}`;
|
||||
const url = `${connection.uri + command}?${query}`;
|
||||
this.setValue('commandId', this.commandId + 1);
|
||||
const options = plexauth.getClientApiOptions(this.clientIdentifier, 5000, this.accessToken);
|
||||
const { data } = await axios.get(_url, options);
|
||||
if (needResponse) {
|
||||
return parser.parse(data);
|
||||
}
|
||||
const options = {
|
||||
...plexauth.getClientApiOptions(this.clientIdentifier, 5000, this.accessToken),
|
||||
transformResponse: xmlutils.parseXML,
|
||||
};
|
||||
await axios.get(url, options);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getTimeline() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let data;
|
||||
try {
|
||||
data = await this.hitApi('/player/timeline/poll', { wait: 0 }, this.chosenConnection, true);
|
||||
if (data) {
|
||||
return resolve(this.updateTimelineObject(data));
|
||||
}
|
||||
return reject(new Error('Invalid data recieved from client'));
|
||||
} catch (e) {
|
||||
return reject(e);
|
||||
}
|
||||
});
|
||||
// Get the timeline object from the client
|
||||
async getTimeline() {
|
||||
const data = await this.hitApi('/player/timeline/poll', { wait: 0 }, this.chosenConnection, true);
|
||||
if (data) {
|
||||
return this.updateTimelineObject(data);
|
||||
}
|
||||
throw new Error('Invalid data recieved from client');
|
||||
}
|
||||
|
||||
updateTimelineObject(result) {
|
||||
updateTimelineObject(timeline) {
|
||||
// Check if we are the SLPlayer
|
||||
let result = timeline;
|
||||
if (this.clientIdentifier === 'PTPLAYER9PLUS10') {
|
||||
// SLPLAYER
|
||||
const tempObj = {
|
||||
|
@ -138,11 +134,12 @@ class PlexClient {
|
|||
},
|
||||
};
|
||||
result = tempObj;
|
||||
if (!this.previousTimeline.MediaContainer || result.MediaContainer.Timeline[0].ratingKey !== this.previousTimeline.MediaContainer.Timeline[0].ratingKey) {
|
||||
if (!this.previousTimeline.MediaContainer || result.MediaContainer.Timeline[0].ratingKey
|
||||
!== this.previousTimeline.MediaContainer.Timeline[0].ratingKey) {
|
||||
window.EventBus.$emit('PLAYBACK_CHANGE', [this, result.MediaContainer.Timeline[0].ratingKey, result.MediaContainer.Timeline[0]]);
|
||||
}
|
||||
this.previousTimeline = tempObj;
|
||||
this.lastTimelineObject = result.MediaContainer.Timeline[0];
|
||||
[this.lastTimelineObject] = result.MediaContainer.Timeline;
|
||||
this.lastTimelineObject.recievedAt = new Date().getTime();
|
||||
window.EventBus.$emit('NEW_TIMELINE', result.MediaContainer.Timeline[0]);
|
||||
return result.MediaContainer.Timeline[0];
|
||||
|
@ -151,9 +148,9 @@ class PlexClient {
|
|||
const timelines = result.MediaContainer.Timeline;
|
||||
let videoTimeline = {};
|
||||
for (let i = 0; i < timelines.length; i += 1) {
|
||||
const _timeline = timelines[i].$;
|
||||
if (_timeline.type === 'video') {
|
||||
videoTimeline = _timeline;
|
||||
const subTimeline = timelines[i].$;
|
||||
if (subTimeline.type === 'video') {
|
||||
videoTimeline = subTimeline;
|
||||
if (videoTimeline.ratingKey !== this.previousTimeline.ratingKey) {
|
||||
window.EventBus.$emit('PLAYBACK_CHANGE', [this, videoTimeline.ratingKey, videoTimeline]);
|
||||
}
|
||||
|
@ -188,7 +185,7 @@ class PlexClient {
|
|||
}
|
||||
|
||||
waitForMovement(startTime) {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve) => {
|
||||
let time = 500;
|
||||
if (this.clientIdentifier === 'PTPLAYER9PLUS10') {
|
||||
time = 50;
|
||||
|
@ -204,20 +201,17 @@ class PlexClient {
|
|||
});
|
||||
}
|
||||
|
||||
skipAhead(current, duration) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const startedAt = new Date().getTime();
|
||||
const now = this.lastTimelineObject.time;
|
||||
await this.seekTo(current + duration);
|
||||
await this.waitForMovement(now);
|
||||
// The client is now ready
|
||||
await this.pressPause();
|
||||
// Calculate how long it took to get to our ready state
|
||||
const elapsed = Math.abs(startedAt - new Date().getTime());
|
||||
await wait(duration - elapsed);
|
||||
await this.pressPlay();
|
||||
resolve();
|
||||
});
|
||||
async skipAhead(current, duration) {
|
||||
const startedAt = new Date().getTime();
|
||||
const now = this.lastTimelineObject.time;
|
||||
await this.seekTo(current + duration);
|
||||
await this.waitForMovement(now);
|
||||
// The client is now ready
|
||||
await this.pressPause();
|
||||
// Calculate how long it took to get to our ready state
|
||||
const elapsed = Math.abs(startedAt - new Date().getTime());
|
||||
await delay(duration - elapsed);
|
||||
await this.pressPlay();
|
||||
}
|
||||
|
||||
cleanSeek(time, isSoft) {
|
||||
|
@ -227,55 +221,55 @@ class PlexClient {
|
|||
return this.seekTo(time);
|
||||
}
|
||||
|
||||
sync(hostTimeline, SYNCFLEXIBILITY, SYNCMODE, POLLINTERVAL) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (this.clientIdentifier === 'PTPLAYER9PLUS10') {
|
||||
await this.getTimeline();
|
||||
}
|
||||
const lastCommandTime = Math.abs(this.lastSyncCommand - new Date().getTime());
|
||||
if (this.lastSyncCommand && this.clientIdentifier !== 'PTPLAYER9PLUS10' && lastCommandTime < POLLINTERVAL) {
|
||||
return reject(new Error('too soon for another sync command'));
|
||||
}
|
||||
const lagTime = Math.abs(hostTimeline.recievedAt - new Date().getTime());
|
||||
if (lagTime) {
|
||||
hostTimeline.time += lagTime;
|
||||
}
|
||||
const timelineAge = new Date().getTime() - this.lastTimelineObject.recievedAt;
|
||||
const ourTime = parseInt(this.lastTimelineObject.time) + parseInt(timelineAge);
|
||||
const difference = Math.abs((parseInt(ourTime)) - parseInt(hostTimeline.time));
|
||||
// console.log('Difference with host is', difference);
|
||||
const bothPaused = hostTimeline.playerState === 'paused' && this.lastTimelineObject.state === 'paused';
|
||||
async sync(hostTime, SYNCFLEXIBILITY, SYNCMODE, POLLINTERVAL) {
|
||||
const hostTimeline = hostTime;
|
||||
if (this.clientIdentifier === 'PTPLAYER9PLUS10') {
|
||||
await this.getTimeline();
|
||||
}
|
||||
const lastCommandTime = Math.abs(this.lastSyncCommand - new Date().getTime());
|
||||
if (this.lastSyncCommand && this.clientIdentifier !== 'PTPLAYER9PLUS10' && lastCommandTime < POLLINTERVAL) {
|
||||
throw new Error('too soon for another sync command');
|
||||
}
|
||||
const lagTime = Math.abs(hostTimeline.recievedAt - new Date().getTime());
|
||||
if (lagTime) {
|
||||
hostTimeline.time += lagTime;
|
||||
}
|
||||
const timelineAge = new Date().getTime() - this.lastTimelineObject.recievedAt;
|
||||
const ourTime = parseInt(this.lastTimelineObject.time, 10) + parseInt(timelineAge, 10);
|
||||
const difference = Math.abs((parseInt(ourTime, 10)) - parseInt(hostTimeline.time, 10));
|
||||
// console.log('Difference with host is', difference);
|
||||
const bothPaused = hostTimeline.playerState === 'paused' && this.lastTimelineObject.state === 'paused';
|
||||
|
||||
if (parseInt(difference, 10) > parseInt(SYNCFLEXIBILITY, 10) || (bothPaused && difference > 10)) {
|
||||
// We need to seek!
|
||||
this.lastSyncCommand = new Date().getTime();
|
||||
// Decide what seeking method we want to use
|
||||
if (SYNCMODE === 'cleanseek' || hostTimeline.playerState === 'paused') {
|
||||
return resolve(await this.cleanSeek(hostTimeline.time));
|
||||
}
|
||||
if (SYNCMODE === 'skipahead') {
|
||||
return resolve(await this.skipAhead(hostTimeline.time, 10000));
|
||||
}
|
||||
// Fall back to skipahead
|
||||
return resolve(await this.skipAhead(hostTimeline.time, 10000));
|
||||
if (parseInt(difference, 10) > parseInt(SYNCFLEXIBILITY, 10)
|
||||
|| (bothPaused && difference > 10)) {
|
||||
// We need to seek!
|
||||
this.lastSyncCommand = new Date().getTime();
|
||||
// Decide what seeking method we want to use
|
||||
if (SYNCMODE === 'cleanseek' || hostTimeline.playerState === 'paused') {
|
||||
return this.cleanSeek(hostTimeline.time);
|
||||
}
|
||||
// Calc the average delay of the last 10 host timeline updates
|
||||
// We do this to avoid any issues with random lag spikes
|
||||
this.differenceCache.unshift(difference);
|
||||
if (this.differenceCache.length > 5) {
|
||||
this.differenceCache.pop();
|
||||
if (SYNCMODE === 'skipahead') {
|
||||
return this.skipAhead(hostTimeline.time, 10000);
|
||||
}
|
||||
let total = 0;
|
||||
for (let i = 0; i < this.differenceCache.length; i += 1) {
|
||||
total += this.differenceCache[i];
|
||||
}
|
||||
const avg = total / this.differenceCache.length;
|
||||
if (this.clientIdentifier === 'PTPLAYER9PLUS10' && avg > 1500) {
|
||||
console.log('Soft syncing because difference is', difference);
|
||||
return resolve(await this.cleanSeek(hostTimeline.time, true));
|
||||
}
|
||||
return resolve('No sync needed');
|
||||
});
|
||||
// Fall back to skipahead
|
||||
return this.skipAhead(hostTimeline.time, 10000);
|
||||
}
|
||||
// Calc the average delay of the last 10 host timeline updates
|
||||
// We do this to avoid any issues with random lag spikes
|
||||
this.differenceCache.unshift(difference);
|
||||
if (this.differenceCache.length > 5) {
|
||||
this.differenceCache.pop();
|
||||
}
|
||||
let total = 0;
|
||||
for (let i = 0; i < this.differenceCache.length; i += 1) {
|
||||
total += this.differenceCache[i];
|
||||
}
|
||||
const avg = total / this.differenceCache.length;
|
||||
if (this.clientIdentifier === 'PTPLAYER9PLUS10' && avg > 1500) {
|
||||
console.log('Soft syncing because difference is', difference);
|
||||
return this.cleanSeek(hostTimeline.time, true);
|
||||
}
|
||||
return 'No sync needed';
|
||||
}
|
||||
|
||||
async playMedia(data) {
|
||||
|
@ -285,117 +279,116 @@ class PlexClient {
|
|||
// Server Ip, Server Port, Server Protocol, Path
|
||||
|
||||
// First we will mirror the item so the user has an idea of what we're about to play
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const command = '/player/playback/playMedia';
|
||||
const offset = Math.round(data.offset) || 0;
|
||||
const serverId = data.server.clientIdentifier;
|
||||
const uri = new URL(data.server.chosenConnection.uri);
|
||||
const address = uri.hostname;
|
||||
const port = uri.port !== '' ? uri.port : (uri.protocol === 'https:' ? '443' : '80'); // port not specified if standard
|
||||
const protocol = uri.protocol.replace(':', ''); // remove extra colon
|
||||
const path = data.server.chosenConnection.uri + data.key;
|
||||
|
||||
const params = {
|
||||
'X-Plex-Client-Identifier': 'SyncLounge',
|
||||
key: data.key,
|
||||
offset,
|
||||
machineIdentifier: serverId,
|
||||
address,
|
||||
port,
|
||||
protocol,
|
||||
path,
|
||||
wait: 0,
|
||||
token: data.server.accessToken,
|
||||
};
|
||||
const command = '/player/playback/playMedia';
|
||||
const offset = Math.round(data.offset) || 0;
|
||||
const serverId = data.server.clientIdentifier;
|
||||
const uri = new URL(data.server.chosenConnection.uri);
|
||||
const address = uri.hostname;
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
const port = uri.port !== '' ? uri.port : (uri.protocol === 'https:' ? '443' : '80'); // port not specified if standard
|
||||
const protocol = uri.protocol.replace(':', ''); // remove extra colon
|
||||
const path = data.server.chosenConnection.uri + data.key;
|
||||
|
||||
if (data.mediaIndex !== undefined || data.mediaIndex !== null) {
|
||||
params.mediaIndex = data.mediaIndex;
|
||||
}
|
||||
const params = {
|
||||
'X-Plex-Client-Identifier': 'SyncLounge',
|
||||
key: data.key,
|
||||
offset,
|
||||
machineIdentifier: serverId,
|
||||
address,
|
||||
port,
|
||||
protocol,
|
||||
path,
|
||||
wait: 0,
|
||||
token: data.server.accessToken,
|
||||
};
|
||||
|
||||
// Now that we've built our params, it's time to hit the client api
|
||||
await this.hitApi(command, params, this.chosenConnection);
|
||||
await this.waitForMovement();
|
||||
resolve(true);
|
||||
});
|
||||
if (data.mediaIndex !== undefined || data.mediaIndex !== null) {
|
||||
params.mediaIndex = data.mediaIndex;
|
||||
}
|
||||
|
||||
// Now that we've built our params, it's time to hit the client api
|
||||
await this.hitApi(command, params, this.chosenConnection);
|
||||
await this.waitForMovement();
|
||||
return true;
|
||||
}
|
||||
|
||||
playContentAutomatically(client, hostData, servers, offset) {
|
||||
async playContentAutomatically(client, hostData, servers, offset) {
|
||||
// Automatically play content on the client searching all servers based on the title
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// First lets find all of our playable items
|
||||
let playables = [];
|
||||
const serversArr = [];
|
||||
for (const i in servers) {
|
||||
serversArr.push(servers[i]);
|
||||
}
|
||||
await Promise.all(serversArr.map(async (server) => new Promise(async (resolve, reject) => {
|
||||
if (!server.chosenConnection) {
|
||||
return resolve();
|
||||
}
|
||||
const results = await server.search(hostData.rawTitle);
|
||||
for (let k = 0; k < results.length; k++) {
|
||||
// Now we need to check the result
|
||||
if (checkResult(results[k], hostData)) {
|
||||
// Its a match!
|
||||
playables.push({
|
||||
server,
|
||||
result: results[k],
|
||||
});
|
||||
}
|
||||
}
|
||||
resolve();
|
||||
})));
|
||||
playables = playables.sort((a, b) => parseInt(b.server.publicAddressMatches) - parseInt(a.server.publicAddressMatches));
|
||||
const start = async (index) => {
|
||||
// Now lets try and play our items one by one
|
||||
if (playables.length === 0 || index === playables.length) {
|
||||
return reject(new Error('Didnt find any playable items'));
|
||||
}
|
||||
const { server } = playables[index];
|
||||
const { key } = playables[index].result;
|
||||
const data = {
|
||||
key,
|
||||
mediaIndex: 0,
|
||||
server,
|
||||
offset: offset || 0,
|
||||
};
|
||||
|
||||
const res = await this.playMedia(data).catch(() => {
|
||||
start(parseInt(parseInt(index) + 1));
|
||||
});
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
return resolve();
|
||||
};
|
||||
start(0);
|
||||
|
||||
function checkResult(data, hostData) {
|
||||
// Do a series of checks to see if this result is OK
|
||||
// Check if rawTitle matches
|
||||
if (data.title !== hostData.rawTitle) {
|
||||
return false;
|
||||
}
|
||||
// Check if length is close enough
|
||||
if (Math.abs(parseInt(data.duration) - parseInt(hostData.maxTime)) > 1000 || !data.duration) {
|
||||
return false;
|
||||
}
|
||||
if (data.type === 'movie') {
|
||||
// We're good!
|
||||
return true;
|
||||
}
|
||||
if (data.type === 'episode') {
|
||||
// Check if the show name is the same
|
||||
const similarity = stringSimilarity.compareTwoStrings(data.grandparentTitle, hostData.showName);
|
||||
return similarity > 0.40;
|
||||
}
|
||||
if (data.type === 'track') {
|
||||
// We're good!
|
||||
return true;
|
||||
}
|
||||
function checkResult(data) {
|
||||
// Do a series of checks to see if this result is OK
|
||||
// Check if rawTitle matches
|
||||
if (data.title !== hostData.rawTitle) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// Check if length is close enough
|
||||
if (Math.abs(parseInt(data.duration, 10) - parseInt(hostData.maxTime, 10)) > 1000
|
||||
|| !data.duration) {
|
||||
return false;
|
||||
}
|
||||
if (data.type === 'movie') {
|
||||
// We're good!
|
||||
return true;
|
||||
}
|
||||
if (data.type === 'episode') {
|
||||
// Check if the show name is the same
|
||||
const similarity = stringSimilarity.compareTwoStrings(data.grandparentTitle,
|
||||
hostData.showName);
|
||||
return similarity > 0.40;
|
||||
}
|
||||
if (data.type === 'track') {
|
||||
// We're good!
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// First lets find all of our playable items
|
||||
let playables = [];
|
||||
const serversArr = Object.values(servers);
|
||||
|
||||
await Promise.all(serversArr.map(async (server) => {
|
||||
if (!server.chosenConnection) {
|
||||
return;
|
||||
}
|
||||
|
||||
const results = await server.search(hostData.rawTitle);
|
||||
for (let k = 0; k < results.length; k += 1) {
|
||||
// Now we need to check the result
|
||||
if (checkResult(results[k])) {
|
||||
// Its a match!
|
||||
playables.push({
|
||||
server,
|
||||
result: results[k],
|
||||
});
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
playables = playables.sort((a, b) => parseInt(b.server.publicAddressMatches, 10)
|
||||
- parseInt(a.server.publicAddressMatches, 10));
|
||||
|
||||
const start = async (index) => {
|
||||
// Now lets try and play our items one by one
|
||||
if (playables.length === 0 || index === playables.length) {
|
||||
throw new Error('Didnt find any playable items');
|
||||
}
|
||||
const { server } = playables[index];
|
||||
const { key } = playables[index].result;
|
||||
const data = {
|
||||
key,
|
||||
mediaIndex: 0,
|
||||
server,
|
||||
offset: offset || 0,
|
||||
};
|
||||
|
||||
await this.playMedia(data).catch(() => {
|
||||
start(parseInt(parseInt(index, 10) + 1, 10), 10);
|
||||
});
|
||||
};
|
||||
start(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ export default {
|
|||
},
|
||||
|
||||
socketConnect({
|
||||
state, commit, rootState, rootGetters,
|
||||
state, commit, rootGetters,
|
||||
}, data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { address } = data;
|
||||
|
@ -91,8 +91,8 @@ export default {
|
|||
}
|
||||
|
||||
console.log('Joining room', data.roomName);
|
||||
data.password = data.password || '';
|
||||
commit('SET_PASSWORD', data.password);
|
||||
|
||||
commit('SET_PASSWORD', data.password || '');
|
||||
let { username } = data.user;
|
||||
|
||||
if (rootGetters['settings/GET_HIDEUSERNAME']) {
|
||||
|
@ -101,10 +101,10 @@ export default {
|
|||
|
||||
state.socket.emit(
|
||||
'join',
|
||||
new HandshakeUser(data.user, data.roomName, data.password, rootState.uuid, username),
|
||||
new HandshakeUser(data.user, data.roomName, data.password || '', rootState.uuid, username),
|
||||
);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve) => {
|
||||
state.socket.on('join-result', async (result, _data, details, currentUsers, partyPausing) => {
|
||||
console.log('Got join result', result);
|
||||
commit('CLEAR_MESSAGES');
|
||||
|
@ -133,7 +133,7 @@ export default {
|
|||
urlOrigin = 'http://app.synclounge.tv';
|
||||
}
|
||||
|
||||
const data = {
|
||||
const inviteData = {
|
||||
urlOrigin,
|
||||
owner: rootGetters['settings/GET_PLEX_USER'].username || rootGetters['settings/GET_PLEX_USER'].title,
|
||||
server: state.server,
|
||||
|
@ -141,7 +141,7 @@ export default {
|
|||
password: state.password || '',
|
||||
};
|
||||
// if (settings.webroot) urlOrigin = urlOrigin + settings.webroot
|
||||
axios.post(`${urlOrigin}/invite`, data).then((res) => {
|
||||
axios.post(`${urlOrigin}/invite`, inviteData).then((res) => {
|
||||
commit('SET_SHORTLINK', res.data.url);
|
||||
});
|
||||
|
||||
|
@ -214,149 +214,154 @@ export default {
|
|||
});
|
||||
});
|
||||
|
||||
state.socket.on('host-update', async (data) => {
|
||||
data.recievedAt = new Date().getTime();
|
||||
const hostTimeline = data;
|
||||
state.socket.on('host-update', async (hostData) => {
|
||||
const hostUpdateData = hostData;
|
||||
hostUpdateData.recievedAt = new Date().getTime();
|
||||
const hostTimeline = hostUpdateData;
|
||||
if (
|
||||
!state.lastHostTimeline
|
||||
|| state.lastHostTimeline.playerState !== data.playerState
|
||||
|| state.lastHostTimeline.playerState !== hostUpdateData.playerState
|
||||
) {
|
||||
window.EventBus.$emit('host-playerstate-change');
|
||||
}
|
||||
const diffBetweenLastUpdate = Math.abs(state.lastHostTimeline.time - data.time);
|
||||
const diffBetweenLastUpdate = Math.abs(state.lastHostTimeline.time
|
||||
- hostUpdateData.time);
|
||||
if (diffBetweenLastUpdate > 5000) {
|
||||
window.EventBus.$emit('host-playerstate-change');
|
||||
}
|
||||
state.lastHostTimeline = data;
|
||||
const decisionMaker = (timelineAge) => {
|
||||
state.lastHostTimeline = hostUpdateData;
|
||||
const decisionMaker = async () => {
|
||||
const ourTimeline = rootState.chosenClient.lastTimelineObject;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (ourTimeline.playerState === 'buffering') {
|
||||
return resolve();
|
||||
}
|
||||
if (
|
||||
(hostTimeline.playerState === 'stopped' || !hostTimeline.playerState)
|
||||
&& ourTimeline.state !== 'stopped'
|
||||
) {
|
||||
sendNotification('The host pressed stop');
|
||||
await rootState.chosenClient.pressStop();
|
||||
return resolve();
|
||||
}
|
||||
|
||||
if (hostTimeline.playerState === 'stopped') {
|
||||
return resolve();
|
||||
}
|
||||
// Check if we need to autoplay
|
||||
if (
|
||||
((ourTimeline.state === 'stopped' || !ourTimeline.state)
|
||||
if (ourTimeline.playerState === 'buffering') {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
(hostTimeline.playerState === 'stopped' || !hostTimeline.playerState)
|
||||
&& ourTimeline.state !== 'stopped'
|
||||
) {
|
||||
sendNotification('The host pressed stop');
|
||||
await rootState.chosenClient.pressStop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (hostTimeline.playerState === 'stopped') {
|
||||
return;
|
||||
}
|
||||
// Check if we need to autoplay
|
||||
if (
|
||||
((ourTimeline.state === 'stopped' || !ourTimeline.state)
|
||||
&& hostTimeline.playerState !== 'stopped')
|
||||
|| state.rawTitle !== hostTimeline.rawTitle
|
||||
) {
|
||||
if (rootState.blockAutoPlay || !hostTimeline.rawTitle) {
|
||||
return resolve();
|
||||
}
|
||||
// We need to autoplay!
|
||||
if (!rootGetters['settings/GET_AUTOPLAY']) {
|
||||
return resolve();
|
||||
}
|
||||
commit('SET_BLOCK_AUTOPLAY', true, { root: true });
|
||||
) {
|
||||
if (rootState.blockAutoPlay || !hostTimeline.rawTitle) {
|
||||
return;
|
||||
}
|
||||
// We need to autoplay!
|
||||
if (!rootGetters['settings/GET_AUTOPLAY']) {
|
||||
return;
|
||||
}
|
||||
commit('SET_BLOCK_AUTOPLAY', true, { root: true });
|
||||
|
||||
const servers = { ...rootState.plex.servers };
|
||||
rootGetters['settings/GET_BLOCKEDSERVERS'].forEach((id) => {
|
||||
if (rootState.plex.servers[id]) {
|
||||
delete servers[id];
|
||||
const servers = { ...rootState.plex.servers };
|
||||
rootGetters['settings/GET_BLOCKEDSERVERS'].forEach((id) => {
|
||||
if (rootState.plex.servers[id]) {
|
||||
delete servers[id];
|
||||
}
|
||||
});
|
||||
|
||||
commit('SET_RAW_TITLE', hostTimeline.rawTitle);
|
||||
sendNotification(`Searching Plex Servers for "${hostTimeline.rawTitle}"`);
|
||||
await rootState.chosenClient
|
||||
.playContentAutomatically(
|
||||
rootState.chosenClient,
|
||||
hostTimeline,
|
||||
servers,
|
||||
hostTimeline.time,
|
||||
)
|
||||
.catch(async () => {
|
||||
const hostServer = rootState.plex.servers[hostTimeline.machineIdentifier];
|
||||
if (hostServer && hostTimeline.key) {
|
||||
if (
|
||||
!rootGetters['settings/GET_BLOCKEDSERVERS'].includes(
|
||||
hostTimeline.machineIdentifier,
|
||||
)
|
||||
) {
|
||||
await rootState.chosenClient.playMedia({
|
||||
// TODO: have timeline updates send out more info like mediaIdentifier etc
|
||||
key: hostTimeline.key,
|
||||
mediaIndex: 0,
|
||||
server: rootState.plex.servers[hostTimeline.machineIdentifier],
|
||||
offset: hostTimeline.time || 0,
|
||||
}).catch(() => {});
|
||||
setTimeout(() => {
|
||||
commit('SET_BLOCK_AUTOPLAY', false, { root: true });
|
||||
}, 15000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
sendNotification(
|
||||
`Failed to find a compatible copy of ${hostTimeline.rawTitle}. If you have access to the content try manually playing it.`,
|
||||
);
|
||||
setTimeout(() => {
|
||||
commit('SET_BLOCK_AUTOPLAY', false, { root: true });
|
||||
}, 15000);
|
||||
});
|
||||
|
||||
commit('SET_RAW_TITLE', hostTimeline.rawTitle);
|
||||
sendNotification(`Searching Plex Servers for "${hostTimeline.rawTitle}"`);
|
||||
const result = await rootState.chosenClient
|
||||
.playContentAutomatically(
|
||||
rootState.chosenClient,
|
||||
hostTimeline,
|
||||
servers,
|
||||
hostTimeline.time,
|
||||
)
|
||||
.catch(async () => {
|
||||
const hostServer = rootState.plex.servers[hostTimeline.machineIdentifier];
|
||||
if (hostServer && hostTimeline.key) {
|
||||
if (
|
||||
!rootGetters['settings/GET_BLOCKEDSERVERS'].includes(
|
||||
hostTimeline.machineIdentifier,
|
||||
)
|
||||
) {
|
||||
await rootState.chosenClient.playMedia({
|
||||
// TODO: have timeline updates send out more info like mediaIdentifier etc
|
||||
key: hostTimeline.key,
|
||||
mediaIndex: 0,
|
||||
server: rootState.plex.servers[hostTimeline.machineIdentifier],
|
||||
offset: hostTimeline.time || 0,
|
||||
}).catch(() => {});
|
||||
setTimeout(() => {
|
||||
commit('SET_BLOCK_AUTOPLAY', false, { root: true });
|
||||
}, 15000);
|
||||
return resolve();
|
||||
}
|
||||
}
|
||||
sendNotification(
|
||||
`Failed to find a compatible copy of ${hostTimeline.rawTitle}. If you have access to the content try manually playing it.`,
|
||||
);
|
||||
setTimeout(() => {
|
||||
commit('SET_BLOCK_AUTOPLAY', false, { root: true });
|
||||
}, 15000);
|
||||
});
|
||||
await delay(1000);
|
||||
|
||||
await delay(1000);
|
||||
setTimeout(() => {
|
||||
commit('SET_BLOCK_AUTOPLAY', false, { root: true });
|
||||
}, 10000);
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
commit('SET_BLOCK_AUTOPLAY', false, { root: true });
|
||||
}, 10000);
|
||||
return resolve();
|
||||
}
|
||||
|
||||
if (hostTimeline.playerState === 'playing' && ourTimeline.state === 'paused') {
|
||||
sendNotification('Resuming..');
|
||||
return resolve(await rootState.chosenClient.pressPlay());
|
||||
}
|
||||
if ((hostTimeline.playerState === 'paused'
|
||||
if (hostTimeline.playerState === 'playing' && ourTimeline.state === 'paused') {
|
||||
sendNotification('Resuming..');
|
||||
resolve(await rootState.chosenClient.pressPlay());
|
||||
return;
|
||||
}
|
||||
if ((hostTimeline.playerState === 'paused'
|
||||
|| hostTimeline.playerState === 'buffering')
|
||||
&& ourTimeline.state === 'playing') {
|
||||
sendNotification('Pausing..');
|
||||
return resolve(await rootState.chosenClient.pressPause());
|
||||
}
|
||||
if (hostTimeline.playerState === 'playing') {
|
||||
// Add on the delay between us and the SLServer plus the delay between the server and the host
|
||||
try {
|
||||
const ourLastDelay = Math.round(
|
||||
state.commands[Object.keys(state.commands).length - 1].difference,
|
||||
);
|
||||
const hostLastDelay = Math.round(hostTimeline.latency);
|
||||
// console.log('adding delays', { ourLastDelay, hostLastDelay });
|
||||
if (ourLastDelay && hostLastDelay) {
|
||||
// console.log(
|
||||
// 'Adding host delay',
|
||||
// hostLastDelay,
|
||||
// 'and our lastDelay',
|
||||
// ourLastDelay,
|
||||
// );
|
||||
data.time = data.time + (ourLastDelay || 0) + (hostLastDelay || 0);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Failed to add extra lag time');
|
||||
}
|
||||
}
|
||||
sendNotification('Pausing..');
|
||||
resolve(await rootState.chosenClient.pressPause());
|
||||
return;
|
||||
}
|
||||
if (hostTimeline.playerState === 'playing') {
|
||||
// Add on the delay between us and the SLServer plus the delay between the server and the host
|
||||
try {
|
||||
await rootState.chosenClient.sync(
|
||||
data,
|
||||
rootGetters['settings/GET_SYNCFLEXIBILITY'],
|
||||
rootGetters['settings/GET_SYNCMODE'],
|
||||
rootGetters['settings/GET_CLIENTPOLLINTERVAL'],
|
||||
const ourLastDelay = Math.round(
|
||||
state.commands[Object.keys(state.commands).length - 1].difference,
|
||||
);
|
||||
const hostLastDelay = Math.round(hostTimeline.latency);
|
||||
// console.log('adding delays', { ourLastDelay, hostLastDelay });
|
||||
if (ourLastDelay && hostLastDelay) {
|
||||
// console.log(
|
||||
// 'Adding host delay',
|
||||
// hostLastDelay,
|
||||
// 'and our lastDelay',
|
||||
// ourLastDelay,
|
||||
// );
|
||||
hostUpdateData.time = hostUpdateData.time + (ourLastDelay || 0)
|
||||
+ (hostLastDelay || 0);
|
||||
}
|
||||
} catch (e) {
|
||||
return resolve();
|
||||
console.log('Failed to add extra lag time');
|
||||
}
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
try {
|
||||
await rootState.chosenClient.sync(
|
||||
hostUpdateData,
|
||||
rootGetters['settings/GET_SYNCFLEXIBILITY'],
|
||||
rootGetters['settings/GET_SYNCMODE'],
|
||||
rootGetters['settings/GET_CLIENTPOLLINTERVAL'],
|
||||
);
|
||||
} catch (e) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
/* This is data from the host, we should react to this data by potentially changing
|
||||
what we're playing or seeking to get back in sync with the host.
|
||||
|
@ -389,6 +394,8 @@ export default {
|
|||
if (!rootState.chosenClient.lastTimelineObject) {
|
||||
console.log('Dont have our first timeline data yet.');
|
||||
if (rootState.chosenClient.clientIdentifier === 'PTPLAYER9PLUS10') {
|
||||
// TODO: come back and fix this
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
rootState.chosenClient.lastTimelineObject = {
|
||||
playerState: 'stopped',
|
||||
};
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import parser from 'fast-xml-parser';
|
||||
|
||||
const options = {
|
||||
attributeNamePrefix: '',
|
||||
ignoreAttributes: false,
|
||||
arrayMode: true,
|
||||
};
|
||||
|
||||
export default {
|
||||
parseXML: (xml) => parser.parse(xml, options),
|
||||
};
|
Loading…
Reference in New Issue