--- a/src/ldt/ldt/api/ldt/handlers.py Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/api/ldt/handlers.py Wed Jan 18 15:36:26 2012 +0100
@@ -1,9 +1,11 @@
-from ldt.ldt_utils.models import Project, Content
+from ldt.ldt_utils.models import Project, Content, Segment
+from django.db.models import F, Q
from piston.handler import BaseHandler
from piston.utils import rc, require_extended
from ldt.ldt_utils.utils import LdtAnnotation
from ldt.ldt_utils.stat import add_annotation_to_stat
from ldt.security.utils import protect_instance, unprotect_instance
+from ldt.ldt_utils.segmentserializer import SegmentSerializer
import logging #@UnresolvedImport
@@ -222,3 +224,27 @@
"""
return Content.objects.get(iri_id=iri_id)
+
+class SegmentHandler(BaseHandler):
+ allowed_methods = ('GET', )
+ model = Segment
+ exclude = (
+ ("project_obj"),
+ ("content"),
+ )
+
+ def read(self, request, iri_id, begin, end):
+ """
+ returns a single Segment
+ """
+
+ content = Content.objects.get(iri_id=iri_id)
+ segments = Segment.objects.filter(content=content).filter(
+ Q(start_ts__gt=begin, start_ts__lt=end) | # segment start between begin and end
+ Q(start_ts__gt=begin-F('duration'), start_ts__lt=end-F('duration')) |# segment ends between begin and end
+ Q(start_ts__lt=begin, start_ts__gt=end-F('duration')) # period [begin:end] is included in the segment
+ )
+
+ a = SegmentSerializer(content, segments, viewable_contents=[content.iri_id])
+ return a.serialize_to_cinelab()
+
--- a/src/ldt/ldt/api/ldt/urls.py Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/api/ldt/urls.py Wed Jan 18 15:36:26 2012 +0100
@@ -1,12 +1,15 @@
from django.conf.urls.defaults import patterns, url
from piston.resource import Resource
-from ldt.api.ldt.handlers import ProjectHandler, ContentHandler
+from ldt.api.ldt.handlers import ProjectHandler, ContentHandler, SegmentHandler
project_handler = Resource(ProjectHandler, None)
content_handler = Resource(ContentHandler, None)
+segment_handler = Resource(SegmentHandler, None)
urlpatterns = patterns('',
url(r'projects/(?P<project_id>[^/.]+)\.?(?P<emitter_format>.*)$', project_handler, name='project_api'),
url(r'contents/(?P<iri_id>[^/.]+)\.?(?P<emitter_format>.*)$', content_handler, name='content_api'),
+ url(r'segments/(?P<iri_id>.*)/(?P<begin>\d+)/(?P<end>\d+)$', segment_handler),
)
+
--- a/src/ldt/ldt/ldt_utils/models.py Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py Wed Jan 18 15:36:26 2012 +0100
@@ -18,6 +18,7 @@
import mimetypes
import os.path
import tagging.fields
+from tagging.models import Tag
import uuid
@@ -364,12 +365,16 @@
admin = User.objects.filter(is_superuser=True)[0]
set_current_user(admin)
- self.front_project = Project.create_project(admin, 'front project : %s' % self.title, [self], cuttings=['chapitrage', 'contribution'] )
+ self.front_project = Project.create_project(admin, 'front project : %s' % self.title, [self], cuttings=['chapitrage', 'contributions'] )
self.front_project.publish(allow_write=True)
set_current_user(request_user)
assign('ldt_utils.change_content', request_user, self)
self.save()
+
+ # Tag management
+ def get_tags(self):
+ return Tag.objects.get_for_object(self)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/segmentserializer.py Wed Jan 18 15:36:26 2012 +0100
@@ -0,0 +1,143 @@
+from django.conf import settings
+from django.utils.datastructures import SortedDict
+import uuid
+
+DATE_FORMATS = ["%d/%m/%Y", "%Y-%m-%d"]
+
+class SegmentSerializer(object):
+ """
+ Serialize a set of annotations to a cinelab compatible array
+ """
+
+ def __init__(self, content, segments, viewable_contents=[], default_color=2194379):
+ self.content = content
+ self.segments = segments
+ self.viewable_contents = viewable_contents
+ self.default_color = default_color
+ self.views = None
+ self.annotation_types = None
+ self.medias = None
+ self.annotations = None
+
+
+ def __parse_views(self):
+
+ view = {
+ "id": "0",
+ "contents": [
+ self.content.iri_id
+ ],
+ "annotation_types": [ ],
+ }
+
+ self.annotation_types = []
+ annotation_types = [seg.cutting_id for seg in self.segments]
+ for a in annotation_types:
+ view['annotation_types'].append(a)
+ self.annotation_types.append({
+ "dc:contributor": "undefined",
+ "dc:creator": "undefined",
+ "dc:title": "cutting %s" % a,
+ "id": "%s" % a,
+ "dc:created": "",
+ "dc:description": "",
+ "dc:modified": ""
+ })
+
+ self.views = [view]
+
+
+ def __parse_content(self):
+
+ href = ""
+ meta_item_value = ""
+ if self.content.iri_id not in self.viewable_contents:
+ href = settings.FORBIDDEN_STREAM_URL
+ elif self.content.videopath:
+ href = self.content.videopath.rstrip('/') + "/" + self.content.src
+ meta_item_value = self.content.videopath.rstrip('/') + "/"
+ else:
+ href = self.content.src
+
+ media = {
+ "http://advene.liris.cnrs.fr/ns/frame_of_reference/ms" : "o=0",
+ "id" : self.content.iri_id,
+ "href" : href,
+ "unit" : "ms",
+ "origin" : "0",
+ "meta": {
+ "dc:creator" : "",
+ "dc:created" : self.content.creation_date.isoformat(),
+ "dc:contributor" : "",
+ "dc:modified" : self.content.update_date.isoformat(),
+ "dc:creator.contents" : "",
+ "dc:title" : self.content.title,
+ "dc:description" : self.content.description,
+ "dc:duration" : self.content.get_duration(),
+ "item": {
+ "name" : "streamer",
+ "value": meta_item_value,
+ },
+ }
+ }
+
+ self.medias = [media]
+
+
+ def __parse_segments(self):
+
+ self.annotations = []
+
+ for seg in self.segments:
+
+ segment = {
+ 'begin': seg.start_ts,
+ 'end': seg.start_ts + seg.duration,
+ 'tags': seg.tags,
+ 'id': "s_%s" % unicode(uuid.uuid1()),
+ 'color': "%s" % self.default_color,
+ 'media': self.content.iri_id,
+ 'content': {
+ 'mimetype': 'application/x-ldt-structured',
+ 'description': seg.abstract,
+ 'img': {
+ 'src': ''
+ },
+ 'title': seg.title,
+ 'color': '2194379',
+ 'polemics': [ ],
+ 'audio': {
+ 'mimetype': 'audio/mp3',
+ 'src': '',
+ 'href': 'null'
+ }
+
+ },
+ 'meta': {
+ "dc:creator": seg.author,
+ "dc:contributor": seg.author,
+ "dc:created": seg.date,
+ "dc:modified": seg.date,
+ "id-ref": seg.iri_id,
+ "project": seg.project_id
+ }
+ }
+
+ self.annotations.append(segment)
+
+ def serialize_to_cinelab(self):
+
+ self.__parse_content()
+ self.__parse_segments()
+ self.__parse_views()
+
+ res = {}
+ res['views'] = self.views
+ res['tags'] = None
+ res['lists'] = None
+ res['medias'] = self.medias
+ res['annotations'] = self.annotations
+ res['annotation-types'] = self.annotation_types
+
+ return res
+
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/stat.py Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/stat.py Wed Jan 18 15:36:26 2012 +0100
@@ -1,5 +1,5 @@
from django.conf import settings
-from ldt.ldt_utils.models import AnnotationStat, Project
+from ldt.ldt_utils.models import AnnotationStat, Project, Segment
from django.db.models.signals import pre_delete
import lxml.etree
import datetime
@@ -14,11 +14,11 @@
doc = lxml.etree.fromstring(project.ldt)
number_division = settings.DIVISIONS_FOR_STAT_ANNOTATION
- contributions = AnnotationStat.objects.filter(project=project)
+ contributions = list(AnnotationStat.objects.filter(project=project))
for content_node in doc.xpath('/iri/annotations/content'):
content_name = content_node.get('id')
- content = contents.filter(iri_id=content_name)
+ content = filter_list(contents, 'iri_id', content_name)
# if the content referenced in the xml belongs to the
# fields contents of the project
@@ -121,7 +121,7 @@
content.last_annotated = datetime.datetime.now()
content.save()
-
+import uuid
def add_annotation_to_stat(content, project, begin, end):
contribution_project = AnnotationStat.objects.get(project=project, content=content)
@@ -131,6 +131,20 @@
contribution_project.nb_annotation += 1
content.nb_annotation += 1
+# print "before segment creation"
+# s = Segment(project_obj=project,
+# content=content,
+# project_id=project.ldt_id,
+# iri_id=content.iri_id,
+# ensemble_id='%s' % unicode(uuid.uuid1()),
+# cutting_id='t',
+# element_id='a',
+# duration=end-begin,
+# start_ts=begin)
+# s.save()
+# print s.id
+# print "segment created"
+
if contribution_project.stat:
number_division = settings.DIVISIONS_FOR_STAT_ANNOTATION
@@ -147,7 +161,12 @@
content.last_annotated = datetime.datetime.now()
content.save()
contribution_project.save()
-
-
\ No newline at end of file
+def filter_list(list, criteria, value):
+ new_list = []
+ for l in list:
+ if getattr(l, criteria) == value:
+ new_list.append(l)
+
+ return new_list
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/templates/front/front_all_contents.html Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_all_contents.html Wed Jan 18 15:36:26 2012 +0100
@@ -63,9 +63,11 @@
{% block body %}
{{block.super}}
<!-- Last annotated contents -->
+{% if tag_cloud|length > 0 %}<p class="tag_link">{% trans 'Filter the medias' %} : {% for t in tag_cloud|slice:":5" %}<a href="{% url ldt.ldt_utils.views.front.all_contents %}?tag={{t.name}}">{{t.name}}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</p>{% endif %}
<ul class="floatlist full_width" id="derniers_medias">
<li class="li_h2">
- <h2>{% trans 'All medias' %}</h2>
+ {% if tag_label %}<h2><a href="{% url ldt.ldt_utils.views.front.all_contents %}">{% trans 'All medias' %}</a>{% if tag_label %}<span class="pink"> > {{tag_label}}</span>{% endif %}</h2>
+ {% else %}<h2>{% trans 'All medias' %}</h2>{% endif %}
</li>
{% for content in content_list %}
<li class="li_media">
@@ -77,5 +79,9 @@
</li>
{% endfor %}
</ul>
+{% if tag_cloud|length > 0 %}<p class="left tag_link">{% trans 'All tags' %} : {% for t in tag_cloud %}<a href="{% url ldt.ldt_utils.views.front.all_contents %}?tag={{t.name}}">
+ <span style="font-size:{{t.font_size|add:"10"}}px;">{{t.name}}</span>
+ </a>{% if not forloop.last %}, {% endif %}{% endfor %}</p>
+{% endif %}
{% endblock %}
--- a/src/ldt/ldt/ldt_utils/templates/front/front_base.html Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_base.html Wed Jan 18 15:36:26 2012 +0100
@@ -34,10 +34,11 @@
</form>
<li id="li_annotation">
<div class="fl">
- <a href="#"><img src="{{LDT_MEDIA_PREFIX}}img/annot_icon.png" id="annot_icon" /></a>
+ <!-- a href="#"><img src="{{LDT_MEDIA_PREFIX}}img/annot_icon.png" id="annot_icon" /></a -->
+ <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a>
</div>
<div class="fl">
- <a href="{% url root-view %}">{% trans 'Annotate' %}</a>
+ <!-- a href="{% url root-view %}">{% trans 'Annotate' %}</a -->
</div>
</li>
<li id="li_connexion">
--- a/src/ldt/ldt/ldt_utils/templates/front/front_home.html Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_home.html Wed Jan 18 15:36:26 2012 +0100
@@ -14,6 +14,7 @@
{% block body %}
{{block.super}}
<!-- Last annotated contents -->
+{% if tag_cloud|length > 0 %}<p class="tag_link">{% trans 'Filter the medias' %} : {% for t in tag_cloud %}<a href="{% url ldt.ldt_utils.views.front.all_contents %}?tag={{t.name}}">{{t.name}}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</p>{% endif %}
<ul class="floatlist full_width" id="derniers_medias">
<li class="li_h2">
<ul class="title_ul">
--- a/src/ldt/ldt/ldt_utils/views/content.py Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/content.py Wed Jan 18 15:36:26 2012 +0100
@@ -70,6 +70,9 @@
media_form = MediaForm(media_instance_val, request.FILES, prefix="media", instance=instance_media)
picture_form = PictureForm(None, request.POST, request.FILES)
+ if request.user.is_staff:
+ content_form.fields['front_project'].queryset = Project.objects.filter(contents__in=[instance_content])
+
media_valid = media_form.is_valid()
content_valid = content_form.is_valid()
picture_valid = picture_form.is_valid()
@@ -288,7 +291,7 @@
img_container = ''
session_key = request.COOKIES[settings.SESSION_COOKIE_NAME]
- cookie_name = settings.SESSION_COOKIE_NAME
+ cookie_name = settings.SESSION_COOKIE_NAME
content_form.fields["media_obj"].queryset = Media.safe_objects.all()
return render_to_response('ldt/ldt_utils/create_content.html', {'content_form': content_form, 'media_form': media_form, 'form_status': form_status, 'create_content_action': create_content_action,
--- a/src/ldt/ldt/ldt_utils/views/front.py Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/front.py Wed Jan 18 15:36:26 2012 +0100
@@ -9,6 +9,7 @@
from ldt.ldt_utils.models import Content, Project
from ldt.ldt_utils.views.workspace import search_index as ws_search_index, search_listing as ws_search_listing
from ldt.security.utils import add_change_attr
+from tagging.models import Tag, TaggedItem
@login_required
@@ -19,12 +20,13 @@
most_contents = Content.objects.order_by('-nb_annotation')[:8]
# Get the active groups
active_groups = Group.objects.exclude(name=settings.PUBLIC_GROUP_NAME)[:5]
-
+ # Get the main tag list
+ tag_cloud = get_content_tags(5)
is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
return render_to_response("front/front_home.html",
- {'last_contents': last_contents, 'most_contents':most_contents, 'active_groups':active_groups,
+ {'last_contents': last_contents, 'most_contents':most_contents, 'active_groups':active_groups, 'tag_cloud':tag_cloud,
'is_gecko': is_gecko},
context_instance=RequestContext(request))
@@ -49,13 +51,20 @@
@login_required
def all_contents(request):
+ # Get the tag parameter if possible
+ tag_label = request.GET.get("tag")
# Get all the public contents group
- content_list = add_change_attr(request.user, Content.safe_objects.all())
+ if tag_label is None :
+ content_list = add_change_attr(request.user, Content.safe_objects.all())
+ else :
+ content_list = TaggedItem.objects.get_by_model(add_change_attr(request.user, Content.safe_objects.all()), '"'+tag_label+'"')
+ # Get the main tag list
+ tag_cloud = get_content_tags()
is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
return render_to_response("front/front_all_contents.html",
- {'content_list':content_list,
+ {'content_list':content_list, 'tag_label':tag_label, 'tag_cloud':tag_cloud,
'is_gecko': is_gecko},
context_instance=RequestContext(request))
@@ -79,7 +88,7 @@
proj = Project.safe_objects.filter(contents__in=[content])[0]
else :
proj = Project.safe_objects.get(ldt_id=project_id)
-
+
# Vars for player
player_id = "player_project_" + proj.ldt_id
@@ -111,3 +120,13 @@
@login_required
def search_listing(request):
return ws_search_listing(request, front_template=True)
+
+
+def get_content_tags(limit=None, steps=10):
+ if limit is None:
+ return Tag.objects.cloud_for_model(Content, steps=steps)
+ else :
+ return Tag.objects.cloud_for_model(Content, steps=steps)[:limit]
+
+
+
--- a/src/ldt/ldt/static/ldt/css/front_common.css Wed Jan 18 15:36:03 2012 +0100
+++ b/src/ldt/ldt/static/ldt/css/front_common.css Wed Jan 18 15:36:26 2012 +0100
@@ -55,7 +55,7 @@
font-family: "DIN-Bold", Helvetica, Arial, sans-serif;
}
-h2 {
+h2, h2 a {
font-family: "DIN-Light", Helvetica, Arial, sans-serif; font-size: 21px; color: #0068c4; margin: 4px 2px;
}
@@ -182,7 +182,7 @@
/* Barre de titre */
#title_bar {
- font-family: "DIN-Light", Helvetica, Arial, sans-serif; height: 50px; font-size: 22px; margin: 0 0 1px 0;
+ font-family: "DIN-Light", Helvetica, Arial, sans-serif; height: 50px; font-size: 22px; margin: 0 0 1px 0; width: 980px;
}
#title_bar a {
@@ -213,6 +213,18 @@
margin: 3px 10px 0 0;
}
+/* Link for media tag/filter */
+.tag_link {
+ float:right;
+}
+.tag_link a {
+ color: #ff3b77;
+}
+.left {
+ float: left;
+}
+
+
/* Footer */