2014-03-08 01:09:45 -07:00
|
|
|
|
(function () {
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
function createVideoPlayer(self) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
var timeout;
|
2014-03-20 01:34:54 -07:00
|
|
|
|
var initialVolume;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
var fullscreenExited = false;
|
2014-03-18 12:57:32 -07:00
|
|
|
|
var idleState = true;
|
2014-03-20 12:12:10 -07:00
|
|
|
|
var remoteFullscreen = false;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
var muteButton = null;
|
|
|
|
|
var unmuteButton = null;
|
|
|
|
|
var volumeSlider = null;
|
|
|
|
|
var positionSlider;
|
|
|
|
|
var isPositionSliderActive;
|
|
|
|
|
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];
|
|
|
|
|
};
|
|
|
|
|
|
2014-03-20 12:12:10 -07:00
|
|
|
|
self.remoteFullscreen = function () {
|
|
|
|
|
|
|
|
|
|
if (remoteFullscreen) {
|
|
|
|
|
exitFullScreenToWindow();
|
|
|
|
|
} else {
|
|
|
|
|
enterFullScreen();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remoteFullscreen = !remoteFullscreen;
|
|
|
|
|
};
|
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
self.toggleFullscreen = function () {
|
|
|
|
|
if (self.isFullScreen()) {
|
2014-03-20 12:12:10 -07:00
|
|
|
|
if (document.cancelFullScreen) {
|
|
|
|
|
document.cancelFullScreen();
|
|
|
|
|
}
|
|
|
|
|
else if (document.mozCancelFullScreen) {
|
|
|
|
|
document.mozCancelFullScreen();
|
|
|
|
|
}
|
|
|
|
|
else if (document.webkitExitFullscreen) {
|
|
|
|
|
document.webkitExitFullscreen();
|
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
else if (document.webkitCancelFullScreen) {
|
|
|
|
|
document.webkitCancelFullScreen();
|
|
|
|
|
}
|
2014-05-29 12:34:20 -07:00
|
|
|
|
$('#videoPlayer').removeClass('fullscreenVideo');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
} else {
|
2014-03-24 20:26:54 -07:00
|
|
|
|
requestFullScreen(document.body);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.resetEnhancements = function () {
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$("#mediaPlayer").hide();
|
2014-10-09 15:22:04 -07:00
|
|
|
|
$('#videoPlayer').removeClass('fullscreenVideo').removeClass('idlePlayer');
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.hiddenOnIdle').removeClass("inactive");
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$("video").remove();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
};
|
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
self.exitFullScreen = function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
if (document.exitFullscreen) {
|
|
|
|
|
document.exitFullscreen();
|
|
|
|
|
} else if (document.mozExitFullScreen) {
|
|
|
|
|
document.mozExitFullScreen();
|
|
|
|
|
} else if (document.webkitExitFullscreen) {
|
|
|
|
|
document.webkitExitFullscreen();
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-29 12:34:20 -07:00
|
|
|
|
$('#videoPlayer').removeClass('fullscreenVideo');
|
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
fullscreenExited = true;
|
2014-03-17 07:48:16 -07:00
|
|
|
|
};
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
self.isFullScreen = function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement ? true : false;
|
2014-03-17 07:48:16 -07:00
|
|
|
|
};
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-02 11:34:08 -07:00
|
|
|
|
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');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
self.showSubtitleMenu = function () {
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var elem = $('.videoSubtitlePopup').html(getSubtitleTracksHtml())
|
|
|
|
|
.trigger('create')
|
2014-07-02 11:34:08 -07:00
|
|
|
|
.popup("option", "positionTo", $('.videoSubtitleButton'))
|
|
|
|
|
.off('popupafterclose', onFlyoutClose)
|
|
|
|
|
.on('popupafterclose', onFlyoutClose);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-02 11:34:08 -07:00
|
|
|
|
onPopupOpen(elem);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.showQualityFlyout = function () {
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var elem = $('.videoQualityPopup').html(getQualityFlyoutHtml())
|
|
|
|
|
.trigger('create')
|
2014-07-02 11:34:08 -07:00
|
|
|
|
.popup("option", "positionTo", $('.videoQualityButton'))
|
|
|
|
|
.off('popupafterclose', onFlyoutClose)
|
|
|
|
|
.on('popupafterclose', onFlyoutClose);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-02 11:34:08 -07:00
|
|
|
|
onPopupOpen(elem);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.showChaptersFlyout = function () {
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var elem = $('.videoChaptersPopup').html(getChaptersFlyoutHtml())
|
|
|
|
|
.trigger('create')
|
2014-07-02 11:34:08 -07:00
|
|
|
|
.popup("option", "positionTo", $('.videoChaptersButton'))
|
|
|
|
|
.off('popupafterclose', onFlyoutClose)
|
|
|
|
|
.on('popupafterclose', onFlyoutClose);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-02 11:34:08 -07:00
|
|
|
|
onPopupOpen(elem);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.showAudioTracksFlyout = function () {
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var elem = $('.videoAudioPopup').html(getAudioTracksHtml())
|
|
|
|
|
.trigger('create')
|
2014-07-02 11:34:08 -07:00
|
|
|
|
.popup("option", "positionTo", $('.videoAudioButton'))
|
|
|
|
|
.off('popupafterclose', onFlyoutClose)
|
|
|
|
|
.on('popupafterclose', onFlyoutClose);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-02 11:34:08 -07:00
|
|
|
|
onPopupOpen(elem);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
};
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
if (!self.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) {
|
|
|
|
|
|
|
|
|
|
if (!currentStream.IsTextSubtitleStream) {
|
|
|
|
|
|
|
|
|
|
// Need to change the transcoded stream to remove subs
|
|
|
|
|
self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: -1 });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (!currentStream && newStream) {
|
|
|
|
|
|
|
|
|
|
if (newStream.IsTextSubtitleStream) {
|
|
|
|
|
selectedTrackElementIndex = index;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// Need to change the transcoded stream to add subs
|
|
|
|
|
self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: index });
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-14 19:24:04 -07:00
|
|
|
|
else if (currentStream && newStream) {
|
|
|
|
|
|
|
|
|
|
if (newStream.IsTextSubtitleStream) {
|
|
|
|
|
selectedTrackElementIndex = index;
|
2014-06-14 19:58:00 -07:00
|
|
|
|
|
2014-06-14 19:24:04 -07:00
|
|
|
|
if (!currentStream.IsTextSubtitleStream) {
|
|
|
|
|
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) {
|
|
|
|
|
|
2014-08-25 19:30:52 -07:00
|
|
|
|
var modes = ['disabled', 'showing', 'hidden'];
|
|
|
|
|
|
2014-06-11 19:38:40 -07:00
|
|
|
|
var textStreams = self.currentMediaSource.MediaStreams.filter(function (s) {
|
|
|
|
|
return s.Type == 'Subtitle' && s.IsTextSubtitleStream;
|
|
|
|
|
});
|
|
|
|
|
|
2014-07-19 21:46:29 -07:00
|
|
|
|
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);
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
var allTracks = self.currentMediaElement.textTracks; // get list of tracks
|
2014-06-11 19:38:40 -07:00
|
|
|
|
|
|
|
|
|
for (var i = 0; i < allTracks.length; i++) {
|
|
|
|
|
|
2014-07-19 21:46:29 -07:00
|
|
|
|
var mode;
|
2014-06-11 19:38:40 -07:00
|
|
|
|
|
2014-07-19 21:46:29 -07:00
|
|
|
|
if (trackIndex == i) {
|
2014-08-25 19:30:52 -07:00
|
|
|
|
mode = 1; // show this track
|
2014-06-11 19:38:40 -07:00
|
|
|
|
} else {
|
2014-08-25 19:30:52 -07:00
|
|
|
|
mode = 0; // hide all other tracks
|
2014-06-11 19:38:40 -07:00
|
|
|
|
}
|
2014-07-19 21:46:29 -07:00
|
|
|
|
|
|
|
|
|
console.log('Setting track ' + i + ' mode to: ' + mode);
|
2014-08-25 19:30:52 -07:00
|
|
|
|
|
|
|
|
|
// 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];
|
|
|
|
|
}
|
2014-06-11 19:38:40 -07:00
|
|
|
|
}
|
2014-05-07 22:04:39 -07:00
|
|
|
|
};
|
|
|
|
|
|
2014-06-14 19:58:00 -07:00
|
|
|
|
self.updateTextStreamUrls = function (startPositionTicks) {
|
|
|
|
|
|
2014-06-15 16:30:04 -07:00
|
|
|
|
if (!self.supportsTextTracks()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
var allTracks = self.currentMediaElement.textTracks; // get list of tracks
|
2014-06-18 09:08:54 -07:00
|
|
|
|
|
|
|
|
|
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');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
$('track', self.currentMediaElement).each(function () {
|
2014-06-14 19:58:00 -07:00
|
|
|
|
|
|
|
|
|
var currentSrc = this.src;
|
|
|
|
|
|
|
|
|
|
currentSrc = replaceQueryString(currentSrc, 'startPositionTicks', startPositionTicks);
|
|
|
|
|
|
|
|
|
|
this.src = currentSrc;
|
2014-06-15 16:30:04 -07:00
|
|
|
|
|
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');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var mediaControls = $("#videoPlayer");
|
|
|
|
|
|
|
|
|
|
var state = self.getPlayerStateInternal(self.currentMediaElement, item, self.currentMediaSource);
|
|
|
|
|
|
|
|
|
|
var url = "";
|
|
|
|
|
|
|
|
|
|
if (state.NowPlayingItem.PrimaryImageTag) {
|
|
|
|
|
|
|
|
|
|
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.PrimaryImageItemId, {
|
|
|
|
|
type: "Primary",
|
|
|
|
|
width: 150,
|
|
|
|
|
tag: state.NowPlayingItem.PrimaryImageTag
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else if (state.NowPlayingItem.PrimaryImageTag) {
|
|
|
|
|
|
|
|
|
|
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.PrimaryImageItemId, {
|
|
|
|
|
type: "Primary",
|
|
|
|
|
width: 150,
|
|
|
|
|
tag: state.NowPlayingItem.PrimaryImageTag
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else if (state.NowPlayingItem.BackdropImageTag) {
|
|
|
|
|
|
|
|
|
|
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.BackdropItemId, {
|
|
|
|
|
type: "Backdrop",
|
|
|
|
|
height: 300,
|
|
|
|
|
tag: state.NowPlayingItem.BackdropImageTag,
|
|
|
|
|
index: 0
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (state.NowPlayingItem.ThumbImageTag) {
|
|
|
|
|
|
|
|
|
|
url = ApiClient.getScaledImageUrl(state.NowPlayingItem.ThumbImageItemId, {
|
|
|
|
|
type: "Thumb",
|
|
|
|
|
height: 300,
|
|
|
|
|
tag: state.NowPlayingItem.ThumbImageTag
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var nowPlayingTextElement = $('.nowPlayingText', mediaControls);
|
|
|
|
|
var nameHtml = self.getNowPlayingNameHtml(state);
|
|
|
|
|
|
|
|
|
|
if (nameHtml.indexOf('<br/>') != -1) {
|
|
|
|
|
nowPlayingTextElement.addClass('nowPlayingDoubleText');
|
|
|
|
|
} else {
|
|
|
|
|
nowPlayingTextElement.removeClass('nowPlayingDoubleText');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (url) {
|
|
|
|
|
$('.nowPlayingImage', mediaControls).html('<img src="' + url + '" />');
|
|
|
|
|
} else {
|
|
|
|
|
$('.nowPlayingImage', mediaControls).html('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('.videoTopControlsLogo', mediaControls).html('<img src="' + url + '" />');
|
|
|
|
|
} else {
|
|
|
|
|
$('.videoTopControlsLogo', mediaControls).html('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nowPlayingTextElement.html(nameHtml);
|
|
|
|
|
};
|
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
function onPositionSliderChange() {
|
|
|
|
|
|
|
|
|
|
isPositionSliderActive = false;
|
|
|
|
|
|
|
|
|
|
var newPercent = parseInt(this.value);
|
|
|
|
|
|
2014-06-11 12:31:33 -07:00
|
|
|
|
var newPositionTicks = (newPercent / 100) * self.currentMediaSource.RunTimeTicks;
|
2014-04-11 08:36:25 -07:00
|
|
|
|
|
|
|
|
|
self.changeStream(Math.floor(newPositionTicks));
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
$(function () {
|
2014-04-11 08:36:25 -07:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
});
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoChaptersPopup').on('click', '.mediaPopupOption', function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
var ticks = parseInt(this.getAttribute('data-positionticks'));
|
|
|
|
|
|
|
|
|
|
self.changeStream(ticks);
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoChaptersPopup').popup('close');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
});
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoAudioPopup').on('click', '.mediaPopupOption', function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (!$(this).hasClass('selectedMediaPopupOption')) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
var index = parseInt(this.getAttribute('data-index'));
|
|
|
|
|
|
2014-05-07 22:04:39 -07:00
|
|
|
|
self.setAudioStreamIndex(index);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoAudioPopup').popup('close');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
});
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoSubtitlePopup').on('click', '.mediaPopupOption', function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-19 21:46:29 -07:00
|
|
|
|
$('.videoSubtitlePopup').popup('close');
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (!$(this).hasClass('selectedMediaPopupOption')) {
|
2014-07-19 21:46:29 -07:00
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
var index = parseInt(this.getAttribute('data-index'));
|
|
|
|
|
|
2014-05-07 22:04:39 -07:00
|
|
|
|
self.setSubtitleStreamIndex(index);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoQualityPopup').on('click', '.mediaPopupOption', function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (!$(this).hasClass('selectedMediaPopupOption')) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
var maxWidth = parseInt(this.getAttribute('data-maxwidth'));
|
|
|
|
|
var bitrate = parseInt(this.getAttribute('data-bitrate'));
|
|
|
|
|
|
2014-09-16 18:38:50 -07:00
|
|
|
|
AppSettings.maxStreamingBitrate(bitrate);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
self.changeStream(self.getCurrentTicks(), {
|
|
|
|
|
|
|
|
|
|
MaxWidth: maxWidth,
|
|
|
|
|
Bitrate: bitrate
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoQualityPopup').popup('close');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
});
|
2014-03-18 12:57:32 -07:00
|
|
|
|
|
2014-03-31 14:39:12 -07:00
|
|
|
|
var trackChange = false;
|
|
|
|
|
|
|
|
|
|
var tooltip = $('<div id="slider-tooltip"></div>');
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$(".videoControls .positionSliderContainer .slider").on("change", function (e) {
|
2014-03-31 14:39:12 -07:00
|
|
|
|
if (!trackChange) return;
|
|
|
|
|
|
|
|
|
|
var pct = $(this).val();
|
|
|
|
|
|
2014-03-31 14:43:49 -07:00
|
|
|
|
var time = self.currentDurationTicks * (Number(pct) * .01);
|
2014-03-31 14:39:12 -07:00
|
|
|
|
|
2014-06-17 22:15:51 -07:00
|
|
|
|
var tooltext = Dashboard.getDisplayTime(time);
|
2014-03-31 14:39:12 -07:00
|
|
|
|
|
|
|
|
|
tooltip.text(tooltext);
|
|
|
|
|
|
2014-03-31 14:43:49 -07:00
|
|
|
|
console.log("slidin", pct, self.currentDurationTicks, time);
|
2014-03-31 14:39:12 -07:00
|
|
|
|
|
|
|
|
|
}).on("slidestart", function (e) {
|
|
|
|
|
trackChange = true;
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var handle = $(".videoControls .positionSliderContainer .ui-slider-handle");
|
2014-03-31 14:39:12 -07:00
|
|
|
|
|
|
|
|
|
handle.after(tooltip);
|
|
|
|
|
}).on("slidestop", function (e) {
|
|
|
|
|
trackChange = false;
|
|
|
|
|
|
|
|
|
|
tooltip.remove();
|
|
|
|
|
});
|
2014-06-21 22:52:31 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoSubtitleButton').on('click', function () {
|
|
|
|
|
|
|
|
|
|
self.showSubtitleMenu();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('.videoQualityButton').on('click', function () {
|
2014-06-25 08:12:39 -07:00
|
|
|
|
|
|
|
|
|
self.showQualityFlyout();
|
2014-06-21 22:52:31 -07:00
|
|
|
|
});
|
2014-06-28 12:35:30 -07:00
|
|
|
|
|
|
|
|
|
$('.videoAudioButton').on('click', function () {
|
|
|
|
|
|
|
|
|
|
self.showAudioTracksFlyout();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('.videoChaptersButton').on('click', function () {
|
|
|
|
|
|
|
|
|
|
self.showChaptersFlyout();
|
|
|
|
|
});
|
2014-03-08 01:09:45 -07:00
|
|
|
|
});
|
|
|
|
|
|
2014-03-18 12:57:32 -07:00
|
|
|
|
function idleHandler() {
|
2014-06-21 22:52:31 -07:00
|
|
|
|
|
2014-03-18 12:57:32 -07:00
|
|
|
|
if (timeout) {
|
|
|
|
|
window.clearTimeout(timeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (idleState == true) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.hiddenOnIdle').removeClass("inactive");
|
2014-10-09 15:22:04 -07:00
|
|
|
|
$('#videoPlayer').removeClass('idlePlayer');
|
2014-03-18 12:57:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
idleState = false;
|
|
|
|
|
|
|
|
|
|
timeout = window.setTimeout(function () {
|
|
|
|
|
idleState = true;
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.hiddenOnIdle').addClass("inactive");
|
2014-10-09 15:22:04 -07:00
|
|
|
|
$('#videoPlayer').addClass('idlePlayer');
|
2014-03-18 12:57:32 -07:00
|
|
|
|
}, 4000);
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-03-18 12:57:32 -07:00
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
function updateVolumeButtons(vol) {
|
|
|
|
|
|
|
|
|
|
if (vol) {
|
|
|
|
|
muteButton.show();
|
|
|
|
|
unmuteButton.hide();
|
|
|
|
|
} else {
|
|
|
|
|
muteButton.hide();
|
|
|
|
|
unmuteButton.show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
function requestFullScreen(element) {
|
2014-03-20 12:12:10 -07:00
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
// Supports most browsers and their versions.
|
2014-03-20 12:12:10 -07:00
|
|
|
|
var requestMethod = element.requestFullscreen || element.webkitRequestFullscreen || element.webkitRequestFullScreen || element.mozRequestFullScreen;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
if (requestMethod) { // Native full screen.
|
|
|
|
|
requestMethod.call(element);
|
|
|
|
|
} else {
|
|
|
|
|
enterFullScreen();
|
|
|
|
|
}
|
2014-03-20 12:12:10 -07:00
|
|
|
|
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
function enterFullScreen() {
|
|
|
|
|
|
2014-03-17 07:48:16 -07:00
|
|
|
|
var player = $("#videoPlayer");
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-05-29 12:34:20 -07:00
|
|
|
|
player.addClass("fullscreenVideo");
|
|
|
|
|
|
2014-03-20 12:12:10 -07:00
|
|
|
|
remoteFullscreen = true;
|
|
|
|
|
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
function exitFullScreenToWindow() {
|
|
|
|
|
|
2014-03-17 07:48:16 -07:00
|
|
|
|
var player = $("#videoPlayer");
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-05-29 12:34:20 -07:00
|
|
|
|
player.removeClass("fullscreenVideo");
|
|
|
|
|
|
2014-03-20 12:12:10 -07:00
|
|
|
|
remoteFullscreen = false;
|
|
|
|
|
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
function getChaptersFlyoutHtml() {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var item = self.currentItem;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
var currentTicks = self.getCurrentTicks();
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var chapters = item.Chapters || [];
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var html = '';
|
|
|
|
|
html += '<div class="videoPlayerPopupContent">';
|
2014-07-02 11:34:08 -07:00
|
|
|
|
html += '<ul data-role="listview" data-inset="true"><li data-role="list-divider">' + Globalize.translate('HeaderScenes') + '</li>';
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '</ul>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '<div class="videoPlayerPopupScroller">';
|
|
|
|
|
html += '<ul data-role="listview" data-inset="true">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var index = 0;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += chapters.map(function (chapter) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var cssClass = "mediaPopupOption";
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var selected = false;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (currentTicks >= chapter.StartPositionTicks) {
|
|
|
|
|
var nextChapter = chapters[index + 1];
|
|
|
|
|
selected = !nextChapter || currentTicks < nextChapter.StartPositionTicks;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var optionHtml = '<li><a data-positionticks="' + chapter.StartPositionTicks + '" class="' + cssClass + '" href="#" style="padding-top:0;padding-bottom:0;">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var imgUrl = "css/images/media/chapterflyout.png";
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
if (chapter.ImageTag) {
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '<img src="' + imgUrl + '" style="visibility:hidden;" />';
|
|
|
|
|
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
|
|
|
|
|
width: 160,
|
2014-03-08 01:09:45 -07:00
|
|
|
|
tag: chapter.ImageTag,
|
|
|
|
|
type: "Chapter",
|
2014-06-28 12:35:30 -07:00
|
|
|
|
index: index
|
2014-03-08 01:09:45 -07:00
|
|
|
|
});
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '<div class="videoChapterPopupImage" style="background-image:url(\'' + imgUrl + '\');"></div>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
} else {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '<img src="' + imgUrl + '" />';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
// TODO: Add some indicator if selected = true
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '<p style="margin:12px 0 0;">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var textLines = [];
|
|
|
|
|
textLines.push(chapter.Name);
|
|
|
|
|
textLines.push(Dashboard.getDisplayTime(chapter.StartPositionTicks));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += textLines.join('<br/>');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '</p>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '</a></li>';
|
|
|
|
|
|
|
|
|
|
index++;
|
|
|
|
|
|
|
|
|
|
return optionHtml;
|
|
|
|
|
|
|
|
|
|
}).join('');
|
|
|
|
|
|
|
|
|
|
html += '</ul>';
|
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
|
|
html += '</div>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
return html;
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
function getAudioTracksHtml() {
|
2014-04-06 10:53:23 -07:00
|
|
|
|
|
2014-06-11 12:31:33 -07:00
|
|
|
|
var streams = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
|
2014-03-20 20:31:40 -07:00
|
|
|
|
return currentStream.Type == "Audio";
|
2014-03-08 01:09:45 -07:00
|
|
|
|
});
|
|
|
|
|
|
2014-10-22 21:26:01 -07:00
|
|
|
|
var currentIndex = getParameterByName('AudioStreamIndex', self.getCurrentSrc(self.currentMediaElement));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
var html = '';
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '<div class="videoPlayerPopupContent">';
|
2014-07-02 11:34:08 -07:00
|
|
|
|
html += '<ul data-role="listview" data-inset="true"><li data-role="list-divider">' + Globalize.translate('HeaderAudioTracks') + '</li>';
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '</ul>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '<div class="videoPlayerPopupScroller">';
|
|
|
|
|
html += '<ul data-role="listview" data-inset="true">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += streams.map(function (stream) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var cssClass = "mediaPopupOption";
|
|
|
|
|
|
|
|
|
|
var selected = stream.Index == currentIndex;
|
|
|
|
|
|
|
|
|
|
if (selected) {
|
|
|
|
|
cssClass += ' selectedMediaPopupOption';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var optionHtml = '<li><a data-index="' + stream.Index + '" class="' + cssClass + '" href="#">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '<p style="margin:0;">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (selected) {
|
|
|
|
|
optionHtml += '<img src="css/images/checkmarkgreen.png" style="width:18px;border-radius:3px;margin-right:.5em;vertical-align:middle;" />';
|
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var textLines = [];
|
2014-07-02 11:34:08 -07:00
|
|
|
|
textLines.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
|
2014-06-28 12:35:30 -07:00
|
|
|
|
|
|
|
|
|
var attributes = [];
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
if (stream.Codec) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
attributes.push(stream.Codec);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
if (stream.Profile) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
attributes.push(stream.Profile);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stream.BitRate) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
attributes.push((Math.floor(stream.BitRate / 1000)) + ' kbps');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stream.Channels) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
attributes.push(stream.Channels + ' ch');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stream.IsDefault) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
attributes.push('(D)');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (attributes.length) {
|
|
|
|
|
textLines.push(attributes.join(' • '));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += textLines.join('<br/>');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '</p>';
|
|
|
|
|
|
|
|
|
|
optionHtml += '</a></li>';
|
|
|
|
|
|
|
|
|
|
return optionHtml;
|
|
|
|
|
|
|
|
|
|
}).join('');
|
|
|
|
|
|
|
|
|
|
html += '</ul>';
|
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
|
|
html += '</div>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
return html;
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
function getSubtitleTracksHtml() {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-11 12:31:33 -07:00
|
|
|
|
var streams = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
|
2014-03-20 20:31:40 -07:00
|
|
|
|
return currentStream.Type == "Subtitle";
|
2014-03-08 01:09:45 -07:00
|
|
|
|
});
|
|
|
|
|
|
2014-06-11 19:38:40 -07:00
|
|
|
|
var currentIndex = self.currentSubtitleStreamIndex || -1;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
streams.unshift({
|
|
|
|
|
Index: -1,
|
|
|
|
|
Language: "Off"
|
|
|
|
|
});
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var html = '';
|
|
|
|
|
html += '<div class="videoPlayerPopupContent">';
|
2014-07-02 11:34:08 -07:00
|
|
|
|
html += '<ul data-role="listview" data-inset="true"><li data-role="list-divider">' + Globalize.translate('HeaderSubtitles') + '</li>';
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '</ul>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '<div class="videoPlayerPopupScroller">';
|
|
|
|
|
html += '<ul data-role="listview" data-inset="true">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += streams.map(function (stream) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var cssClass = "mediaPopupOption";
|
|
|
|
|
|
|
|
|
|
var selected = stream.Index == currentIndex;
|
|
|
|
|
|
|
|
|
|
if (selected) {
|
|
|
|
|
cssClass += ' selectedMediaPopupOption';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var optionHtml = '<li><a data-index="' + stream.Index + '" class="' + cssClass + '" href="#">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '<p style="margin:0;">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (selected) {
|
|
|
|
|
optionHtml += '<img src="css/images/checkmarkgreen.png" style="width:18px;border-radius:3px;margin-right:.5em;vertical-align:middle;" />';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var textLines = [];
|
2014-07-02 11:34:08 -07:00
|
|
|
|
textLines.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
if (stream.Codec) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
textLines.push(stream.Codec);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var attributes = [];
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
if (stream.IsDefault) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
attributes.push('Default');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
if (stream.IsForced) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
attributes.push('Forced');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
if (stream.IsExternal) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
attributes.push('External');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (attributes.length) {
|
|
|
|
|
textLines.push(attributes.join(' • '));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += textLines.join('<br/>');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '</p>';
|
|
|
|
|
|
|
|
|
|
optionHtml += '</a></li>';
|
|
|
|
|
|
|
|
|
|
return optionHtml;
|
|
|
|
|
|
|
|
|
|
}).join('');
|
|
|
|
|
|
|
|
|
|
html += '</ul>';
|
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
|
|
html += '</div>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
return html;
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
function getQualityFlyoutHtml() {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-10-22 21:26:01 -07:00
|
|
|
|
var currentSrc = self.getCurrentSrc(self.currentMediaElement).toLowerCase();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
var isStatic = currentSrc.indexOf('static=true') != -1;
|
|
|
|
|
|
2014-10-03 18:42:38 -07:00
|
|
|
|
var options = getVideoQualityOptions(self.currentMediaSource.MediaStreams);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
if (isStatic) {
|
|
|
|
|
options[0].name = "Direct";
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var html = '';
|
2014-07-02 11:34:08 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '<div class="videoPlayerPopupContent">';
|
2014-07-02 11:34:08 -07:00
|
|
|
|
html += '<ul data-role="listview" data-inset="true"><li data-role="list-divider">' + Globalize.translate('HeaderVideoQuality') + '</li>';
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += '</ul>';
|
|
|
|
|
|
|
|
|
|
html += '<div class="videoPlayerPopupScroller">';
|
|
|
|
|
html += '<ul data-role="listview" data-inset="true">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
html += options.map(function (option) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var cssClass = "mediaPopupOption";
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
if (option.selected) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
cssClass += ' selectedMediaPopupOption';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var optionHtml = '<li><a data-maxwidth="' + option.maxWidth + '" data-bitrate="' + option.bitrate + '" class="' + cssClass + '" href="#">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '<p style="margin:0;">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (option.selected) {
|
|
|
|
|
optionHtml += '<img src="css/images/checkmarkgreen.png" style="width:18px;border-radius:3px;margin-right:.5em;vertical-align:middle;" />';
|
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += option.name;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
optionHtml += '</p>';
|
|
|
|
|
|
|
|
|
|
optionHtml += '</a></li>';
|
|
|
|
|
|
|
|
|
|
return optionHtml;
|
|
|
|
|
|
|
|
|
|
}).join('');
|
|
|
|
|
|
|
|
|
|
html += '</ul>';
|
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
|
|
html += '</div>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
return html;
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
function getVideoQualityOptions(mediaStreams) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
var videoStream = mediaStreams.filter(function (stream) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
return stream.Type == "Video";
|
|
|
|
|
})[0];
|
|
|
|
|
|
2014-09-16 18:38:50 -07:00
|
|
|
|
var bitrateSetting = AppSettings.maxStreamingBitrate();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-10-07 18:37:45 -07:00
|
|
|
|
var maxAllowedWidth = self.getMaxPlayableWidth();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
var options = [];
|
|
|
|
|
|
|
|
|
|
// We have media info
|
|
|
|
|
if (videoStream && videoStream.Width) {
|
|
|
|
|
|
|
|
|
|
maxAllowedWidth = videoStream.Width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Some 1080- videos are reported as 1912?
|
2014-07-03 19:22:57 -07:00
|
|
|
|
if (maxAllowedWidth >= 1900) {
|
2014-04-02 14:55:19 -07:00
|
|
|
|
options.push({ name: '1080p - 30Mbps', maxWidth: 1920, bitrate: 30000000 });
|
|
|
|
|
options.push({ name: '1080p - 25Mbps', maxWidth: 1920, bitrate: 25000000 });
|
2014-03-08 01:09:45 -07:00
|
|
|
|
options.push({ name: '1080p - 20Mbps', maxWidth: 1920, bitrate: 20000000 });
|
|
|
|
|
options.push({ name: '1080p - 15Mbps', maxWidth: 1920, bitrate: 15000000 });
|
|
|
|
|
options.push({ name: '1080p - 10Mbps', maxWidth: 1920, bitrate: 10000000 });
|
|
|
|
|
options.push({ name: '1080p - 8Mbps', maxWidth: 1920, bitrate: 8000000 });
|
|
|
|
|
options.push({ name: '1080p - 6Mbps', maxWidth: 1920, bitrate: 6000000 });
|
|
|
|
|
options.push({ name: '1080p - 5Mbps', maxWidth: 1920, bitrate: 5000000 });
|
|
|
|
|
}
|
2014-07-03 19:22:57 -07:00
|
|
|
|
else if (maxAllowedWidth >= 1260) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
options.push({ name: '720p - 10Mbps', maxWidth: 1280, bitrate: 10000000 });
|
|
|
|
|
options.push({ name: '720p - 8Mbps', maxWidth: 1280, bitrate: 8000000 });
|
|
|
|
|
options.push({ name: '720p - 6Mbps', maxWidth: 1280, bitrate: 6000000 });
|
|
|
|
|
options.push({ name: '720p - 5Mbps', maxWidth: 1280, bitrate: 5000000 });
|
|
|
|
|
}
|
2014-07-03 19:22:57 -07:00
|
|
|
|
else if (maxAllowedWidth >= 460) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
options.push({ name: '480p - 4Mbps', maxWidth: 720, bitrate: 4000000 });
|
|
|
|
|
options.push({ name: '480p - 3Mbps', maxWidth: 720, bitrate: 3000000 });
|
|
|
|
|
options.push({ name: '480p - 2.5Mbps', maxWidth: 720, bitrate: 2500000 });
|
|
|
|
|
options.push({ name: '480p - 2Mbps', maxWidth: 720, bitrate: 2000000 });
|
|
|
|
|
options.push({ name: '480p - 1.5Mbps', maxWidth: 720, bitrate: 1500000 });
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-03 19:22:57 -07:00
|
|
|
|
if (maxAllowedWidth >= 1260) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
options.push({ name: '720p - 4Mbps', maxWidth: 1280, bitrate: 4000000 });
|
|
|
|
|
options.push({ name: '720p - 3Mbps', maxWidth: 1280, bitrate: 3000000 });
|
|
|
|
|
options.push({ name: '720p - 2Mbps', maxWidth: 1280, bitrate: 2000000 });
|
2014-06-11 12:31:33 -07:00
|
|
|
|
|
2014-06-02 12:32:41 -07:00
|
|
|
|
// The extra 1 is because they're keyed off the bitrate value
|
|
|
|
|
options.push({ name: '720p - 1Mbps', maxWidth: 1280, bitrate: 1000001 });
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
options.push({ name: '480p - 1.0Mbps', maxWidth: 720, bitrate: 1000000 });
|
2014-09-16 18:38:50 -07:00
|
|
|
|
options.push({ name: '480p - 720kbps', maxWidth: 720, bitrate: 720000 });
|
|
|
|
|
options.push({ name: '480p - 420kbps', maxWidth: 720, bitrate: 420000 });
|
2014-03-08 01:09:45 -07:00
|
|
|
|
options.push({ name: '360p', maxWidth: 640, bitrate: 400000 });
|
|
|
|
|
options.push({ name: '240p', maxWidth: 426, bitrate: 320000 });
|
|
|
|
|
|
|
|
|
|
var i, length, option;
|
|
|
|
|
var selectedIndex = -1;
|
|
|
|
|
for (i = 0, length = options.length; i < length; i++) {
|
|
|
|
|
|
|
|
|
|
option = options[i];
|
|
|
|
|
|
|
|
|
|
if (selectedIndex == -1 && option.bitrate <= bitrateSetting) {
|
|
|
|
|
selectedIndex = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (selectedIndex == -1) {
|
|
|
|
|
|
|
|
|
|
selectedIndex = options.length - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
options[selectedIndex].selected = true;
|
|
|
|
|
|
|
|
|
|
return options;
|
2014-04-06 19:06:09 -07:00
|
|
|
|
}
|
2014-04-11 08:36:25 -07:00
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
function bindEventsForPlayback() {
|
|
|
|
|
|
2014-07-03 19:22:57 -07:00
|
|
|
|
var hideElementsOnIdle = !$.browser.mobile;
|
2014-07-16 20:17:14 -07:00
|
|
|
|
|
2014-07-03 19:22:57 -07:00
|
|
|
|
if (hideElementsOnIdle) {
|
2014-06-21 22:52:31 -07:00
|
|
|
|
$('.itemVideo').off('mousemove.videoplayer keydown.videoplayer scroll.videoplayer', idleHandler);
|
2014-07-03 19:22:57 -07:00
|
|
|
|
$('.itemVideo').on('mousemove.videoplayer keydown.videoplayer scroll.videoplayer', idleHandler).trigger('mousemove');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$(document).on('webkitfullscreenchange.videoplayer mozfullscreenchange.videoplayer fullscreenchange.videoplayer', function (e) {
|
2014-06-21 22:52:31 -07:00
|
|
|
|
|
|
|
|
|
if (self.isFullScreen()) {
|
|
|
|
|
enterFullScreen();
|
|
|
|
|
idleState = true;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
exitFullScreenToWindow();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fullscreenExited = self.isFullScreen() == false;
|
|
|
|
|
|
|
|
|
|
}).on("msfullscreenchange.videoplayer", function (e) {
|
|
|
|
|
|
|
|
|
|
fullscreenExited = self.isFullScreen() == false;
|
|
|
|
|
|
|
|
|
|
}).on("keyup.videoplayer", function (e) {
|
|
|
|
|
|
|
|
|
|
if (fullscreenExited) {
|
|
|
|
|
$("#videoPlayer", $("#mediaPlayer")).removeClass("fullscreenVideo");
|
|
|
|
|
fullscreenExited = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (e.keyCode == 27) {
|
|
|
|
|
self.stop();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Stop playback on browser back button nav
|
|
|
|
|
$(window).one("popstate.videoplayer", function () {
|
|
|
|
|
self.stop();
|
|
|
|
|
return;
|
|
|
|
|
});
|
|
|
|
|
|
2014-07-03 19:22:57 -07:00
|
|
|
|
if (hideElementsOnIdle) {
|
|
|
|
|
$(document.body).on("mousemove.videplayer", "#itemVideo", function () {
|
2014-06-21 22:52:31 -07:00
|
|
|
|
|
2014-07-03 19:22:57 -07:00
|
|
|
|
idleHandler(this);
|
|
|
|
|
});
|
|
|
|
|
}
|
2014-06-21 22:52:31 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function unbindEventsForPlayback() {
|
|
|
|
|
|
|
|
|
|
$(document).off('webkitfullscreenchange.videoplayer mozfullscreenchange.videoplayer fullscreenchange.videoplayer').off("msfullscreenchange.videoplayer").off("keyup.videoplayer");
|
|
|
|
|
|
|
|
|
|
// Stop playback on browser back button nav
|
|
|
|
|
$(window).off("popstate.videoplayer");
|
|
|
|
|
|
2014-07-03 19:22:57 -07:00
|
|
|
|
$(document.body).off("mousemove.videplayer");
|
2014-06-21 22:52:31 -07:00
|
|
|
|
|
|
|
|
|
$('.itemVideo').off('mousemove.videoplayer keydown.videoplayer scroll.videoplayer');
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-01 19:34:45 -07:00
|
|
|
|
self.canAutoPlayVideo = function () {
|
|
|
|
|
|
|
|
|
|
if ($.browser.msie || $.browser.mobile) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
2014-08-10 15:13:17 -07:00
|
|
|
|
// Replace audio version
|
|
|
|
|
self.cleanup = function (playerElement) {
|
|
|
|
|
|
|
|
|
|
if (playerElement.tagName.toLowerCase() == 'video') {
|
|
|
|
|
currentTimeElement.html('--:--');
|
|
|
|
|
|
|
|
|
|
unbindEventsForPlayback();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
self.playVideo = function (item, mediaSource, startPosition) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-22 09:16:43 -07:00
|
|
|
|
var mediaStreams = mediaSource.MediaStreams || [];
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-11 12:31:33 -07:00
|
|
|
|
var subtitleStreams = mediaStreams.filter(function (s) {
|
|
|
|
|
return s.Type == 'Subtitle';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var selectedSubtitleStream = subtitleStreams.filter(function (s) {
|
|
|
|
|
return s.Index == mediaSource.DefaultSubtitleStreamIndex;
|
|
|
|
|
|
|
|
|
|
})[0];
|
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
var baseParams = {
|
|
|
|
|
audioChannels: 2,
|
2014-04-02 14:55:19 -07:00
|
|
|
|
StartTimeTicks: startPosition,
|
2014-05-12 11:04:25 -07:00
|
|
|
|
AudioStreamIndex: mediaSource.DefaultAudioStreamIndex,
|
2014-03-08 01:09:45 -07:00
|
|
|
|
deviceId: ApiClient.deviceId(),
|
2014-03-21 20:35:03 -07:00
|
|
|
|
Static: false,
|
2014-03-22 09:16:43 -07:00
|
|
|
|
mediaSourceId: mediaSource.Id
|
2014-03-08 01:09:45 -07:00
|
|
|
|
};
|
|
|
|
|
|
2014-06-11 19:38:40 -07:00
|
|
|
|
if (selectedSubtitleStream && (!selectedSubtitleStream.IsTextSubtitleStream || !self.supportsTextTracks())) {
|
2014-06-11 12:31:33 -07:00
|
|
|
|
baseParams.SubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
var mp4Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
return opt.selected;
|
|
|
|
|
})[0];
|
2014-03-22 09:16:43 -07:00
|
|
|
|
mp4Quality = $.extend(mp4Quality, self.getFinalVideoParams(mediaSource, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4'));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
var webmQuality = getVideoQualityOptions(mediaStreams).filter(function (opt) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
return opt.selected;
|
|
|
|
|
})[0];
|
2014-03-22 09:16:43 -07:00
|
|
|
|
webmQuality = $.extend(webmQuality, self.getFinalVideoParams(mediaSource, webmQuality.maxWidth, webmQuality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.webm'));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 20:31:40 -07:00
|
|
|
|
var m3U8Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
return opt.selected;
|
|
|
|
|
})[0];
|
2014-03-22 09:16:43 -07:00
|
|
|
|
m3U8Quality = $.extend(m3U8Quality, self.getFinalVideoParams(mediaSource, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4'));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
var isStatic = mp4Quality.isStatic;
|
|
|
|
|
|
|
|
|
|
self.startTimeTicksOffset = isStatic ? 0 : startPosition || 0;
|
|
|
|
|
|
2014-07-16 20:17:14 -07:00
|
|
|
|
var startPositionInSeekParam = startPosition ? (startPosition / 10000000) : 0;
|
|
|
|
|
var seekParam = startPositionInSeekParam ? '#t=' + startPositionInSeekParam : '';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-21 20:35:03 -07:00
|
|
|
|
var mp4VideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.mp4', $.extend({}, baseParams, {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
Static: isStatic,
|
|
|
|
|
maxWidth: mp4Quality.maxWidth,
|
|
|
|
|
videoBitrate: mp4Quality.videoBitrate,
|
|
|
|
|
audioBitrate: mp4Quality.audioBitrate,
|
|
|
|
|
VideoCodec: mp4Quality.videoCodec,
|
2014-04-11 08:36:25 -07:00
|
|
|
|
AudioCodec: mp4Quality.audioCodec,
|
2014-05-12 15:30:32 -07:00
|
|
|
|
profile: 'baseline',
|
|
|
|
|
level: '3',
|
2014-04-11 20:48:57 -07:00
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
// None of the browsers seem to like this
|
2015-01-03 22:55:34 -07:00
|
|
|
|
//EnableAutoStreamCopy: false
|
2014-06-28 12:35:30 -07:00
|
|
|
|
}));
|
|
|
|
|
|
2014-10-07 18:37:45 -07:00
|
|
|
|
if (isStatic && mediaSource.Protocol == 'Http' && !mediaSource.RequiredHttpHeaders.length) {
|
|
|
|
|
mp4VideoUrl = mediaSource.Path;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-03 18:42:38 -07:00
|
|
|
|
if (isStatic) {
|
|
|
|
|
mp4VideoUrl += seekParam;
|
|
|
|
|
} else {
|
|
|
|
|
mp4VideoUrl += "&ClientTime=" + new Date().getTime();
|
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-21 20:35:03 -07:00
|
|
|
|
var webmVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.webm', $.extend({}, baseParams, {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
VideoCodec: 'vpx',
|
|
|
|
|
AudioCodec: 'Vorbis',
|
|
|
|
|
maxWidth: webmQuality.maxWidth,
|
|
|
|
|
videoBitrate: webmQuality.videoBitrate,
|
2014-04-11 08:36:25 -07:00
|
|
|
|
audioBitrate: webmQuality.audioBitrate,
|
2014-09-17 21:50:21 -07:00
|
|
|
|
EnableAutoStreamCopy: false,
|
|
|
|
|
ClientTime: new Date().getTime()
|
2014-06-28 12:35:30 -07:00
|
|
|
|
}));
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-01 14:13:32 -07:00
|
|
|
|
var hlsVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/master.m3u8', $.extend({}, baseParams, {
|
|
|
|
|
maxWidth: m3U8Quality.maxWidth,
|
|
|
|
|
videoBitrate: m3U8Quality.videoBitrate,
|
|
|
|
|
audioBitrate: m3U8Quality.audioBitrate,
|
|
|
|
|
VideoCodec: m3U8Quality.videoCodec,
|
|
|
|
|
AudioCodec: m3U8Quality.audioCodec,
|
|
|
|
|
profile: 'baseline',
|
|
|
|
|
level: '3',
|
2014-09-17 21:50:21 -07:00
|
|
|
|
StartTimeTicks: 0,
|
|
|
|
|
ClientTime: new Date().getTime()
|
2014-06-28 12:35:30 -07:00
|
|
|
|
|
2014-07-01 14:13:32 -07:00
|
|
|
|
})) + seekParam;
|
2014-06-28 12:35:30 -07:00
|
|
|
|
|
|
|
|
|
//======================================================================================>
|
2014-03-20 01:34:54 -07:00
|
|
|
|
|
|
|
|
|
// Create video player
|
2014-03-08 01:09:45 -07:00
|
|
|
|
var html = '';
|
|
|
|
|
|
2014-08-01 19:34:45 -07:00
|
|
|
|
var requiresNativeControls = !self.canAutoPlayVideo();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
// Can't autoplay in these browsers so we need to use the full controls
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (requiresNativeControls) {
|
|
|
|
|
html += '<video class="itemVideo" id="itemVideo" preload="none" autoplay="autoplay" controls="controls">';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
} else {
|
2014-05-29 12:34:20 -07:00
|
|
|
|
|
2014-04-14 20:54:52 -07:00
|
|
|
|
// Chrome 35 won't play with preload none
|
|
|
|
|
html += '<video class="itemVideo" id="itemVideo" preload="metadata" autoplay>';
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isStatic) {
|
|
|
|
|
// HLS must be at the top for safari
|
|
|
|
|
html += '<source type="application/x-mpegURL" src="' + hlsVideoUrl + '" />';
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-14 19:31:03 -07:00
|
|
|
|
var mp4BeforeWebm = self.getVideoTranscodingExtension() != '.webm';
|
2014-10-03 18:42:38 -07:00
|
|
|
|
|
|
|
|
|
if (mp4BeforeWebm) {
|
|
|
|
|
html += '<source type="video/mp4" src="' + mp4VideoUrl + '" />';
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-06 10:53:23 -07:00
|
|
|
|
// Have to put webm ahead of mp4 because it will play in fast forward in chrome
|
|
|
|
|
// And firefox doesn't like fragmented mp4
|
|
|
|
|
if (!isStatic) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
html += '<source type="video/webm" src="' + webmVideoUrl + '" />';
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-03 18:42:38 -07:00
|
|
|
|
if (!mp4BeforeWebm) {
|
|
|
|
|
html += '<source type="video/mp4" src="' + mp4VideoUrl + '" />';
|
|
|
|
|
}
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-11 19:38:40 -07:00
|
|
|
|
if (self.supportsTextTracks()) {
|
|
|
|
|
var textStreams = subtitleStreams.filter(function (s) {
|
|
|
|
|
return s.IsTextSubtitleStream;
|
|
|
|
|
});
|
2014-06-11 12:31:33 -07:00
|
|
|
|
|
2014-06-11 19:38:40 -07:00
|
|
|
|
for (var i = 0, length = textStreams.length; i < length; i++) {
|
2014-06-11 12:31:33 -07:00
|
|
|
|
|
2014-06-11 19:38:40 -07:00
|
|
|
|
var textStream = textStreams[i];
|
|
|
|
|
var textStreamUrl = ApiClient.getUrl('Videos/' + item.Id + '/' + mediaSource.Id + '/Subtitles/' + textStream.Index + '/Stream.vtt', {
|
2014-06-14 19:58:00 -07:00
|
|
|
|
startPositionTicks: (startPosition || 0)
|
2014-06-11 19:38:40 -07:00
|
|
|
|
});
|
2014-06-11 12:31:33 -07:00
|
|
|
|
|
2014-06-14 19:24:04 -07:00
|
|
|
|
var defaultAttribute = textStream.Index == mediaSource.DefaultSubtitleStreamIndex ? ' default' : '';
|
2014-06-11 12:31:33 -07:00
|
|
|
|
|
2014-06-14 19:24:04 -07:00
|
|
|
|
html += '<track kind="subtitles" src="' + textStreamUrl + '" srclang="' + (textStream.Language || 'und') + '"' + defaultAttribute + '></track>';
|
2014-06-11 19:38:40 -07:00
|
|
|
|
}
|
2014-06-11 12:31:33 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-20 01:34:54 -07:00
|
|
|
|
html += '</video>';
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
var mediaPlayerContainer = $("#mediaPlayer").show();
|
2014-06-28 12:35:30 -07:00
|
|
|
|
var videoControls = $('.videoControls', mediaPlayerContainer);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
//show stop button
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$('#video-playButton', videoControls).hide();
|
|
|
|
|
$('#video-pauseButton', videoControls).show();
|
|
|
|
|
$('#video-previousTrackButton', videoControls).hide();
|
|
|
|
|
$('#video-nextTrackButton', videoControls).hide();
|
2014-06-21 22:52:31 -07:00
|
|
|
|
|
|
|
|
|
var videoElement = $('#videoElement', mediaPlayerContainer).prepend(html);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoQualityButton', videoControls).show();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-11 12:31:33 -07:00
|
|
|
|
if (mediaStreams.filter(function (s) {
|
|
|
|
|
return s.Type == "Audio";
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}).length) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoAudioButton').show();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
} else {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoAudioButton').hide();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-11 12:31:33 -07:00
|
|
|
|
if (subtitleStreams.length) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoSubtitleButton').show();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
} else {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoSubtitleButton').hide();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-21 20:35:03 -07:00
|
|
|
|
if (item.Chapters && item.Chapters.length) {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoChaptersButton').show();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
} else {
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('.videoChaptersButton').hide();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if (requiresNativeControls) {
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$('#video-fullscreenButton', videoControls).hide();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
} else {
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$('#video-fullscreenButton', videoControls).show();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
if ($.browser.mobile) {
|
|
|
|
|
$('.volumeSliderContainer', videoControls).addClass('hide');
|
|
|
|
|
$('.muteButton', videoControls).addClass('hide');
|
|
|
|
|
$('.unmuteButton', videoControls).addClass('hide');
|
|
|
|
|
} else {
|
|
|
|
|
$('.volumeSliderContainer', videoControls).removeClass('hide');
|
|
|
|
|
$('.muteButton', videoControls).removeClass('hide');
|
|
|
|
|
$('.unmuteButton', videoControls).removeClass('hide');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (requiresNativeControls) {
|
|
|
|
|
videoControls.addClass('hide');
|
|
|
|
|
} else {
|
|
|
|
|
videoControls.removeClass('hide');
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-08 16:12:09 -07:00
|
|
|
|
var video = $("video", videoElement);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
initialVolume = self.getSavedVolume();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-04-08 16:12:09 -07:00
|
|
|
|
video.each(function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
this.volume = initialVolume;
|
|
|
|
|
});
|
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
volumeSlider.val(initialVolume).slider('refresh');
|
|
|
|
|
updateVolumeButtons(initialVolume);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-16 20:17:14 -07:00
|
|
|
|
video.one("loadedmetadata.mediaplayerevent", function (e) {
|
|
|
|
|
|
2014-10-07 18:37:45 -07:00
|
|
|
|
// TODO: This is not working in chrome. Is it too early?
|
|
|
|
|
|
2014-07-16 20:17:14 -07:00
|
|
|
|
// Appending #t=xxx to the query string doesn't seem to work with HLS
|
|
|
|
|
if (startPositionInSeekParam && this.currentSrc && this.currentSrc.toLowerCase().indexOf('.m3u8') != -1) {
|
|
|
|
|
this.currentTime = startPositionInSeekParam;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}).on("volumechange.mediaplayerevent", function (e) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
var vol = this.volume;
|
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
updateVolumeButtons(vol);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
}).one("playing.mediaplayerevent", function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-08-10 15:13:17 -07:00
|
|
|
|
|
|
|
|
|
// For some reason this is firing at the start, so don't bind until playback has begun
|
|
|
|
|
$(this).on("ended.playbackstopped", self.onPlaybackStopped).one('ended.playnext', self.playNextAfterEnded);
|
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
self.onPlaybackStart(this, item, mediaSource);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
}).on("pause.mediaplayerevent", function (e) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$('#video-playButton', videoControls).show();
|
|
|
|
|
$('#video-pauseButton', videoControls).hide();
|
|
|
|
|
$("#pause", videoElement).show().addClass("fadeOut");
|
2014-03-08 01:09:45 -07:00
|
|
|
|
setTimeout(function () {
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$("#pause", videoElement).hide().removeClass("fadeOut");
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}, 300);
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
}).on("playing.mediaplayerevent", function (e) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$('#video-playButton', videoControls).hide();
|
|
|
|
|
$('#video-pauseButton', videoControls).show();
|
|
|
|
|
$("#play", videoElement).show().addClass("fadeOut");
|
2014-03-08 01:09:45 -07:00
|
|
|
|
setTimeout(function () {
|
2014-03-20 01:34:54 -07:00
|
|
|
|
$("#play", videoElement).hide().removeClass("fadeOut");
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}, 300);
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
}).on("timeupdate.mediaplayerevent", function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
if (!isPositionSliderActive) {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-04-11 08:36:25 -07:00
|
|
|
|
self.setCurrentTime(self.getCurrentTicks(this), positionSlider, currentTimeElement);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
}).on("error.mediaplayerevent", function () {
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-01 14:13:32 -07:00
|
|
|
|
self.stop();
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
|
|
|
|
var errorCode = this.error ? this.error.code : '';
|
2014-03-20 01:34:54 -07:00
|
|
|
|
console.log('Html5 Video error code: ' + errorCode);
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-07-02 11:34:08 -07:00
|
|
|
|
var errorMsg = Globalize.translate('MessageErrorPlayingVideo');
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-03-17 18:45:28 -07:00
|
|
|
|
if (item.Type == "TvChannel") {
|
2014-07-21 18:29:06 -07:00
|
|
|
|
errorMsg += '<p>';
|
|
|
|
|
errorMsg += Globalize.translate('MessageEnsureOpenTuner');
|
|
|
|
|
errorMsg += '</p>';
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-14 06:24:30 -07:00
|
|
|
|
if ($.browser.msie && !$.browser.mobile && !self.canPlayWebm()) {
|
2014-07-21 18:29:06 -07:00
|
|
|
|
errorMsg += '<p>';
|
|
|
|
|
errorMsg += '<a href="https://tools.google.com/dlpage/webmmf/" target="_blank">';
|
|
|
|
|
errorMsg += Globalize.translate('MessageInternetExplorerWebm');
|
|
|
|
|
errorMsg += '</a>';
|
|
|
|
|
errorMsg += '</p>';
|
2014-07-01 14:13:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
Dashboard.alert({
|
2014-07-21 18:29:06 -07:00
|
|
|
|
title: Globalize.translate('HeaderVideoError'),
|
2014-03-08 01:09:45 -07:00
|
|
|
|
message: errorMsg
|
|
|
|
|
});
|
|
|
|
|
|
2014-07-01 14:13:32 -07:00
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
}).on("click.mediaplayerevent", function (e) {
|
2014-03-20 01:34:54 -07:00
|
|
|
|
|
|
|
|
|
if (this.paused) {
|
|
|
|
|
self.unpause();
|
|
|
|
|
} else {
|
|
|
|
|
self.pause();
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
}).on("dblclick.mediaplayerevent", function () {
|
2014-03-20 01:34:54 -07:00
|
|
|
|
|
|
|
|
|
self.toggleFullscreen();
|
|
|
|
|
|
2014-08-10 15:13:17 -07:00
|
|
|
|
});
|
2014-03-20 01:34:54 -07:00
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
bindEventsForPlayback();
|
2014-03-20 01:34:54 -07:00
|
|
|
|
|
2014-06-21 22:52:31 -07:00
|
|
|
|
mediaPlayerContainer.trigger("create");
|
2014-03-20 01:34:54 -07:00
|
|
|
|
|
|
|
|
|
fullscreenExited = false;
|
|
|
|
|
|
2014-06-11 12:31:33 -07:00
|
|
|
|
self.currentSubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
|
2014-03-08 01:09:45 -07:00
|
|
|
|
|
2014-06-28 12:35:30 -07:00
|
|
|
|
$('body').addClass('bodyWithPopupOpen');
|
|
|
|
|
|
2014-04-08 16:12:09 -07:00
|
|
|
|
return video[0];
|
2014-06-21 22:52:31 -07:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createVideoPlayer(MediaPlayer);
|
|
|
|
|
|
2014-03-08 01:09:45 -07:00
|
|
|
|
})();
|