241 lines
12 KiB
JavaScript
Executable file
241 lines
12 KiB
JavaScript
Executable file
// vim: et:ts=4:sw=4:sts=4:ft=javascript
|
|
'use strict';
|
|
|
|
Ox.load('UI', {
|
|
debug: false,
|
|
hideScreen: false,
|
|
loadImages: true,
|
|
showScreen: true,
|
|
theme: 'oxdark'
|
|
}, function() {
|
|
var videoKeys = [ 'duration', 'layers', 'parts', 'posterFrame', 'rightslevel', 'size', 'title', 'videoRatio' ];
|
|
window.pandora = new Ox.App({url: '/api/'}).bindEvent({
|
|
load: function(data) {
|
|
Ox.extend(pandora, {
|
|
site: data.site,
|
|
user: data.user.level == 'guest' ? Ox.clone(data.site.user) : data.user,
|
|
$ui: {},
|
|
ui: {
|
|
player: function(options) {
|
|
var that = Ox.Element();
|
|
pandora.user.ui.item = options.item;
|
|
pandora.api.get({id: options.item, keys: videoKeys}, function(result) {
|
|
var data = getVideoOptions(result.data);
|
|
that.append(pandora.$player = Ox.VideoPlayer({
|
|
censored: data.censored,
|
|
censoredIcon: pandora.site.cantPlay.icon,
|
|
censoredTooltip: pandora.site.cantPlay.text,
|
|
controlsTooltips: {open: 'Open in ' + pandora.site.site.name},
|
|
controlsTop: (Ox.Fullscreen.available ? ['fullscreen'] : []).concat(
|
|
['space', 'open']
|
|
),
|
|
controlsBottom: ['play', 'volume', 'scale', 'timeline', 'settings'],
|
|
duration: data.duration,
|
|
enableFind: false,
|
|
enableFullscreen: Ox.Fullscreen.available,
|
|
enableKeyboard: true,
|
|
enableMouse: true,
|
|
enableTimeline: true,
|
|
enableVolume: true,
|
|
externalControls: false,
|
|
height: window.innerHeight,
|
|
'in': options['in'],
|
|
out: options.out,
|
|
paused: options.paused,
|
|
position: options['in'],
|
|
poster: '/' + options.item + '/' + '96p' + options['in'] +'.jpg',
|
|
resolution: pandora.user.ui.videoResolution,
|
|
showMarkers: false,
|
|
showMilliseconds: 0,
|
|
subtitles: data.subtitles,
|
|
timeline: '/' + options.item + '/' + 'timeline16p.png',
|
|
title: result.data.title,
|
|
video: data.video,
|
|
width: window.innerWidth
|
|
})
|
|
.bindEvent({
|
|
open: function() {
|
|
pandora.$player.options({paused: true});
|
|
var url = document.location.protocol
|
|
+ '//' + document.location.hostname
|
|
+ '/' + options.item + '/'
|
|
+ Ox.formatDuration(pandora.$player.options('position'));
|
|
window.open(url, '_blank');
|
|
},
|
|
playing: checkRange,
|
|
position: checkRange,
|
|
resolution: function(data) {
|
|
pandora.api.setUI({'videoResolution': data.resolution});
|
|
},
|
|
fullscreen: function(data) {
|
|
Ox.Fullscreen.toggle();
|
|
}
|
|
})
|
|
);
|
|
Ox.UI.hideLoadingScreen();
|
|
|
|
});
|
|
return that;
|
|
},
|
|
timeline: function(options) {
|
|
var that = Ox.Element();
|
|
pandora.user.ui.item = options.item;
|
|
pandora.api.get({id: options.item, keys: videoKeys}, function(result) {
|
|
Ox.UI.hideLoadingScreen();
|
|
var data = getVideoOptions(result.data),
|
|
ui = pandora.user.ui;
|
|
that.append(pandora.player = Ox.VideoTimelinePlayer({
|
|
censored: data.censored,
|
|
censoredIcon: pandora.site.cantPlay.icon,
|
|
censoredTooltip: pandora.site.cantPlay.text,
|
|
cuts: data.cuts || [],
|
|
duration: data.duration,
|
|
followPlayer: ui.followPlayer,
|
|
getFrameURL: function(position) {
|
|
return '/' + ui.item + '/' + ui.videoResolution + 'p' + position + '.jpg';
|
|
},
|
|
getLargeTimelineURL: function(type, i) {
|
|
return '/' + ui.item + '/timeline' + type + '64p' + i + '.jpg';
|
|
},
|
|
height: that.height(),
|
|
muted: ui.videoMuted,
|
|
'in': options['in'],
|
|
out: options.out,
|
|
paused: options.paused,
|
|
position: options['in'],
|
|
resolution: pandora.site.video.resolutions[0],
|
|
smallTimelineURL: '/' + ui.item + '/timeline16p.jpg',
|
|
subtitles: data.subtitles,
|
|
timeline: ui.videoTimeline,
|
|
timelines: pandora.site.timelines,
|
|
video: data.video,
|
|
videoRatio: data.videoRatio,
|
|
volume: ui.videoVolume,
|
|
width: that.width()
|
|
})
|
|
.bindEvent({
|
|
playing: checkRange,
|
|
position: checkRange,
|
|
resolution: function(data) {
|
|
pandora.api.setUI({'videoResolution': data.resolution});
|
|
},
|
|
})
|
|
);
|
|
});
|
|
return that;
|
|
}
|
|
}
|
|
});
|
|
function checkRange(data) {
|
|
if (
|
|
data.position < options['in'] - 0.04
|
|
|| data.position > options.out
|
|
) {
|
|
if (!pandora.$player.options('paused')) {
|
|
pandora.$player.togglePaused();
|
|
}
|
|
pandora.$player.options({
|
|
position: options['in']
|
|
});
|
|
}
|
|
}
|
|
Ox.extend(pandora.user, {
|
|
videoFormat: Ox.UI.getVideoFormat(pandora.site.video.formats)
|
|
});
|
|
var options = parseQuery();
|
|
if (['video', 'player'].indexOf(options.view) > -1) {
|
|
pandora.$ui.player = pandora.ui.player(options)
|
|
.css({top: 0, bottom: 0, left: 0, right: 0, position: 'absolute'})
|
|
.appendTo(document.body);
|
|
} else if (options.view == 'timeline') {
|
|
pandora.$ui.timeline = pandora.ui.timeline(options)
|
|
.css({top: 0, bottom: 0, left: 0, right: 0, position: 'absolute'})
|
|
.appendTo(document.body);
|
|
}
|
|
}
|
|
});
|
|
function getVideoUrl(id, resolution, part) {
|
|
var prefix = pandora.site.site.videoprefix
|
|
.replace('{id}', id)
|
|
.replace('{part}', part)
|
|
.replace('{resolution}', resolution)
|
|
.replace('{uid}', Ox.uid());
|
|
return prefix + '/' + id + '/' + resolution + 'p' + part + '.' + pandora.user.videoFormat;
|
|
}
|
|
|
|
function getVideoOptions(data) {
|
|
var canPlayClips = data.editable || pandora.site.capabilities.canPlayClips[pandora.user.level] >= data.rightslevel,
|
|
canPlayVideo = data.editable || pandora.site.capabilities.canPlayVideo[pandora.user.level] >= data.rightslevel,
|
|
options = {};
|
|
options.subtitles = data.layers.subtitles
|
|
? data.layers.subtitles.map(function(subtitle) {
|
|
return {'in': subtitle['in'], out: subtitle.out, text: subtitle.value};
|
|
})
|
|
: [];
|
|
options.censored = canPlayVideo ? []
|
|
: canPlayClips ? (
|
|
options.subtitles.length
|
|
? options.subtitles.map(function(subtitle, i) {
|
|
return {
|
|
'in': i == 0 ? 0 : options.subtitles[i - 1].out,
|
|
out: subtitle['in']
|
|
};
|
|
}).concat(
|
|
[{'in': Ox.last(options.subtitles).out, out: data.duration}]
|
|
).filter(function(censored) {
|
|
// don't include gaps shorter than one second
|
|
return censored.out - censored['in'] >= 1;
|
|
})
|
|
: Ox.range(0, data.duration - 5, 60).map(function(position) {
|
|
return {
|
|
'in': position + 5,
|
|
out: Math.min(position + 60, data.duration)
|
|
};
|
|
})
|
|
)
|
|
: [{'in': 0, out: data.duration}];
|
|
options.video = {};
|
|
pandora.site.video.resolutions.forEach(function(resolution) {
|
|
options.video[resolution] = Ox.range(data.parts).map(function(i) {
|
|
return getVideoUrl(data.item || pandora.user.ui.item, resolution, i + 1);
|
|
});
|
|
});
|
|
options.layers = [];
|
|
pandora.site.layers.forEach(function(layer, i) {
|
|
options.layers[i] = Ox.extend({}, layer, {
|
|
items: data.layers[layer.id].map(function(annotation) {
|
|
annotation.duration = Math.abs(annotation.out - annotation['in']);
|
|
annotation.editable = annotation.editable
|
|
|| annotation.user == pandora.user.username
|
|
|| pandora.site.capabilities['canEditAnnotations'][pandora.user.level];
|
|
return annotation;
|
|
})
|
|
});
|
|
});
|
|
options.duration = data.duration;
|
|
options.videoRatio = data.videoRatio;
|
|
return options;
|
|
}
|
|
|
|
function parseQuery() {
|
|
var vars = window.location.search.length
|
|
? window.location.search.slice(1).split('&')
|
|
: [],
|
|
query = {
|
|
item: window.location.pathname.slice(1).split('/')[0]
|
|
},
|
|
defaults = {
|
|
view: 'video',
|
|
'in': 0,
|
|
out: 10,
|
|
paused: true,
|
|
item: ''
|
|
};
|
|
vars.forEach(function(v) {
|
|
v = v.split('=');
|
|
query[v[0]] = decodeURIComponent(v[1]);
|
|
});
|
|
|
|
return Ox.extend({}, defaults, query);
|
|
}
|
|
});
|