2020-08-14 08:46:34 +02:00
|
|
|
import datetime from '../../scripts/datetime';
|
|
|
|
import backdrop from '../backdrop/backdrop';
|
|
|
|
import listView from '../listview/listview';
|
|
|
|
import imageLoader from '../images/imageLoader';
|
|
|
|
import playbackManager from '../playback/playbackmanager';
|
|
|
|
import nowPlayingHelper from '../playback/nowplayinghelper';
|
|
|
|
import events from 'jellyfin-apiclient';
|
|
|
|
import connectionManager from 'jellyfin-apiclient';
|
|
|
|
import appHost from '../apphost';
|
|
|
|
import globalize from '../../scripts/globalize';
|
|
|
|
import layoutManager from '../layoutManager';
|
|
|
|
import * as userSettings from '../../scripts/settings/userSettings';
|
|
|
|
import cardBuilder from '../cardbuilder/cardBuilder';
|
|
|
|
import itemContextMenu from '../itemContextMenu';
|
|
|
|
import '../cardbuilder/card.css';
|
|
|
|
import '../../elements/emby-itemscontainer/emby-itemscontainer';
|
|
|
|
import './remotecontrol.css';
|
|
|
|
import '../../elements/emby-ratingbutton/emby-ratingbutton';
|
2020-08-06 15:55:10 +01:00
|
|
|
|
|
|
|
/*eslint prefer-const: "error"*/
|
|
|
|
|
|
|
|
let showMuteButton = true;
|
|
|
|
let showVolumeSlider = true;
|
|
|
|
|
|
|
|
function showAudioMenu(context, player, button, item) {
|
|
|
|
const currentIndex = playbackManager.getAudioStreamIndex(player);
|
|
|
|
const streams = playbackManager.audioTracks(player);
|
|
|
|
const menuItems = streams.map(function (s) {
|
|
|
|
const menuItem = {
|
|
|
|
name: s.DisplayTitle,
|
|
|
|
id: s.Index
|
|
|
|
};
|
2020-07-31 09:12:44 +01:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (s.Index == currentIndex) {
|
|
|
|
menuItem.selected = true;
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
return menuItem;
|
|
|
|
});
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../actionSheet/actionSheet').then((actionsheet) => {
|
2020-08-06 15:55:10 +01:00
|
|
|
actionsheet.show({
|
|
|
|
items: menuItems,
|
|
|
|
positionTo: button,
|
|
|
|
callback: function (id) {
|
|
|
|
playbackManager.setAudioStreamIndex(parseInt(id), player);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
|
|
|
});
|
2020-08-06 15:55:10 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function showSubtitleMenu(context, player, button, item) {
|
|
|
|
const currentIndex = playbackManager.getSubtitleStreamIndex(player);
|
|
|
|
const streams = playbackManager.subtitleTracks(player);
|
|
|
|
const menuItems = streams.map(function (s) {
|
|
|
|
const menuItem = {
|
|
|
|
name: s.DisplayTitle,
|
|
|
|
id: s.Index
|
|
|
|
};
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (s.Index == currentIndex) {
|
|
|
|
menuItem.selected = true;
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
return menuItem;
|
|
|
|
});
|
|
|
|
menuItems.unshift({
|
|
|
|
id: -1,
|
2020-08-16 20:34:39 +09:00
|
|
|
name: globalize.translate('Off'),
|
2020-08-06 15:55:10 +01:00
|
|
|
selected: currentIndex == null
|
|
|
|
});
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../actionSheet/actionSheet').then((actionsheet) => {
|
2020-08-06 15:55:10 +01:00
|
|
|
actionsheet.show({
|
|
|
|
items: menuItems,
|
|
|
|
positionTo: button,
|
|
|
|
callback: function (id) {
|
|
|
|
playbackManager.setSubtitleStreamIndex(parseInt(id), player);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
|
|
|
});
|
2020-08-06 15:55:10 +01:00
|
|
|
});
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function getNowPlayingNameHtml(nowPlayingItem, includeNonNameInfo) {
|
|
|
|
return nowPlayingHelper.getNowPlayingNames(nowPlayingItem, includeNonNameInfo).map(function (i) {
|
|
|
|
return i.text;
|
|
|
|
}).join('<br/>');
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function seriesImageUrl(item, options) {
|
|
|
|
if (item.Type !== 'Episode') {
|
|
|
|
return null;
|
2019-02-02 11:08:20 -05:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
options = options || {};
|
|
|
|
options.type = options.type || 'Primary';
|
|
|
|
if (options.type === 'Primary' && item.SeriesPrimaryImageTag) {
|
|
|
|
options.tag = item.SeriesPrimaryImageTag;
|
2020-08-30 06:06:47 +02:00
|
|
|
return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (options.type === 'Thumb') {
|
|
|
|
if (item.SeriesThumbImageTag) {
|
|
|
|
options.tag = item.SeriesThumbImageTag;
|
2020-08-30 06:06:47 +02:00
|
|
|
return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (item.ParentThumbImageTag) {
|
|
|
|
options.tag = item.ParentThumbImageTag;
|
2020-08-30 06:06:47 +02:00
|
|
|
return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
return null;
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function imageUrl(item, options) {
|
|
|
|
options = options || {};
|
|
|
|
options.type = options.type || 'Primary';
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (item.ImageTags && item.ImageTags[options.type]) {
|
|
|
|
options.tag = item.ImageTags[options.type];
|
2020-08-30 06:06:47 +02:00
|
|
|
return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options);
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
|
|
|
options.tag = item.AlbumPrimaryImageTag;
|
2020-08-30 06:06:47 +02:00
|
|
|
return window.connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options);
|
2019-02-02 11:08:20 -05:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateNowPlayingInfo(context, state, serverId) {
|
|
|
|
const item = state.NowPlayingItem;
|
|
|
|
const displayName = item ? getNowPlayingNameHtml(item).replace('<br/>', ' - ') : '';
|
2020-08-26 17:05:01 -04:00
|
|
|
if (item) {
|
2020-08-06 15:55:10 +01:00
|
|
|
const nowPlayingServerId = (item.ServerId || serverId);
|
|
|
|
if (item.Type == 'Audio' || item.MediaStreams[0].Type == 'Audio') {
|
|
|
|
const songName = item.Name;
|
|
|
|
let artistsSeries = '';
|
|
|
|
let albumName = '';
|
|
|
|
if (item.Artists != null) {
|
|
|
|
if (item.ArtistItems != null) {
|
|
|
|
for (const artist of item.ArtistItems) {
|
|
|
|
const artistName = artist.Name;
|
|
|
|
const artistId = artist.Id;
|
|
|
|
artistsSeries += `<a class="button-link emby-button" is="emby-linkbutton" href="details?id=${artistId}&serverId=${nowPlayingServerId}">${artistName}</a>`;
|
|
|
|
if (artist !== item.ArtistItems.slice(-1)[0]) {
|
|
|
|
artistsSeries += ', ';
|
2020-06-22 12:41:22 +02:00
|
|
|
}
|
2020-04-12 10:55:52 -04:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
} else if (item.Artists) {
|
|
|
|
// For some reason, Chromecast Player doesn't return a item.ArtistItems object, so we need to fallback
|
|
|
|
// to normal item.Artists item.
|
|
|
|
// TODO: Normalise fields returned by all the players
|
|
|
|
for (const artist of item.Artists) {
|
|
|
|
artistsSeries += `<a>${artist}</a>`;
|
|
|
|
if (artist !== item.Artists.slice(-1)[0]) {
|
|
|
|
artistsSeries += ', ';
|
|
|
|
}
|
2020-04-12 10:55:52 -04:00
|
|
|
}
|
|
|
|
}
|
2020-04-10 13:06:26 -04:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
if (item.Album != null) {
|
|
|
|
albumName = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.AlbumId + `&serverId=${nowPlayingServerId}">` + item.Album + '</a>';
|
|
|
|
}
|
|
|
|
context.querySelector('.nowPlayingAlbum').innerHTML = albumName;
|
|
|
|
context.querySelector('.nowPlayingArtist').innerHTML = artistsSeries;
|
|
|
|
context.querySelector('.nowPlayingSongName').innerHTML = songName;
|
|
|
|
} else if (item.Type == 'Episode') {
|
|
|
|
if (item.SeasonName != null) {
|
|
|
|
const seasonName = item.SeasonName;
|
|
|
|
context.querySelector('.nowPlayingSeason').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.SeasonId + `&serverId=${nowPlayingServerId}">${seasonName}</a>`;
|
|
|
|
}
|
|
|
|
if (item.SeriesName != null) {
|
|
|
|
const seriesName = item.SeriesName;
|
|
|
|
if (item.SeriesId != null) {
|
|
|
|
context.querySelector('.nowPlayingSerie').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.SeriesId + `&serverId=${nowPlayingServerId}">${seriesName}</a>`;
|
|
|
|
} else {
|
|
|
|
context.querySelector('.nowPlayingSerie').innerHTML = seriesName;
|
|
|
|
}
|
2020-04-12 10:55:52 -04:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
context.querySelector('.nowPlayingEpisode').innerHTML = item.Name;
|
|
|
|
} else {
|
|
|
|
context.querySelector('.nowPlayingPageTitle').innerHTML = displayName;
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (displayName.length > 0 && item.Type != 'Audio' && item.Type != 'Episode') {
|
|
|
|
context.querySelector('.nowPlayingPageTitle').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
context.querySelector('.nowPlayingPageTitle').classList.add('hide');
|
|
|
|
}
|
|
|
|
|
2020-08-26 17:18:23 -04:00
|
|
|
const url = seriesImageUrl(item, {
|
2020-08-06 15:55:10 +01:00
|
|
|
maxHeight: 300
|
|
|
|
}) || imageUrl(item, {
|
|
|
|
maxHeight: 300
|
2020-08-26 17:18:23 -04:00
|
|
|
});
|
2020-08-06 15:55:10 +01:00
|
|
|
|
|
|
|
let contextButton = context.querySelector('.btnToggleContextMenu');
|
|
|
|
// We remove the previous event listener by replacing the item in each update event
|
|
|
|
const autoFocusContextButton = document.activeElement === contextButton;
|
|
|
|
const contextButtonClone = contextButton.cloneNode(true);
|
|
|
|
contextButton.parentNode.replaceChild(contextButtonClone, contextButton);
|
|
|
|
contextButton = context.querySelector('.btnToggleContextMenu');
|
|
|
|
if (autoFocusContextButton) {
|
|
|
|
contextButton.focus();
|
|
|
|
}
|
|
|
|
const stopPlayback = !!layoutManager.mobile;
|
|
|
|
const options = {
|
|
|
|
play: false,
|
|
|
|
queue: false,
|
|
|
|
stopPlayback: stopPlayback,
|
|
|
|
clearQueue: true,
|
|
|
|
openAlbum: false,
|
|
|
|
positionTo: contextButton
|
|
|
|
};
|
2020-08-30 06:06:47 +02:00
|
|
|
const apiClient = window.connectionManager.getApiClient(item.ServerId);
|
2020-08-06 15:55:10 +01:00
|
|
|
apiClient.getItem(apiClient.getCurrentUserId(), item.Id).then(function (fullItem) {
|
|
|
|
apiClient.getCurrentUser().then(function (user) {
|
|
|
|
contextButton.addEventListener('click', function () {
|
|
|
|
itemContextMenu.show(Object.assign({
|
|
|
|
item: fullItem,
|
|
|
|
user: user
|
|
|
|
}, options));
|
2020-06-17 22:09:30 +02:00
|
|
|
});
|
|
|
|
});
|
2020-08-06 15:55:10 +01:00
|
|
|
});
|
|
|
|
setImageUrl(context, state, url);
|
2020-08-26 18:35:20 -04:00
|
|
|
backdrop.setBackdrops([item]);
|
|
|
|
apiClient.getItem(apiClient.getCurrentUserId(), item.Id).then(function (fullItem) {
|
|
|
|
const userData = fullItem.UserData || {};
|
|
|
|
const likes = userData.Likes == null ? '' : userData.Likes;
|
|
|
|
context.querySelector('.nowPlayingPageUserDataButtonsTitle').innerHTML = '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + fullItem.Id + '" data-serverid="' + fullItem.ServerId + '" data-itemtype="' + fullItem.Type + '" data-likes="' + likes + '" data-isfavorite="' + userData.IsFavorite + '"><span class="material-icons favorite"></span></button>';
|
|
|
|
context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + fullItem.Id + '" data-serverid="' + fullItem.ServerId + '" data-itemtype="' + fullItem.Type + '" data-likes="' + likes + '" data-isfavorite="' + userData.IsFavorite + '"><span class="material-icons favorite"></span></button>';
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
backdrop.clearBackdrop();
|
|
|
|
context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '';
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function setImageUrl(context, state, url) {
|
|
|
|
const item = state.NowPlayingItem;
|
|
|
|
const imgContainer = context.querySelector('.nowPlayingPageImageContainer');
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (url) {
|
|
|
|
imgContainer.innerHTML = '<img class="nowPlayingPageImage" src="' + url + '" />';
|
|
|
|
if (item.Type == 'Audio') {
|
|
|
|
context.querySelector('.nowPlayingPageImage').classList.add('nowPlayingPageImageAudio');
|
|
|
|
context.querySelector('.nowPlayingPageImageContainer').classList.remove('nowPlayingPageImageAudio');
|
2019-02-02 11:14:40 -05:00
|
|
|
} else {
|
2020-08-06 15:55:10 +01:00
|
|
|
context.querySelector('.nowPlayingPageImageContainer').classList.add('nowPlayingPageImagePoster');
|
|
|
|
context.querySelector('.nowPlayingPageImage').classList.remove('nowPlayingPageImageAudio');
|
2019-02-02 11:08:20 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
} else {
|
|
|
|
imgContainer.innerHTML = '<div class="nowPlayingPageImageContainerNoAlbum"><button data-action="link" class="cardImageContainer coveredImage ' + cardBuilder.getDefaultBackgroundClass(item.Name) + ' cardContent cardContent-shadow itemAction"><span class="cardImageIcon material-icons album"></span></button></div>';
|
2019-02-02 11:08:20 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function buttonVisible(btn, enabled) {
|
|
|
|
if (enabled) {
|
|
|
|
btn.classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
btn.classList.add('hide');
|
2019-02-02 11:08:20 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function updateSupportedCommands(context, commands) {
|
|
|
|
const all = context.querySelectorAll('.btnCommand');
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
for (let i = 0, length = all.length; i < length; i++) {
|
|
|
|
const enableButton = commands.indexOf(all[i].getAttribute('data-command')) !== -1;
|
|
|
|
all[i].disabled = !enableButton;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default function () {
|
|
|
|
function toggleRepeat() {
|
|
|
|
switch (playbackManager.getRepeatMode()) {
|
|
|
|
case 'RepeatAll':
|
|
|
|
playbackManager.setRepeatMode('RepeatOne');
|
|
|
|
break;
|
|
|
|
case 'RepeatOne':
|
|
|
|
playbackManager.setRepeatMode('RepeatNone');
|
|
|
|
break;
|
|
|
|
case 'RepeatNone':
|
|
|
|
playbackManager.setRepeatMode('RepeatAll');
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
}
|
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function updatePlayerState(player, context, state) {
|
|
|
|
lastPlayerState = state;
|
|
|
|
const item = state.NowPlayingItem;
|
|
|
|
const playerInfo = playbackManager.getPlayerInfo();
|
|
|
|
const supportedCommands = playerInfo.supportedCommands;
|
|
|
|
currentPlayerSupportedCommands = supportedCommands;
|
|
|
|
const playState = state.PlayState || {};
|
|
|
|
const isSupportedCommands = supportedCommands.includes('DisplayMessage') || supportedCommands.includes('SendString') || supportedCommands.includes('Select');
|
|
|
|
buttonVisible(context.querySelector('.btnToggleFullscreen'), item && item.MediaType == 'Video' && supportedCommands.includes('ToggleFullscreen'));
|
|
|
|
updateAudioTracksDisplay(player, context);
|
|
|
|
updateSubtitleTracksDisplay(player, context);
|
|
|
|
|
|
|
|
if (supportedCommands.includes('DisplayMessage') && !currentPlayer.isLocalPlayer) {
|
|
|
|
context.querySelector('.sendMessageSection').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
context.querySelector('.sendMessageSection').classList.add('hide');
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (supportedCommands.includes('SendString') && !currentPlayer.isLocalPlayer) {
|
|
|
|
context.querySelector('.sendTextSection').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
context.querySelector('.sendTextSection').classList.add('hide');
|
|
|
|
}
|
2020-02-19 02:10:40 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (supportedCommands.includes('Select') && !currentPlayer.isLocalPlayer) {
|
|
|
|
context.querySelector('.navigationSection').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
context.querySelector('.navigationSection').classList.add('hide');
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (isSupportedCommands && !currentPlayer.isLocalPlayer) {
|
|
|
|
context.querySelector('.remoteControlSection').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
context.querySelector('.remoteControlSection').classList.add('hide');
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
buttonVisible(context.querySelector('.btnStop'), item != null);
|
|
|
|
buttonVisible(context.querySelector('.btnNextTrack'), item != null);
|
|
|
|
buttonVisible(context.querySelector('.btnPreviousTrack'), item != null);
|
|
|
|
if (layoutManager.mobile) {
|
2020-08-19 19:19:23 -04:00
|
|
|
const playingVideo = playbackManager.isPlayingVideo() && item !== null;
|
|
|
|
const playingAudio = !playbackManager.isPlayingVideo() && item !== null;
|
2020-08-15 14:33:31 -04:00
|
|
|
buttonVisible(context.querySelector('.btnRepeat'), playingAudio);
|
|
|
|
buttonVisible(context.querySelector('.btnShuffleQueue'), playingAudio);
|
|
|
|
buttonVisible(context.querySelector('.btnRewind'), playingVideo);
|
|
|
|
buttonVisible(context.querySelector('.btnFastForward'), playingVideo);
|
|
|
|
buttonVisible(context.querySelector('.nowPlayingSecondaryButtons .btnShuffleQueue'), playingVideo);
|
|
|
|
buttonVisible(context.querySelector('.nowPlayingSecondaryButtons .btnRepeat'), playingVideo);
|
2020-08-06 15:55:10 +01:00
|
|
|
} else {
|
|
|
|
buttonVisible(context.querySelector('.btnRewind'), item != null);
|
|
|
|
buttonVisible(context.querySelector('.btnFastForward'), item != null);
|
|
|
|
}
|
|
|
|
const positionSlider = context.querySelector('.nowPlayingPositionSlider');
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (positionSlider && item && item.RunTimeTicks) {
|
|
|
|
positionSlider.setKeyboardSteps(userSettings.skipBackLength() * 1000000 / item.RunTimeTicks,
|
|
|
|
userSettings.skipForwardLength() * 1000000 / item.RunTimeTicks);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (positionSlider && !positionSlider.dragging) {
|
|
|
|
positionSlider.disabled = !playState.CanSeek;
|
|
|
|
const isProgressClear = state.MediaSource && state.MediaSource.RunTimeTicks == null;
|
|
|
|
positionSlider.setIsClear(isProgressClear);
|
2019-02-02 11:08:20 -05:00
|
|
|
}
|
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
updatePlayPauseState(playState.IsPaused, item != null);
|
|
|
|
updateTimeDisplay(playState.PositionTicks, item ? item.RunTimeTicks : null);
|
|
|
|
updatePlayerVolumeState(context, playState.IsMuted, playState.VolumeLevel);
|
|
|
|
|
|
|
|
if (item && item.MediaType == 'Video') {
|
|
|
|
context.classList.remove('hideVideoButtons');
|
|
|
|
} else {
|
|
|
|
context.classList.add('hideVideoButtons');
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
updateRepeatModeDisplay(playbackManager.getRepeatMode());
|
|
|
|
onShuffleQueueModeChange(false);
|
|
|
|
updateNowPlayingInfo(context, state);
|
|
|
|
}
|
2020-06-23 19:09:22 +02:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function updateAudioTracksDisplay(player, context) {
|
|
|
|
const supportedCommands = currentPlayerSupportedCommands;
|
|
|
|
buttonVisible(context.querySelector('.btnAudioTracks'), playbackManager.audioTracks(player).length > 1 && supportedCommands.indexOf('SetAudioStreamIndex') != -1);
|
|
|
|
}
|
2020-06-23 19:09:22 +02:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function updateSubtitleTracksDisplay(player, context) {
|
|
|
|
const supportedCommands = currentPlayerSupportedCommands;
|
|
|
|
buttonVisible(context.querySelector('.btnSubtitles'), playbackManager.subtitleTracks(player).length && supportedCommands.indexOf('SetSubtitleStreamIndex') != -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateRepeatModeDisplay(repeatMode) {
|
|
|
|
const context = dlg;
|
|
|
|
const toggleRepeatButtons = context.querySelectorAll('.repeatToggleButton');
|
|
|
|
const cssClass = 'buttonActive';
|
|
|
|
let innHtml = '<span class="material-icons repeat"></span>';
|
|
|
|
let repeatOn = true;
|
|
|
|
|
|
|
|
switch (repeatMode) {
|
|
|
|
case 'RepeatAll':
|
|
|
|
break;
|
|
|
|
case 'RepeatOne':
|
|
|
|
innHtml = '<span class="material-icons repeat_one"></span>';
|
|
|
|
break;
|
|
|
|
case 'RepeatNone':
|
|
|
|
default:
|
|
|
|
repeatOn = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const toggleRepeatButton of toggleRepeatButtons) {
|
|
|
|
toggleRepeatButton.classList.toggle(cssClass, repeatOn);
|
|
|
|
toggleRepeatButton.innerHTML = innHtml;
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function updatePlayerVolumeState(context, isMuted, volumeLevel) {
|
|
|
|
const view = context;
|
|
|
|
const supportedCommands = currentPlayerSupportedCommands;
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (supportedCommands.indexOf('Mute') === -1) {
|
|
|
|
showMuteButton = false;
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (supportedCommands.indexOf('SetVolume') === -1) {
|
|
|
|
showVolumeSlider = false;
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (currentPlayer.isLocalPlayer && appHost.supports('physicalvolumecontrol')) {
|
|
|
|
showMuteButton = false;
|
|
|
|
showVolumeSlider = false;
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
const buttonMute = view.querySelector('.buttonMute');
|
|
|
|
const buttonMuteIcon = buttonMute.querySelector('.material-icons');
|
2020-05-02 14:02:44 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
buttonMuteIcon.classList.remove('volume_off', 'volume_up');
|
2020-05-02 14:02:44 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (isMuted) {
|
|
|
|
buttonMute.setAttribute('title', globalize.translate('Unmute'));
|
|
|
|
buttonMuteIcon.classList.add('volume_off');
|
|
|
|
} else {
|
|
|
|
buttonMute.setAttribute('title', globalize.translate('Mute'));
|
|
|
|
buttonMuteIcon.classList.add('volume_up');
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (!showMuteButton && !showVolumeSlider) {
|
|
|
|
context.querySelector('.volumecontrol').classList.add('hide');
|
|
|
|
} else {
|
|
|
|
buttonMute.classList.toggle('hide', !showMuteButton);
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
const nowPlayingVolumeSlider = context.querySelector('.nowPlayingVolumeSlider');
|
|
|
|
const nowPlayingVolumeSliderContainer = context.querySelector('.nowPlayingVolumeSliderContainer');
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (nowPlayingVolumeSlider) {
|
|
|
|
nowPlayingVolumeSliderContainer.classList.toggle('hide', !showVolumeSlider);
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (!nowPlayingVolumeSlider.dragging) {
|
|
|
|
nowPlayingVolumeSlider.value = volumeLevel || 0;
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function updatePlayPauseState(isPaused, isActive) {
|
|
|
|
const context = dlg;
|
|
|
|
const btnPlayPause = context.querySelector('.btnPlayPause');
|
|
|
|
const btnPlayPauseIcon = btnPlayPause.querySelector('.material-icons');
|
2020-05-02 14:02:44 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
btnPlayPauseIcon.classList.remove('play_circle_filled', 'pause_circle_filled');
|
|
|
|
btnPlayPauseIcon.classList.add(isPaused ? 'play_circle_filled' : 'pause_circle_filled');
|
2020-05-02 14:02:44 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
buttonVisible(btnPlayPause, isActive);
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function updateTimeDisplay(positionTicks, runtimeTicks) {
|
|
|
|
const context = dlg;
|
|
|
|
const positionSlider = context.querySelector('.nowPlayingPositionSlider');
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (positionSlider && !positionSlider.dragging) {
|
|
|
|
if (runtimeTicks) {
|
|
|
|
let pct = positionTicks / runtimeTicks;
|
|
|
|
pct *= 100;
|
|
|
|
positionSlider.value = pct;
|
|
|
|
} else {
|
|
|
|
positionSlider.value = 0;
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
context.querySelector('.positionTime').innerHTML = positionTicks == null ? '--:--' : datetime.getDisplayRunningTime(positionTicks);
|
|
|
|
context.querySelector('.runtime').innerHTML = runtimeTicks != null ? datetime.getDisplayRunningTime(runtimeTicks) : '--:--';
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function getPlaylistItems(player) {
|
|
|
|
return playbackManager.getPlaylist(player);
|
|
|
|
}
|
2020-06-23 23:45:21 +02:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function loadPlaylist(context, player) {
|
|
|
|
getPlaylistItems(player).then(function (items) {
|
|
|
|
let html = '';
|
|
|
|
let favoritesEnabled = true;
|
|
|
|
if (layoutManager.mobile) {
|
|
|
|
if (items.length > 0) {
|
|
|
|
context.querySelector('.btnTogglePlaylist').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
context.querySelector('.btnTogglePlaylist').classList.add('hide');
|
|
|
|
}
|
|
|
|
favoritesEnabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
html += listView.getListViewHtml({
|
|
|
|
items: items,
|
|
|
|
smallIcon: true,
|
|
|
|
action: 'setplaylistindex',
|
|
|
|
enableUserDataButtons: favoritesEnabled,
|
|
|
|
rightButtons: [{
|
|
|
|
icon: 'remove_circle_outline',
|
|
|
|
title: globalize.translate('ButtonRemove'),
|
|
|
|
id: 'remove'
|
|
|
|
}],
|
|
|
|
dragHandle: true
|
|
|
|
});
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
const itemsContainer = context.querySelector('.playlist');
|
|
|
|
let focusedItemPlaylistId = itemsContainer.querySelector('button:focus');
|
|
|
|
itemsContainer.innerHTML = html;
|
|
|
|
if (focusedItemPlaylistId !== null) {
|
|
|
|
focusedItemPlaylistId = focusedItemPlaylistId.getAttribute('data-playlistitemid');
|
|
|
|
const newFocusedItem = itemsContainer.querySelector(`button[data-playlistitemid="${focusedItemPlaylistId}"]`);
|
|
|
|
if (newFocusedItem !== null) {
|
|
|
|
newFocusedItem.focus();
|
2020-06-30 19:28:52 +02:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2020-06-30 19:28:52 +02:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
const playlistItemId = playbackManager.getCurrentPlaylistItemId(player);
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (playlistItemId) {
|
|
|
|
const img = itemsContainer.querySelector(`.listItem[data-playlistItemId="${playlistItemId}"] .listItemImage`);
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (img) {
|
|
|
|
img.classList.remove('lazy');
|
|
|
|
img.classList.add('playlistIndexIndicatorImage');
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
imageLoader.lazyChildren(itemsContainer);
|
|
|
|
});
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onPlaybackStart(e, state) {
|
|
|
|
console.debug('remotecontrol event: ' + e.type);
|
|
|
|
const player = this;
|
|
|
|
onStateChanged.call(player, e, state);
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onRepeatModeChange() {
|
|
|
|
updateRepeatModeDisplay(playbackManager.getRepeatMode());
|
|
|
|
}
|
2020-06-22 17:55:28 +02:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onShuffleQueueModeChange(updateView = true) {
|
|
|
|
const shuffleMode = playbackManager.getQueueShuffleMode(this);
|
|
|
|
const context = dlg;
|
|
|
|
const cssClass = 'buttonActive';
|
|
|
|
const shuffleButtons = context.querySelectorAll('.btnShuffleQueue');
|
2020-06-30 19:28:52 +02:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
for (const shuffleButton of shuffleButtons) {
|
|
|
|
switch (shuffleMode) {
|
|
|
|
case 'Shuffle':
|
|
|
|
shuffleButton.classList.add(cssClass);
|
|
|
|
break;
|
|
|
|
case 'Sorted':
|
|
|
|
default:
|
|
|
|
shuffleButton.classList.remove(cssClass);
|
|
|
|
break;
|
2020-06-30 19:28:52 +02:00
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (updateView) {
|
|
|
|
onPlaylistUpdate();
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function onPlaylistUpdate(e) {
|
|
|
|
loadPlaylist(dlg, this);
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onPlaylistItemRemoved(e, info) {
|
|
|
|
const context = dlg;
|
|
|
|
if (info !== undefined) {
|
|
|
|
const playlistItemIds = info.playlistItemIds;
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
for (let i = 0, length = playlistItemIds.length; i < length; i++) {
|
|
|
|
const listItem = context.querySelector('.listItem[data-playlistItemId="' + playlistItemIds[i] + '"]');
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (listItem) {
|
|
|
|
listItem.parentNode.removeChild(listItem);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
} else {
|
|
|
|
onPlaylistUpdate();
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onPlaybackStopped(e, state) {
|
|
|
|
console.debug('remotecontrol event: ' + e.type);
|
|
|
|
const player = this;
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (!state.NextMediaType) {
|
|
|
|
updatePlayerState(player, dlg, {});
|
|
|
|
Emby.Page.back();
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onPlayPauseStateChanged(e) {
|
|
|
|
updatePlayPauseState(this.paused(), true);
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onStateChanged(event, state) {
|
|
|
|
const player = this;
|
|
|
|
updatePlayerState(player, dlg, state);
|
|
|
|
onPlaylistUpdate();
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onTimeUpdate(e) {
|
|
|
|
const now = new Date().getTime();
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (!(now - lastUpdateTime < 700)) {
|
|
|
|
lastUpdateTime = now;
|
|
|
|
const player = this;
|
|
|
|
currentRuntimeTicks = playbackManager.duration(player);
|
2020-08-15 11:30:36 -04:00
|
|
|
updateTimeDisplay(playbackManager.currentTime(player) * 10000, currentRuntimeTicks);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onVolumeChanged(e) {
|
|
|
|
const player = this;
|
|
|
|
updatePlayerVolumeState(dlg, player.isMuted(), player.getVolume());
|
|
|
|
}
|
|
|
|
|
|
|
|
function releaseCurrentPlayer() {
|
|
|
|
const player = currentPlayer;
|
|
|
|
|
|
|
|
if (player) {
|
|
|
|
events.off(player, 'playbackstart', onPlaybackStart);
|
|
|
|
events.off(player, 'statechange', onStateChanged);
|
|
|
|
events.off(player, 'repeatmodechange', onRepeatModeChange);
|
|
|
|
events.off(player, 'shufflequeuemodechange', onShuffleQueueModeChange);
|
|
|
|
events.off(player, 'playlistitemremove', onPlaylistItemRemoved);
|
|
|
|
events.off(player, 'playlistitemmove', onPlaylistUpdate);
|
|
|
|
events.off(player, 'playlistitemadd', onPlaylistUpdate);
|
|
|
|
events.off(player, 'playbackstop', onPlaybackStopped);
|
|
|
|
events.off(player, 'volumechange', onVolumeChanged);
|
|
|
|
events.off(player, 'pause', onPlayPauseStateChanged);
|
|
|
|
events.off(player, 'unpause', onPlayPauseStateChanged);
|
|
|
|
events.off(player, 'timeupdate', onTimeUpdate);
|
|
|
|
currentPlayer = null;
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function bindToPlayer(context, player) {
|
|
|
|
if (releaseCurrentPlayer(), currentPlayer = player, player) {
|
|
|
|
const state = playbackManager.getPlayerState(player);
|
|
|
|
onStateChanged.call(player, {
|
|
|
|
type: 'init'
|
|
|
|
}, state);
|
|
|
|
events.on(player, 'playbackstart', onPlaybackStart);
|
|
|
|
events.on(player, 'statechange', onStateChanged);
|
|
|
|
events.on(player, 'repeatmodechange', onRepeatModeChange);
|
|
|
|
events.on(player, 'shufflequeuemodechange', onShuffleQueueModeChange);
|
|
|
|
events.on(player, 'playlistitemremove', onPlaylistItemRemoved);
|
|
|
|
events.on(player, 'playlistitemmove', onPlaylistUpdate);
|
|
|
|
events.on(player, 'playlistitemadd', onPlaylistUpdate);
|
|
|
|
events.on(player, 'playbackstop', onPlaybackStopped);
|
|
|
|
events.on(player, 'volumechange', onVolumeChanged);
|
|
|
|
events.on(player, 'pause', onPlayPauseStateChanged);
|
|
|
|
events.on(player, 'unpause', onPlayPauseStateChanged);
|
|
|
|
events.on(player, 'timeupdate', onTimeUpdate);
|
|
|
|
const playerInfo = playbackManager.getPlayerInfo();
|
|
|
|
const supportedCommands = playerInfo.supportedCommands;
|
|
|
|
currentPlayerSupportedCommands = supportedCommands;
|
|
|
|
updateSupportedCommands(context, supportedCommands);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onBtnCommandClick() {
|
|
|
|
if (currentPlayer) {
|
|
|
|
if (this.classList.contains('repeatToggleButton')) {
|
|
|
|
toggleRepeat();
|
|
|
|
} else {
|
|
|
|
playbackManager.sendCommand({
|
|
|
|
Name: this.getAttribute('data-command')
|
|
|
|
}, currentPlayer);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function getSaveablePlaylistItems() {
|
|
|
|
return getPlaylistItems(currentPlayer).then(function (items) {
|
|
|
|
return items.filter(function (i) {
|
|
|
|
return i.Id && i.ServerId;
|
2019-02-02 11:14:40 -05:00
|
|
|
});
|
2020-08-06 15:55:10 +01:00
|
|
|
});
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function savePlaylist() {
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../playlisteditor/playlisteditor').then((playlistEditor) => {
|
2020-08-06 15:55:10 +01:00
|
|
|
getSaveablePlaylistItems().then(function (items) {
|
|
|
|
const serverId = items.length ? items[0].ServerId : ApiClient.serverId();
|
2020-08-08 17:51:10 +01:00
|
|
|
new playlistEditor({
|
2020-08-06 15:55:10 +01:00
|
|
|
items: items.map(function (i) {
|
|
|
|
return i.Id;
|
|
|
|
}),
|
|
|
|
serverId: serverId,
|
|
|
|
enableAddToPlayQueue: false,
|
|
|
|
defaultValue: 'new'
|
2019-02-02 11:14:40 -05:00
|
|
|
});
|
|
|
|
});
|
2020-08-06 15:55:10 +01:00
|
|
|
});
|
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function bindEvents(context) {
|
|
|
|
const btnCommand = context.querySelectorAll('.btnCommand');
|
|
|
|
const positionSlider = context.querySelector('.nowPlayingPositionSlider');
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
for (let i = 0, length = btnCommand.length; i < length; i++) {
|
|
|
|
btnCommand[i].addEventListener('click', onBtnCommandClick);
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
context.querySelector('.btnToggleFullscreen').addEventListener('click', function (e) {
|
|
|
|
if (currentPlayer) {
|
|
|
|
playbackManager.sendCommand({
|
|
|
|
Name: e.target.getAttribute('data-command')
|
|
|
|
}, currentPlayer);
|
2020-06-22 17:55:28 +02:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
});
|
|
|
|
context.querySelector('.btnAudioTracks').addEventListener('click', function (e) {
|
|
|
|
if (currentPlayer && lastPlayerState && lastPlayerState.NowPlayingItem) {
|
|
|
|
showAudioMenu(context, currentPlayer, e.target, lastPlayerState.NowPlayingItem);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
context.querySelector('.btnSubtitles').addEventListener('click', function (e) {
|
|
|
|
if (currentPlayer && lastPlayerState && lastPlayerState.NowPlayingItem) {
|
|
|
|
showSubtitleMenu(context, currentPlayer, e.target, lastPlayerState.NowPlayingItem);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
context.querySelector('.btnStop').addEventListener('click', function () {
|
|
|
|
if (currentPlayer) {
|
|
|
|
playbackManager.stop(currentPlayer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
context.querySelector('.btnPlayPause').addEventListener('click', function () {
|
|
|
|
if (currentPlayer) {
|
|
|
|
playbackManager.playPause(currentPlayer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
context.querySelector('.btnNextTrack').addEventListener('click', function () {
|
|
|
|
if (currentPlayer) {
|
|
|
|
playbackManager.nextTrack(currentPlayer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
context.querySelector('.btnRewind').addEventListener('click', function () {
|
|
|
|
if (currentPlayer) {
|
|
|
|
playbackManager.rewind(currentPlayer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
context.querySelector('.btnFastForward').addEventListener('click', function () {
|
|
|
|
if (currentPlayer) {
|
|
|
|
playbackManager.fastForward(currentPlayer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
for (const shuffleButton of context.querySelectorAll('.btnShuffleQueue')) {
|
|
|
|
shuffleButton.addEventListener('click', function () {
|
2019-02-02 11:14:40 -05:00
|
|
|
if (currentPlayer) {
|
2020-08-06 15:55:10 +01:00
|
|
|
playbackManager.toggleQueueShuffleMode(currentPlayer);
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
|
|
|
});
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2020-06-18 09:30:31 +02:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
context.querySelector('.btnPreviousTrack').addEventListener('click', function (e) {
|
|
|
|
if (currentPlayer) {
|
|
|
|
if (lastPlayerState.NowPlayingItem.MediaType === 'Audio' && (currentPlayer._currentTime >= 5 || !playbackManager.previousTrack(currentPlayer))) {
|
|
|
|
// Cancel this event if doubleclick is fired
|
|
|
|
if (e.detail > 1 && playbackManager.previousTrack(currentPlayer)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
playbackManager.seekPercent(0, currentPlayer);
|
|
|
|
// This is done automatically by playbackManager. However, setting this here gives instant visual feedback.
|
|
|
|
// TODO: Check why seekPercentage doesn't reflect the changes inmmediately, so we can remove this workaround.
|
|
|
|
positionSlider.value = 0;
|
|
|
|
} else {
|
2019-02-02 11:14:40 -05:00
|
|
|
playbackManager.previousTrack(currentPlayer);
|
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
|
|
|
});
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
context.querySelector('.btnPreviousTrack').addEventListener('dblclick', function () {
|
|
|
|
if (currentPlayer) {
|
|
|
|
playbackManager.previousTrack(currentPlayer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
positionSlider.addEventListener('change', function () {
|
|
|
|
const value = this.value;
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (currentPlayer) {
|
|
|
|
const newPercent = parseFloat(value);
|
|
|
|
playbackManager.seekPercent(newPercent, currentPlayer);
|
|
|
|
}
|
|
|
|
});
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
positionSlider.getBubbleText = function (value) {
|
|
|
|
const state = lastPlayerState;
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (!state || !state.NowPlayingItem || !currentRuntimeTicks) {
|
|
|
|
return '--:--';
|
|
|
|
}
|
2020-02-15 16:51:37 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
let ticks = currentRuntimeTicks;
|
|
|
|
ticks /= 100;
|
|
|
|
ticks *= value;
|
|
|
|
return datetime.getDisplayRunningTime(ticks);
|
|
|
|
};
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
context.querySelector('.nowPlayingVolumeSlider').addEventListener('input', (e) => {
|
|
|
|
playbackManager.setVolume(e.target.value, currentPlayer);
|
|
|
|
});
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
context.querySelector('.buttonMute').addEventListener('click', function () {
|
|
|
|
playbackManager.toggleMute(currentPlayer);
|
|
|
|
});
|
|
|
|
const playlistContainer = context.querySelector('.playlist');
|
|
|
|
playlistContainer.addEventListener('action-remove', function (e) {
|
|
|
|
playbackManager.removeFromPlaylist([e.detail.playlistItemId], currentPlayer);
|
|
|
|
});
|
|
|
|
playlistContainer.addEventListener('itemdrop', function (e) {
|
|
|
|
const newIndex = e.detail.newIndex;
|
|
|
|
const playlistItemId = e.detail.playlistItemId;
|
|
|
|
playbackManager.movePlaylistItem(playlistItemId, newIndex, currentPlayer);
|
|
|
|
});
|
|
|
|
context.querySelector('.btnSavePlaylist').addEventListener('click', savePlaylist);
|
|
|
|
context.querySelector('.btnTogglePlaylist').addEventListener('click', function () {
|
|
|
|
if (context.querySelector('.playlist').classList.contains('hide')) {
|
|
|
|
context.querySelector('.playlist').classList.remove('hide');
|
|
|
|
context.querySelector('.btnSavePlaylist').classList.remove('hide');
|
|
|
|
context.querySelector('.volumecontrol').classList.add('hide');
|
|
|
|
if (layoutManager.mobile) {
|
|
|
|
context.querySelector('.playlistSectionButton').classList.remove('playlistSectionButtonTransparent');
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
context.querySelector('.playlist').classList.add('hide');
|
|
|
|
context.querySelector('.btnSavePlaylist').classList.add('hide');
|
|
|
|
if (showMuteButton || showVolumeSlider) {
|
|
|
|
context.querySelector('.volumecontrol').classList.remove('hide');
|
|
|
|
}
|
|
|
|
if (layoutManager.mobile) {
|
|
|
|
context.querySelector('.playlistSectionButton').classList.add('playlistSectionButtonTransparent');
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onPlayerChange() {
|
|
|
|
bindToPlayer(dlg, playbackManager.getCurrentPlayer());
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onMessageSubmit(e) {
|
|
|
|
const form = e.target;
|
|
|
|
playbackManager.sendCommand({
|
|
|
|
Name: 'DisplayMessage',
|
|
|
|
Arguments: {
|
|
|
|
Header: form.querySelector('#txtMessageTitle').value,
|
|
|
|
Text: form.querySelector('#txtMessageText', form).value
|
|
|
|
}
|
|
|
|
}, currentPlayer);
|
|
|
|
form.querySelector('input').value = '';
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../toast/toast').then((toast) => {
|
2020-08-06 15:55:10 +01:00
|
|
|
toast('Message sent.');
|
|
|
|
});
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
return false;
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onSendStringSubmit(e) {
|
|
|
|
const form = e.target;
|
|
|
|
playbackManager.sendCommand({
|
|
|
|
Name: 'SendString',
|
|
|
|
Arguments: {
|
|
|
|
String: form.querySelector('#txtTypeText', form).value
|
2020-04-28 15:57:34 +03:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}, currentPlayer);
|
|
|
|
form.querySelector('input').value = '';
|
|
|
|
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../toast/toast').then((toast) => {
|
2020-08-06 15:55:10 +01:00
|
|
|
toast('Text sent.');
|
|
|
|
});
|
2020-04-28 15:57:34 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
return false;
|
|
|
|
}
|
2020-02-19 02:10:40 +03:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function init(ownerView, context) {
|
|
|
|
let volumecontrolHtml = '<div class="volumecontrol flex align-items-center flex-wrap-wrap justify-content-center">';
|
|
|
|
volumecontrolHtml += `<button is="paper-icon-button-light" class="buttonMute autoSize" title=${globalize.translate('Mute')}><span class="xlargePaperIconButton material-icons volume_up"></span></button>`;
|
|
|
|
volumecontrolHtml += '<div class="sliderContainer nowPlayingVolumeSliderContainer"><input is="emby-slider" type="range" step="1" min="0" max="100" value="0" class="nowPlayingVolumeSlider"/></div>';
|
|
|
|
volumecontrolHtml += '</div>';
|
|
|
|
const optionsSection = context.querySelector('.playlistSectionButton');
|
|
|
|
if (!layoutManager.mobile) {
|
|
|
|
context.querySelector('.nowPlayingSecondaryButtons').insertAdjacentHTML('beforeend', volumecontrolHtml);
|
|
|
|
optionsSection.classList.remove('align-items-center', 'justify-content-center');
|
|
|
|
optionsSection.classList.add('align-items-right', 'justify-content-flex-end');
|
|
|
|
context.querySelector('.playlist').classList.remove('hide');
|
|
|
|
context.querySelector('.btnSavePlaylist').classList.remove('hide');
|
|
|
|
context.classList.add('padded-bottom');
|
|
|
|
} else {
|
|
|
|
optionsSection.querySelector('.btnTogglePlaylist').insertAdjacentHTML('afterend', volumecontrolHtml);
|
|
|
|
optionsSection.classList.add('playlistSectionButtonTransparent');
|
|
|
|
context.querySelector('.btnTogglePlaylist').classList.remove('hide');
|
|
|
|
context.querySelector('.playlistSectionButton').classList.remove('justify-content-center');
|
|
|
|
context.querySelector('.playlistSectionButton').classList.add('justify-content-space-between');
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
bindEvents(context);
|
|
|
|
context.querySelector('.sendMessageForm').addEventListener('submit', onMessageSubmit);
|
|
|
|
context.querySelector('.typeTextForm').addEventListener('submit', onSendStringSubmit);
|
|
|
|
events.on(playbackManager, 'playerchange', onPlayerChange);
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
if (layoutManager.tv) {
|
|
|
|
const positionSlider = context.querySelector('.nowPlayingPositionSlider');
|
|
|
|
positionSlider.classList.add('focusable');
|
|
|
|
positionSlider.enableKeyboardDragging();
|
2019-02-02 11:14:40 -05:00
|
|
|
}
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|
2019-02-02 11:08:20 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onDialogClosed(e) {
|
|
|
|
releaseCurrentPlayer();
|
|
|
|
events.off(playbackManager, 'playerchange', onPlayerChange);
|
|
|
|
lastPlayerState = null;
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
function onShow(context, tab) {
|
|
|
|
bindToPlayer(context, playbackManager.getCurrentPlayer());
|
|
|
|
}
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
let dlg;
|
|
|
|
let currentPlayer;
|
|
|
|
let lastPlayerState;
|
|
|
|
let currentPlayerSupportedCommands = [];
|
|
|
|
let lastUpdateTime = 0;
|
|
|
|
let currentRuntimeTicks = 0;
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
self.init = function (ownerView, context) {
|
|
|
|
dlg = context;
|
|
|
|
init(ownerView, dlg);
|
|
|
|
};
|
2019-02-02 11:14:40 -05:00
|
|
|
|
2020-08-06 15:55:10 +01:00
|
|
|
self.onShow = function () {
|
|
|
|
onShow(dlg, window.location.hash);
|
|
|
|
};
|
|
|
|
|
|
|
|
self.destroy = function () {
|
|
|
|
onDialogClosed();
|
2019-02-02 11:08:20 -05:00
|
|
|
};
|
2020-08-06 15:55:10 +01:00
|
|
|
}
|