/);
+ return match ? match[1] : null;
+ }
+
function getPosition(e) {
// fixme: no offsetX in firefox???
if ($.browser.mozilla) {
- //Ox.Log('Video', e, e.layerX - 56)
return Ox.limit(
(e.layerX - 48 - self.barHeight / 2) / self.timelineImageWidth * self.$video.duration(),
0, self.$video.duration()
);
} else {
- /*Ox.Log('Video', e.offsetX, Ox.limit(
- (e.offsetX - self.barHeight / 2) / self.timelineImageWidth * self.video.duration,
- 0, self.video.duration
- ))*/
return Ox.limit(
(e.offsetX - self.barHeight / 2) / self.timelineImageWidth * self.$video.duration(),
0, self.$video.duration()
@@ -1560,7 +1587,6 @@ Ox.VideoPlayer = function(options, self) {
}
function getProgressImageURL() {
- //Ox.Log('Video', '---', self.timelineImageWidth)
if (!self.timelineImageWidth) return;
var width = self.timelineImageWidth,
height = self.barHeight,
@@ -1595,6 +1621,7 @@ Ox.VideoPlayer = function(options, self) {
if (
v['in'] <= self.options.position
&& v.out >= self.options.position
+ && v.track == self.options.subtitlesTrack
) {
subtitle = v.text;
return false; // break
@@ -1603,6 +1630,14 @@ Ox.VideoPlayer = function(options, self) {
return subtitle;
}
+ function getSubtitles() {
+ return self.options.enableSubtitles
+ ? self.options.subtitles.map(function(v) {
+ return v.track == self.options.subtitlesTrack;
+ })
+ : [];
+ }
+
function getTimeline() {
var $timeline = Ox.SmallVideoTimeline({
//_offset: getTimelineLeft(),
@@ -1634,7 +1669,6 @@ Ox.VideoPlayer = function(options, self) {
});
}
});
- //Ox.Log('Video', '??', $timeline.find('.OxInterface'))
$timeline.children().css({
marginLeft: getTimelineLeft() + 'px'
});
@@ -1668,8 +1702,8 @@ Ox.VideoPlayer = function(options, self) {
}
function getTitleWidth() {
- return (self.options.fullscreen ? window.innerWidth : self.options.width) -
- self.options.controlsTop.reduce(function(prev, curr) {
+ return (self.options.fullscreen ? window.innerWidth : self.options.width)
+ - self.options.controlsTop.reduce(function(prev, curr) {
return prev + (
curr == 'title' || curr == 'chapterTitle' || curr == 'space' ? 0
: Ox.startsWith(curr, 'space') ? parseInt(curr.substr(5))
@@ -1678,6 +1712,13 @@ Ox.VideoPlayer = function(options, self) {
}, 0);
}
+ function getVideo() {
+ return self.options.video.filter(function(video) {
+ return video.audioTrack == self.options.audioTrack
+ && video.resolution == self.options.resolution;
+ });
+ }
+
function getVideoCSS(videoWidth, videoHeight) {
// optional arguments allow for this function to be used for poster CSS
var playerWidth = self.width,
@@ -1758,7 +1799,11 @@ Ox.VideoPlayer = function(options, self) {
//Ox.Log('Video', 'hideControls');
clearTimeout(self.interfaceTimeout);
self.interfaceTimeout = setTimeout(function() {
- if (!self.exitFullscreen && !self.inputHasFocus && !self.mouseIsInControls) {
+ if (
+ !self.exitFullscreen
+ && !self.inputHasFocus
+ && !self.mouseIsInControls
+ ) {
self.interfaceIsVisible = false;
self.controlsTopAreVisible = false;
self.controlsBottomAreVisible = false;
@@ -1812,10 +1857,6 @@ Ox.VideoPlayer = function(options, self) {
return Math.abs(a - b) < 0.001;
}
- function isResolution(str) {
- return str.slice(0, -1).match(/^\d+$/) && str.slice(-1) == 'p';
- }
-
function itemchange(data) {
var item = self.$video.options('items')[data.item];
Ox.Log('Video', 'ITEMCHANGE', item);
@@ -1856,9 +1897,12 @@ Ox.VideoPlayer = function(options, self) {
self.posterMarkerCSS = getPosterMarkerCSS();
self.$video.css(self.videoCSS);
self.$poster && self.$poster.css(self.videoCSS);
- self.$posterMarker && Ox.forEach(self.$posterMarker, function(marker, position) {
- marker.css(self.posterMarkerCSS[position]);
- });
+ self.$posterMarker && Ox.forEach(
+ self.$posterMarker,
+ function(marker, position) {
+ marker.css(self.posterMarkerCSS[position]);
+ }
+ );
self.out = self.options.playInToOut && self.out < self.$video.duration()
? self.out : self.$video.duration();
@@ -1899,6 +1943,15 @@ Ox.VideoPlayer = function(options, self) {
}
function loadedsubtitles() {
+ if (!self.subtitlesTracks || Ox.isEmpty(self.subtitlesTracks)) {
+ self.subtitlesTracks = [{
+ code: self.options.subtitlesDefaultTrack,
+ name: Ox.getLanguageNameByCode(
+ self.options.subtitlesDefaultTrack
+ )
+ }];
+ }
+ self.subtitlesTracks.push({code: '', name: 'None'});
if (self.options.find) {
submitFindInput(self.options.find);
if (self.options.duration) {
@@ -1917,6 +1970,21 @@ Ox.VideoPlayer = function(options, self) {
function loadSubtitles() {
if (self.options.subtitles) {
if (Ox.isArray(self.options.subtitles)) {
+ self.subtitlesTracks = Ox.sortBy(
+ Ox.unique(
+ self.options.subtitles.map(function(subtitle) {
+ return subtitle.track;
+ }).filter(function(track) {
+ return !!track;
+ })
+ ).map(function(track) {
+ return {
+ code: track,
+ name: Ox.getLanguageNameByCode(track)
+ };
+ }),
+ 'name'
+ );
loadedsubtitles();
} else {
if (self.options.subtitles.indexOf('\n') > -1) {
@@ -1982,24 +2050,32 @@ Ox.VideoPlayer = function(options, self) {
}
function renderSettings() {
+ // fixme: use proper ids (as class of span)
var $settings = $('')
.addClass('OxControls OxSettings')
.on({
click: function(e) {
- var $target = $(e.target), resolution, title, type;
+ var $target = $(e.target), resolution, title, track, type;
self.$settings.hide();
if (!$target.is('.OxLine') && !$target.is('.OxSpace')) {
title = $(e.target).parent().children()[0].innerHTML;
if (title == Ox._('Download')) {
that.triggerEvent('download');
- } else if (title == Ox._('Subtitles')) {
- toggleSubtitles();
- } else if (isResolution(title)) {
- resolution = parseInt(title, 10);
+ } else if (getMenuSection(title) == 'resolution') {
+ resolution = parseInt(Ox.stripTags(title), 10);
if (resolution != self.options.resolution) {
self.options.resolution = resolution;
setResolution();
}
+ } else if (getMenuSection(title) == 'audioTrack') {
+ track = Ox.stripTags(title);
+ self.options.audioTrack = Ox.getLanguageCodeByName(track);
+ setAudioTrack();
+ } else if (getMenuSection(title) == 'subtitlesTrack') {
+ track = Ox.stripTags(title);
+ self.options.subtitlesTrack = track == 'None'
+ ? '' : Ox.getLanguageCodeByName(track);
+ setSubtitleTrack();
} else {
type = self.options.timelineTypes[
Ox.indexOf(self.options.timelineTypes, function(type) {
@@ -2037,33 +2113,49 @@ Ox.VideoPlayer = function(options, self) {
}
}),
items = [{
- disabled: true,
- title: Ox._('Resolution')
- }].concat(
+ disabled: true,
+ title: Ox._('Resolution')
+ }].concat(
self.resolutions.map(function(resolution) {
return {
checked: resolution == self.options.resolution,
- title: resolution + 'p'
+ title: ''
+ + resolution + 'p'
};
}),
+ self.audioTracks.length > 1
+ ? [{}, {disabled: true, title: Ox._('Audio')}].concat(
+ self.audioTracks.map(function(track) {
+ return {
+ checked: track.code == self.options.audioTrack,
+ title: ''
+ + Ox._(track.name) + ''
+ };
+ })
+ )
+ : [],
self.options.subtitles.length
- ? [{}, {
- checked: self.options.enableSubtitles,
- title: Ox._('Subtitles')
- }]
+ ? [{}, {disabled: true, title: Ox._('Subtitles')}].concat(
+ self.subtitlesTracks.map(function(track) {
+ return {
+ checked: track.code == self.options.enableSubtitles
+ ? self.options.subtitlesTrack : '',
+ title: ''
+ + Ox._(track.name) + ''
+ };
+ })
+ )
: [],
self.options.timelineTypes.length
- ? [{}, {
- disabled: true,
- title: Ox._('Timeline')
- }] : [],
- self.options.timelineTypes.length
- ? self.options.timelineTypes.map(function(type) {
- return {
- checked: type.id == self.options.timelineType,
- title: type.title
- };
- })
+ ? [{}, {disabled: true, title: Ox._('Timeline')}].concat(
+ self.options.timelineTypes.map(function(type) {
+ return {
+ checked: type.id == self.options.timelineType,
+ title: ''
+ + type.title + ''
+ };
+ })
+ )
: [],
self.options.enableDownload
? [{}, {title: Ox._('Download')}]
@@ -2130,6 +2222,10 @@ Ox.VideoPlayer = function(options, self) {
}
}
+ function setAudioTrack() {
+ // ...
+ }
+
function setCensored() {
var censored = getCensored();
if (censored != self.censored) {
@@ -2152,15 +2248,17 @@ Ox.VideoPlayer = function(options, self) {
isEqual(self.options.position, self.options.posterFrame)
? marker.show() : marker.hide();
});
- self.$pointMarker && Ox.forEach(self.$pointMarker, function(markers, point) {
- Ox.forEach(markers, function(marker) {
- //Ox.Log('Video', self.options.position, self.options[point], isEqual(self.options.position, self.options[point]))
- // fixme: there's a bug in jquery and/or webkit
- // on load, show() doesn't work
- isEqual(self.options.position, self.options[point])
- ? marker.css({display: 'block'}) : marker.hide();
- });
- });
+ self.$pointMarker && Ox.forEach(
+ self.$pointMarker,
+ function(markers, point) {
+ Ox.forEach(markers, function(marker) {
+ // fixme: there's a bug in jquery and/or webkit
+ // on load, show() doesn't work
+ isEqual(self.options.position, self.options[point])
+ ? marker.css({display: 'block'}) : marker.hide();
+ });
+ }
+ );
}
function setPoint() {
@@ -2206,7 +2304,7 @@ Ox.VideoPlayer = function(options, self) {
}
self.loadedMetadata = false;
showLoadingIcon();
- self.video = self.options.video[self.options.resolution];
+ self.video = getVideo();
self.$video.options({
items: self.video
});
@@ -2230,8 +2328,10 @@ Ox.VideoPlayer = function(options, self) {
}
function setSizes(animate, callback) {
- self.width = self.options.fullscreen ? window.innerWidth : self.options.width;
- self.height = self.options.fullscreen ? window.innerHeight : self.options.height;
+ self.width = self.options.fullscreen
+ ? window.innerWidth : self.options.width;
+ self.height = self.options.fullscreen
+ ? window.innerHeight : self.options.height;
self.videoCSS = getVideoCSS();
self.iconSize = Ox.limit(Math.round(self.height / 10), 16, 32);
if (self.$timeline || self.$spaceBottom) {
@@ -2293,24 +2393,59 @@ Ox.VideoPlayer = function(options, self) {
function setSubtitleText() {
self.$subtitle.html(
self.subtitle
- ? Ox.highlight(self.subtitle, self.options.find, 'OxHighlight', true)
- .replace(/\n/g, '
')
+ ? Ox.highlight(
+ self.subtitle, self.options.find, 'OxHighlight', true
+ ).replace(/\n/g, '
')
: '
'
// FIXME: weird bug, only in fullscreen, only in chrome
);
}
+ function setSubtitlesTrack() {
+ var enableSubtitles = !!self.options.subtitlesTrack;
+ setSubtitle();
+ self.$timeline && self.$timeline.options({
+ subtitles: getSubtitles()
+ });
+ if (enableSubtitles != self.options.enableSubtitles) {
+ self.options.enableSubtitles = enableSubtitles;
+ that.triggerEvent('subtitles', {
+ subtitles: self.options.enableSubtitles
+ });
+ }
+ }
+
function setTimelineType() {
that.triggerEvent('timeline', {timeline: self.options.timelineType});
}
function setVideo() {
- if (Ox.isObject(self.options.video)) {
- self.resolutions = Ox.sort(Object.keys(self.options.video));
- if (!(self.options.resolution in self.options.video)) {
+ if (Ox.isObject(self.options.video[0])) {
+ self.audioTracks = Ox.sortBy(Ox.unique(
+ self.options.video.map(function(video) {
+ return {
+ code: video.track,
+ name: Ox.getLanguageNameByCode(video.track)
+ };
+ })
+ ), 'name');
+ if (!Ox.contains(
+ self.audioTracks.map(function(track) {
+ return track.code;
+ }),
+ self.options.audioTrack
+ )) {
+ self.options.audioTrack = self.audioTracks[0].code;
+ }
+ self.resolutions = Ox.sort(Ox.unique(
+ self.options.video.map(function(video) {
+ return video.resolution;
+ })
+ ));
+ if (!Ox.contains(self.resolutions, self.options.resolution)) {
self.options.resolution = self.resolutions[0];
}
- self.video = self.options.video[self.options.resolution];
+ self.video = getVideo();
} else {
self.video = self.options.video;
}
@@ -2578,7 +2713,10 @@ Ox.VideoPlayer = function(options, self) {
self.playInToOut = false;
} else {
hidePoster();
- if (self.options.playInToOut && self.options.position > self.options.out - self.secondsPerFrame) {
+ if (
+ self.options.playInToOut
+ && self.options.position > self.options.out - self.secondsPerFrame
+ ) {
setPosition(self.options['in']);
}
self.$video.play();
@@ -2639,17 +2777,6 @@ Ox.VideoPlayer = function(options, self) {
});
}
- function toggleSubtitles() {
- self.options.enableSubtitles = !self.options.enableSubtitles;
- setSubtitle();
- self.$timeline && self.$timeline.options({
- subtitles: self.options.enableSubtitles ? self.options.subtitles : []
- });
- that.triggerEvent('subtitles', {
- subtitles: self.options.enableSubtitles
- });
- }
-
function toggleVolume() {
self.$volume.toggle();
}
diff --git a/source/Ox.UI/js/Video/VideoPlayerPanel.js b/source/Ox.UI/js/Video/VideoPlayerPanel.js
index 08b0997d..71cd12c7 100644
--- a/source/Ox.UI/js/Video/VideoPlayerPanel.js
+++ b/source/Ox.UI/js/Video/VideoPlayerPanel.js
@@ -74,6 +74,7 @@ Ox.VideoPlayerPanel = function(options, self) {
showUsers: false,
smallTimelineURL: '',
subtitles: [],
+ subtitlesDefaultTrack: 'en',
timeline: '',
timelineTooltip: 'timeline',
video: '',
@@ -227,6 +228,7 @@ Ox.VideoPlayerPanel = function(options, self) {
resolution: self.options.resolution,
scaleToFill: self.options.scaleToFill,
subtitles: self.options.subtitles,
+ subtitlesDefaultTrack: self.options.subtitlesDefaultTrack,
timeline: self.options.smallTimelineURL,
video: self.options.video,
volume: self.options.volume,