jellyfin-web/dashboard-ui/scripts/mediaplayer-video.js

1339 lines
49 KiB
JavaScript
Raw Normal View History

2016-06-06 17:44:15 -07:00
define(['appSettings', 'datetime', 'mediaInfo', 'scrollStyles', 'paper-icon-button-light'], function (appSettings, datetime, mediaInfo) {
2014-06-21 22:52:31 -07:00
function createVideoPlayer(self) {
var initialVolume;
var idleState = true;
var muteButton = null;
var unmuteButton = null;
var volumeSlider = null;
2016-06-24 09:51:13 -07:00
var volumeSliderContainer = null;
var positionSlider;
var currentTimeElement;
2014-06-11 12:31:33 -07:00
self.currentSubtitleStreamIndex = null;
2014-06-11 19:38:40 -07:00
self.getCurrentSubtitleStream = function () {
return self.getSubtitleStream(self.currentSubtitleStreamIndex);
};
self.getSubtitleStream = function (index) {
return self.currentMediaSource.MediaStreams.filter(function (s) {
return s.Type == 'Subtitle' && s.Index == index;
})[0];
};
self.toggleFullscreen = function () {
if (self.isFullScreen()) {
2015-05-17 18:27:48 -07:00
self.exitFullScreen();
} else {
requestFullScreen(document.body);
}
};
2016-06-06 17:44:15 -07:00
function setClass(elems, method, className) {
for (var i = 0, length = elems.length; i < length; i++) {
elems[i].classList[method](className);
}
}
self.resetEnhancements = function () {
2015-08-28 12:10:44 -07:00
2015-12-14 08:43:03 -07:00
if (!initComplete) {
return;
}
if (self.isFullScreen()) {
self.exitFullScreen();
}
2016-06-04 09:10:10 -07:00
var videoPlayerElement = document.querySelector('#videoPlayer');
fadeOut(videoPlayerElement);
videoPlayerElement.classList.remove('fullscreenVideo');
videoPlayerElement.classList.remove('idlePlayer');
2016-06-06 17:44:15 -07:00
setClass(document.querySelectorAll('.hiddenOnIdle'), 'remove', 'inactive');
var video = videoPlayerElement.querySelector('video');
if (video) {
video.parentNode.removeChild(video);
}
2015-08-28 12:10:44 -07:00
document.querySelector('.mediaButton.infoButton').classList.remove('active');
document.querySelector('.videoControls .nowPlayingInfo').classList.add('hide');
document.querySelector('.videoControls').classList.add('hiddenOnIdle');
};
2014-03-20 20:31:40 -07:00
self.exitFullScreen = function () {
2015-05-17 18:27:48 -07:00
if (document.exitFullscreen) {
document.exitFullscreen();
2015-05-27 22:51:48 -07:00
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
2015-05-17 18:27:48 -07:00
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
2016-06-04 09:10:10 -07:00
document.querySelector('#videoPlayer').classList.remove('fullscreenVideo');
2014-03-17 07:48:16 -07:00
};
2014-03-20 20:31:40 -07:00
self.isFullScreen = function () {
return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement ? true : false;
2014-03-17 07:48:16 -07:00
};
2015-05-21 13:53:14 -07:00
self.showSubtitleMenu = function () {
2015-06-27 12:53:36 -07:00
var streams = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
return currentStream.Type == "Subtitle";
});
2015-05-21 13:53:14 -07:00
2015-12-23 10:46:01 -07:00
var currentIndex = self.currentSubtitleStreamIndex;
if (currentIndex == null) {
currentIndex = -1;
}
2015-06-27 12:53:36 -07:00
streams.unshift({
Index: -1,
2015-12-23 10:46:01 -07:00
Language: Globalize.translate('ButtonOff')
2015-06-27 12:53:36 -07:00
});
var menuItems = streams.map(function (stream) {
var attributes = [];
attributes.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
if (stream.Codec) {
attributes.push(stream.Codec);
}
var name = attributes.join(' - ');
if (stream.IsDefault) {
name += ' (D)';
}
if (stream.IsForced) {
name += ' (F)';
}
if (stream.External) {
name += ' (EXT)';
}
var opt = {
2016-05-14 11:02:06 -07:00
name: stream.DisplayTitle || name,
2015-06-27 12:53:36 -07:00
id: stream.Index
};
if (stream.Index == currentIndex) {
2016-04-16 12:22:09 -07:00
opt.selected = true;
2015-06-27 12:53:36 -07:00
}
return opt;
});
2016-01-30 21:04:00 -07:00
require(['actionsheet'], function (actionsheet) {
2015-06-27 12:53:36 -07:00
2016-01-30 21:04:00 -07:00
actionsheet.show({
2015-06-27 12:53:36 -07:00
items: menuItems,
2016-02-01 10:02:46 -07:00
// history.back() will cause the video player to stop
enableHistory: false,
2016-06-04 09:10:10 -07:00
positionTo: document.querySelector('.videoSubtitleButton'),
2015-06-27 12:53:36 -07:00
callback: function (id) {
var index = parseInt(id);
if (index != currentIndex) {
self.onSubtitleOptionSelected(index);
}
}
});
2015-06-27 12:53:36 -07:00
});
};
2015-05-21 13:53:14 -07:00
self.showQualityFlyout = function () {
2016-01-30 21:04:00 -07:00
require(['qualityoptions', 'actionsheet'], function (qualityoptions, actionsheet) {
2015-12-30 10:02:11 -07:00
var currentSrc = self.getCurrentSrc(self.currentMediaRenderer).toLowerCase();
var isStatic = currentSrc.indexOf('static=true') != -1;
2015-06-27 12:53:36 -07:00
2015-12-30 10:02:11 -07:00
var videoStream = self.currentMediaSource.MediaStreams.filter(function (stream) {
return stream.Type == "Video";
})[0];
var videoWidth = videoStream ? videoStream.Width : null;
2015-06-27 12:53:36 -07:00
2016-02-29 23:02:03 -07:00
var options = qualityoptions.getVideoQualityOptions(appSettings.maxStreamingBitrate(), videoWidth);
2015-06-27 12:53:36 -07:00
2015-12-30 10:02:11 -07:00
if (isStatic) {
options[0].name = "Direct";
}
2015-06-27 12:53:36 -07:00
2015-12-30 10:02:11 -07:00
var menuItems = options.map(function (o) {
2015-06-27 12:53:36 -07:00
2015-12-30 10:02:11 -07:00
var opt = {
name: o.name,
id: o.bitrate
};
2015-12-30 10:02:11 -07:00
if (o.selected) {
2016-04-16 12:22:09 -07:00
opt.selected = true;
2015-12-30 10:02:11 -07:00
}
2015-06-27 12:53:36 -07:00
2015-12-30 10:02:11 -07:00
return opt;
});
2015-06-27 12:53:36 -07:00
2015-12-30 10:02:11 -07:00
var selectedId = options.filter(function (o) {
return o.selected;
});
selectedId = selectedId.length ? selectedId[0].bitrate : null;
2016-01-30 21:04:00 -07:00
actionsheet.show({
2015-06-27 12:53:36 -07:00
items: menuItems,
2016-02-01 10:02:46 -07:00
// history.back() will cause the video player to stop
enableHistory: false,
2016-06-04 09:10:10 -07:00
positionTo: document.querySelector('.videoQualityButton'),
2015-06-27 12:53:36 -07:00
callback: function (id) {
var bitrate = parseInt(id);
if (bitrate != selectedId) {
self.onQualityOptionSelected(bitrate);
}
}
});
});
};
self.showAudioTracksFlyout = function () {
2015-06-27 12:53:36 -07:00
var options = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
return currentStream.Type == "Audio";
});
2015-05-21 13:53:14 -07:00
2015-06-27 12:53:36 -07:00
var currentIndex = getParameterByName('AudioStreamIndex', self.getCurrentSrc(self.currentMediaRenderer));
var menuItems = options.map(function (stream) {
var attributes = [];
attributes.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
if (stream.Codec) {
attributes.push(stream.Codec);
}
if (stream.Profile) {
attributes.push(stream.Profile);
}
if (stream.BitRate) {
attributes.push((Math.floor(stream.BitRate / 1000)) + ' kbps');
}
if (stream.Channels) {
attributes.push(stream.Channels + ' ch');
}
var name = attributes.join(' - ');
if (stream.IsDefault) {
name += ' (D)';
}
var opt = {
2016-05-14 11:02:06 -07:00
name: stream.DisplayTitle || name,
2015-06-27 12:53:36 -07:00
id: stream.Index
};
if (stream.Index == currentIndex) {
2016-04-16 12:22:09 -07:00
opt.selected = true;
2015-06-27 12:53:36 -07:00
}
return opt;
});
2016-01-30 21:04:00 -07:00
require(['actionsheet'], function (actionsheet) {
2015-06-27 12:53:36 -07:00
2016-01-30 21:04:00 -07:00
actionsheet.show({
2015-06-27 12:53:36 -07:00
items: menuItems,
2016-02-01 10:02:46 -07:00
// history.back() will cause the video player to stop
enableHistory: false,
2016-06-04 09:10:10 -07:00
positionTo: document.querySelector('.videoAudioButton'),
2015-06-27 12:53:36 -07:00
callback: function (id) {
2015-06-27 12:53:36 -07:00
var index = parseInt(id);
if (index != currentIndex) {
self.onAudioOptionSelected(index);
}
}
});
});
};
2014-05-07 22:04:39 -07:00
self.setAudioStreamIndex = function (index) {
self.changeStream(self.getCurrentTicks(), { AudioStreamIndex: index });
};
self.setSubtitleStreamIndex = function (index) {
2014-06-11 19:38:40 -07:00
2015-06-13 07:46:59 -07:00
if (!self.currentMediaRenderer.supportsTextTracks()) {
2014-07-19 21:46:29 -07:00
2014-06-11 19:38:40 -07:00
self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: index });
self.currentSubtitleStreamIndex = index;
return;
}
var currentStream = self.getCurrentSubtitleStream();
var newStream = self.getSubtitleStream(index);
if (!currentStream && !newStream) return;
var selectedTrackElementIndex = -1;
if (currentStream && !newStream) {
2015-03-30 12:57:37 -07:00
if (currentStream.DeliveryMethod != 'External') {
2014-06-11 19:38:40 -07:00
// Need to change the transcoded stream to remove subs
self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: -1 });
}
}
else if (!currentStream && newStream) {
2015-03-30 12:57:37 -07:00
if (newStream.DeliveryMethod == 'External') {
2014-06-11 19:38:40 -07:00
selectedTrackElementIndex = index;
} else {
// Need to change the transcoded stream to add subs
self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: index });
}
}
else if (currentStream && newStream) {
2015-03-30 12:57:37 -07:00
if (newStream.DeliveryMethod == 'External') {
selectedTrackElementIndex = index;
2014-06-14 19:58:00 -07:00
2015-03-30 12:57:37 -07:00
if (currentStream.DeliveryMethod != 'External') {
self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: -1 });
}
} else {
// Need to change the transcoded stream to add subs
self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: index });
}
}
2014-06-11 19:38:40 -07:00
self.setCurrentTrackElement(selectedTrackElementIndex);
2014-07-19 21:46:29 -07:00
2014-06-11 19:38:40 -07:00
self.currentSubtitleStreamIndex = index;
};
self.setCurrentTrackElement = function (index) {
2016-02-24 09:52:36 -07:00
self.currentMediaRenderer.setCurrentTrackElement(index);
2014-05-07 22:04:39 -07:00
};
2014-06-14 19:58:00 -07:00
self.updateTextStreamUrls = function (startPositionTicks) {
2015-06-13 07:46:59 -07:00
self.currentMediaRenderer.updateTextStreamUrls(startPositionTicks);
2014-06-14 19:58:00 -07:00
};
2014-06-28 12:35:30 -07:00
self.updateNowPlayingInfo = function (item) {
if (!item) {
throw new Error('item cannot be null');
}
2016-06-06 17:44:15 -07:00
var mediaControls = document.querySelector("#videoPlayer");
2014-06-28 12:35:30 -07:00
var state = self.getPlayerStateInternal(self.currentMediaRenderer, item.CurrentProgram || item, self.currentMediaSource);
2014-06-28 12:35:30 -07:00
var url = "";
2015-05-13 13:55:08 -07:00
var imageWidth = 400;
2015-05-13 22:42:55 -07:00
var imageHeight = 300;
2014-06-28 12:35:30 -07:00
if (state.NowPlayingItem.PrimaryImageTag) {
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.PrimaryImageItemId, {
type: "Primary",
2015-05-13 10:53:26 -07:00
width: imageWidth,
2014-06-28 12:35:30 -07:00
tag: state.NowPlayingItem.PrimaryImageTag
});
}
else if (state.NowPlayingItem.PrimaryImageTag) {
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.PrimaryImageItemId, {
type: "Primary",
2015-05-13 10:53:26 -07:00
width: imageWidth,
2014-06-28 12:35:30 -07:00
tag: state.NowPlayingItem.PrimaryImageTag
});
}
else if (state.NowPlayingItem.BackdropImageTag) {
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.BackdropItemId, {
type: "Backdrop",
2015-05-13 10:53:26 -07:00
height: imageHeight,
2014-06-28 12:35:30 -07:00
tag: state.NowPlayingItem.BackdropImageTag,
index: 0
});
}
else if (state.NowPlayingItem.ThumbImageTag) {
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.ThumbImageItemId, {
type: "Thumb",
2015-05-13 10:53:26 -07:00
height: imageHeight,
2014-06-28 12:35:30 -07:00
tag: state.NowPlayingItem.ThumbImageTag
});
}
if (url) {
2016-06-06 17:44:15 -07:00
mediaControls.querySelector('.nowPlayingImage').innerHTML = '<img src="' + url + '" />';
2014-06-28 12:35:30 -07:00
} else {
2016-06-06 17:44:15 -07:00
mediaControls.querySelector('.nowPlayingImage').innerHTML = '';
2014-06-28 12:35:30 -07:00
}
if (state.NowPlayingItem.LogoItemId) {
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.LogoItemId, {
type: "Logo",
2014-06-28 19:30:20 -07:00
height: 42,
2014-06-28 12:35:30 -07:00
tag: state.NowPlayingItem.LogoImageTag
});
2016-06-06 17:44:15 -07:00
mediaControls.querySelector('.videoTopControlsLogo').innerHTML = '<img src="' + url + '" />';
2014-06-28 12:35:30 -07:00
} else {
2016-06-06 17:44:15 -07:00
mediaControls.querySelector('.videoTopControlsLogo').innerHTML = '';
2014-06-28 12:35:30 -07:00
}
2016-06-06 17:44:15 -07:00
var elem = mediaControls.querySelector('.nowPlayingTabs');
elem.innerHTML = getNowPlayingTabsHtml(item.CurrentProgram || item);
ImageLoader.lazyChildren(elem);
2015-05-13 20:24:25 -07:00
2016-06-06 17:44:15 -07:00
function onTabButtonClick() {
if (!this.classList.contains('selectedNowPlayingTabButton')) {
2015-05-13 20:24:25 -07:00
2016-06-06 17:44:15 -07:00
var selectedNowPlayingTabButton = document.querySelector('.selectedNowPlayingTabButton');
if (selectedNowPlayingTabButton) {
selectedNowPlayingTabButton.classList.remove('selectedNowPlayingTabButton');
}
this.classList.add('selectedNowPlayingTabButton');
setClass(document.querySelectorAll('.nowPlayingTab'), 'add', 'hide');
document.querySelector('.' + this.getAttribute('data-tab')).classList.remove('hide');
2015-05-13 20:24:25 -07:00
}
2016-06-06 17:44:15 -07:00
}
2015-05-13 20:24:25 -07:00
2016-06-06 17:44:15 -07:00
var nowPlayingTabButtons = elem.querySelectorAll('.nowPlayingTabButton');
for (var i = 0, length = nowPlayingTabButtons.length; i < length; i++) {
nowPlayingTabButtons[i].addEventListener('click', onTabButtonClick);
}
2016-06-06 22:42:26 -07:00
elem.addEventListener('click', function (e) {
2015-05-13 20:24:25 -07:00
2016-06-06 22:42:26 -07:00
var chapterCard = parentWithClass(e.target, 'chapterCard');
if (chapterCard) {
self.seek(parseInt(chapterCard.getAttribute('data-position')));
}
2015-05-13 20:24:25 -07:00
});
};
2016-06-06 22:42:26 -07:00
function parentWithClass(elem, className) {
while (!elem.classList || !elem.classList.contains(className)) {
elem = elem.parentNode;
if (!elem) {
return null;
}
}
return elem;
}
2015-05-13 20:24:25 -07:00
function getNowPlayingTabsHtml(item) {
var html = '';
html += '<div class="nowPlayingTabButtons">';
html += '<a href="#" class="nowPlayingTabButton selectedNowPlayingTabButton" data-tab="tabInfo">' + Globalize.translate('TabInfo') + '</a>';
if (item.Chapters && item.Chapters.length) {
html += '<a href="#" class="nowPlayingTabButton" data-tab="tabScenes">' + Globalize.translate('TabScenes') + '</a>';
}
if (item.People && item.People.length) {
html += '<a href="#" class="nowPlayingTabButton" data-tab="tabCast">' + Globalize.translate('TabCast') + '</a>';
}
html += '</div>';
html += '<div class="tabInfo nowPlayingTab">';
var nameHtml = MediaController.getNowPlayingNameHtml(item, false);
2015-05-13 10:53:26 -07:00
nameHtml = '<div class="videoNowPlayingName">' + nameHtml + '</div>';
2016-05-11 22:58:05 -07:00
var miscInfo = mediaInfo.getPrimaryMediaInfoHtml(item);
2015-05-13 10:53:26 -07:00
if (miscInfo) {
nameHtml += '<div class="videoNowPlayingRating">' + miscInfo + '</div>';
}
if (item.Overview) {
nameHtml += '<div class="videoNowPlayingOverview">' + item.Overview + '</div>';
}
2015-05-13 20:24:25 -07:00
html += nameHtml;
html += '</div>';
if (item.Chapters && item.Chapters.length) {
2016-06-06 17:44:15 -07:00
html += '<div class="tabScenes nowPlayingTab smoothScrollX hide" style="white-space:nowrap;margin-bottom:2em;">';
2015-05-13 20:24:25 -07:00
var chapterIndex = 0;
html += item.Chapters.map(function (c) {
2015-06-11 10:57:59 -07:00
var width = 240;
2015-05-13 20:24:25 -07:00
var chapterHtml = '<a class="card backdropCard chapterCard" href="#" style="margin-right:1em;width:' + width + 'px;" data-position="' + c.StartPositionTicks + '">';
chapterHtml += '<div class="cardBox">';
2016-08-23 23:13:15 -07:00
chapterHtml += '<div class="cardScalable visualCardBox-cardScalable">';
2016-08-11 13:28:49 -07:00
chapterHtml += '<div class="cardPadder cardPadder-backdrop"></div>';
2015-05-13 20:24:25 -07:00
chapterHtml += '<div class="cardContent">';
if (c.ImageTag) {
var chapterImageUrl = ApiClient.getScaledImageUrl(item.Id, {
width: width,
tag: c.ImageTag,
type: "Chapter",
index: chapterIndex
});
chapterHtml += '<div class="cardImage lazy" data-src="' + chapterImageUrl + '"></div>';
} else {
chapterHtml += '<div class="cardImage" style="background:#444;"></div>';
}
chapterHtml += '<div class="cardFooter">';
if (c.Name) {
chapterHtml += '<div class="cardText">' + c.Name + '</div>';
}
2016-05-05 20:09:36 -07:00
chapterHtml += '<div class="cardText">' + datetime.getDisplayRunningTime(c.StartPositionTicks) + '</div>';
2015-05-13 20:24:25 -07:00
chapterHtml += '</div>';
chapterHtml += '</div>';
chapterHtml += '</div>';
chapterHtml += '</div>';
chapterHtml += '</a>';
chapterIndex++;
return chapterHtml;
}).join('');
html += '</div>';
}
if (item.People && item.People.length) {
2016-06-06 17:44:15 -07:00
html += '<div class="tabCast nowPlayingTab smoothScrollX hide" style="white-space:nowrap;">';
2015-05-13 20:24:25 -07:00
html += item.People.map(function (cast) {
var personHtml = '<div class="tileItem smallPosterTileItem" style="width:300px;">';
var imgUrl;
2015-07-03 04:51:45 -07:00
var height = 150;
2015-05-13 20:24:25 -07:00
if (cast.PrimaryImageTag) {
imgUrl = ApiClient.getScaledImageUrl(cast.Id, {
2015-05-27 22:51:48 -07:00
height: height,
2015-05-13 20:24:25 -07:00
tag: cast.PrimaryImageTag,
type: "primary",
minScale: 2
});
2015-09-11 19:18:09 -07:00
personHtml += '<div class="tileImage lazy" data-src="' + imgUrl + '" style="height:' + height + 'px;"></div>';
2015-05-13 20:24:25 -07:00
} else {
imgUrl = "css/images/items/list/person.png";
2015-09-11 19:18:09 -07:00
personHtml += '<div class="tileImage" style="background-image:url(\'' + imgUrl + '\');height:' + height + 'px;"></div>';
2015-05-13 20:24:25 -07:00
}
personHtml += '<div class="tileContent">';
personHtml += '<p>' + cast.Name + '</p>';
var role = cast.Role ? Globalize.translate('ValueAsRole', cast.Role) : cast.Type;
if (role == "GuestStar") {
role = Globalize.translate('ValueGuestStar');
}
role = role || "";
var maxlength = 40;
if (role.length > maxlength) {
role = role.substring(0, maxlength - 3) + '...';
}
personHtml += '<p>' + role + '</p>';
personHtml += '</div>';
personHtml += '</div>';
return personHtml;
}).join('');
html += '</div>';
}
return html;
}
2014-06-28 12:35:30 -07:00
2015-09-09 10:49:44 -07:00
function getSeekableDuration() {
if (self.currentMediaSource && self.currentMediaSource.RunTimeTicks) {
return self.currentMediaSource.RunTimeTicks;
}
if (self.currentMediaRenderer) {
return self.getCurrentTicks(self.currentMediaRenderer);
}
return null;
}
function onPositionSliderChange() {
2016-08-19 22:22:08 -07:00
var newPercent = parseFloat(this.value);
2015-09-09 10:49:44 -07:00
var newPositionTicks = (newPercent / 100) * getSeekableDuration();
self.changeStream(Math.floor(newPositionTicks));
}
2015-06-27 12:53:36 -07:00
self.onAudioOptionSelected = function (index) {
2015-05-21 13:53:14 -07:00
2015-06-27 12:53:36 -07:00
self.setAudioStreamIndex(index);
};
2015-05-22 13:15:29 -07:00
2015-06-27 12:53:36 -07:00
self.onSubtitleOptionSelected = function (index) {
self.setSubtitleStreamIndex(index);
2015-05-22 13:15:29 -07:00
};
2015-05-21 13:53:14 -07:00
2015-06-27 12:53:36 -07:00
self.onQualityOptionSelected = function (bitrate) {
2015-05-21 13:53:14 -07:00
2016-02-29 23:02:03 -07:00
appSettings.maxStreamingBitrate(bitrate);
appSettings.enableAutomaticBitrateDetection(false);
2015-05-21 13:53:14 -07:00
2015-06-27 12:53:36 -07:00
self.changeStream(self.getCurrentTicks(), {
Bitrate: bitrate
});
2015-05-22 13:15:29 -07:00
};
2015-08-28 12:10:44 -07:00
self.toggleInfo = function () {
var button = document.querySelector('.mediaButton.infoButton');
var nowPlayingInfo = document.querySelector('.videoControls .nowPlayingInfo');
if (button.classList.contains('active')) {
button.classList.remove('active');
document.querySelector('.videoControls').classList.add('hiddenOnIdle');
fadeOutDown(nowPlayingInfo);
} else {
button.classList.add('active');
document.querySelector('.videoControls').classList.remove('hiddenOnIdle');
nowPlayingInfo.classList.remove('hide');
fadeInUp(nowPlayingInfo);
}
};
2015-10-08 12:12:53 -07:00
self.toggleGuide = function () {
var button = document.querySelector('.mediaButton.guideButton');
var nowPlayingInfo = document.querySelector('.videoControls .guide');
if (button.classList.contains('active')) {
button.classList.remove('active');
document.querySelector('.videoControls').classList.add('hiddenOnIdle');
fadeOutDown(nowPlayingInfo);
} else {
button.classList.add('active');
document.querySelector('.videoControls').classList.remove('hiddenOnIdle');
nowPlayingInfo.classList.remove('hide');
fadeInUp(nowPlayingInfo);
if (!self.guideInstance) {
require(['tvguide'], function (tvguide) {
self.guideInstance = new tvguide({
element: nowPlayingInfo,
enablePaging: false
});
});
}
}
};
2015-08-28 12:10:44 -07:00
function fadeInUp(elem) {
var keyframes = [
{ transform: 'translate3d(0, 100%, 0)', offset: 0 },
2016-04-11 21:03:07 -07:00
{ transform: 'translate3d(0, 0, 0)', offset: 1 }];
2015-08-28 12:10:44 -07:00
var timing = { duration: 300, iterations: 1 };
2016-04-11 21:03:07 -07:00
if (elem.animate) {
elem.animate(keyframes, timing);
}
2015-08-28 12:10:44 -07:00
}
function fadeOutDown(elem) {
2016-04-11 21:03:07 -07:00
var keyframes = [{ transform: 'translate3d(0, 0, 0)', offset: 0 },
2015-08-28 12:10:44 -07:00
{ transform: 'translate3d(0, 100%, 0)', offset: 1 }];
var timing = { duration: 300, iterations: 1 };
2016-04-11 21:03:07 -07:00
var onFinish = function () {
2015-08-28 12:10:44 -07:00
elem.classList.add('hide');
};
2016-04-11 21:03:07 -07:00
if (elem.animate) {
elem.animate(keyframes, timing).onfinish = onFinish;
} else {
onFinish();
}
2015-08-28 12:10:44 -07:00
}
2015-06-27 12:53:36 -07:00
function ensureVideoPlayerElements() {
2015-05-22 13:15:29 -07:00
2015-12-14 08:43:03 -07:00
var html = '';
2015-05-22 13:15:29 -07:00
2015-12-14 08:43:03 -07:00
html += '<div id="videoPlayer" class="hide">';
2015-05-22 13:15:29 -07:00
2015-06-27 12:53:36 -07:00
html += '<div id="videoElement">';
html += '<div id="play" class="status"></div>';
html += '<div id="pause" class="status"></div>';
html += '</div>';
2015-05-22 13:15:29 -07:00
2016-05-09 22:00:50 -07:00
var hiddenOnIdleClass = AppInfo.isNativeApp && browserInfo.android ? 'hiddenOnIdle hide' : 'hiddenOnIdle';
html += '<div class="videoTopControls ' + hiddenOnIdleClass + '">';
2015-06-27 12:53:36 -07:00
html += '<div class="videoTopControlsLogo"></div>';
html += '<div class="videoAdvancedControls">';
2015-05-22 13:15:29 -07:00
2016-06-14 20:12:32 -07:00
html += '<button is="paper-icon-button-light" class="previousTrackButton mediaButton videoTrackControl hide autoSize" onclick="MediaPlayer.previousTrack();"><i class="md-icon">skip_previous</i></button>';
html += '<button is="paper-icon-button-light" class="nextTrackButton mediaButton videoTrackControl hide autoSize" onclick="MediaPlayer.nextTrack();"><i class="md-icon">skip_next</i></button>';
2015-05-21 13:53:14 -07:00
2015-06-27 12:53:36 -07:00
// Embedding onclicks due to issues not firing in cordova safari
2016-06-14 20:12:32 -07:00
html += '<button is="paper-icon-button-light" class="mediaButton videoAudioButton autoSize" onclick="MediaPlayer.showAudioTracksFlyout();"><i class="md-icon">audiotrack</i></button>';
html += '<button is="paper-icon-button-light" class="mediaButton videoSubtitleButton autoSize" onclick="MediaPlayer.showSubtitleMenu();"><i class="md-icon">closed_caption</i></button>';
html += '<button is="paper-icon-button-light" class="mediaButton videoQualityButton autoSize" onclick="MediaPlayer.showQualityFlyout();"><i class="md-icon">settings</i></button>';
html += '<button is="paper-icon-button-light" class="mediaButton autoSize" onclick="MediaPlayer.stop();"><i class="md-icon">close</i></button>';
2015-06-27 12:53:36 -07:00
html += '</div>'; // videoAdvancedControls
html += '</div>'; // videoTopControls
2015-06-27 12:53:36 -07:00
// Create controls
2016-05-09 22:00:50 -07:00
html += '<div class="videoControls ' + hiddenOnIdleClass + '">';
2015-08-28 12:10:44 -07:00
html += '<div class="nowPlayingInfo hide">';
2015-06-27 12:53:36 -07:00
html += '<div class="nowPlayingImage"></div>';
html += '<div class="nowPlayingTabs"></div>';
html += '</div>'; // nowPlayingInfo
2015-10-08 12:12:53 -07:00
html += '<div class="guide hide">';
html += '</div>'; // guide
2015-08-28 12:10:44 -07:00
html += '<div class="videoControlButtons">';
2016-06-14 20:12:32 -07:00
html += '<button is="paper-icon-button-light" class="previousTrackButton mediaButton videoTrackControl hide autoSize" onclick="MediaPlayer.previousTrack();"><i class="md-icon">skip_previous</i></button>';
html += '<button is="paper-icon-button-light" id="video-playButton" class="mediaButton unpauseButton autoSize" onclick="MediaPlayer.unpause();"><i class="md-icon">play_arrow</i></button>';
html += '<button is="paper-icon-button-light" id="video-pauseButton" class="mediaButton pauseButton autoSize" onclick="MediaPlayer.pause();"><i class="md-icon">pause</i></button>';
html += '<button is="paper-icon-button-light" class="nextTrackButton mediaButton videoTrackControl hide autoSize" onclick="MediaPlayer.nextTrack();"><i class="md-icon">skip_next</i></button>';
2016-06-13 12:02:48 -07:00
html += '<div class="sliderContainer videoPositionSliderContainer" style="display:inline-flex;margin-right:2em;">';
html += '<input type="range" is="emby-slider" pin step=".1" min="0" max="100" value="0" class="videoPositionSlider" />';
html += '</div>'; // guide
2015-06-27 12:53:36 -07:00
html += '<div class="currentTime">--:--</div>';
2016-06-14 20:12:32 -07:00
html += '<button is="paper-icon-button-light" class="muteButton mediaButton autoSize" onclick="MediaPlayer.mute();"><i class="md-icon">volume_up</i></button>';
html += '<button is="paper-icon-button-light" class="unmuteButton mediaButton autoSize" onclick="MediaPlayer.unMute();"><i class="md-icon">volume_off</i></button>';
2016-06-24 09:51:13 -07:00
html += '<div class="sliderContainer volumeSliderContainer" style="width:100px;vertical-align:middle;;margin-right:2em;display:inline-flex;">';
2016-06-13 12:02:48 -07:00
html += '<input type="range" is="emby-slider" pin step="1" min="0" max="100" value="0" class="videoVolumeSlider"/>';
html += '</div>'; // guide
2016-08-06 23:38:46 -07:00
html += '<button is="paper-icon-button-light" class="mediaButton castButton autoSize" onclick="MediaController.showPlayerSelection(this, false);"><i class="md-icon">cast</i></button>';
2016-06-14 20:12:32 -07:00
html += '<button is="paper-icon-button-light" class="mediaButton fullscreenButton autoSize" onclick="MediaPlayer.toggleFullscreen();" id="video-fullscreenButton"><i class="md-icon">fullscreen</i></button>';
html += '<button is="paper-icon-button-light" class="mediaButton infoButton autoSize" onclick="MediaPlayer.toggleInfo();"><i class="md-icon">info</i></button>';
2016-05-07 10:47:41 -07:00
2015-08-28 12:10:44 -07:00
html += '</div>';
2015-06-27 12:53:36 -07:00
html += '</div>'; // videoControls
2015-06-27 12:53:36 -07:00
html += '</div>'; // videoPlayer
2015-06-29 11:45:42 -07:00
var div = document.createElement('div');
div.innerHTML = html;
document.body.appendChild(div);
2015-06-27 12:53:36 -07:00
}
2015-12-14 08:43:03 -07:00
var initComplete;
function initVideoElements() {
2015-06-27 12:53:36 -07:00
2015-12-14 08:43:03 -07:00
if (initComplete) {
return;
}
initComplete = true;
2015-06-27 12:53:36 -07:00
ensureVideoPlayerElements();
2016-06-06 17:44:15 -07:00
var parent = document.querySelector("#videoPlayer");
2015-06-27 12:53:36 -07:00
2016-06-06 17:44:15 -07:00
muteButton = parent.querySelector('.muteButton');
unmuteButton = parent.querySelector('.unmuteButton');
currentTimeElement = parent.querySelector('.currentTime');
2015-06-27 12:53:36 -07:00
2016-06-06 17:44:15 -07:00
positionSlider = parent.querySelector(".videoPositionSlider", parent);
positionSlider.addEventListener('change', onPositionSliderChange);
2015-06-27 12:53:36 -07:00
2016-06-13 23:40:21 -07:00
positionSlider.getBubbleText = function (value) {
2015-06-27 12:53:36 -07:00
2015-09-09 10:49:44 -07:00
var seekableDuration = getSeekableDuration();
if (!self.currentMediaSource || !seekableDuration) {
2016-06-13 23:40:21 -07:00
return '--:--';
2015-06-27 12:53:36 -07:00
}
2015-09-09 10:49:44 -07:00
var ticks = seekableDuration;
2015-06-27 12:53:36 -07:00
ticks /= 100;
ticks *= value;
2016-06-13 23:40:21 -07:00
return datetime.getDisplayRunningTime(ticks);
2015-06-27 12:53:36 -07:00
};
2016-06-06 17:44:15 -07:00
volumeSlider = parent.querySelector('.videoVolumeSlider');
2016-06-24 09:51:13 -07:00
volumeSliderContainer = parent.querySelector('.volumeSliderContainer');
2016-06-06 17:44:15 -07:00
volumeSlider.addEventListener('change', function () {
2015-06-27 12:53:36 -07:00
var vol = this.value;
updateVolumeButtons(vol);
self.setVolume(vol);
2016-06-06 17:44:15 -07:00
});
2015-12-14 08:43:03 -07:00
}
2015-05-25 10:32:22 -07:00
var idleHandlerTimeout;
function idleHandler() {
2014-06-21 22:52:31 -07:00
2015-05-25 10:32:22 -07:00
if (idleHandlerTimeout) {
window.clearTimeout(idleHandlerTimeout);
}
if (idleState == true) {
2016-06-06 17:44:15 -07:00
setClass(document.querySelectorAll('.hiddenOnIdle'), 'remove', 'inactive');
document.querySelector('#videoPlayer').classList.remove('idlePlayer');
}
idleState = false;
2015-05-25 10:32:22 -07:00
idleHandlerTimeout = window.setTimeout(function () {
idleState = true;
2016-06-06 17:44:15 -07:00
setClass(document.querySelectorAll('.hiddenOnIdle'), 'add', 'inactive');
document.querySelector('#videoPlayer').classList.add('idlePlayer');
2015-06-26 08:53:49 -07:00
}, 3500);
}
function updateVolumeButtons(vol) {
2016-06-24 09:51:13 -07:00
if (!AppInfo.hasPhysicalVolumeButtons) {
if (vol) {
muteButton.classList.remove('hide');
unmuteButton.classList.add('hide');
} else {
muteButton.classList.add('hide');
unmuteButton.classList.remove('hide');
}
}
}
function requestFullScreen(element) {
// Supports most browsers and their versions.
2015-05-17 18:27:48 -07:00
var requestMethod = element.requestFullscreen || element.webkitRequestFullscreen || element.mozRequestFullScreen || element.msRequestFullscreen;
if (requestMethod) { // Native full screen.
requestMethod.call(element);
} else {
enterFullScreen();
}
}
function enterFullScreen() {
2016-06-06 17:44:15 -07:00
document.querySelector("#videoPlayer").classList.add("fullscreenVideo");
}
function exitFullScreenToWindow() {
2016-06-06 17:44:15 -07:00
document.querySelector("#videoPlayer").classList.remove("fullscreenVideo");
}
2015-06-29 11:45:42 -07:00
function onPopState() {
// Stop playback on browser back button nav
2016-06-04 09:10:10 -07:00
window.removeEventListener("popstate", onPopState);
2015-06-29 11:45:42 -07:00
self.stop();
return;
}
2014-06-21 22:52:31 -07:00
2015-06-29 11:45:42 -07:00
function onFullScreenChange() {
if (self.isFullScreen()) {
enterFullScreen();
idleState = true;
} else {
exitFullScreenToWindow();
}
2015-06-29 11:45:42 -07:00
}
2015-10-23 09:04:33 -07:00
var lastMousePosition = {};
function onMouseMove(evt) {
if (evt.clientX == lastMousePosition.x && evt.clientY == lastMousePosition.y) {
return;
}
lastMousePosition.x = evt.clientX;
lastMousePosition.y = evt.clientY;
idleHandler();
}
2015-06-29 11:45:42 -07:00
function bindEventsForPlayback(mediaRenderer) {
2014-06-21 22:52:31 -07:00
2015-12-23 10:46:01 -07:00
Events.on(mediaRenderer, 'playing', onOnePlaying);
Events.on(mediaRenderer, 'playing', onPlaying);
Events.on(mediaRenderer, 'volumechange', onVolumeChange);
Events.on(mediaRenderer, 'pause', onPause);
Events.on(mediaRenderer, 'timeupdate', onTimeUpdate);
Events.on(mediaRenderer, 'error', onError);
Events.on(mediaRenderer, 'click', onClick);
Events.on(mediaRenderer, 'dblclick', onDoubleClick);
2015-06-29 11:45:42 -07:00
var hideElementsOnIdle = true;
2014-06-21 22:52:31 -07:00
2015-06-29 11:45:42 -07:00
if (hideElementsOnIdle) {
var itemVideo = document.querySelector('.itemVideo');
if (itemVideo) {
2015-10-23 09:04:33 -07:00
//Events.on(itemVideo, 'mousemove', onMouseMove);
2015-12-14 08:43:03 -07:00
itemVideo.addEventListener('keydown', idleHandler);
itemVideo.addEventListener('scroll', idleHandler);
itemVideo.addEventListener('mousedown', idleHandler);
2015-06-29 11:45:42 -07:00
idleHandler();
2014-06-21 22:52:31 -07:00
}
2015-06-29 11:45:42 -07:00
}
2014-06-21 22:52:31 -07:00
2016-06-04 09:10:10 -07:00
document.addEventListener('webkitfullscreenchange', onFullScreenChange);
document.addEventListener('mozfullscreenchange', onFullScreenChange);
document.addEventListener('msfullscreenchange', onFullScreenChange);
document.addEventListener('fullscreenchange', onFullScreenChange);
2014-06-21 22:52:31 -07:00
2016-06-04 09:10:10 -07:00
window.addEventListener("popstate", onPopState);
2014-06-21 22:52:31 -07:00
2015-06-29 11:45:42 -07:00
if (hideElementsOnIdle) {
2016-06-04 09:10:10 -07:00
document.body.addEventListener("mousemove", onMouseMove);
}
2014-06-21 22:52:31 -07:00
}
2015-06-29 11:45:42 -07:00
function unbindEventsForPlayback(mediaRenderer) {
2014-06-21 22:52:31 -07:00
2015-12-23 10:46:01 -07:00
Events.off(mediaRenderer, 'playing', onOnePlaying);
Events.off(mediaRenderer, 'playing', onPlaying);
Events.off(mediaRenderer, 'volumechange', onVolumeChange);
Events.off(mediaRenderer, 'pause', onPause);
Events.off(mediaRenderer, 'timeupdate', onTimeUpdate);
Events.off(mediaRenderer, 'error', onError);
Events.off(mediaRenderer, 'click', onClick);
Events.off(mediaRenderer, 'dblclick', onDoubleClick);
2016-06-04 09:10:10 -07:00
document.removeEventListener('webkitfullscreenchange', onFullScreenChange);
document.removeEventListener('mozfullscreenchange', onFullScreenChange);
document.removeEventListener('msfullscreenchange', onFullScreenChange);
document.removeEventListener('fullscreenchange', onFullScreenChange);
2014-06-21 22:52:31 -07:00
// Stop playback on browser back button nav
2016-06-04 09:10:10 -07:00
window.removeEventListener("popstate", onPopState);
2014-06-21 22:52:31 -07:00
2016-06-04 09:10:10 -07:00
document.body.removeEventListener("mousemove", onMouseMove);
2014-06-21 22:52:31 -07:00
2015-06-29 11:45:42 -07:00
var itemVideo = document.querySelector('.itemVideo');
if (itemVideo) {
2015-10-23 09:04:33 -07:00
//Events.off(itemVideo, 'mousemove', onMouseMove);
2015-12-14 08:43:03 -07:00
itemVideo.removeEventListener('keydown', idleHandler);
itemVideo.removeEventListener('scroll', idleHandler);
itemVideo.removeEventListener('mousedown', idleHandler);
2015-06-29 11:45:42 -07:00
}
2014-06-21 22:52:31 -07:00
}
2014-08-10 15:13:17 -07:00
// Replace audio version
2015-06-07 13:06:18 -07:00
self.cleanup = function (mediaRenderer) {
2014-08-10 15:13:17 -07:00
2015-12-14 08:43:03 -07:00
if (currentTimeElement) {
2016-06-06 17:44:15 -07:00
currentTimeElement.innerHTML = '--:--';
2015-12-14 08:43:03 -07:00
}
2014-08-10 15:13:17 -07:00
2015-06-29 11:45:42 -07:00
unbindEventsForPlayback(mediaRenderer);
2014-08-10 15:13:17 -07:00
};
2015-07-08 09:10:34 -07:00
self.playVideo = function (item, mediaSource, startPosition, callback) {
2016-08-06 07:07:44 -07:00
if (browserInfo.msie) {
2016-07-31 12:03:38 -07:00
2016-08-06 07:07:44 -07:00
if (!window.MediaSource || !mediaSource.RunTimeTicks) {
2016-07-31 12:03:38 -07:00
alert('Playback of this content is not supported in Internet Explorer. For a better experience, please try a modern browser such as Google Chrome, Firefox, Opera, or Microsoft Edge.');
}
}
2015-12-14 08:43:03 -07:00
// TODO: remove dependency on nowplayingbar
2016-06-13 12:02:48 -07:00
requirejs(['videorenderer', 'css!css/nowplayingbar.css', 'css!css/mediaplayer-video.css', 'emby-slider'], function () {
2015-12-14 08:43:03 -07:00
initVideoElements();
2015-12-14 08:43:03 -07:00
self.createStreamInfo('Video', item, mediaSource, startPosition).then(function (streamInfo) {
2015-04-28 06:56:57 -07:00
2016-01-13 22:18:46 -07:00
var isHls = streamInfo.url.toLowerCase().indexOf('.m3u8') != -1;
2015-09-21 08:43:10 -07:00
// Huge hack alert. Safari doesn't seem to like if the segments aren't available right away when playback starts
// This will start the transcoding process before actually feeding the video url into the player
2016-01-13 22:18:46 -07:00
// Edit: Also seeing stalls from hls.js
2016-04-14 12:12:00 -07:00
if (!mediaSource.RunTimeTicks && isHls) {
2015-04-28 06:56:57 -07:00
2015-09-21 08:43:10 -07:00
Dashboard.showLoadingMsg();
2015-12-30 11:02:44 -07:00
var hlsPlaylistUrl = streamInfo.url.replace('master.m3u8', 'live.m3u8');
2015-09-21 08:43:10 -07:00
ApiClient.ajax({
2015-12-14 08:43:03 -07:00
2015-09-21 08:43:10 -07:00
type: 'GET',
2015-12-30 11:02:44 -07:00
url: hlsPlaylistUrl
2015-08-24 13:37:34 -07:00
2015-12-14 08:43:03 -07:00
}).then(function () {
2015-09-21 08:43:10 -07:00
Dashboard.hideLoadingMsg();
2015-12-30 11:02:44 -07:00
streamInfo.url = hlsPlaylistUrl;
2016-04-14 12:12:00 -07:00
// add a delay to continue building up the buffer. without this we see failures in safari mobile
setTimeout(function () {
self.playVideoInternal(item, mediaSource, startPosition, streamInfo, callback);
2016-04-16 21:07:06 -07:00
}, 2000);
2016-04-14 12:12:00 -07:00
2015-12-14 08:43:03 -07:00
}, function () {
Dashboard.hideLoadingMsg();
2015-09-21 08:43:10 -07:00
});
2015-04-28 06:56:57 -07:00
2015-09-21 08:43:10 -07:00
} else {
self.playVideoInternal(item, mediaSource, startPosition, streamInfo, callback);
}
});
2015-06-07 20:16:42 -07:00
});
2015-04-28 06:56:57 -07:00
};
2015-12-14 08:43:03 -07:00
function fadeOut(elem) {
if (elem.classList.contains('hide')) {
return;
}
var onfinish = function () {
elem.classList.add('hide');
};
2015-12-30 11:02:44 -07:00
//if (!browserInfo.animate) {
2015-12-30 13:25:17 -07:00
onfinish();
return;
2015-12-30 11:02:44 -07:00
//}
2015-12-14 08:43:03 -07:00
requestAnimationFrame(function () {
var keyframes = [
{ opacity: '1', offset: 0 },
{ opacity: '0', offset: 1 }];
var timing = { duration: 600, iterations: 1, easing: 'ease-out' };
elem.animate(keyframes, timing).onfinish = onfinish;
});
}
function fadeIn(elem) {
if (!elem.classList.contains('hide')) {
return;
}
elem.classList.remove('hide');
2016-08-06 07:07:44 -07:00
if (!browserInfo.animate || browserInfo.slow) {
2015-12-14 08:43:03 -07:00
return;
}
requestAnimationFrame(function () {
var keyframes = [
{ transform: 'scale3d(.2, .2, .2) ', opacity: '.6', offset: 0 },
{ transform: 'none', opacity: '1', offset: 1 }
];
var timing = { duration: 200, iterations: 1, easing: 'ease-out' };
elem.animate(keyframes, timing);
});
}
2015-07-08 09:10:34 -07:00
self.playVideoInternal = function (item, mediaSource, startPosition, streamInfo, callback) {
2015-04-28 06:56:57 -07:00
self.startTimeTicksOffset = streamInfo.startTimeTicksOffset;
var mediaStreams = mediaSource.MediaStreams || [];
2014-06-11 12:31:33 -07:00
var subtitleStreams = mediaStreams.filter(function (s) {
return s.Type == 'Subtitle';
});
// Create video player
2015-12-14 08:43:03 -07:00
var mediaPlayerContainer = document.querySelector('#videoPlayer');
fadeIn(mediaPlayerContainer);
2016-06-06 17:44:15 -07:00
var videoControls = mediaPlayerContainer.querySelector('.videoControls');
//show stop button
2016-06-06 17:44:15 -07:00
document.querySelector('#video-playButton').classList.add('hide');
document.querySelector('#video-pauseButton').classList.remove('hide');
2014-06-21 22:52:31 -07:00
2016-06-06 17:44:15 -07:00
document.querySelector('.videoTrackControl').classList.add('hide');
document.querySelector('.videoQualityButton').classList.remove('hide');
2014-06-11 12:31:33 -07:00
if (mediaStreams.filter(function (s) {
return s.Type == "Audio";
}).length) {
2016-06-06 17:44:15 -07:00
document.querySelector('.videoAudioButton').classList.remove('hide');
} else {
2016-06-06 17:44:15 -07:00
document.querySelector('.videoAudioButton').classList.add('hide');
}
2014-06-11 12:31:33 -07:00
if (subtitleStreams.length) {
2016-06-06 17:44:15 -07:00
document.querySelector('.videoSubtitleButton').classList.remove('hide');
} else {
2016-06-06 17:44:15 -07:00
document.querySelector('.videoSubtitleButton').classList.add('hide');
}
2015-07-03 09:49:49 -07:00
var mediaRenderer = new VideoRenderer({
2015-09-09 20:22:52 -07:00
2015-07-03 09:49:49 -07:00
poster: self.getPosterUrl(item)
});
2015-07-03 04:51:45 -07:00
var requiresNativeControls = !mediaRenderer.enableCustomVideoControls();
2015-09-08 07:35:52 -07:00
if (requiresNativeControls || AppInfo.isNativeApp) {
2016-06-06 17:44:15 -07:00
videoControls.querySelector('#video-fullscreenButton').classList.add('hide');
} else {
2016-06-06 17:44:15 -07:00
videoControls.querySelector('#video-fullscreenButton').classList.remove('hide');
}
2015-05-21 13:53:14 -07:00
if (AppInfo.hasPhysicalVolumeButtons) {
2016-06-24 09:51:13 -07:00
volumeSliderContainer.classList.add('hide');
2016-06-06 17:44:15 -07:00
videoControls.querySelector('.muteButton').classList.add('hide');
videoControls.querySelector('.unmuteButton').classList.add('hide');
2014-06-28 12:35:30 -07:00
} else {
2016-06-24 09:51:13 -07:00
volumeSliderContainer.classList.remove('hide');
2016-06-06 17:44:15 -07:00
videoControls.querySelector('.muteButton').classList.remove('hide');
videoControls.querySelector('.unmuteButton').classList.remove('hide');
2014-06-28 12:35:30 -07:00
}
if (requiresNativeControls) {
2016-06-06 17:44:15 -07:00
videoControls.classList.add('hide');
2014-06-28 12:35:30 -07:00
} else {
2016-06-06 17:44:15 -07:00
videoControls.classList.remove('hide');
2014-06-28 12:35:30 -07:00
}
initialVolume = self.getSavedVolume();
2015-06-07 13:06:18 -07:00
mediaRenderer.volume(initialVolume);
2015-06-27 12:53:36 -07:00
volumeSlider.value = initialVolume * 100;
updateVolumeButtons(initialVolume);
2015-12-23 10:46:01 -07:00
bindEventsForPlayback(mediaRenderer);
2015-12-23 10:46:01 -07:00
self.currentSubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
2016-06-06 17:44:15 -07:00
document.body.classList.add('bodyWithPopupOpen');
2014-08-10 15:13:17 -07:00
2015-12-23 10:46:01 -07:00
self.currentMediaRenderer = mediaRenderer;
self.currentDurationTicks = self.currentMediaSource.RunTimeTicks;
2015-12-23 10:46:01 -07:00
self.updateNowPlayingInfo(item);
2015-12-23 10:46:01 -07:00
mediaRenderer.init().then(function () {
2015-12-23 10:46:01 -07:00
self.onBeforePlaybackStart(mediaRenderer, item, mediaSource);
2015-12-23 10:46:01 -07:00
self.setSrcIntoRenderer(mediaRenderer, streamInfo, item, self.currentMediaSource);
self.streamInfo = streamInfo;
2015-12-23 10:46:01 -07:00
if (callback) {
callback();
}
});
};
2015-12-23 10:46:01 -07:00
function onOnePlaying() {
2015-12-23 10:46:01 -07:00
Events.off(this, 'playing', onOnePlaying);
2015-12-23 10:46:01 -07:00
// For some reason this is firing at the start, so don't bind until playback has begun
Events.on(this, 'ended', self.onPlaybackStopped);
Events.on(this, 'ended', self.playNextAfterEnded);
2015-12-23 10:46:01 -07:00
self.onPlaybackStart(this, self.currentItem, self.currentMediaSource);
}
2015-12-23 10:46:01 -07:00
function onPlaying() {
2014-07-21 18:29:06 -07:00
2015-12-23 10:46:01 -07:00
var videoControls = document.querySelector('#videoPlayer .videoControls');
var videoElement = document.querySelector('#videoPlayer #videoElement');
2016-06-06 17:44:15 -07:00
videoControls.querySelector('#video-playButton').classList.add('hide');
videoControls.querySelector('#video-pauseButton').classList.remove('hide');
var buttonToAnimate = videoElement.querySelector('#play');
buttonToAnimate.classList.remove('hide');
buttonToAnimate.classList.add('fadeOut');
2015-12-23 10:46:01 -07:00
setTimeout(function () {
2016-06-06 17:44:15 -07:00
buttonToAnimate.classList.add('hide');
buttonToAnimate.classList.remove('fadeOut');
2015-12-23 10:46:01 -07:00
}, 300);
}
2015-08-27 08:58:07 -07:00
2015-12-23 10:46:01 -07:00
function onVolumeChange() {
2015-12-23 10:46:01 -07:00
updateVolumeButtons(this.volume());
}
2015-12-23 10:46:01 -07:00
function onPause() {
2015-12-23 10:46:01 -07:00
var videoControls = document.querySelector('#videoPlayer .videoControls');
var videoElement = document.querySelector('#videoPlayer #videoElement');
2016-06-06 17:44:15 -07:00
videoControls.querySelector('#video-playButton').classList.remove('hide');
videoControls.querySelector('#video-pauseButton').classList.add('hide');
var buttonToAnimate = videoElement.querySelector('#pause');
buttonToAnimate.classList.remove('hide');
buttonToAnimate.classList.add('fadeOut');
2015-12-23 10:46:01 -07:00
setTimeout(function () {
2016-06-06 17:44:15 -07:00
buttonToAnimate.classList.add('hide');
buttonToAnimate.classList.remove('fadeOut');
2015-12-23 10:46:01 -07:00
}, 300);
}
2015-12-23 10:46:01 -07:00
function onTimeUpdate() {
if (!positionSlider.dragging) {
2015-12-23 10:46:01 -07:00
self.setCurrentTime(self.getCurrentTicks(this), positionSlider, currentTimeElement);
}
}
2014-06-28 12:35:30 -07:00
2015-12-23 10:46:01 -07:00
function onError() {
var errorMsg = Globalize.translate('MessageErrorPlayingVideo');
2015-04-28 06:56:57 -07:00
2016-01-21 13:40:10 -07:00
var item = self.currentItem;
var mediaSource = self.currentMediaSource;
2016-01-21 13:40:10 -07:00
if (item && item.Type == "TvChannel") {
errorMsg += '<br/>';
errorMsg += '<br/>';
2015-12-23 10:46:01 -07:00
errorMsg += Globalize.translate('MessageEnsureOpenTuner');
}
2016-09-12 11:10:09 -07:00
else if (mediaSource && mediaSource.VideoType && mediaSource.VideoType != "VideoFile") {
errorMsg += '<br/>';
errorMsg += '<br/>';
errorMsg += Globalize.translate('MessageFolderRipPlaybackExperimental');
2015-12-23 10:46:01 -07:00
}
2015-07-03 04:51:45 -07:00
2015-12-23 10:46:01 -07:00
Dashboard.alert({
title: Globalize.translate('HeaderVideoError'),
message: errorMsg
});
2015-07-03 09:49:49 -07:00
2016-01-21 13:41:09 -07:00
var mediaRenderer = self.currentMediaRenderer;
if (mediaRenderer) {
self.onPlaybackStopped.call(mediaRenderer);
}
2015-12-23 10:46:01 -07:00
self.nextTrack();
}
2015-09-25 19:31:13 -07:00
2015-12-23 10:46:01 -07:00
function onClick() {
2015-07-03 04:51:45 -07:00
2015-12-23 10:46:01 -07:00
if (!browserInfo.mobile) {
if (this.paused()) {
self.unpause();
} else {
self.pause();
2015-07-08 09:10:34 -07:00
}
2015-12-23 10:46:01 -07:00
}
}
function onDoubleClick() {
if (!browserInfo.mobile) {
self.toggleFullscreen();
}
}
self.updatePlaylistUi = function () {
2015-12-14 08:43:03 -07:00
if (!initComplete) {
return;
}
2015-05-27 22:51:48 -07:00
var index = self.currentPlaylistIndex(null);
var length = self.playlist.length;
2015-07-03 04:51:45 -07:00
var requiresNativeControls = false;
2015-09-10 11:28:22 -07:00
if (self.currentMediaRenderer && self.currentMediaRenderer.enableCustomVideoControls) {
2015-07-03 04:51:45 -07:00
requiresNativeControls = self.currentMediaRenderer.enableCustomVideoControls();
}
2015-03-23 10:19:21 -07:00
if (length < 2) {
2016-06-06 17:44:15 -07:00
document.querySelector('.videoTrackControl').classList.add('hide');
return;
}
2015-06-28 07:45:21 -07:00
var controls = requiresNativeControls ? '.videoAdvancedControls' : '.videoControls';
2015-06-29 11:45:42 -07:00
controls = document.querySelector(controls);
2015-06-28 07:45:21 -07:00
var previousTrackButton = controls.getElementsByClassName('previousTrackButton')[0];
var nextTrackButton = controls.getElementsByClassName('nextTrackButton')[0];
if (index === 0) {
2015-06-28 07:45:21 -07:00
previousTrackButton.setAttribute('disabled', 'disabled');
} else {
2015-06-28 07:45:21 -07:00
previousTrackButton.removeAttribute('disabled');
}
if ((index + 1) >= length) {
2015-06-28 07:45:21 -07:00
nextTrackButton.setAttribute('disabled', 'disabled');
} else {
2015-06-28 07:45:21 -07:00
nextTrackButton.removeAttribute('disabled');
}
2016-06-06 17:44:15 -07:00
previousTrackButton.classList.remove('hide');
nextTrackButton.classList.remove('hide');
};
2014-06-21 22:52:31 -07:00
}
createVideoPlayer(MediaPlayer);
2016-02-29 23:02:03 -07:00
});