pandora/pandora/clip/models.py

196 lines
7.3 KiB
Python
Raw Normal View History

2011-10-02 18:16:28 +00:00
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
from django.db import models
from django.conf import settings
2014-02-05 13:21:17 +00:00
import ox
2011-10-02 18:16:28 +00:00
from archive import extract
import managers
2011-10-20 19:32:31 +00:00
class MetaClip:
2011-10-02 18:16:28 +00:00
def update_calculated_values(self):
2011-11-22 16:49:38 +00:00
start = self.start
end = self.end
if self.item.sort.duration:
start = min(self.start, self.item.sort.duration)
end = min(self.end, self.item.sort.duration)
self.duration = end - start
2012-10-09 17:22:16 +00:00
if int(end*25) - int(start*25) > 0:
2011-10-02 18:16:28 +00:00
self.hue, self.saturation, self.lightness = extract.average_color(
self.item.timeline_prefix, self.start, self.end)
self.volume = extract.average_volume(self.item.timeline_prefix, self.start, self.end)
else:
self.hue = self.saturation = self.lightness = 0
self.volume = 0
2011-10-02 18:16:28 +00:00
def save(self, *args, **kwargs):
if self.duration != self.end - self.start:
self.update_calculated_values()
if not self.aspect_ratio and self.item:
streams = self.item.streams()
if streams:
self.aspect_ratio = streams[0].aspect_ratio
2012-03-22 21:33:42 +00:00
if self.item:
self.user = self.item.user and self.item.user.id
self.sort = self.item.sort
2011-11-02 14:46:27 +00:00
if self.id:
2012-03-07 10:36:32 +00:00
sortvalue = ''
if self.id:
2012-04-02 15:33:09 +00:00
for l in settings.CONFIG.get('clipLayers', []):
2012-03-07 10:36:32 +00:00
sortvalue += ''.join(filter(lambda s: s,
[a.sortvalue
for a in self.annotations.filter(layer=l).order_by('sortvalue')]))
if sortvalue:
self.sortvalue = sortvalue[:900]
else:
self.sortvalue = None
self.findvalue = '\n'.join(filter(None, [a.findvalue for a in self.annotations.all()]))
for l in [k['id'] for k in settings.CONFIG['layers']]:
2011-11-02 14:46:27 +00:00
setattr(self, l, self.annotations.filter(layer=l).count()>0)
models.Model.save(self, *args, **kwargs)
2011-10-02 18:16:28 +00:00
clip_keys = ('id', 'in', 'out', 'position', 'created', 'modified',
'hue', 'saturation', 'lightness', 'volume', 'videoRatio')
def json(self, keys=None, qs=None):
2011-10-02 18:16:28 +00:00
j = {}
for key in self.clip_keys:
j[key] = getattr(self, {
2011-10-02 18:16:28 +00:00
'id': 'public_id',
'in': 'start',
'out': 'end',
2011-10-09 12:02:16 +00:00
'position': 'start',
'videoRatio': 'aspect_ratio',
}.get(key, key))
2011-12-30 06:44:12 +00:00
if not j['videoRatio']:
j['videoRatio'] = 4/3
2011-10-02 18:16:28 +00:00
if keys:
for key in j.keys():
if key not in keys:
del j[key]
2011-11-03 11:17:50 +00:00
#needed here to make item find with clips work
if 'annotations' in keys:
#annotations = self.annotations.filter(layer__in=settings.CONFIG['clipLayers'])
annotations = self.annotations.all()
if qs:
annotations = annotations.filter(qs)
j['annotations'] = [a.json(keys=['value', 'id', 'layer']) for a in annotations]
2014-02-05 13:21:17 +00:00
if 'layers' in keys:
j['layers'] = self.get_layers()
if 'cuts' in keys:
2014-11-18 14:54:41 +00:00
j['cuts'] = tuple([c for c in self.item.get('cuts', []) if c > self.start and c < self.end])
for key in keys:
if key not in self.clip_keys and key not in j:
value = self.item.get(key) or self.item.json.get(key)
2011-10-28 23:35:01 +00:00
if not value and hasattr(self.item.sort, key):
value = getattr(self.item.sort, key)
if value != None:
j[key] = value
2011-10-02 18:16:28 +00:00
return j
2014-02-05 13:21:17 +00:00
def edit_json(self, user=None):
data = {
'id': ox.toAZ(self.id),
}
2014-09-19 12:26:46 +00:00
data['item'] = self.item.public_id
2014-02-05 13:21:17 +00:00
data['in'] = self.start
data['out'] = self.end
data['parts'] = self.item.json['parts']
data['durations'] = self.item.json['durations']
for key in ('title', 'director', 'year', 'videoRatio'):
value = self.item.json.get(key)
if value:
data[key] = value
data['duration'] = data['out'] - data['in']
2014-11-18 14:54:41 +00:00
data['cuts'] = tuple([c for c in self.item.get('cuts', []) if c > self.start and c < self.end])
2014-02-05 13:21:17 +00:00
data['layers'] = self.get_layers(user)
return data
def get_layers(self, user=None):
from annotation.models import Annotation
start = self.start
end = self.end
item = self.item
layers = {}
for l in settings.CONFIG['layers']:
name = l['id']
ll = layers.setdefault(name, [])
qs = Annotation.objects.filter(layer=name, item=item).order_by(
'start', 'end', 'sortvalue')
if name == 'subtitles':
qs = qs.exclude(value='')
qs = qs.filter(start__lt=end, end__gt=start)
if l.get('private'):
if user and user.is_anonymous():
user = None
qs = qs.filter(user=user)
for a in qs.order_by('start'):
ll.append(a.json(user=user))
return layers
2011-10-20 19:32:31 +00:00
@classmethod
def get_or_create(cls, item, start, end):
start = float(start)
end = float(end)
2012-06-18 14:36:04 +00:00
start = float('%0.03f' % start)
end = float('%0.03f' % end)
qs = cls.objects.filter(item=item, start=start, end=end)
2011-10-20 19:32:31 +00:00
if qs.count() == 0:
2013-03-24 12:25:09 +00:00
clip, created = cls.objects.get_or_create(item=item, start=start, end=end)
2011-10-20 19:32:31 +00:00
clip.save()
created = True
else:
clip = qs[0]
created = False
return clip, created
2012-06-18 14:36:04 +00:00
@property
def public_id(self):
2014-09-19 12:26:46 +00:00
return u"%s/%0.03f-%0.03f" % (self.item.public_id, float(self.start), float(self.end))
2012-06-18 14:36:04 +00:00
2011-10-02 18:16:28 +00:00
def __unicode__(self):
2011-10-20 19:32:31 +00:00
return self.public_id
2011-10-02 18:16:28 +00:00
class Meta:
unique_together = ("item", "start", "end")
attrs = {
'__module__': 'clip.models',
'Meta': Meta,
'objects': managers.ClipManager(),
'created': models.DateTimeField(auto_now_add=True),
'modified': models.DateTimeField(auto_now=True),
'aspect_ratio': models.FloatField(default=0),
'item': models.ForeignKey('item.Item', related_name='clips'),
'sort': models.ForeignKey('item.ItemSort', related_name='matching_clips'),
2012-03-22 21:33:42 +00:00
'user': models.IntegerField(db_index=True, null=True),
#seconds
'start': models.FloatField(default=-1, db_index=True),
'end': models.FloatField(default=-1),
'duration': models.FloatField(default=0, db_index=True),
#get from annotation
'hue': models.FloatField(default=0, db_index=True),
'saturation': models.FloatField(default=0, db_index=True),
'lightness': models.FloatField(default=0, db_index=True),
'volume': models.FloatField(default=0, null=True, db_index=True),
'sortvalue': models.CharField(max_length=1000, null=True, db_index=True),
'findvalue': models.TextField(null=True, db_index=settings.DB_GIN_TRGM),
}
for name in [k['id'] for k in settings.CONFIG['layers']]:
attrs[name] = models.BooleanField(default=False, db_index=True)
Clip = type('Clip', (MetaClip,models.Model), attrs)
2012-03-22 19:40:37 +00:00
class Random(models.Model):
clip = models.ForeignKey(Clip, primary_key=True)
random = models.BigIntegerField(db_index=True, null=True)