add canPlayClips flag to annotation layers and use those layers to limit playback to clips

This commit is contained in:
j 2015-08-27 11:27:27 +02:00
parent 83013bbe5e
commit 41b50ccdb8
5 changed files with 63 additions and 23 deletions

View file

@ -733,6 +733,8 @@
Optional keys are: Optional keys are:
"autocomplete": Available if the layer is used as a filter "autocomplete": Available if the layer is used as a filter
"canAddAnnotations": Permissions per user level "canAddAnnotations": Permissions per user level
"canPlayClips": If true, clips from this layer will play for users
with canPlayClips access
"entity": ID of the referenced entity (if type is "entity") "entity": ID of the referenced entity (if type is "entity")
"hasEvents": If true, the calendar will be populated with matches from "hasEvents": If true, the calendar will be populated with matches from
this layer this layer
@ -768,6 +770,7 @@
"id": "subtitles", "id": "subtitles",
"title": "Subtitles", "title": "Subtitles",
"canAddAnnotations": {"staff": true, "admin": true}, "canAddAnnotations": {"staff": true, "admin": true},
"canPlayClips": true,
"hasEvents": true, "hasEvents": true,
"hasPlaces": true, "hasPlaces": true,
"isSubtitles": true, "isSubtitles": true,

View file

@ -752,6 +752,8 @@
Optional keys are: Optional keys are:
"autocomplete": Available if the layer is used as a filter "autocomplete": Available if the layer is used as a filter
"canAddAnnotations": Permissions per user level "canAddAnnotations": Permissions per user level
"canPlayClips": If true, clips from this layer will play for users
with canPlayClips access
"entity": ID of the referenced entity (if type is "entity") "entity": ID of the referenced entity (if type is "entity")
"hasEvents": If true, the calendar will be populated with matches from "hasEvents": If true, the calendar will be populated with matches from
this layer this layer
@ -778,6 +780,7 @@
"id": "notes", "id": "notes",
"title": "Notes", "title": "Notes",
"canAddAnnotations": {"member": true, "researcher": true, "staff": true, "admin": true}, "canAddAnnotations": {"member": true, "researcher": true, "staff": true, "admin": true},
"canPlayClips": true,
"hasEvents": true, "hasEvents": true,
"hasPlaces": true, "hasPlaces": true,
"item": "Note", "item": "Note",
@ -789,6 +792,7 @@
"id": "subtitles", "id": "subtitles",
"title": "Subtitles", "title": "Subtitles",
"canAddAnnotations": {"researcher": true, "staff": true, "admin": true}, "canAddAnnotations": {"researcher": true, "staff": true, "admin": true},
"canPlayClips": true,
"hasEvents": true, "hasEvents": true,
"hasPlaces": true, "hasPlaces": true,
"isSubtitles": true, "isSubtitles": true,

View file

@ -634,6 +634,8 @@
Optional keys are: Optional keys are:
"autocomplete": Available if the layer is used as a filter "autocomplete": Available if the layer is used as a filter
"canAddAnnotations": Permissions per user level "canAddAnnotations": Permissions per user level
"canPlayClips": If true, clips from this layer will play for users
with canPlayClips access
"entity": ID of the referenced entity (if type is "entity") "entity": ID of the referenced entity (if type is "entity")
"hasEvents": If true, the calendar will be populated with matches from "hasEvents": If true, the calendar will be populated with matches from
this layer this layer
@ -683,6 +685,7 @@
"id": "transcripts", "id": "transcripts",
"title": "Transcripts", "title": "Transcripts",
"canAddAnnotations": {"member": true, "staff": true, "admin": true}, "canAddAnnotations": {"member": true, "staff": true, "admin": true},
"canPlayClips": true,
"isSubtitles": true, "isSubtitles": true,
"item": "Transcript", "item": "Transcript",
"showInfo": true, "showInfo": true,

View file

@ -573,6 +573,8 @@ examples (config.SITENAME.jsonc) that are part of this pan.do/ra distribution.
Optional keys are: Optional keys are:
"autocomplete": Available if the layer is used as a filter "autocomplete": Available if the layer is used as a filter
"canAddAnnotations": Permissions per user level "canAddAnnotations": Permissions per user level
"canPlayClips": If true, clips from this layer will play for users
with canPlayClips access
"entity": ID of the referenced entity (if type is "entity") "entity": ID of the referenced entity (if type is "entity")
"hasEvents": If true, the calendar will be populated with matches from "hasEvents": If true, the calendar will be populated with matches from
this layer this layer
@ -616,6 +618,7 @@ examples (config.SITENAME.jsonc) that are part of this pan.do/ra distribution.
"id": "subtitles", "id": "subtitles",
"title": "Subtitles", "title": "Subtitles",
"canAddAnnotations": {"staff": true, "admin": true}, "canAddAnnotations": {"staff": true, "admin": true},
"canPlayClips": true,
"hasEvents": true, "hasEvents": true,
"hasPlaces": true, "hasPlaces": true,
"isSubtitles": true, "isSubtitles": true,

View file

@ -1948,6 +1948,54 @@ pandora.getVideoURL = function(id, resolution, part, track) {
+ pandora.getVideoURLName(id, resolution, part, track); + pandora.getVideoURLName(id, resolution, part, track);
}; };
pandora.getCensoredClips = function(data) {
var annotations = [],
clips = [],
last;
pandora.site.layers.filter(function(layer) {
return layer.canPlayClips;
}).forEach(function(layer) {
data.layers[layer.id] && data.layers[layer.id].forEach(function(annotation, i) {
annotations.push(annotation)
});
});
if (annotations.length) {
Ox.sort(annotations, function(clip) {
return clip['in'];
}).forEach(function(clip) {
if (last && last['out'] >= clip['in']) {
last['out'] = Math.max(last['out'], clip['out']);
} else {
last = {
'in': clip['in'],
out: clip.out
};
clips.push(last);
}
});
}
return clips.length
? clips.map(function(clip, i) {
return {
'in': i == 0 ? 0
: clips[i - 1].out,
out: clip['in']
};
}).concat([{
'in': Ox.last(clips).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)
};
});
};
pandora.getVideoOptions = function(data) { pandora.getVideoOptions = function(data) {
var canPlayClips = data.editable var canPlayClips = data.editable
|| pandora.site.capabilities.canPlayClips[pandora.user.level] || pandora.site.capabilities.canPlayClips[pandora.user.level]
@ -1958,29 +2006,8 @@ pandora.getVideoOptions = function(data) {
options = {}; options = {};
options.subtitlesLayer = pandora.getSubtitlesLayer(); options.subtitlesLayer = pandora.getSubtitlesLayer();
options.censored = canPlayVideo ? [] options.censored = canPlayVideo ? []
: canPlayClips ? ( : canPlayClips ? pandora.getCensoredClips(data)
options.subtitlesLayer && data.layers[options.subtitlesLayer].length : [{'in': 0, out: data.duration}];
? data.layers[options.subtitlesLayer].map(function(subtitle, i) {
return {
'in': i == 0 ? 0
: data.layers[options.subtitlesLayer][i - 1].out,
out: subtitle['in']
};
}).concat([{
'in': Ox.last(data.layers[options.subtitlesLayer]).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 = []; options.video = [];
pandora.site.video.resolutions.forEach(function(resolution) { pandora.site.video.resolutions.forEach(function(resolution) {
if (data.audioTracks) { if (data.audioTracks) {