(function () { function createVideoPlayer(self) { var timeout; var initialVolume; var idleState = true; var muteButton = null; var unmuteButton = null; var volumeSlider = null; var positionSlider; var isPositionSliderActive; var currentTimeElement; self.currentSubtitleStreamIndex = null; 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()) { self.exitFullScreen(); } else { requestFullScreen(document.body); } }; self.resetEnhancements = function () { $("#mediaPlayer").hide(); $('#videoPlayer').removeClass('fullscreenVideo').removeClass('idlePlayer'); $('.hiddenOnIdle').removeClass("inactive"); $("video").remove(); }; self.exitFullScreen = function () { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozExitFullScreen) { document.mozExitFullScreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } $('#videoPlayer').removeClass('fullscreenVideo'); }; self.isFullScreen = function () { return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement ? true : false; }; function onFlyoutClose() { $('.itemVideo').css('visibility', 'visible'); } function onPopupOpen(elem) { elem.popup("open").parents(".ui-popup-container").css("margin-top", 30); if ($.browser.safari) { $('.itemVideo').css('visibility', 'hidden'); } } self.showSubtitleMenu = function () { var elem = $('.videoSubtitlePopup').html(getSubtitleTracksHtml()) .trigger('create') .popup("option", "positionTo", $('.videoSubtitleButton')) .off('popupafterclose', onFlyoutClose) .on('popupafterclose', onFlyoutClose); onPopupOpen(elem); }; self.showQualityFlyout = function () { var elem = $('.videoQualityPopup').html(getQualityFlyoutHtml()) .trigger('create') .popup("option", "positionTo", $('.videoQualityButton')) .off('popupafterclose', onFlyoutClose) .on('popupafterclose', onFlyoutClose); onPopupOpen(elem); }; self.showChaptersFlyout = function () { var elem = $('.videoChaptersPopup').html(getChaptersFlyoutHtml()) .trigger('create') .popup("option", "positionTo", $('.videoChaptersButton')) .off('popupafterclose', onFlyoutClose) .on('popupafterclose', onFlyoutClose); onPopupOpen(elem); }; self.showAudioTracksFlyout = function () { var elem = $('.videoAudioPopup').html(getAudioTracksHtml()) .trigger('create') .popup("option", "positionTo", $('.videoAudioButton')) .off('popupafterclose', onFlyoutClose) .on('popupafterclose', onFlyoutClose); onPopupOpen(elem); }; self.setAudioStreamIndex = function (index) { self.changeStream(self.getCurrentTicks(), { AudioStreamIndex: index }); }; self.setSubtitleStreamIndex = function (index) { if (!self.supportsTextTracks()) { 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) { if (currentStream.DeliveryMethod != 'External') { // Need to change the transcoded stream to remove subs self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: -1 }); } } else if (!currentStream && newStream) { if (newStream.DeliveryMethod == 'External') { selectedTrackElementIndex = index; } else { // Need to change the transcoded stream to add subs self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: index }); } } else if (currentStream && newStream) { if (newStream.DeliveryMethod == 'External') { selectedTrackElementIndex = index; 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 }); } } self.setCurrentTrackElement(selectedTrackElementIndex); self.currentSubtitleStreamIndex = index; }; self.setCurrentTrackElement = function (index) { var modes = ['disabled', 'showing', 'hidden']; var textStreams = self.currentMediaSource.MediaStreams.filter(function (s) { return s.DeliveryMethod == 'External'; }); var newStream = textStreams.filter(function (s) { return s.Index == index; })[0]; var trackIndex = newStream ? textStreams.indexOf(newStream) : -1; console.log('Setting new text track index to: ' + trackIndex); var allTracks = self.currentMediaElement.textTracks; // get list of tracks for (var i = 0; i < allTracks.length; i++) { var mode; if (trackIndex == i) { mode = 1; // show this track } else { mode = 0; // hide all other tracks } console.log('Setting track ' + i + ' mode to: ' + mode); // Safari uses integers for the mode property // http://www.jwplayer.com/html5/scripting/ var useNumericMode = false; if (!isNaN(allTracks[i].mode)) { useNumericMode = true; } if (useNumericMode) { allTracks[i].mode = mode; } else { allTracks[i].mode = modes[mode]; } } }; self.updateTextStreamUrls = function (startPositionTicks) { if (!self.supportsTextTracks()) { return; } var allTracks = self.currentMediaElement.textTracks; // get list of tracks for (var i = 0; i < allTracks.length; i++) { var track = allTracks[i]; // This throws an error in IE, but is fine in chrome // In IE it's not necessary anyway because changing the src seems to be enough try { while (track.cues.length) { track.removeCue(track.cues[0]); } } catch (e) { console.log('Error removing cue from textTrack'); } } $('track', self.currentMediaElement).each(function () { var currentSrc = this.src; currentSrc = replaceQueryString(currentSrc, 'startPositionTicks', startPositionTicks); this.src = currentSrc; }); }; self.updateNowPlayingInfo = function (item) { if (!item) { throw new Error('item cannot be null'); } var mediaControls = $("#videoPlayer"); var state = self.getPlayerStateInternal(self.currentMediaElement, item, self.currentMediaSource); var url = ""; var imageWidth = 400; var imageHeight = 300; if (state.NowPlayingItem.PrimaryImageTag) { url = ApiClient.getScaledImageUrl(state.NowPlayingItem.PrimaryImageItemId, { type: "Primary", width: imageWidth, tag: state.NowPlayingItem.PrimaryImageTag }); } else if (state.NowPlayingItem.PrimaryImageTag) { url = ApiClient.getScaledImageUrl(state.NowPlayingItem.PrimaryImageItemId, { type: "Primary", width: imageWidth, tag: state.NowPlayingItem.PrimaryImageTag }); } else if (state.NowPlayingItem.BackdropImageTag) { url = ApiClient.getScaledImageUrl(state.NowPlayingItem.BackdropItemId, { type: "Backdrop", height: imageHeight, tag: state.NowPlayingItem.BackdropImageTag, index: 0 }); } else if (state.NowPlayingItem.ThumbImageTag) { url = ApiClient.getScaledImageUrl(state.NowPlayingItem.ThumbImageItemId, { type: "Thumb", height: imageHeight, tag: state.NowPlayingItem.ThumbImageTag }); } if (url) { $('.nowPlayingImage', mediaControls).html(''); } else { $('.nowPlayingImage', mediaControls).html(''); } if (state.NowPlayingItem.LogoItemId) { url = ApiClient.getScaledImageUrl(state.NowPlayingItem.LogoItemId, { type: "Logo", height: 42, tag: state.NowPlayingItem.LogoImageTag }); $('.videoTopControlsLogo', mediaControls).html(''); } else { $('.videoTopControlsLogo', mediaControls).html(''); } var elem = $('.nowPlayingTabs', mediaControls).html(getNowPlayingTabsHtml(item)).lazyChildren(); $('.nowPlayingTabButton', elem).on('click', function () { if (!$(this).hasClass('selectedNowPlayingTabButton')) { $('.selectedNowPlayingTabButton').removeClass('selectedNowPlayingTabButton'); $(this).addClass('selectedNowPlayingTabButton'); $('.nowPlayingTab').hide(); $('.' + this.getAttribute('data-tab')).show().trigger('scroll'); } }); $('.chapterCard', elem).on('click', function () { self.seek(parseInt(this.getAttribute('data-position'))); }); }; function getNowPlayingTabsHtml(item) { var html = ''; html += '
'; html += ' '; if (item.Chapters && item.Chapters.length) { html += ' '; } if (item.People && item.People.length) { html += ' '; } return html; } function onPositionSliderChange() { isPositionSliderActive = false; var newPercent = parseInt(this.value); var newPositionTicks = (newPercent / 100) * self.currentMediaSource.RunTimeTicks; self.changeStream(Math.floor(newPositionTicks)); } $(function () { var parent = $("#mediaPlayer"); muteButton = $('.muteButton', parent); unmuteButton = $('.unmuteButton', parent); currentTimeElement = $('.currentTime', parent); positionSlider = $(".positionSlider", parent).on('slidestart', function (e) { isPositionSliderActive = true; }).on('slidestop', onPositionSliderChange); volumeSlider = $('.volumeSlider', parent).on('slidestop', function () { var vol = this.value; updateVolumeButtons(vol); self.setVolume(vol * 100); }); $('.videoChaptersPopup').on('click', '.mediaPopupOption', function () { var ticks = parseInt(this.getAttribute('data-positionticks') || '0'); self.changeStream(ticks); $('.videoChaptersPopup').popup('close'); }); $('.videoAudioPopup').on('click', '.mediaPopupOption', function () { if (!$(this).hasClass('selectedMediaPopupOption')) { var index = parseInt(this.getAttribute('data-index')); self.setAudioStreamIndex(index); } $('.videoAudioPopup').popup('close'); }); $('.videoSubtitlePopup').on('click', '.mediaPopupOption', function () { $('.videoSubtitlePopup').popup('close'); if (!$(this).hasClass('selectedMediaPopupOption')) { var index = parseInt(this.getAttribute('data-index')); self.setSubtitleStreamIndex(index); } }); $('.videoQualityPopup').on('click', '.mediaPopupOption', function () { if (!$(this).hasClass('selectedMediaPopupOption')) { var bitrate = parseInt(this.getAttribute('data-bitrate')); AppSettings.maxStreamingBitrate(bitrate); self.changeStream(self.getCurrentTicks(), { Bitrate: bitrate }); } $('.videoQualityPopup').popup('close'); }); var trackChange = false; var tooltip = $(''); $(".videoControls .positionSliderContainer .slider").on("change", function (e) { if (!trackChange) return; var pct = $(this).val(); var time = self.currentDurationTicks * (Number(pct) * .01); var tooltext = Dashboard.getDisplayTime(time); tooltip.text(tooltext); console.log("slidin", pct, self.currentDurationTicks, time); }).on("slidestart", function (e) { trackChange = true; var handle = $(".videoControls .positionSliderContainer .ui-slider-handle"); handle.after(tooltip); }).on("slidestop", function (e) { trackChange = false; tooltip.remove(); }); $('.videoSubtitleButton').on('click', function () { self.showSubtitleMenu(); }); $('.videoQualityButton').on('click', function () { self.showQualityFlyout(); }); $('.videoAudioButton').on('click', function () { self.showAudioTracksFlyout(); }); $('.videoChaptersButton').on('click', function () { self.showChaptersFlyout(); }); }); function idleHandler() { if (timeout) { window.clearTimeout(timeout); } if (idleState == true) { $('.hiddenOnIdle').removeClass("inactive"); $('#videoPlayer').removeClass('idlePlayer'); } idleState = false; timeout = window.setTimeout(function () { idleState = true; $('.hiddenOnIdle').addClass("inactive"); $('#videoPlayer').addClass('idlePlayer'); }, 5000); } function updateVolumeButtons(vol) { if (vol) { muteButton.show(); unmuteButton.hide(); } else { muteButton.hide(); unmuteButton.show(); } } function requestFullScreen(element) { // Supports most browsers and their versions. var requestMethod = element.requestFullscreen || element.webkitRequestFullscreen || element.mozRequestFullScreen || element.msRequestFullscreen; if (requestMethod) { // Native full screen. requestMethod.call(element); } else { enterFullScreen(); } } function enterFullScreen() { var player = $("#videoPlayer"); player.addClass("fullscreenVideo"); } function exitFullScreenToWindow() { var player = $("#videoPlayer"); player.removeClass("fullscreenVideo"); } function getChaptersFlyoutHtml() { var item = self.currentItem; var currentTicks = self.getCurrentTicks(); var chapters = item.Chapters || []; var html = ''; html += '';
var textLines = [];
textLines.push(chapter.Name);
textLines.push(Dashboard.getDisplayTime(chapter.StartPositionTicks));
optionHtml += textLines.join('
');
optionHtml += '
';
if (selected) {
optionHtml += '';
}
var textLines = [];
textLines.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
var attributes = [];
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');
}
if (stream.IsDefault) {
attributes.push('(D)');
}
if (attributes.length) {
textLines.push(attributes.join(' '));
}
optionHtml += textLines.join('
');
optionHtml += '
';
if (selected) {
optionHtml += '';
}
var textLines = [];
textLines.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
if (stream.Codec) {
textLines.push(stream.Codec);
}
var attributes = [];
if (stream.IsDefault) {
attributes.push('Default');
}
if (stream.IsForced) {
attributes.push('Forced');
}
if (stream.IsExternal) {
attributes.push('External');
}
if (attributes.length) {
textLines.push(attributes.join(' '));
}
optionHtml += textLines.join('
');
optionHtml += '
'; if (option.selected) { optionHtml += ''; } optionHtml += option.name; optionHtml += '
'; optionHtml += '