diff --git a/pandora/archive/models.py b/pandora/archive/models.py index f6199e8e..1b951b5b 100644 --- a/pandora/archive/models.py +++ b/pandora/archive/models.py @@ -135,8 +135,9 @@ class File(models.Model): self.is_subtitle = False self.type = self.get_type() - info = ox.parse_movie_path(self.path) - self.language = info['language'] + if self.instances.count()>0: + info = ox.parse_movie_path(self.path) + self.language = info['language'] self.part = self.get_part() if self.type not in ('audio', 'video'): diff --git a/pandora/archive/tasks.py b/pandora/archive/tasks.py index f6b53cb1..89b352c7 100644 --- a/pandora/archive/tasks.py +++ b/pandora/archive/tasks.py @@ -3,16 +3,18 @@ from celery.decorators import task import ox -from item.models import get_item from django.conf import settings +from item.models import get_item +import item.tasks + import models _INSTANCE_KEYS = ('mtime', 'path') def get_or_create_item(volume, info, user): - item_info = ox.parse_movie_info(info['path']) + item_info = ox.parse_movie_path(info['path']) return get_item(item_info, user) def get_or_create_file(volume, f, user, item=None): @@ -67,17 +69,23 @@ def update_files(user, volume, files): user = models.User.objects.get(username=user) volume, created = models.Volume.objects.get_or_create(user=user, name=volume) all_files = [] + #ignore extras etc, + #imdb stlye is L/Last, First/Title (Year)/Title.. 4 + #otherwise T/Title (Year)/Title... 3 + folder_depth = settings.USE_IMDB and 4 or 3 for f in files: - #ignore extras etc, - #imdb stlye is L/Last, First/Title (Year)/Title.. 4 - #otherwise T/Title (Year)/Title... 3 - folder_depth = settings.USE_IMDB and 4 or 3 if len(f['path'].split('/')) == folder_depth: all_files.append(f['oshash']) update_or_create_instance(volume, f) #remove deleted files - models.Instance.objects.filter(volume=volume).exclude(file__oshash__in=all_files).delete() + removed = models.Instance.objects.filter(volume=volume).exclude(file__oshash__in=all_files) + ids = [i['itemId'] for i in Item.models.objects.filter( + files__instances__in=removed.filter(selected=True)).distinct().values('itemId')] + removed.delete() + for i in ids: + i = Item.models.objects.get(itemId=i) + i.update_selected() @task(queue="encoding") def process_stream(fileId): diff --git a/pandora/clip/models.py b/pandora/clip/models.py index 41f1430b..f5444356 100644 --- a/pandora/clip/models.py +++ b/pandora/clip/models.py @@ -53,7 +53,7 @@ class Clip(models.Model): self.title = self.item.sort.title def save(self, *args, **kwargs): - self.public_id = u"%s/%s-%s" %(self.item.itemId, self.start, self.end) + self.public_id = u"%s/%s-%s" %(self.item.itemId, float(self.start), float(self.end)) if self.duration != self.end - self.start: self.update_calculated_values() super(Clip, self).save(*args, **kwargs) @@ -93,11 +93,13 @@ class Clip(models.Model): @classmethod def get_or_create(cls, item, start, end): + start = float(start) + end = float(end) public_id = u"%s/%s-%s" %(item.itemId, start, end) qs = cls.objects.filter(public_id=public_id) if qs.count() == 0: clip = Clip(item=item, start=start, end=end, public_id=public_id) - clips.save() + clip.save() created = True else: clip = qs[0] diff --git a/static/js/pandora.js b/static/js/pandora.js index ee79f447..91ebdbea 100644 --- a/static/js/pandora.js +++ b/static/js/pandora.js @@ -174,7 +174,25 @@ Ox.load({ pandora.$ui.info.resizeInfo(); if (!pandora.user.ui.item) { pandora.resizeGroups(pandora.$ui.rightPanel.width()); - if (pandora.user.ui.listView == 'map') { + if (pandora.user.ui.listView == 'clips') { + var clipsItems = pandora.getClipsItems(); + previousClipsItems = pandora.getClipsItems(pandora.$ui.list.options('width')); + pandora.$ui.list.options({ + width: window.innerWidth + - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1 + - Ox.UI.SCROLLBAR_SIZE + }); + if (clipsItems != previousClipsItems) { + Ox.Request.clearCache(); // fixme + pandora.$ui.list.reloadList(true); + } + } else if (pandora.user.ui.listView == 'timelines') { + pandora.$ui.list.options({ + width: window.innerWidth + - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1 + - Ox.UI.SCROLLBAR_SIZE + }); + } else if (pandora.user.ui.listView == 'map') { pandora.$ui.map.resizeMap(); } else if (pandora.user.ui.listView == 'calendar') { pandora.$ui.calendar.resizeCalendar(); diff --git a/static/js/pandora/ui/item.js b/static/js/pandora/ui/item.js index efb0078b..a5ed11fe 100644 --- a/static/js/pandora/ui/item.js +++ b/static/js/pandora/ui/item.js @@ -6,7 +6,8 @@ pandora.ui.item = function() { pandora.api.get({ id: pandora.user.ui.item, - keys: [] + keys: ['video', 'timeline'].indexOf(pandora.user.ui.itemView)>-1 ? + ['rendered', 'cuts', 'videoRatio', 'duration', 'layers', 'parts', 'size'] : [] }, pandora.user.level == 'admin' && pandora.user.ui.itemView == 'info' ? 0 : -1, function(result) { if (result.status.code == 200) { @@ -102,190 +103,186 @@ pandora.ui.item = function() { ); } else if (pandora.user.ui.itemView == 'video') { - pandora.api.get({id: pandora.user.ui.item, keys: ['layers']}, function(r) { - // fixme: duplicated - var clipsQuery = pandora.getClipsQuery(), - isClipsQuery = !!clipsQuery.conditions.length, - layers = [], - video = {}; - pandora.site.layers.forEach(function(layer, i) { - layers[i] = Ox.extend({}, layer, {items: r.data.layers[layer.id]}); - }); - pandora.site.video.resolutions.forEach(function(resolution) { - video[resolution] = Ox.range(result.data.parts).map(function(i) { - return '/' + pandora.user.ui.item + '/' - + resolution + 'p' + (i + 1) + '.' + pandora.user.videoFormat; - }); - }); - // - pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.player = Ox.VideoPanelPlayer({ - annotationsSize: pandora.user.ui.annotationsSize, - cuts: result.data.cuts || [], - duration: result.data.duration, - find: isClipsQuery ? clipsQuery.conditions[0].value : '', - getTimelineImageURL: function(i) { - return '/' + pandora.user.ui.item + '/timeline64p' + i + '.png'; - }, - height: pandora.$ui.contentPanel.size(1), - 'in': pandora.user.ui.videoPoints[pandora.user.ui.item]['in'], - muted: pandora.user.ui.videoMuted, - out: pandora.user.ui.videoPoints[pandora.user.ui.item].out, - position: pandora.user.ui.videoPoints[pandora.user.ui.item].position, - scaleToFill: pandora.user.ui.videoScale == 'fill', - showAnnotations: pandora.user.ui.showAnnotations, - showControls: pandora.user.ui.showControls, - subtitles: r.data.layers.subtitles ? - r.data.layers.subtitles.map(function(subtitle) { - return {'in': subtitle['in'], out: subtitle.out, text: subtitle.value}; - }) : [], - tooltips: true, - timeline: '/' + pandora.user.ui.item + '/timeline16p.png', - video: video, - volume: pandora.user.ui.videoVolume, - width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1 - }).bindEvent({ - muted: function(data) { - pandora.UI.set('muted', data.muted); - }, - position: function(data) { - pandora.UI.set('videoPoints.' + pandora.user.ui.item + '.position', data.position); - }, - resizeannotations: function(data) { - pandora.UI.set('annotationsSize', data.annotationsSize); - }, - scale: function(data) { - pandora.UI.set('videoScale', data.scale); - }, - toggleannotations: function(data) { - pandora.UI.set('showAnnotations', data.showAnnotations); - }, - togglecontrols: function(data) { - pandora.UI.set('showControls', data.showControls); - }, - volume: function(data) { - pandora.UI.set('volume', data.volume); - }, - pandora_showannotations: function(data) { - pandora.$ui.player.options({showAnnotations: data.value}); - } - })); + // fixme: duplicated + var clipsQuery = pandora.getClipsQuery(), + isClipsQuery = !!clipsQuery.conditions.length, + layers = [], + video = {}; + pandora.site.layers.forEach(function(layer, i) { + layers[i] = Ox.extend({}, layer, {items: result.data.layers[layer.id]}); }); + pandora.site.video.resolutions.forEach(function(resolution) { + video[resolution] = Ox.range(result.data.parts).map(function(i) { + return '/' + pandora.user.ui.item + '/' + + resolution + 'p' + (i + 1) + '.' + pandora.user.videoFormat; + }); + }); + // + pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.player = Ox.VideoPanelPlayer({ + annotationsSize: pandora.user.ui.annotationsSize, + cuts: result.data.cuts || [], + duration: result.data.duration, + find: isClipsQuery ? clipsQuery.conditions[0].value : '', + getTimelineImageURL: function(i) { + return '/' + pandora.user.ui.item + '/timeline64p' + i + '.png'; + }, + height: pandora.$ui.contentPanel.size(1), + 'in': pandora.user.ui.videoPoints[pandora.user.ui.item]['in'], + muted: pandora.user.ui.videoMuted, + out: pandora.user.ui.videoPoints[pandora.user.ui.item].out, + position: pandora.user.ui.videoPoints[pandora.user.ui.item].position, + scaleToFill: pandora.user.ui.videoScale == 'fill', + showAnnotations: pandora.user.ui.showAnnotations, + showControls: pandora.user.ui.showControls, + subtitles: result.data.layers.subtitles ? + result.data.layers.subtitles.map(function(subtitle) { + return {'in': subtitle['in'], out: subtitle.out, text: subtitle.value}; + }) : [], + tooltips: true, + timeline: '/' + pandora.user.ui.item + '/timeline16p.png', + video: video, + volume: pandora.user.ui.videoVolume, + width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1 + }).bindEvent({ + muted: function(data) { + pandora.UI.set('muted', data.muted); + }, + position: function(data) { + pandora.UI.set('videoPoints.' + pandora.user.ui.item + '.position', data.position); + }, + resizeannotations: function(data) { + pandora.UI.set('annotationsSize', data.annotationsSize); + }, + scale: function(data) { + pandora.UI.set('videoScale', data.scale); + }, + toggleannotations: function(data) { + pandora.UI.set('showAnnotations', data.showAnnotations); + }, + togglecontrols: function(data) { + pandora.UI.set('showControls', data.showControls); + }, + volume: function(data) { + pandora.UI.set('volume', data.volume); + }, + pandora_showannotations: function(data) { + pandora.$ui.player.options({showAnnotations: data.value}); + } + })); } else if (pandora.user.ui.itemView == 'timeline') { - pandora.api.get({id: pandora.user.ui.item, keys: ['layers']}, function(r) { - var clipsQuery = pandora.getClipsQuery(), - isClipsQuery = !!clipsQuery.conditions.length, - layers = [], - video = {}; - pandora.site.layers.forEach(function(layer) { - layers.push(Ox.extend({items: r.data.layers[layer.id]}, layer)); + var clipsQuery = pandora.getClipsQuery(), + isClipsQuery = !!clipsQuery.conditions.length, + layers = [], + video = {}; + pandora.site.layers.forEach(function(layer) { + layers.push(Ox.extend({items: result.data.layers[layer.id]}, layer)); + }); + pandora.site.video.resolutions.forEach(function(resolution) { + video[resolution] = Ox.range(result.data.parts).map(function(i) { + return '/' + pandora.user.ui.item + '/' + + resolution + 'p' + (i + 1) + '.' + pandora.user.videoFormat; }); - pandora.site.video.resolutions.forEach(function(resolution) { - video[resolution] = Ox.range(result.data.parts).map(function(i) { - return '/' + pandora.user.ui.item + '/' - + resolution + 'p' + (i + 1) + '.' + pandora.user.videoFormat; + }); + pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.editor = Ox.VideoEditor({ + annotationsSize: pandora.user.ui.annotationsSize, + cuts: result.data.cuts || [], + duration: result.data.duration, + find: isClipsQuery ? clipsQuery.conditions[0].value : '', + getFrameURL: function(position) { + return '/' + pandora.user.ui.item + '/' + Ox.last(pandora.site.video.resolutions) + 'p' + position + '.jpg'; + }, + getLargeTimelineImageURL: function(i) { + return '/' + pandora.user.ui.item + '/timeline64p' + i + '.png'; + }, + getSmallTimelineImageURL: function(i) { + return '/' + pandora.user.ui.item + '/timeline16p' + i + '.png'; + }, + height: pandora.$ui.contentPanel.size(1), + id: 'editor', + 'in': pandora.user.ui.videoPoints[pandora.user.ui.item]['in'], + layers: layers, + muted: pandora.user.ui.videoMuted, + out: pandora.user.ui.videoPoints[pandora.user.ui.item].out, + position: pandora.user.ui.videoPoints[pandora.user.ui.item].position, + posterFrame: parseInt(video.duration / 2), + showAnnotations: pandora.user.ui.showAnnotations, + showLargeTimeline: true, + // fixme: layers have value, subtitles has text? + subtitles: result.data.layers.subtitles ? + result.data.layers.subtitles.map(function(subtitle) { + return {'in': subtitle['in'], out: subtitle.out, text: subtitle.value}; + }) : [], + tooltips: true, + video: video, + videoRatio: result.data.videoRatio, + videoSize: pandora.user.ui.videoSize, + width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1 + }).bindEvent({ + points: function(data) { + pandora.UI.set('videoPoints.' + pandora.user.ui.item, { + 'in': data['in'], + out: data.out, + position: pandora.user.ui.videoPoints[pandora.user.ui.item].position }); - }); - pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.editor = Ox.VideoEditor({ - annotationsSize: pandora.user.ui.annotationsSize, - cuts: result.data.cuts || [], - duration: result.data.duration, - find: isClipsQuery ? clipsQuery.conditions[0].value : '', - getFrameURL: function(position) { - return '/' + pandora.user.ui.item + '/' + Ox.last(pandora.site.video.resolutions) + 'p' + position + '.jpg'; - }, - getLargeTimelineImageURL: function(i) { - return '/' + pandora.user.ui.item + '/timeline64p' + i + '.png'; - }, - getSmallTimelineImageURL: function(i) { - return '/' + pandora.user.ui.item + '/timeline16p' + i + '.png'; - }, - height: pandora.$ui.contentPanel.size(1), - id: 'editor', - 'in': pandora.user.ui.videoPoints[pandora.user.ui.item]['in'], - layers: layers, - muted: pandora.user.ui.videoMuted, - out: pandora.user.ui.videoPoints[pandora.user.ui.item].out, - position: pandora.user.ui.videoPoints[pandora.user.ui.item].position, - posterFrame: parseInt(video.duration / 2), - showAnnotations: pandora.user.ui.showAnnotations, - showLargeTimeline: true, - // fixme: layers have value, subtitles has text? - subtitles: r.data.layers.subtitles ? - r.data.layers.subtitles.map(function(subtitle) { - return {'in': subtitle['in'], out: subtitle.out, text: subtitle.value}; - }) : [], - tooltips: true, - video: video, - videoRatio: result.data.videoRatio, - videoSize: pandora.user.ui.videoSize, - width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1 - }).bindEvent({ - points: function(data) { - pandora.UI.set('videoPoints.' + pandora.user.ui.item, { - 'in': data['in'], - out: data.out, - position: pandora.user.ui.videoPoints[pandora.user.ui.item].position - }); - }, - position: function(data) { - pandora.UI.set('videoPoints.' + pandora.user.ui.item + '.position', data.position); - }, - resize: function(data) { - Ox.print('RESIZE!!', data.size) - pandora.$ui.editor.options({ - height: data.size - }); - }, - resizeend: function(data) { - pandora.UI.set({annotationsSize: data.size}); - }, - togglesize: function(data) { - pandora.UI.set({videoSize: data.size}); - }, - addannotation: function(data) { - Ox.print('addAnnotation', data); - data.item = pandora.user.ui.item; - data.value = 'Click to edit'; - pandora.api.addAnnotation(data, function(result) { - pandora.$ui.editor.addAnnotation(data.layer, result.data); - }); - }, - removeannotations: function(data) { - pandora.api.removeAnnotations(data, function(result) { - //fixme: check for errors - pandora.$ui.editor.removeAnnotations(data.layer, data.ids); - }); - }, - toggleannotations: function(data) { - pandora.UI.set('showAnnotations', data.showAnnotations); - }, - updateannotation: function(data) { - //fixme: check that edit was successfull - pandora.api.editAnnotation(data, function(result) { - Ox.print('done updateAnnotation', result); - - }); - }, - pandora_showannotations: function(data) { - pandora.$ui.editor.options({showAnnotations: data.value}); - } - })); - that.bindEvent('resize', function(data) { - //Ox.print('resize item', data) + }, + position: function(data) { + pandora.UI.set('videoPoints.' + pandora.user.ui.item + '.position', data.position); + }, + resize: function(data) { + Ox.print('RESIZE!!', data.size) pandora.$ui.editor.options({ height: data.size }); - }); - /* - pandora.$ui.rightPanel.bindEvent('resize', function(data) { - Ox.print('... rightPanel resize', data, pandora.$ui.timelinePanel.size(1)) - pandora.$ui.editor.options({ - width: data - pandora.$ui.timelinePanel.size(1) - 1 + }, + resizeend: function(data) { + pandora.UI.set({annotationsSize: data.size}); + }, + togglesize: function(data) { + pandora.UI.set({videoSize: data.size}); + }, + addannotation: function(data) { + Ox.print('addAnnotation', data); + data.item = pandora.user.ui.item; + data.value = 'Click to edit'; + pandora.api.addAnnotation(data, function(result) { + pandora.$ui.editor.addAnnotation(data.layer, result.data); }); + }, + removeannotations: function(data) { + pandora.api.removeAnnotations(data, function(result) { + //fixme: check for errors + pandora.$ui.editor.removeAnnotations(data.layer, data.ids); + }); + }, + toggleannotations: function(data) { + pandora.UI.set('showAnnotations', data.showAnnotations); + }, + updateannotation: function(data) { + //fixme: check that edit was successfull + pandora.api.editAnnotation(data, function(result) { + Ox.print('done updateAnnotation', result); + + }); + }, + pandora_showannotations: function(data) { + pandora.$ui.editor.options({showAnnotations: data.value}); + } + })); + that.bindEvent('resize', function(data) { + //Ox.print('resize item', data) + pandora.$ui.editor.options({ + height: data.size }); - */ }); + /* + pandora.$ui.rightPanel.bindEvent('resize', function(data) { + Ox.print('... rightPanel resize', data, pandora.$ui.timelinePanel.size(1)) + pandora.$ui.editor.options({ + width: data - pandora.$ui.timelinePanel.size(1) - 1 + }); + }); + */ } else if (pandora.user.ui.itemView == 'map') { pandora.$ui.contentPanel.replaceElement(1, pandora.ui.navigationView('map', result.data.videoRatio)); diff --git a/static/js/pandora/ui/itemClips.js b/static/js/pandora/ui/itemClips.js index 87cc3d9a..414216dc 100644 --- a/static/js/pandora/ui/itemClips.js +++ b/static/js/pandora/ui/itemClips.js @@ -39,7 +39,9 @@ pandora.ui.itemClips = function(options) { .addClass('OxInfoIcon') .css({ float: 'left', - margin: '2px' + margin: i == 0 ? '2px 2px 2px -2px' + : i == self.options.clips.length - 1 ? '2px -2px 2px 2px' + : '2px' }) .data({'in': clip['in'], out: clip.out}); $item.$element.find('.OxTarget').addClass('OxSpecialTarget'); diff --git a/static/js/pandora/ui/list.js b/static/js/pandora/ui/list.js index 0459e319..df25b94e 100644 --- a/static/js/pandora/ui/list.js +++ b/static/js/pandora/ui/list.js @@ -233,7 +233,7 @@ pandora.ui.list = function() { query: pandora.user.ui.find, clips: { query: pandora.getClipsQuery(), - items: 5, + items: pandora.getClipsItems(), keys: [] } }), callback); @@ -242,7 +242,10 @@ pandora.ui.list = function() { selected: pandora.user.ui.listSelection, size: 192, sort: pandora.user.ui.listSort, - unique: 'id' + unique: 'id', + width: window.innerWidth + - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1 + - Ox.UI.SCROLLBAR_SIZE }) .bindEvent({ key_left: function() { diff --git a/static/js/pandora/ui/rightPanel.js b/static/js/pandora/ui/rightPanel.js index eb78bb2c..3a8ab336 100644 --- a/static/js/pandora/ui/rightPanel.js +++ b/static/js/pandora/ui/rightPanel.js @@ -25,7 +25,15 @@ pandora.ui.rightPanel = function() { if (!pandora.user.ui.item) { pandora.resizeGroups(); pandora.$ui.list.size(); - if (pandora.user.ui.listView == 'timelines') { + if (pandora.user.ui.listView == 'clips') { + var clipsItems = pandora.getClipsItems(); + previousClipsItems = pandora.getClipsItems(pandora.$ui.list.options('width')); + pandora.$ui.list.options({width: data.size}); + if (clipsItems != previousClipsItems) { + Ox.Request.clearCache(); // fixme + pandora.$ui.list.reloadList(true); + } + } else if (pandora.user.ui.listView == 'timelines') { pandora.$ui.list.options({width: data.size}); } else if (pandora.user.ui.listView == 'map') { pandora.$ui.map.resizeMap(); diff --git a/static/js/pandora/utils.js b/static/js/pandora/utils.js index c63acf66..8bc7248a 100644 --- a/static/js/pandora/utils.js +++ b/static/js/pandora/utils.js @@ -416,6 +416,13 @@ pandora.exitFullscreen = function() { pandora.user.ui.showBrowser && pandora.$ui.contentPanel.size(0, 112 + Ox.UI.SCROLLBAR_SIZE); }; +pandora.getClipsItems = function(width) { + width = width || window.innerWidth + - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1 + - Ox.UI.SCROLLBAR_SIZE; + return Math.floor((width - 8) / (128 + 8)) - 1; +}; + pandora.getClipsQuery = function() { function addClipsConditions(conditions) { conditions.forEach(function(condition) {