# HG changeset patch # User cavaliet # Date 1351508660 -3600 # Node ID 9eae65727f546ea101539f39361fce894da0b791 # Parent dd8fe34c5abed12eb7afd4f0dc3e117bee1f3498# Parent 4a5c5436844758a727f4c060d2e8e5a2c90a81d1 Merge with new rest api branch 4a5c5436844758a727f4c060d2e8e5a2c90a81d1 diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/api/ldt/handlers.py --- a/src/ldt/ldt/api/ldt/handlers.py Sun Oct 21 22:48:17 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ -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 import protect_models, unprotect_models -from ldt.ldt_utils.segmentserializer import SegmentSerializer -import logging #@UnresolvedImport - - -class ProjectHandler(BaseHandler): - allowed_methods = ('GET', 'PUT',) - model = Project - - def read(self, request, project_id): - """ - returns a single project - """ - return Project.objects.get(ldt_id=project_id) - - @require_extended - def update(self, request, project_id): - #return rc.ALL_OK - logging.debug("request " + repr(request)) - data = request.data - ldt_str = data["ldt"] - - logging.debug("request data" + repr(ldt_str)) - - if not ldt_str: - return rc.BAD_REQUEST - - project = Project.objects.get(ldt_id=project_id) - - project.ldt = ldt_str - - unprotect_models() - project.save() - protect_models() - - return rc.ALL_OK - - -class AnnotationHandler(BaseHandler): - allowed_methods = ('PUT',) - - @require_extended - def update(self, request, project_id): - """ - This method is called when a PUT request is sent to http:///api/ldt/projects/.. - is the ldt_id field of the project. If does not match any project on the platform, a 410 ("Gone") - error will be returned. - is the format of the data sent back by the server. It can be 'json', 'yaml', 'xml' or 'pickle'. - - If the request contains a content-type header whose value is set to "application/json" and a valid utf-8 encoded JSON file, - the following conditions will be checked before the annotations are added : - If the submitted file is not valid or refers to a media that is not contained in the project, a 500 ("Bad Request") - error will be returned. If the "type" field of an annotation matches an already existing cutting, it will be added to that - cutting. Otherwise, a new cutting will be added (as well as a new ensemble if needed). New cuttings are added to the view - "View at the last recording" if it exists, or to the view "Init view" else. If none of those views exist, the server will - not add the cutting to a view. Several annotations can be added at the same time if the submitted file contains multiple - annotations. The server returns the file submitted if all annotations have been added successfully, and adds to this file - IDs of created annotations to the file with a 200("OK") error code. - - If no content-type header is set, the file submitted must be a valid XML file and will replace entirely the ldt field - of the project without any verifications. - - Example : - - Remark : The file below contain the minimum necessary fields and attributes for the handler to work. If one field or attribute is - missing (e.g. author, or date) during submission, an error will occur. - - A platform is reachable at http://localhost/. It contains a project with ID a0593b58-f258-11df-80e1-00145ea4a2be. This project has - a content milosforman_amadeus, which has a cutting Salieri inside the view "View at the last recording". The following JSON file exists in the current directory : - - Example of ajax call with 2 differents annotations : - $('#mon_ajax').click(function(e) { - var url = "{% url project_api project_id='c8448f21-272d-11e1-876b-c8bcc896c290' emitter_format='.json' %}"; // Don't forget the "." before "json" ! - - var monjson = '{\ - "annotations": [\ - {\ - "type": "c_07BA1284-5F24-71A8-1EE2-423EED999B8A",\ - "type_title": "New cutting name if necessary",\ - "media": "briandepalma_scarfacedepalma",\ - "begin": 1600000,\ - "end": 2100000,\ - "content": {\ - "data": "new scar annot"\ - "audio": {\ - "mimetype": "audio/mp3",\ - "src": "mic",\ - "href": "rtmp://media.iri.centrepompidou.fr/ddc_micro_record/r_20120606190143793"\ - }\ - },\ - "tags": [ "json","dude" ]\ - }\ - ],\ - "meta": {\ - "creator": "John Doe",\ - "created": "2011-09-10T09:12:58"\ - }\ - }'; - var monjson2 = '{\ - "annotations": [\ - {\ - "type": "c_07BA1284-5F24-71A8-1EE2-423EED999B8A",\ - "type_title": "New cutting name if necessary",\ - "media": "briandepalma_scarfacedepalma",\ - "begin": 2400000,\ - "end": 3000000,\ - "content": {\ - "data": "ntm iam 2"\ - },\ - "tags": [ "jak" ]\ - }\ - ],\ - "meta": {\ - "creator": "John Doe",\ - "created": "2011-09-10T09:12:58"\ - }\ - }'; - - $.ajax({ - url: url, - type: 'PUT', - contentType: 'application/json', - data: monjson, - // bug with jquery >= 1.5, "json" adds a callback so we don't specify dataType - //dataType: 'json', - success: function(json, textStatus, XMLHttpRequest) { - alert("success = " + json); - }, - error: function(jqXHR, textStatus, errorThrown) { - alert("ERROR = " + jqXHR.responseText + ", " + errorThrown); - } - }); - }); - - If we send a PUT request with curl : - $curl -X PUT http://localhost/api/ldt/projects/a0593b58-f258-11df-80e1-00145ea4a2be.json -d @example.JSON -H "content-type:application/json" - A new cutting titled "New cutting name" will be created with the first annotation inside, and the annotation "Annotation about Salieri" - will be added to the Salieri cutting. The returned file is : - - { - "annotations": [ - { - "id": "6d8baf01-ffb1-11e0-810c-001485352c9a", - "type": "id_annot_type", - "type_title": "New cutting name", - "media": "milosforman_amadeus", - "begin": 50000, - "end": 900000, - "content": { - "data": "new annotation" - }, - "tags": [ "json" ] - }, - { - "id": "6d8baf00-ffb1-11e0-8097-001485352c9b", - "type": "another_id_annot_type", - "type_title": "Salieri", - "media": "milosforman_amadeus", - "begin": 700000, - "end": 1200000, - "content": { - "data": "Annotation about Salieri" - }, - "tags": [ "xml", "test", "blop" ] - } - ], - - "meta": { - "creator": "John Doe", - "created": "2011-09-10T09:12:58" - } - } - - """ - #return rc.ALL_OK - try: - project = Project.objects.get(ldt_id=project_id) - except Project.DoesNotExist: - return rc.NOT_HERE - - adder = LdtAnnotation(project) - logging.debug("request json " + repr(request.data)) - - unprotect_models() # Allows anonymous user to modify models in this request only - - meta = request.data['meta'] - author = meta['creator'] - date = meta['created'] - new_annotations = request.data['annotations'] - - for a in new_annotations: - dur = str(a['end'] - a['begin']) - begin = str(a['begin']) - # We test if the annotation has audio node - audio_src = "" - audio_href = "" - if a['content'].has_key('audio') : - if a['content']['audio'].has_key('src') : - audio_src = a['content']['audio']['src'] - if a['content']['audio'].has_key('href') : - audio_href = a['content']['audio']['href'] - type_id, new_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['data'], '', a['tags'], begin, dur, author, date, None, "2194379", audio_src, audio_href) - if not new_id: - protect_models() - return rc.BAD_REQUEST - - - content = project.contents.get(iri_id=a['media']) - add_annotation_to_stat(content, a['begin'], a['end']) - - # We update the ids - a['type'] = type_id - a['id'] = new_id - if not a['content'].has_key('audio') : - a['content']['audio'] = {'src':audio_src, 'href':audio_href} - - # We save if there were added annotation - if len(new_annotations)>0 : - adder.save() - - protect_models() - - return request.data - - - -class ContentHandler(BaseHandler): - allowed_methods = ('GET', 'PUT') - model = Content - exclude = ( - ("media_obj"), - ) - - def read(self, request, iri_id): - """ - returns a single content - """ - return Content.objects.get(iri_id=iri_id) - - @require_extended - def update(self, request, iri_id): - """ - Receives a json exactly like AnnotationHandler, but without any project indicated. - We get or set the current content front project, and add the annotation - """ - try: - content = Content.objects.get(iri_id=iri_id) - except Content.DoesNotExist: - return rc.NOT_HERE - proj = content.get_or_create_front_project() - ah = AnnotationHandler() - updated_data = ah.update(request, proj.ldt_id) - - return updated_data - - -class SegmentHandler(BaseHandler): - allowed_methods = ('GET', ) - model = Segment - exclude = ( - ("project_obj"), - ("content"), - ) - - def read(self, request, iri_id, begin, end): - """ - returns segments about content iri_id between timecodes begin and end - """ - begin = int(begin) - end = int(end) - - content = Content.objects.filter(iri_id=iri_id) - if not content: - return rc.NOT_FOUND - content = content[0] - - segments = Segment.objects.filter(content=content).filter( - Q(start_ts__gte=begin, start_ts__lte=end) | # segment starts between begin and end - Q(start_ts__gte=begin-F('duration'), start_ts__lte=end-F('duration')) |# segment ends between begin and end - Q(start_ts__lte=begin, start_ts__gte=end-F('duration')) # period [begin:end] is included in the segment - ) - - a = SegmentSerializer(content, segments) - return a.serialize_to_cinelab() - diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/api/ldt/resources/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/api/ldt/resources/__init__.py Mon Oct 29 12:04:20 2012 +0100 @@ -0,0 +1,6 @@ +from annotation import AnnotationResource +from content import ContentResource +from project import ProjectResource +from segment import SegmentResource + +__all__ = ["AnnotationResource", "ContentResource", "ProjectResource", "SegmentResource"] diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/api/ldt/resources/annotation.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/api/ldt/resources/annotation.py Mon Oct 29 12:04:20 2012 +0100 @@ -0,0 +1,110 @@ +from ldt.ldt_utils.models import Project, Content +from ldt.ldt_utils.stat import add_annotation_to_stat +from ldt.ldt_utils.utils import LdtAnnotation +from ldt.security import protect_models, unprotect_models +from tastypie import fields +from tastypie.authorization import Authorization +from tastypie.exceptions import NotFound, BadRequest +from tastypie.resources import Resource +import logging #@UnresolvedImport + + +class AnnotationObject(object): + # For the moment, these attributes are useless. We just need to define AnnotationObject + id = "" + project = "" + type = "" + type_title = "" + media = "" + begin = "" + end = "" + content = {"title":"", "description":""} + tags = [] + meta = {"creator":"","created":""} + +class AnnotationResource(Resource): + # For the moment, these attributes are useless. We just prepare relations to AnnotationObject + id = fields.CharField(attribute = 'id') + project = fields.CharField(attribute = 'project') + type = fields.CharField(attribute = 'type') + type_title = fields.CharField(attribute = 'type_title') + media = fields.CharField(attribute = 'media') + begin = fields.IntegerField(attribute = 'begin') + end = fields.IntegerField(attribute = 'end') + content = fields.DictField(attribute = 'content') + tags = fields.ListField(attribute = 'tags') + meta = fields.DictField(attribute = 'meta') + + class Meta: + allowed_methods = ['put'] + resource_name = 'annotations' + object_class = AnnotationObject + authorization = Authorization() + # always_return_data = True because we want the api returns the data with the updated ids + always_return_data = True + + def obj_delete_list(self, request=None, **kwargs): + return True + + def obj_create(self, bundle, request=None, **kwargs): + """ + """ + logging.debug("ICI 0-1 bundle.data = " + repr(bundle.data)) + project_id = "" + if bundle.data.has_key('project') : + project_id = bundle.data["project"] + if project_id and project_id != "" : + try: + project = Project.objects.get(ldt_id=project_id) + except Project.DoesNotExist: + raise NotFound("Project not found. project_id = " + project_id) + else : + # If the project's is not defined, we get or create the content's front project. + iri_id = bundle.data["media"] + try: + content = Content.objects.get(iri_id=iri_id) + except Content.DoesNotExist: + raise NotFound("Content not found. iri_id = " + iri_id) + project = content.get_or_create_front_project() + bundle.data["project"] = project.ldt_id + + adder = LdtAnnotation(project) + unprotect_models() # Allows anonymous user to modify models in this request only + # Here the bundle.data has the datas for only one annotation. The others api's functions parse the "objects" from the request's json. + a = bundle.data + dur = str(a['end'] - a['begin']) + begin = str(a['begin']) + # We test if the annotation has audio node + audio_src = "" + audio_href = "" + if a['content'].has_key('audio') : + if a['content']['audio'].has_key('src') : + audio_src = a['content']['audio']['src'] + if a['content']['audio'].has_key('href') : + audio_href = a['content']['audio']['href'] + meta = a['meta'] + author = meta['creator'] + date = meta['created'] + # add(media, cutting_id, cutting_title, title, text, tags_list, begin, dur, author, date + type_id, new_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['title'], a['content']['description'], a['tags'], begin, dur, author, date, None, "2194379", audio_src, audio_href) + if not new_id: + protect_models() + raise BadRequest + + content = project.contents.get(iri_id=a['media']) + add_annotation_to_stat(content, a['begin'], a['end']) + + # We update the ids + bundle.data['type'] = type_id + bundle.data['id'] = new_id + if not bundle.data['content'].has_key('audio') : + bundle.data['content']['audio'] = {'src':audio_src, 'href':audio_href} + # We reinject the datas in the bundle's response + bundle = self.full_hydrate(bundle) + + # We save the added annotation and reprotect the contents and projects + adder.save() + protect_models() + return bundle + + \ No newline at end of file diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/api/ldt/resources/content.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/api/ldt/resources/content.py Mon Oct 29 12:04:20 2012 +0100 @@ -0,0 +1,18 @@ +from django.conf.urls.defaults import url +from ldt.ldt_utils.models import Content +from tastypie.resources import ModelResource + + +class ContentResource(ModelResource): + class Meta: + allowed_methods = ['get'] + resource_name = 'contents' + queryset = Content.objects.all() + excludes = ['media_obj'] + + def override_urls(self): + # WARNING : in tastypie <= 1.0, override_urls is used instead of prepend_urls. From 1.0.0, prepend_urls will be prefered and override_urls deprecated + return [ + url(r"^(?P%s)/(?P[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), + ] + \ No newline at end of file diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/api/ldt/resources/project.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/api/ldt/resources/project.py Mon Oct 29 12:04:20 2012 +0100 @@ -0,0 +1,23 @@ +from django.conf.urls.defaults import url +from ldt.ldt_utils.models import Project +from tastypie.authorization import Authorization +from tastypie.resources import ModelResource + + +class ProjectResource(ModelResource): + class Meta: + allowed_methods = ['get', 'put'] + authorization= Authorization() # BE CAREFUL WITH THAT, it's unsecure + resource_name = 'projects' + queryset = Project.objects.all() + +# # WARNING : this project API will only accepts and returns json format, no matter format get parameter. +# def determine_format(self, request): +# return "application/json" + + def override_urls(self): + # WARNING : in tastypie <= 1.0, override_urls is used instead of prepend_urls. From 1.0.0, prepend_urls will be prefered and override_urls deprecated + return [ + url(r"^(?P%s)/(?P[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), + ] + \ No newline at end of file diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/api/ldt/resources/segment.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/api/ldt/resources/segment.py Mon Oct 29 12:04:20 2012 +0100 @@ -0,0 +1,99 @@ +from django.conf import settings +from django.conf.urls.defaults import url +from django.core.paginator import Paginator, InvalidPage +from django.db.models import F, Q +from ldt.indexation import get_results_with_context +from ldt.ldt_utils.models import Content, Segment +from ldt.ldt_utils.segmentserializer import SegmentSerializer +from tastypie.http import HttpNotFound +from tastypie.resources import ModelResource +from tastypie.utils import trailing_slash + + +class SegmentResource(ModelResource): + class Meta: + allowed_methods = ['get'] + resource_name = 'segments' + excludes = ['project_obj', 'content'] + queryset = Segment.objects.all() + filtering = { + 'iri_id': ['exact'], + 'start_ts': ['lte', 'gte'], + } + +# # WARNING : this segment API will only return json format, no matter format get parameter. +# def determine_format(self, request): +# return "application/json" + + def override_urls(self): + # WARNING : in tastypie <= 0.9.11, override_urls is used instead of prepend_urls. From 0.9.12, prepend_urls will be prefered and override_urls deprecated + return [ + url(r"^(?P%s)/search%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_search'), name="api_get_search"), + url(r"^(?P%s)/bytimecode%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_segments_by_timecode'), name='segment_api_empty'), + url(r"^(?P%s)/bytimecode/(?P.*)/(?P.*)/(?P.*)$" % self._meta.resource_name, self.wrap_view('get_segments_by_timecode'), name='segment_api'), + ] + + def get_search(self, request, **kwargs): + self.method_check(request, allowed=['get']) + # Do the query. + search = request.GET.get('q', '') + field = "all" + content_list = None + if u'author:' in search.lower() : + sub = search[7:] + sub = sub.upper() + if sub[0] != u'"': + sub = u'"' + sub + if sub[-1] != u'"': + sub = sub + u'"' + search = u'author:' + sub + results = get_results_with_context(field, search, content_list) + all_segments = Segment.objects.filter(element_id__in=[e['element_id'] for e in results]) + paginator = Paginator(all_segments, getattr(settings, 'API_LIMIT_PER_PAGE', 20)) + + try: + page = paginator.page(int(request.GET.get('page', 1))) + except InvalidPage: + raise HttpNotFound("Sorry, no results on that page.") + + objects = [] + + for segment in page.object_list: + bundle = self.build_bundle(obj=segment, request=request) + bundle = self.full_dehydrate(bundle) + objects.append(bundle) + + object_list = { + 'objects': objects, + } + + self.log_throttled_access(request) + return self.create_response(request, object_list) + + + + def get_segments_by_timecode(self, request, api_name, resource_name, iri_id=None, begin=None, end=None): + """ + returns segments about content iri_id between timecodes begin and end + """ + if not begin: + return HttpNotFound("begin timecode argument is missing.") + if not end: + return HttpNotFound("end timecode argument is missing.") + begin = int(begin) + end = int(end) + + content = Content.objects.filter(iri_id=iri_id) + if not content: + return HttpNotFound("Content does not exist or id is not correct.") + content = content[0] + + segments = Segment.objects.filter(content=content).filter( + Q(start_ts__gte=begin, start_ts__lte=end) | # segment starts between begin and end + Q(start_ts__gte=begin-F('duration'), start_ts__lte=end-F('duration')) |# segment ends between begin and end + Q(start_ts__lte=begin, start_ts__gte=end-F('duration')) # period [begin:end] is included in the segment + ) + + a = SegmentSerializer(content, segments) + return self.create_response(request, a.serialize_to_cinelab()) + \ No newline at end of file diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/api/ldt/urls.py --- a/src/ldt/ldt/api/ldt/urls.py Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/api/ldt/urls.py Mon Oct 29 12:04:20 2012 +0100 @@ -1,20 +1,13 @@ -from django.conf.urls.defaults import patterns, url -from django.views.defaults import page_not_found -from piston.resource import Resource -from ldt.api.ldt.handlers import ProjectHandler, AnnotationHandler, ContentHandler, SegmentHandler +from django.conf.urls.defaults import patterns, include +from ldt.api.ldt.resources import ProjectResource, ContentResource, SegmentResource, AnnotationResource +from tastypie.api import Api -project_handler = Resource(ProjectHandler, None) -annotation_handler = Resource(AnnotationHandler, None) -content_handler = Resource(ContentHandler, None) -segment_handler = Resource(SegmentHandler, None) +v1_api = Api(api_name='1.0') +v1_api.register(ProjectResource()) +v1_api.register(ContentResource()) +v1_api.register(SegmentResource()) +v1_api.register(AnnotationResource()) urlpatterns = patterns('', - url(r'projects/(?P[^/.]+)\.?(?P.*)$', project_handler, name='project_api'), - url(r'annotations/$', page_not_found, name='annotation_api_empty'), - url(r'annotations/(?P[^/.]+)\.?(?P.*)$', annotation_handler, name='annotation_api'), - url(r'contents/(?P[^/.]+)\.?(?P.*)$', content_handler, name='content_api'), - url(r'segments/$', page_not_found, name='segment_api_empty'), - url(r'segments/(?P.*)/(?P.*)/(?P.*)$', segment_handler, name='segment_api'), + (r'', include(v1_api.urls)), ) - - diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/ldt_utils/models.py --- a/src/ldt/ldt/ldt_utils/models.py Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/ldt_utils/models.py Mon Oct 29 12:04:20 2012 +0100 @@ -1,7 +1,6 @@ from django.conf import settings from django.contrib.auth.models import User, Group from django.db import models -from django.db import transaction from django.utils.translation import ugettext_lazy as _ from guardian.shortcuts import assign, remove_perm, get_perms from ldt.core.models import Document @@ -20,10 +19,8 @@ import os.path import re import tagging.fields -import tagging.utils import uuid -import logging -from shutil import rmtree, move +from shutil import move from django.core.files.storage import default_storage #from ldt.core.models import Document, Owner diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/ldt_utils/segmentserializer.py --- a/src/ldt/ldt/ldt_utils/segmentserializer.py Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/ldt_utils/segmentserializer.py Mon Oct 29 12:04:20 2012 +0100 @@ -2,6 +2,7 @@ from ldt.ldt_utils.models import Project from ldt.ldt_utils.stat import get_string_from_buckets from ldt.security.utils import use_forbidden_url +from tagging.utils import parse_tag_input import lxml.etree import uuid @@ -138,7 +139,7 @@ for seg in self.segments: segment_tags = [] - for tag in seg.tags.split(';'): + for tag in parse_tag_input(seg.tags): if not self.tags.has_key(tag): new_tag = { "meta": { diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html --- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html Mon Oct 29 12:04:20 2012 +0100 @@ -69,7 +69,7 @@ },{ type: "AnnotationsList", container: "AnnotationsList_ext", - ajax_url: "{{WEB_URL}}{% url segment_api_empty %}{% templatetag openvariable %}media{% templatetag closevariable %}/{% templatetag openvariable %}begin{% templatetag closevariable %}/{% templatetag openvariable %}end{% templatetag closevariable %}", + ajax_url: "{{WEB_URL}}{% url segment_api_empty resource_name='segments' api_name='1.0' %}{% templatetag openvariable %}media{% templatetag closevariable %}/{% templatetag openvariable %}begin{% templatetag closevariable %}/{% templatetag openvariable %}end{% templatetag closevariable %}", ajax_granularity : 300000, default_thumbnail : "{{WEB_URL}}{{LDT_MEDIA_PREFIX}}css/imgs/video_sequence.png", show_audio: true, @@ -89,7 +89,7 @@ hide_timeout: 5000 },{% if annotation_block %}{ type: "CreateAnnotation", - api_endpoint_template: "{{WEB_URL}}{% url annotation_api_empty %}{% templatetag openvariable %}id{% templatetag closevariable %}.json", + api_endpoint_template: "{{WEB_URL}}{% url api_dispatch_list resource_name='annotations' api_name='1.0' %}", api_method: "PUT", after_send_timeout: 8000, show_mic_record: {% if show_mic_record %}true{% else %}false{% endif %}, diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/ldt_utils/views/content.py --- a/src/ldt/ldt/ldt_utils/views/content.py Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/ldt_utils/views/content.py Mon Oct 29 12:04:20 2012 +0100 @@ -5,7 +5,6 @@ from django.forms.models import model_to_dict from django.core.files import File from django.db import transaction -#from django.core.files.temp import NamedTemporaryFile from django.forms.util import ErrorList from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render_to_response, redirect @@ -21,14 +20,13 @@ import ldt.utils.path as ldt_utils_path import logging import mimetypes -import os, stat +import os import urllib2 import subprocess import re import datetime import math import requests -import django.utils.simplejson as simplejson import urlparse import tempfile diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/ldt_utils/views/workspace.py --- a/src/ldt/ldt/ldt_utils/views/workspace.py Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/ldt_utils/views/workspace.py Mon Oct 29 12:04:20 2012 +0100 @@ -3,7 +3,7 @@ from django.contrib.auth.models import Group from django.core.urlresolvers import reverse#, resolve from django.core.paginator import Paginator, InvalidPage, EmptyPage -from django.http import (HttpResponseRedirect, HttpResponseForbidden ) +from django.http import HttpResponseForbidden from ldt.indexation import get_results_with_context, highlight_documents from django.shortcuts import render_to_response from django.template import RequestContext @@ -17,15 +17,12 @@ from ldt.ldt_utils.views.content import get_contents_page, get_content_tags from ldt.ldt_utils.views.project import get_projects_page, get_published_projects_page from ldt.security.utils import add_change_attr, get_userlist -from lxml.html import fragment_fromstring from operator import itemgetter from itertools import groupby import base64 import django.core.urlresolvers import ldt.auth as ldt_auth -import lxml.etree -import logging -from django.utils.safestring import SafeUnicode, mark_safe +from django.utils.safestring import mark_safe diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/settings.py --- a/src/ldt/ldt/settings.py Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/settings.py Mon Oct 29 12:04:20 2012 +0100 @@ -30,11 +30,11 @@ 'ldt.indexation', 'oauth_provider', 'django_openid_consumer', - 'piston', 'social_auth', 'south', 'guardian', 'sorl.thumbnail', + 'tastypie', ) MIDDLEWARE_CLASSES = ( @@ -49,7 +49,6 @@ 'django.contrib.messages.middleware.MessageMiddleware', 'django_openid_consumer.middleware.OpenIDMiddleware', 'ldt.ldt_utils.middleware.userprofile.LanguageMiddleware', - 'ldt.api.middleware.pistonput.PistonPutMiddleware', ) diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.js --- a/src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.js Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.js Mon Oct 29 12:04:20 2012 +0100 @@ -223,8 +223,15 @@ audio : (_this.show_audio && _annotation.audio && _annotation.audio.href && _annotation.audio.href != "null" ? _annotation.audio.href : undefined), l10n: _this.l10n }; - var _html = Mustache.to_html(_this.annotationTemplate, _data); - var _el = IriSP.jQuery(_html); + var _html = Mustache.to_html(_this.annotationTemplate, _data), + _el = IriSP.jQuery(_html), + _onselect = function() { + _this.annotations_$.removeClass("selected"); + _el.addClass("selected"); + }, + _onunselect = function() { + _this.annotations_$.removeClass("selected"); + }; _el.mouseover(function() { _annotation.trigger("select"); }) @@ -232,13 +239,12 @@ _annotation.trigger("unselect"); }) .appendTo(_this.list_$); - _annotation.on("select", function() { - _this.annotations_$.removeClass("selected"); - _el.addClass("selected"); + _el.on("remove", function() { + _annotation.off("select", _onselect); + _annotation.off("unselect", _onunselect); }); - _annotation.on("unselect", function() { - _this.annotations_$.removeClass("selected"); - });; + _annotation.on("select", _onselect); + _annotation.on("unselect", _onunselect); }); this.annotations_$ = this.$.find('.Ldt-AnnotationsList-li'); @@ -247,7 +253,7 @@ this.$.find('.Ldt-AnnotationsList-Tag-Li').each(function() { var _el = IriSP.jQuery(this); if (!_el.text().replace(/(^\s+|\s+$)/g,'')) { - _el.detach(); + _el.remove(); } }); diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/Controller.js --- a/src/ldt/ldt/static/ldt/metadataplayer/Controller.js Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/Controller.js Mon Oct 29 12:04:20 2012 +0100 @@ -157,9 +157,6 @@ }); this.timeDisplayUpdater(new IriSP.Model.Time(0)); - /* some players - including jwplayer - save the state of the mute button between sessions */ - //TODO: MOVE TO THE PLAYER/ - window.setTimeout(this.functionWrapper("volumeUpdater"), 1000); }; @@ -201,11 +198,7 @@ }; IriSP.Widgets.Controller.prototype.muteHandler = function() { - if (this.media.getMuted()) { - this.media.unmute(); - } else { - this.media.mute(); - } + this.media.setMuted(!this.media.getMuted()); }; IriSP.Widgets.Controller.prototype.volumeUpdater = function() { diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.css --- a/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.css Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.css Mon Oct 29 12:04:20 2012 +0100 @@ -34,6 +34,11 @@ border-radius: 2px; } +.Ldt-CreateAnnotation-Title.empty, .Ldt-CreateAnnotation-Creator.empty { + font-style: italic; + color: #90b0d0; +} + .Ldt-CreateAnnotation-Times { color: #ff3b77 } @@ -67,6 +72,10 @@ border-radius: 2px; } +.Ldt-CreateAnnotation-Description.empty { + font-style: italic; color: #999999; +} + .Ldt-CreateAnnotation-Avatar { float: right; width: 48px; diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.js --- a/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.js Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.js Mon Oct 29 12:04:20 2012 +0100 @@ -7,7 +7,7 @@ IriSP.Widgets.CreateAnnotation.prototype = new IriSP.Widgets.Widget(); IriSP.Widgets.CreateAnnotation.prototype.defaults = { - show_title_field : false, /* For the moment, titles can't be sent to ldtplatform */ + show_title_field : true, show_creator_field : true, start_visible : true, always_visible : false, @@ -106,12 +106,12 @@ + '{{^show_slice}}{{#show_arrow}}
{{/show_arrow}}{{/show_slice}}' + '
' + '
' - + '

{{#show_title_field}}{{/show_title_field}}' + + '

{{#show_title_field}}{{/show_title_field}}' + '{{^show_title_field}}{{l10n.no_title}} {{/show_title_field}}' - + ' {{#show_slice}}{{l10n.from_time}} {{/show_slice}}{{^show_slice}}{{l10n.at_time}} {{/show_slice}} 00:00' + + ' {{#show_slice}}{{l10n.from_time}} {{/show_slice}}{{^show_slice}}{{l10n.at_time}} {{/show_slice}} 00:00' + '{{#show_slice}} {{l10n.to_time}} {{end}}{{/show_slice}}' - + '{{#show_creator_field}}{{l10n.your_name_}}

{{/show_creator_field}}' - + '' + + '{{#show_creator_field}}{{l10n.your_name_}}

{{/show_creator_field}}' + + '' + '
' + '' + '{{#show_mic_record}}
Add voice annotation
' @@ -261,12 +261,15 @@ IriSP.Widgets.CreateAnnotation.prototype.show = function() { this.visible = true; this.showScreen('Main'); - this.$.find(".Ldt-CreateAnnotation-Description").val("").css("border-color", "#666666"); + this.$.find(".Ldt-CreateAnnotation-Description").val("").css("border-color", "#666666").addClass("empty"); if (this.show_title_field) { - this.$.find(".Ldt-CreateAnnotation-Title").val("").css("border-color", "#666666"); + this.$.find(".Ldt-CreateAnnotation-Title").val("").css("border-color", "#666666").addClass("empty"); } if (this.show_creator_field) { this.$.find(".Ldt-CreateAnnotation-Creator").val(this.creator_name).css("border-color", "#666666"); + if (!this.creator_name) { + this.$.find(".Ldt-CreateAnnotation-Creator").addClass("empty"); + } } this.$.find(".Ldt-CreateAnnotation-TagLi, .Ldt-CreateAnnotation-PolemicLi").removeClass("selected"); this.$.slideDown(); @@ -320,6 +323,11 @@ var _field = this.$.find(".Ldt-CreateAnnotation-Description"), _contents = _field.val(); _field.css("border-color", !!_contents ? "#666666" : "#ff0000"); + if (!!_contents) { + _field.removeClass("empty"); + } else { + _field.addClass("empty"); + } this.$.find(".Ldt-CreateAnnotation-TagLi, .Ldt-CreateAnnotation-PolemicLi").each(function() { var _rx = IriSP.Model.regexpFromTextOrArray(IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,'')); if (_contents.match(_rx)) { @@ -336,6 +344,11 @@ var _field = this.$.find(".Ldt-CreateAnnotation-Title"), _contents = _field.val(); _field.css("border-color", !!_contents ? "#666666" : "#ff0000"); + if (!!_contents) { + _field.removeClass("empty"); + } else { + _field.addClass("empty"); + } this.pauseOnWrite(); return !!_contents; } @@ -345,6 +358,11 @@ var _field = this.$.find(".Ldt-CreateAnnotation-Creator"), _contents = _field.val(); _field.css("border-color", !!_contents ? "#666666" : "#ff0000"); + if (!!_contents) { + _field.removeClass("empty"); + } else { + _field.addClass("empty"); + } this.pauseOnWrite(); return !!_contents; } @@ -392,7 +410,6 @@ _annotation.description = this.$.find(".Ldt-CreateAnnotation-Description").val(); /* Champ description */ _annotation.setTags(this.$.find(".Ldt-CreateAnnotation-TagLi.selected") .map(function() { return IriSP.jQuery(this).attr("tag-id")})); /*Liste des ids de tags */ - if (this.audio_url) { _annotation.audio = { src: "mic", @@ -400,14 +417,11 @@ href: this.audio_url }; } - - /* Les données créateur/date de création sont envoyées non pas dans l'annotation, mais dans le projet */ if (this.show_creator_field) { - _export.creator = this.$.find(".Ldt-CreateAnnotation-Creator").val(); + _annotation.creator = this.$.find(".Ldt-CreateAnnotation-Creator").val(); } else { - _export.creator = this.creator_name; + _annotation.creator = this.creator_name; } - _export.created = new Date(); _exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */ _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */ @@ -425,7 +439,7 @@ function() { _this.close_after_send ? _this.hide() - : _this.showScreen("Main"); + : _this.show(); }, _this.after_send_timeout ); diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/JwpPlayer.js --- a/src/ldt/ldt/static/ldt/metadataplayer/JwpPlayer.js Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/JwpPlayer.js Mon Oct 29 12:04:20 2012 +0100 @@ -48,46 +48,47 @@ _pauseState = false; this.media.trigger("play"); } + // Binding functions to jwplayer - this.media.getCurrentTime = function() { - return new IriSP.Model.Time(1000*_player.getPosition() || 0); - } - this.media.getVolume = function() { - return _player.getVolume() / 100; - } - this.media.getPaused = function() { - return _pauseState; - } - this.media.getMuted = function() { - return _player.getMute(); - } - this.media.setCurrentTime = function(_milliseconds) { + var _media = this.media; + + _media.on("setcurrenttime", function(_milliseconds) { _seekPause = _pauseState; - return _player.seek(_milliseconds / 1000); - } - this.media.setVolume = function(_vol) { - return _player.setVolume(Math.floor(_vol*100)); - } - this.media.mute = function() { - return _player.setMute(true); - } - this.media.unmute = function() { - return _player.setMute(false); - } - this.media.play = function() { - return _player.play(true); - } - this.media.pause = function() { - return _player.pause(true); - } + _player.seek(_milliseconds / 1000); + }); + + _media.on("setvolume", function(_vol) { + _player.setVolume(Math.floor(_vol*100)); + _media.volume = _vol; + }); + + _media.on("setmuted", function(_muted) { + _player.setMute(_muted); + _media.muted = _muted; + }); + + _media.on("setplay", function() { + _player.play(true); + _media.paused = false; + }); + + _media.on("setpause", function() { + _player.pause(true); + _media.paused = true; + }); // Binding jwplater events to media - var _media = this.media; + function getVolume() { + _media.muted = _player.getMute(); + _media.volume = _player.getVolume() / 100; + } _opts.events = { onReady: function() { + getVolume(); + _media.currentTime = new IriSP.Model.Time(1000*_player.getPosition() || 0); _media.trigger("loadedmetadata"); }, onTime: function(_progress) { @@ -114,6 +115,14 @@ }, onSeek: function() { _media.trigger("seeked"); + }, + onMute: function(_event) { + _media.muted = _event.mute; + _media.trigger("volumechange"); + }, + onVolume: function(_event) { + _media.volume = _event.volume / 100; + _media.trigger("volumechange"); } } _player.setup(_opts); diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js --- a/src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js Mon Oct 29 12:04:20 2012 +0100 @@ -124,12 +124,12 @@ } IriSP.Metadataplayer.prototype.loadMetadata = function(_metadataInfo) { + if (_metadataInfo.elementType === "source") { + return _metadataInfo; + } if (typeof _metadataInfo.serializer === "undefined" && typeof _metadataInfo.format !== "undefined") { _metadataInfo.serializer = IriSP.serializers[_metadataInfo.format]; } - if (typeof _metadataInfo.url === "undefined" && typeof _metadataInfo.src !== "undefined") { - _metadataInfo.url = _metadataInfo.src; - } if (typeof _metadataInfo.url !== "undefined" && typeof _metadataInfo.serializer !== "undefined") { return this.sourceManager.remoteSource(_metadataInfo); } else { @@ -235,8 +235,9 @@ /* TODO: Separate Project-specific data from Source */ /* model.js is where data is stored in a standard form, whatever the serializer */ +IriSP.Model = (function (ns) { -IriSP.Model = { +var Model = { _SOURCE_STATUS_EMPTY : 0, _SOURCE_STATUS_WAITING : 1, _SOURCE_STATUS_READY : 2, @@ -262,20 +263,25 @@ } return "autoid-" + this._ID_BASE + '-' + _n; }, - regexpFromTextOrArray : function(_textOrArray, _testOnly) { - var _testOnly = _testOnly || false; + regexpFromTextOrArray : function(_textOrArray, _testOnly, _iexact) { + var _testOnly = _testOnly || false, + _iexact = _iexact || false; function escapeText(_text) { return _text.replace(/([\\\*\+\?\|\{\[\}\]\(\)\^\$\.\#\/])/gm, '\\$1'); } var _source = typeof _textOrArray === "string" ? escapeText(_textOrArray) - : IriSP._(_textOrArray).map(escapeText).join("|"); - if (_testOnly) { - return new RegExp( _source, 'im'); - } else { - return new RegExp( '(' + _source + ')', 'gim'); + : ns._(_textOrArray).map(escapeText).join("|"), + _flags = 'im'; + if (!_testOnly) { + _source = '(' + _source + ')'; + _flags += 'g'; } + if (_iexact) { + _source = '^' + _source + '$'; + } + return new RegExp( _source, _flags); }, isoToDate : function(_str) { // http://delete.me.uk/2005/03/iso8601.html @@ -314,83 +320,83 @@ } /* - * IriSP.Model.List is a class for a list of elements (e.g. annotations, medias, etc. that each have a distinct ID) + * Model.List is a class for a list of elements (e.g. annotations, medias, etc. that each have a distinct ID) */ -IriSP.Model.List = function(_directory) { +Model.List = function(_directory) { Array.call(this); this.directory = _directory; this.idIndex = []; this.__events = {}; if (typeof _directory == "undefined") { console.trace(); - throw "Error : new IriSP.Model.List(directory): directory is undefined"; + throw "Error : new Model.List(directory): directory is undefined"; } } -IriSP.Model.List.prototype = new Array(); +Model.List.prototype = new Array(); -IriSP.Model.List.prototype.hasId = function(_id) { - return IriSP._(this.idIndex).include(_id); +Model.List.prototype.hasId = function(_id) { + return ns._(this.idIndex).include(_id); } /* On recent browsers, forEach and map are defined and do what we want. * Otherwise, we'll use the Underscore.js functions */ if (typeof Array.prototype.forEach === "undefined") { - IriSP.Model.List.prototype.forEach = function(_callback) { + Model.List.prototype.forEach = function(_callback) { var _this = this; - IriSP._(this).forEach(function(_value, _key) { + ns._(this).forEach(function(_value, _key) { _callback(_value, _key, _this); }); } } if (typeof Array.prototype.map === "undefined") { - IriSP.Model.List.prototype.map = function(_callback) { + Model.List.prototype.map = function(_callback) { var _this = this; - return IriSP._(this).map(function(_value, _key) { + return ns._(this).map(function(_value, _key) { return _callback(_value, _key, _this); }); } } -IriSP.Model.List.prototype.pluck = function(_key) { +Model.List.prototype.pluck = function(_key) { return this.map(function(_value) { return _value[_key]; }); } -/* We override Array's filter function because it doesn't return an IriSP.Model.List +/* We override Array's filter function because it doesn't return an Model.List */ -IriSP.Model.List.prototype.filter = function(_callback) { +Model.List.prototype.filter = function(_callback) { var _this = this, - _res = new IriSP.Model.List(this.directory); - _res.addElements(IriSP._(this).filter(function(_value, _key) { + _res = new Model.List(this.directory); + _res.addElements(ns._(this).filter(function(_value, _key) { return _callback(_value, _key, _this); })); return _res; } -IriSP.Model.List.prototype.slice = function(_start, _end) { - var _res = new IriSP.Model.List(this.directory); +Model.List.prototype.slice = function(_start, _end) { + var _res = new Model.List(this.directory); _res.addElements(Array.prototype.slice.call(this, _start, _end)); return _res; } -IriSP.Model.List.prototype.splice = function(_start, _end) { - var _res = new IriSP.Model.List(this.directory); +Model.List.prototype.splice = function(_start, _end) { + var _res = new Model.List(this.directory); _res.addElements(Array.prototype.splice.call(this, _start, _end)); this.idIndex.splice(_start, _end); return _res; } /* Array has a sort function, but it's not as interesting as Underscore.js's sortBy - * and won't return a new IriSP.Model.List + * and won't return a new Model.List */ -IriSP.Model.List.prototype.sortBy = function(_callback) { +Model.List.prototype.sortBy = function(_callback) { var _this = this, - _res = new IriSP.Model.List(this.directory); - _res.addElements(IriSP._(this).sortBy(function(_value, _key) { + _res = new Model.List(this.directory); + _res.addElements(ns._(this).sortBy(function(_value, _key) { return _callback(_value, _key, _this); })); return _res; @@ -399,34 +405,37 @@ /* Title and Description are basic information for (almost) all element types, * here we can search by these criteria */ -IriSP.Model.List.prototype.searchByTitle = function(_text) { - var _rgxp = IriSP.Model.regexpFromTextOrArray(_text, true); +Model.List.prototype.searchByTitle = function(_text, _iexact) { + var _iexact = _iexact || false, + _rgxp = Model.regexpFromTextOrArray(_text, true); return this.filter(function(_element) { return _rgxp.test(_element.title); }); } -IriSP.Model.List.prototype.searchByDescription = function(_text) { - var _rgxp = IriSP.Model.regexpFromTextOrArray(_text, true); +Model.List.prototype.searchByDescription = function(_text, _iexact) { + var _iexact = _iexact || false, + _rgxp = Model.regexpFromTextOrArray(_text, true); return this.filter(function(_element) { return _rgxp.test(_element.description); }); } -IriSP.Model.List.prototype.searchByTextFields = function(_text) { - var _rgxp = IriSP.Model.regexpFromTextOrArray(_text, true); +Model.List.prototype.searchByTextFields = function(_text, _iexact) { + var _iexact = _iexact || false, + _rgxp = Model.regexpFromTextOrArray(_text, true); return this.filter(function(_element) { return _rgxp.test(_element.description) || _rgxp.test(_element.title); }); } -IriSP.Model.List.prototype.getTitles = function() { +Model.List.prototype.getTitles = function() { return this.map(function(_el) { return _el.title; }); } -IriSP.Model.List.prototype.addId = function(_id) { +Model.List.prototype.addId = function(_id) { var _el = this.directory.getElement(_id) if (!this.hasId(_id) && typeof _el !== "undefined") { this.idIndex.push(_id); @@ -434,11 +443,11 @@ } } -IriSP.Model.List.prototype.push = function(_el) { +Model.List.prototype.push = function(_el) { if (typeof _el === "undefined") { return; } - var _index = (IriSP._(this.idIndex).indexOf(_el.id)); + var _index = (ns._(this.idIndex).indexOf(_el.id)); if (_index === -1) { this.idIndex.push(_el.id); Array.prototype.push.call(this, _el); @@ -447,24 +456,24 @@ } } -IriSP.Model.List.prototype.addIds = function(_array) { +Model.List.prototype.addIds = function(_array) { var _l = _array.length, _this = this; - IriSP._(_array).forEach(function(_id) { + ns._(_array).forEach(function(_id) { _this.addId(_id); }); } -IriSP.Model.List.prototype.addElements = function(_array) { +Model.List.prototype.addElements = function(_array) { var _this = this; - IriSP._(_array).forEach(function(_el) { + ns._(_array).forEach(function(_el) { _this.push(_el); }); } -IriSP.Model.List.prototype.removeId = function(_id, _deleteFromDirectory) { +Model.List.prototype.removeId = function(_id, _deleteFromDirectory) { var _deleteFromDirectory = _deleteFromDirectory || false, - _index = (IriSP._(this.idIndex).indexOf(_id)); + _index = (ns._(this.idIndex).indexOf(_id)); if (_index !== -1) { this.splice(_index,1); } @@ -473,37 +482,45 @@ } } -IriSP.Model.List.prototype.removeElement = function(_el, _deleteFromDirectory) { +Model.List.prototype.removeElement = function(_el, _deleteFromDirectory) { var _deleteFromDirectory = _deleteFromDirectory || false; this.removeId(_el.id); } -IriSP.Model.List.prototype.removeIds = function(_list, _deleteFromDirectory) { +Model.List.prototype.removeIds = function(_list, _deleteFromDirectory) { var _deleteFromDirectory = _deleteFromDirectory || false, _this = this; - IriSP._(_list).forEach(function(_id) { + ns._(_list).forEach(function(_id) { _this.removeId(_id); }); } -IriSP.Model.List.prototype.removeElements = function(_list, _deleteFromDirectory) { +Model.List.prototype.removeElements = function(_list, _deleteFromDirectory) { var _deleteFromDirectory = _deleteFromDirectory || false, _this = this; - IriSP._(_list).forEach(function(_el) { + ns._(_list).forEach(function(_el) { _this.removeElement(_el); }); } -IriSP.Model.List.prototype.on = function(_event, _callback) { +Model.List.prototype.on = function(_event, _callback) { if (typeof this.__events[_event] === "undefined") { this.__events[_event] = []; } this.__events[_event].push(_callback); } -IriSP.Model.List.prototype.trigger = function(_event, _data) { +Model.List.prototype.off = function(_event, _callback) { + if (typeof this.__events[_event] !== "undefined") { + this.__events[_event] = ns._(this.__events[_event]).reject(function(_fn) { + return _fn === _callback; + }); + } +} + +Model.List.prototype.trigger = function(_event, _data) { var _list = this; - IriSP._(this.__events[_event]).each(function(_callback) { + ns._(this.__events[_event]).each(function(_callback) { _callback.call(_list, _data); }); } @@ -512,12 +529,12 @@ * without the clumsiness of the original Date object. */ -IriSP.Model.Time = function(_milliseconds) { +Model.Time = function(_milliseconds) { this.milliseconds = 0; this.setMilliseconds(_milliseconds); } -IriSP.Model.Time.prototype.setMilliseconds = function(_milliseconds) { +Model.Time.prototype.setMilliseconds = function(_milliseconds) { var _ante = _milliseconds; switch(typeof _milliseconds) { case "string": @@ -537,15 +554,15 @@ } } -IriSP.Model.Time.prototype.setSeconds = function(_seconds) { +Model.Time.prototype.setSeconds = function(_seconds) { this.milliseconds = 1000 * _seconds; } -IriSP.Model.Time.prototype.getSeconds = function() { +Model.Time.prototype.getSeconds = function() { return this.milliseconds / 1000; } -IriSP.Model.Time.prototype.getHMS = function() { +Model.Time.prototype.getHMS = function() { var _totalSeconds = Math.abs(Math.floor(this.getSeconds())); return { hours : Math.floor(_totalSeconds / 3600), @@ -554,15 +571,15 @@ } } -IriSP.Model.Time.prototype.add = function(_milliseconds) { - this.milliseconds += new IriSP.Model.Time(_milliseconds).milliseconds; +Model.Time.prototype.add = function(_milliseconds) { + this.milliseconds += new Model.Time(_milliseconds).milliseconds; } -IriSP.Model.Time.prototype.valueOf = function() { +Model.Time.prototype.valueOf = function() { return this.milliseconds; } -IriSP.Model.Time.prototype.toString = function() { +Model.Time.prototype.toString = function() { function pad(_n) { var _res = _n.toString(); while (_res.length < 2) { @@ -579,10 +596,10 @@ return _res; } -/* IriSP.Model.Reference handles references between elements +/* Model.Reference handles references between elements */ -IriSP.Model.Reference = function(_source, _idRef) { +Model.Reference = function(_source, _idRef) { this.source = _source; this.id = _idRef; if (typeof _idRef === "object") { @@ -593,9 +610,9 @@ this.refresh(); } -IriSP.Model.Reference.prototype.refresh = function() { +Model.Reference.prototype.refresh = function() { if (this.isList) { - this.contents = new IriSP.Model.List(this.source.directory); + this.contents = new Model.List(this.source.directory); this.contents.addIds(this.id); } else { this.contents = this.source.getElement(this.id); @@ -603,16 +620,16 @@ } -IriSP.Model.Reference.prototype.getContents = function() { +Model.Reference.prototype.getContents = function() { if (typeof this.contents === "undefined" || (this.isList && this.contents.length != this.id.length)) { this.refresh(); } return this.contents; } -IriSP.Model.Reference.prototype.isOrHasId = function(_idRef) { +Model.Reference.prototype.isOrHasId = function(_idRef) { if (this.isList) { - return (IriSP._(this.id).indexOf(_idRef) !== -1) + return (ns._(this.id).indexOf(_idRef) !== -1) } else { return (this.id == _idRef); } @@ -620,13 +637,13 @@ /* */ -IriSP.Model.Element = function(_id, _source) { +Model.Element = function(_id, _source) { this.elementType = 'element'; if (typeof _source === "undefined") { return; } if (typeof _id === "undefined" || !_id) { - _id = IriSP.Model.getUID(); + _id = Model.getUID(); } this.source = _source; this.id = _id; @@ -636,50 +653,122 @@ this.source.directory.addElement(this); } -IriSP.Model.Element.prototype.toString = function() { +Model.Element.prototype.toString = function() { return this.elementType + (this.elementType !== 'element' ? ', id=' + this.id + ', title="' + this.title + '"' : ''); } -IriSP.Model.Element.prototype.setReference = function(_elementType, _idRef) { - this[_elementType] = new IriSP.Model.Reference(this.source, _idRef); +Model.Element.prototype.setReference = function(_elementType, _idRef) { + this[_elementType] = new Model.Reference(this.source, _idRef); } -IriSP.Model.Element.prototype.getReference = function(_elementType) { +Model.Element.prototype.getReference = function(_elementType) { if (typeof this[_elementType] !== "undefined") { return this[_elementType].getContents(); } } -IriSP.Model.Element.prototype.getRelated = function(_elementType, _global) { +Model.Element.prototype.getRelated = function(_elementType, _global) { _global = (typeof _global !== "undefined" && _global); var _this = this; return this.source.getList(_elementType, _global).filter(function(_el) { var _ref = _el[_this.elementType]; - return _ref.isOrHasId(_this.id); + return _ref && _ref.isOrHasId(_this.id); }); } -IriSP.Model.Element.prototype.on = function(_event, _callback) { +Model.Element.prototype.on = function(_event, _callback) { if (typeof this.__events[_event] === "undefined") { this.__events[_event] = []; } this.__events[_event].push(_callback); } -IriSP.Model.Element.prototype.trigger = function(_event, _data) { +Model.Element.prototype.off = function(_event, _callback) { + if (typeof this.__events[_event] !== "undefined") { + this.__events[_event] = ns._(this.__events[_event]).reject(function(_fn) { + return _fn === _callback; + }); + } +} + +Model.Element.prototype.trigger = function(_event, _data) { var _element = this; - IriSP._(this.__events[_event]).each(function(_callback) { + ns._(this.__events[_event]).each(function(_callback) { _callback.call(_element, _data); }); } /* */ -IriSP.Model.Media = function(_id, _source) { - IriSP.Model.Element.call(this, _id, _source); +Model.Playable = function(_id, _source) { + Model.Element.call(this, _id, _source); + if (typeof _source === "undefined") { + return; + } + this.elementType = 'playable'; + this.currentTime = new Model.Time(); + this.volume = .5; + this.paused = true; + this.muted = false; + var _this = this; + this.on("play", function() { + _this.paused = false; + }); + this.on("pause", function() { + _this.paused = true; + }); + this.on("timeupdate", function(_time) { + _this.currentTime = _time; + }); +} + +Model.Playable.prototype = new Model.Element(); + +Model.Playable.prototype.getCurrentTime = function() { + return this.currentTime; +} + +Model.Playable.prototype.getVolume = function() { + return this.volume; +} + +Model.Playable.prototype.getPaused = function() { + return this.paused; +} + +Model.Playable.prototype.getMuted = function() { + return this.muted; +} + +Model.Playable.prototype.setCurrentTime = function(_time) { + this.trigger("setcurrenttime",_time); +} + +Model.Playable.prototype.setVolume = function(_vol) { + this.trigger("setvolume",_vol); +} + +Model.Playable.prototype.setMuted = function(_muted) { + this.trigger("setmuted",_muted); +} + +Model.Playable.prototype.play = function() { + this.trigger("setplay"); +} + +Model.Playable.prototype.pause = function() { + this.trigger("setpause"); +} + + +/* */ + +Model.Media = function(_id, _source) { + Model.Playable.call(this, _id, _source); this.elementType = 'media'; - this.duration = new IriSP.Model.Time(); + this.duration = new Model.Time(); this.video = ''; + var _this = this; this.on("timeupdate", function(_time) { _this.getAnnotations().filter(function(_a) { @@ -697,78 +786,63 @@ }); } -IriSP.Model.Media.prototype = new IriSP.Model.Element(); +Model.Media.prototype = new Model.Playable(); /* Default functions to be overriden by players */ - -IriSP.Model.Media.prototype.getCurrentTime = function() { return new IriSP.Model.Time(0); } - -IriSP.Model.Media.prototype.getVolume = function() { return .5; } - -IriSP.Model.Media.prototype.getPaused = function() { return true; } - -IriSP.Model.Media.prototype.getMuted = function() { return false; } - -IriSP.Model.Media.prototype.setCurrentTime - = IriSP.Model.Media.prototype.setVolume - = IriSP.Model.Media.prototype.setMuted - = IriSP.Model.Media.prototype.play - = IriSP.Model.Media.prototype.pause - = function() {} -IriSP.Model.Media.prototype.setDuration = function(_durationMs) { +Model.Media.prototype.setDuration = function(_durationMs) { this.duration.setMilliseconds(_durationMs); } -IriSP.Model.Media.prototype.getAnnotations = function() { +Model.Media.prototype.getAnnotations = function() { return this.getRelated("annotation"); } -IriSP.Model.Media.prototype.getAnnotationsByTypeTitle = function(_title) { +Model.Media.prototype.getAnnotationsByTypeTitle = function(_title) { var _annTypes = this.source.getAnnotationTypes().searchByTitle(_title).pluck("id"); if (_annTypes.length) { return this.getAnnotations().filter(function(_annotation) { - return IriSP._(_annTypes).indexOf(_annotation.getAnnotationType().id) !== -1; + return ns._(_annTypes).indexOf(_annotation.getAnnotationType().id) !== -1; }); } else { - return new IriSP.Model.List(this.source.directory) + return new Model.List(this.source.directory) } } /* */ -IriSP.Model.Tag = function(_id, _source) { - IriSP.Model.Element.call(this, _id, _source); +Model.Tag = function(_id, _source) { + Model.Element.call(this, _id, _source); this.elementType = 'tag'; } -IriSP.Model.Tag.prototype = new IriSP.Model.Element(); +Model.Tag.prototype = new Model.Element(); -IriSP.Model.Tag.prototype.getAnnotations = function() { +Model.Tag.prototype.getAnnotations = function() { return this.getRelated("annotation"); } /* */ - -IriSP.Model.AnnotationType = function(_id, _source) { - IriSP.Model.Element.call(this, _id, _source); +Model.AnnotationType = function(_id, _source) { + Model.Element.call(this, _id, _source); this.elementType = 'annotationType'; } -IriSP.Model.AnnotationType.prototype = new IriSP.Model.Element(); +Model.AnnotationType.prototype = new Model.Element(); -IriSP.Model.AnnotationType.prototype.getAnnotations = function() { +Model.AnnotationType.prototype.getAnnotations = function() { return this.getRelated("annotation"); } /* Annotation * */ -IriSP.Model.Annotation = function(_id, _source) { - IriSP.Model.Element.call(this, _id, _source); +Model.Annotation = function(_id, _source) { + Model.Element.call(this, _id, _source); this.elementType = 'annotation'; - this.begin = new IriSP.Model.Time(); - this.end = new IriSP.Model.Time(); + this.begin = new Model.Time(); + this.end = new Model.Time(); + this.tag = new Model.Reference(_source, []); this.playing = false; var _this = this; this.on("click", function() { @@ -776,56 +850,56 @@ }); } -IriSP.Model.Annotation.prototype = new IriSP.Model.Element(null); +Model.Annotation.prototype = new Model.Element(); -IriSP.Model.Annotation.prototype.setBegin = function(_beginMs) { +Model.Annotation.prototype.setBegin = function(_beginMs) { this.begin.setMilliseconds(_beginMs); } -IriSP.Model.Annotation.prototype.setEnd = function(_beginMs) { +Model.Annotation.prototype.setEnd = function(_beginMs) { this.end.setMilliseconds(_beginMs); } -IriSP.Model.Annotation.prototype.setMedia = function(_idRef) { +Model.Annotation.prototype.setMedia = function(_idRef) { this.setReference("media", _idRef); } -IriSP.Model.Annotation.prototype.getMedia = function() { +Model.Annotation.prototype.getMedia = function() { return this.getReference("media"); } -IriSP.Model.Annotation.prototype.setAnnotationType = function(_idRef) { +Model.Annotation.prototype.setAnnotationType = function(_idRef) { this.setReference("annotationType", _idRef); } -IriSP.Model.Annotation.prototype.getAnnotationType = function() { +Model.Annotation.prototype.getAnnotationType = function() { return this.getReference("annotationType"); } -IriSP.Model.Annotation.prototype.setTags = function(_idRefs) { +Model.Annotation.prototype.setTags = function(_idRefs) { this.setReference("tag", _idRefs); } -IriSP.Model.Annotation.prototype.getTags = function() { +Model.Annotation.prototype.getTags = function() { return this.getReference("tag"); } -IriSP.Model.Annotation.prototype.getTagTexts = function() { +Model.Annotation.prototype.getTagTexts = function() { return this.getTags().getTitles(); } -IriSP.Model.Annotation.prototype.getDuration = function() { - return new IriSP.Model.Time(this.end.milliseconds - this.begin.milliseconds) +Model.Annotation.prototype.getDuration = function() { + return new Model.Time(this.end.milliseconds - this.begin.milliseconds) } /* */ -IriSP.Model.MashedAnnotation = function(_mashup, _annotation) { - IriSP.Model.Element.call(this, _mashup.id + "_" + _annotation.id, _annotation.source); +Model.MashedAnnotation = function(_mashup, _annotation) { + Model.Element.call(this, _mashup.id + "_" + _annotation.id, _annotation.source); this.elementType = 'mashedAnnotation'; this.annotation = _annotation; - this.begin = new IriSP.Model.Time(_mashup.duration); - this.end = new IriSP.Model.Time(_mashup.duration + _annotation.getDuration()); + this.begin = new Model.Time(_mashup.duration); + this.end = new Model.Time(_mashup.duration + _annotation.getDuration()); this.title = this.annotation.title; this.description = this.annotation.description; this.color = this.annotation.color; @@ -835,36 +909,36 @@ }); } -IriSP.Model.MashedAnnotation.prototype = new IriSP.Model.Element(null); +Model.MashedAnnotation.prototype = new Model.Element(null); -IriSP.Model.MashedAnnotation.prototype.getMedia = function() { +Model.MashedAnnotation.prototype.getMedia = function() { return this.annotation.getReference("media"); } -IriSP.Model.MashedAnnotation.prototype.getAnnotationType = function() { +Model.MashedAnnotation.prototype.getAnnotationType = function() { return this.annotation.getReference("annotationType"); } -IriSP.Model.MashedAnnotation.prototype.getTags = function() { +Model.MashedAnnotation.prototype.getTags = function() { return this.annotation.getReference("tag"); } -IriSP.Model.MashedAnnotation.prototype.getTagTexts = function() { +Model.MashedAnnotation.prototype.getTagTexts = function() { return this.annotation.getTags().getTitles(); } -IriSP.Model.MashedAnnotation.prototype.getDuration = function() { +Model.MashedAnnotation.prototype.getDuration = function() { return this.annotation.getDuration(); } /* */ -IriSP.Model.Mashup = function(_id, _source) { - IriSP.Model.Element.call(this, _id, _source); +Model.Mashup = function(_id, _source) { + Model.Playable.call(this, _id, _source); this.elementType = 'mashup'; - this.duration = new IriSP.Model.Time(); - this.segments = new IriSP.Model.List(_source.directory); - this.medias = new IriSP.Model.List(_source.directory); + this.duration = new Model.Time(); + this.segments = new Model.List(_source.directory); + this.medias = new Model.List(_source.directory); var _currentMedia = null; var _this = this; this.on("timeupdate", function(_time) { @@ -891,42 +965,42 @@ }); } -IriSP.Model.Mashup.prototype = new IriSP.Model.Element(); +Model.Mashup.prototype = new Model.Playable(); -IriSP.Model.Mashup.prototype.addSegment = function(_annotation) { - var _mashedAnnotation = new IriSP.Model.MashedAnnotation(this, _annotation); +Model.Mashup.prototype.addSegment = function(_annotation) { + var _mashedAnnotation = new Model.MashedAnnotation(this, _annotation); this.duration.setMilliseconds(_mashedAnnotation.end); this.segments.push(_mashedAnnotation); this.medias.push(_annotation.getMedia()); } -IriSP.Model.Mashup.prototype.addSegmentById = function(_elId) { +Model.Mashup.prototype.addSegmentById = function(_elId) { var _annotation = this.source.getElement(_elId); if (typeof _annotation !== "undefined") { this.addSegment(_annotation); } } -IriSP.Model.Mashup.prototype.getAnnotations = function() { +Model.Mashup.prototype.getAnnotations = function() { return this.segments; } -IriSP.Model.Mashup.prototype.getMedias = function() { +Model.Mashup.prototype.getMedias = function() { return this.medias; } -IriSP.Model.Mashup.prototype.getAnnotationsByTypeTitle = function(_title) { +Model.Mashup.prototype.getAnnotationsByTypeTitle = function(_title) { var _annTypes = this.source.getAnnotationTypes().searchByTitle(_title).pluck("id"); if (_annTypes.length) { return this.getAnnotations().filter(function(_annotation) { - return IriSP._(_annTypes).indexOf(_annotation.getAnnotationType().id) !== -1; + return ns._(_annTypes).indexOf(_annotation.getAnnotationType().id) !== -1; }); } else { - return new IriSP.Model.List(this.source.directory) + return new Model.List(this.source.directory) } } -IriSP.Model.Mashup.prototype.getAnnotationAtTime = function(_time) { +Model.Mashup.prototype.getAnnotationAtTime = function(_time) { var _list = this.segments.filter(function(_annotation) { return _annotation.begin <= _time && _annotation.end > _time; }); @@ -937,7 +1011,7 @@ } } -IriSP.Model.Mashup.prototype.getMediaAtTime = function(_time) { +Model.Mashup.prototype.getMediaAtTime = function(_time) { var _annotation = this.getAnnotationAtTime(_time); if (typeof _annotation !== "undefined") { return _annotation.getMedia(); @@ -946,30 +1020,14 @@ } } -/* Default functions to be overriden by players */ - -IriSP.Model.Mashup.prototype.getCurrentTime = function() { return new IriSP.Model.Time(0); } - -IriSP.Model.Mashup.prototype.getVolume = function() { return .5; } - -IriSP.Model.Mashup.prototype.getPaused = function() { return true; } - -IriSP.Model.Mashup.prototype.getMuted = function() { return false; } - -IriSP.Model.Mashup.prototype.setCurrentTime - = IriSP.Model.Mashup.prototype.setVolume - = IriSP.Model.Mashup.prototype.setMuted - = IriSP.Model.Mashup.prototype.play - = IriSP.Model.Mashup.prototype.pause - = function() {} - /* */ -IriSP.Model.Source = function(_config) { - this.status = IriSP.Model._SOURCE_STATUS_EMPTY; +Model.Source = function(_config) { + this.status = Model._SOURCE_STATUS_EMPTY; + this.elementType = "source"; if (typeof _config !== "undefined") { var _this = this; - IriSP._(_config).forEach(function(_v, _k) { + ns._(_config).forEach(function(_v, _k) { _this[_k] = _v; }) this.callbackQueue = []; @@ -978,14 +1036,16 @@ } } -IriSP.Model.Source.prototype.addList = function(_listId, _contents) { +Model.Source.prototype = new Model.Element(); + +Model.Source.prototype.addList = function(_listId, _contents) { if (typeof this.contents[_listId] === "undefined") { - this.contents[_listId] = new IriSP.Model.List(this.directory); + this.contents[_listId] = new Model.List(this.directory); } this.contents[_listId].addElements(_contents); } -IriSP.Model.Source.prototype.getList = function(_listId, _global) { +Model.Source.prototype.getList = function(_listId, _global) { _global = (typeof _global !== "undefined" && _global); if (_global || typeof this.contents[_listId] === "undefined") { return this.directory.getGlobalList().filter(function(_e) { @@ -996,80 +1056,80 @@ } } -IriSP.Model.Source.prototype.forEach = function(_callback) { +Model.Source.prototype.forEach = function(_callback) { var _this = this; - IriSP._(this.contents).forEach(function(_value, _key) { + ns._(this.contents).forEach(function(_value, _key) { _callback.call(_this, _value, _key); }) } -IriSP.Model.Source.prototype.getElement = function(_elId) { +Model.Source.prototype.getElement = function(_elId) { return this.directory.getElement(_elId); } -IriSP.Model.Source.prototype.get = function() { - this.status = IriSP.Model._SOURCE_STATUS_WAITING; +Model.Source.prototype.get = function() { + this.status = Model._SOURCE_STATUS_WAITING; this.handleCallbacks(); } /* We defer the callbacks calls so they execute after the queue is cleared */ -IriSP.Model.Source.prototype.deferCallback = function(_callback) { +Model.Source.prototype.deferCallback = function(_callback) { var _this = this; - IriSP._.defer(function() { + ns._.defer(function() { _callback.call(_this); }); } -IriSP.Model.Source.prototype.handleCallbacks = function() { - this.status = IriSP.Model._SOURCE_STATUS_READY; +Model.Source.prototype.handleCallbacks = function() { + this.status = Model._SOURCE_STATUS_READY; while (this.callbackQueue.length) { this.deferCallback(this.callbackQueue.splice(0,1)[0]); } } -IriSP.Model.Source.prototype.onLoad = function(_callback) { - if (this.status === IriSP.Model._SOURCE_STATUS_READY) { +Model.Source.prototype.onLoad = function(_callback) { + if (this.status === Model._SOURCE_STATUS_READY) { this.deferCallback(_callback); } else { this.callbackQueue.push(_callback); } } -IriSP.Model.Source.prototype.serialize = function() { +Model.Source.prototype.serialize = function() { return this.serializer.serialize(this); } -IriSP.Model.Source.prototype.deSerialize = function(_data) { +Model.Source.prototype.deSerialize = function(_data) { this.serializer.deSerialize(_data, this); } -IriSP.Model.Source.prototype.getAnnotations = function(_global) { +Model.Source.prototype.getAnnotations = function(_global) { _global = (typeof _global !== "undefined" && _global); return this.getList("annotation", _global); } -IriSP.Model.Source.prototype.getMedias = function(_global) { +Model.Source.prototype.getMedias = function(_global) { _global = (typeof _global !== "undefined" && _global); return this.getList("media", _global); } -IriSP.Model.Source.prototype.getTags = function(_global) { +Model.Source.prototype.getTags = function(_global) { _global = (typeof _global !== "undefined" && _global); return this.getList("tag", _global); } -IriSP.Model.Source.prototype.getMashups = function(_global) { +Model.Source.prototype.getMashups = function(_global) { _global = (typeof _global !== "undefined" && _global); return this.getList("mashup", _global); } -IriSP.Model.Source.prototype.getAnnotationTypes = function(_global) { +Model.Source.prototype.getAnnotationTypes = function(_global) { _global = (typeof _global !== "undefined" && _global); return this.getList("annotationType", _global); } -IriSP.Model.Source.prototype.getAnnotationsByTypeTitle = function(_title, _global) { +Model.Source.prototype.getAnnotationsByTypeTitle = function(_title, _global) { _global = (typeof _global !== "undefined" && _global); - var _res = new IriSP.Model.List(this.directory), + var _res = new Model.List(this.directory), _annTypes = this.getAnnotationTypes(_global).searchByTitle(_title); _annTypes.forEach(function(_annType) { _res.addElements(_annType.getAnnotations(_global)); @@ -1077,14 +1137,14 @@ return _res; } -IriSP.Model.Source.prototype.getDuration = function() { +Model.Source.prototype.getDuration = function() { var _m = this.currentMedia; if (typeof _m !== "undefined") { return this.currentMedia.duration; } } -IriSP.Model.Source.prototype.getCurrentMedia = function(_opts) { +Model.Source.prototype.getCurrentMedia = function(_opts) { if (typeof this.currentMedia === "undefined") { if (_opts.is_mashup) { var _mashups = this.getMashups(); @@ -1094,14 +1154,14 @@ } else { var _medias = this.getMedias(); if (_medias.length) { - _media = _medias[0]; + this.currentMedia = _medias[0]; } } } return this.currentMedia; } -IriSP.Model.Source.prototype.merge = function(_source) { +Model.Source.prototype.merge = function(_source) { var _this = this; _source.forEach(function(_value, _key) { _this.getList(_key).addElements(_value); @@ -1110,14 +1170,14 @@ /* */ -IriSP.Model.RemoteSource = function(_config) { - IriSP.Model.Source.call(this, _config); +Model.RemoteSource = function(_config) { + Model.Source.call(this, _config); } -IriSP.Model.RemoteSource.prototype = new IriSP.Model.Source(); +Model.RemoteSource.prototype = new Model.Source(); -IriSP.Model.RemoteSource.prototype.get = function() { - this.status = IriSP.Model._SOURCE_STATUS_WAITING; +Model.RemoteSource.prototype.get = function() { + this.status = Model._SOURCE_STATUS_WAITING; var _this = this; this.serializer.loadData(this.url, function(_result) { _this.deSerialize(_result); @@ -1127,43 +1187,45 @@ /* */ -IriSP.Model.Directory = function() { +Model.Directory = function() { this.remoteSources = {}; this.elements = {}; } -IriSP.Model.Directory.prototype.remoteSource = function(_properties) { +Model.Directory.prototype.remoteSource = function(_properties) { if (typeof _properties !== "object" || typeof _properties.url === "undefined") { - throw "Error : IriSP.Model.Directory.remoteSource(configuration): configuration.url is undefined"; + throw "Error : Model.Directory.remoteSource(configuration): configuration.url is undefined"; } - var _config = IriSP._({ directory: this }).extend(_properties); + var _config = ns._({ directory: this }).extend(_properties); if (typeof this.remoteSources[_properties.url] === "undefined") { - this.remoteSources[_properties.url] = new IriSP.Model.RemoteSource(_config); + this.remoteSources[_properties.url] = new Model.RemoteSource(_config); } return this.remoteSources[_properties.url]; } -IriSP.Model.Directory.prototype.newLocalSource = function(_properties) { - var _config = IriSP._({ directory: this }).extend(_properties), - _res = new IriSP.Model.Source(_config); +Model.Directory.prototype.newLocalSource = function(_properties) { + var _config = ns._({ directory: this }).extend(_properties), + _res = new Model.Source(_config); return _res; } -IriSP.Model.Directory.prototype.getElement = function(_id) { +Model.Directory.prototype.getElement = function(_id) { return this.elements[_id]; } -IriSP.Model.Directory.prototype.addElement = function(_element) { +Model.Directory.prototype.addElement = function(_element) { this.elements[_element.id] = _element; } -IriSP.Model.Directory.prototype.getGlobalList = function() { - var _res = new IriSP.Model.List(this); - _res.addIds(IriSP._(this.elements).keys()); +Model.Directory.prototype.getGlobalList = function() { + var _res = new Model.List(this); + _res.addIds(ns._(this.elements).keys()); return _res; } -/* */ +return Model; + +})(IriSP); IriSP.language = 'en'; IriSP.libFiles = { @@ -1225,9 +1287,6 @@ AutoPlayer: { noCss: true }, - MashupPlayer: { - noCss: true - }, AnnotationsList: { requires: [ "jwplayer" ] }, @@ -1649,67 +1708,59 @@ } IriSP.serializers.ldt_annotate = { - types : { - annotation : { - serialized_name : "annotations", - serializer : function(_data, _source) { - var _annType = _data.getAnnotationType(); - return { - begin: _data.begin.milliseconds, - end: _data.end.milliseconds, - content: { - data: _data.description, - audio: _data.audio - }, - tags: _data.getTagTexts(), - media: _data.getMedia().id, - type_title: _annType.title, - type: ( typeof _annType.dont_send_id !== "undefined" && _annType.dont_send_id ? "" : _annType.id ) - } + serializeAnnotation : function(_data, _source) { + var _annType = _data.getAnnotationType(); + return { + begin: _data.begin.milliseconds, + end: _data.end.milliseconds, + content: { + description: _data.description, + title: _data.title, + audio: _data.audio + }, + tags: _data.getTagTexts(), + media: _data.getMedia().id, + type_title: _annType.title, + type: ( typeof _annType.dont_send_id !== "undefined" && _annType.dont_send_id ? "" : _annType.id ), + meta: { + created: _data.created, + creator: _data.creator } } }, serialize : function(_source) { - var _res = {}, - _this = this; - _source.forEach(function(_list, _typename) { - if (typeof _this.types[_typename] !== "undefined") { - _res[_this.types[_typename].serialized_name] = _list.map(function(_el) { - return _this.types[_typename].serializer(_el, _source); - }); - } - }); - _res.meta = { - creator: _source.creator, - created: _source.created - } + var _this = this + _res = { + "objects": _source.getAnnotations().map(function(_annotation) { + return _this.serializeAnnotation(_annotation, _source); + }) + }; return JSON.stringify(_res); }, deSerialize : function(_data, _source) { if (typeof _data == "string") { _data = JSON.parse(_data); } + _source.addList('tag', new IriSP.Model.List(_source.directory)); _source.addList('annotationType', new IriSP.Model.List(_source.directory)); _source.addList('annotation', new IriSP.Model.List(_source.directory)); - if (typeof _data.annotations == "object" && _data.annotations && _data.annotations.length) { - var _anndata = _data.annotations[0], - _ann = new IriSP.Model.Annotation(_anndata.id, _source); - _ann.description = _anndata.content.data || ""; - _ann.title = _data.creator || ""; - _ann.created = new Date(_data.meta.created); + IriSP._(_data.objects).each(function(_anndata) { + var _ann = new IriSP.Model.Annotation(_anndata.id, _source); + _ann.description = _anndata.content.description || ""; + _ann.title = _anndata.content.title || ""; + _ann.creator = _anndata.meta.creator || ""; + _ann.created = new Date(_anndata.meta.created); _ann.setMedia(_anndata.media, _source); - var _anntypes = _source.getAnnotationTypes(true).searchByTitle(_anndata.type_title); - if (_anntypes.length) { - var _anntype = _anntypes[0]; - } else { - var _anntype = new IriSP.Model.AnnotationType(_anndata.type, _source); + var _anntype = _source.getElement(_anndata.type); + if (!_anntype) { + _anntype = new IriSP.Model.AnnotationType(_anndata.type, _source); _anntype.title = _anndata.type_title; _source.getAnnotationTypes().push(_anntype); } _ann.setAnnotationType(_anntype.id); var _tagIds = IriSP._(_anndata.tags).map(function(_title) { - var _tags = _source.getTags(true).searchByTitle(_title); + var _tags = _source.getTags(true).searchByTitle(_title, true); if (_tags.length) { var _tag = _tags[0]; } @@ -1723,11 +1774,10 @@ _ann.setTags(_tagIds); _ann.setBegin(_anndata.begin); _ann.setEnd(_anndata.end); - _ann.creator = _data.meta.creator; if (typeof _anndata.content.audio !== "undefined" && _anndata.content.audio.href) { _ann.audio = _anndata.content.audio; } _source.getAnnotations().push(_ann); - } + }); } } \ No newline at end of file diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/PopcornPlayer.js --- a/src/ldt/ldt/static/ldt/metadataplayer/PopcornPlayer.js Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/PopcornPlayer.js Mon Oct 29 12:04:20 2012 +0100 @@ -83,57 +83,64 @@ } } - + var _media = this.media; + // Binding functions to Popcorn - this.media.getCurrentTime = function() { - return new IriSP.Model.Time(1000*_popcorn.currentTime()); - } - this.media.getVolume = function() { - return _popcorn.volume(); - } - this.media.getPaused = function() { - return _popcorn.media.paused; - } - this.media.getMuted = function() { - return _popcorn.muted(); - } - this.media.setCurrentTime = function(_milliseconds) { - return _popcorn.currentTime(_milliseconds / 1000); - } - this.media.setVolume = function(_vol) { - return _popcorn.volume(_vol); - } - this.media.mute = function() { - return _popcorn.muted(true); - } - this.media.unmute = function() { - return _popcorn.muted(false); - } - this.media.play = function() { - return _popcorn.play(); - } - this.media.pause = function() { - return _popcorn.pause(); - } + _media.on("setcurrenttime", function(_milliseconds) { + _popcorn.currentTime(_milliseconds / 1000); + }); + + _media.on("setvolume", function(_vol) { + _popcorn.volume(_vol); + _media.volume = _vol; + }); + + _media.on("setmuted", function(_muted) { + _popcorn.muted(_muted); + _media.muted = _muted; + }); + + _media.on("setplay", function() { + _popcorn.play(); + }); + + _media.on("setpause", function() { + _popcorn.pause(); + }); // Binding Popcorn events to media - var _media = this.media; + function getVolume() { + _media.muted = _popcorn.muted(); + _media.volume = _popcorn.volume(); + } + + _popcorn.on("loadedmetadata", function() { + getVolume(); + _media.trigger("loadedmetadata"); + _media.trigger("volumechange"); + }) + _popcorn.on("timeupdate", function() { - _media.trigger("timeupdate", _media.getCurrentTime()); + _media.trigger("timeupdate", new IriSP.Model.Time(1000*_popcorn.currentTime())); }); - function simpleEventBind(_eventname) { - _popcorn.on(_eventname, function() { - _media.trigger(_eventname); - }); - } + _popcorn.on("volumechange", function() { + getVolume(); + _media.trigger("volumechange"); + }) - simpleEventBind("play"); - simpleEventBind("pause"); - simpleEventBind("seeked"); - simpleEventBind("loadedmetadata"); - simpleEventBind("volumechange"); + _popcorn.on("play", function() { + _media.trigger("play"); + }); + + _popcorn.on("pause", function() { + _media.trigger("pause"); + }); + + _popcorn.on("seeked", function() { + _media.trigger("seeked"); + }); } \ No newline at end of file diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/Slice.js --- a/src/ldt/ldt/static/ldt/metadataplayer/Slice.js Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/Slice.js Mon Oct 29 12:04:20 2012 +0100 @@ -48,7 +48,7 @@ }, start: function() { _this.sliding = true; - if (!_this.media.getPaused) { + if (!_this.media.getPaused()) { _this.media.pause(); } _currentTime = _this.media.getCurrentTime(); diff -r dd8fe34c5abe -r 9eae65727f54 src/ldt/ldt/static/ldt/metadataplayer/Slider.css --- a/src/ldt/ldt/static/ldt/metadataplayer/Slider.css Sun Oct 21 22:48:17 2012 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/Slider.css Mon Oct 29 12:04:20 2012 +0100 @@ -14,6 +14,6 @@ .Ldt-Slider-Time { position: absolute; top: -16px; background: #ffffc0; color: #000000; border-radius: 3px; z-index: 8; - font-size: 9px; width: 34px; border: 1px solid #999999; padding: 1px; margin-left: -20px; + font-size: 10px; width: 34px; border: 1px solid #999999; padding: 1px; margin-left: -20px; display: none; text-align: center; font-weight: bold; } diff -r dd8fe34c5abe -r 9eae65727f54 virtualenv/res/lib/lib_create_env.py --- a/virtualenv/res/lib/lib_create_env.py Sun Oct 21 22:48:17 2012 +0200 +++ b/virtualenv/res/lib/lib_create_env.py Mon Oct 29 12:04:20 2012 +0100 @@ -21,7 +21,6 @@ 'DJANGO-EXTENSIONS': { 'setup': 'django-extensions', 'url':'https://github.com/django-extensions/django-extensions/tarball/0.8', 'local':"django-extensions-0.8.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'DJANGO-REGISTRATION': { 'setup': 'django-registration', 'url':'https://bitbucket.org/ubernostrum/django-registration/get/v0.8.tar.gz', 'local':"django-registration-0.8.tar.gz", 'install': {'method': 'easy_install', 'option_str': '-Z', 'dict_extra_env': None}}, 'DJANGO-TAGGING': { 'setup': 'django-tagging', 'url':'http://django-tagging.googlecode.com/files/django-tagging-0.3.1.tar.gz', 'local':"django-tagging-0.3.1.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, - 'DJANGO-PISTON': { 'setup': 'django-piston', 'url':'django-piston-7c90898072ce-modifed.tar.gz', 'local':'django-piston-7c90898072ce-modifed.tar.gz', 'install': {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}}, 'OAUTH2': { 'setup': 'python-oauth2', 'url':"https://github.com/simplegeo/python-oauth2/tarball/hudson-python-oauth2-211", 'local':"oauth2-1.5.211.tar.gz", 'install': {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}}, 'HTTPLIB2': { 'setup': 'python-httplib2', 'url':'http://code.google.com/p/httplib2/downloads/detail?name=httplib2-0.7.4.tar.gz&can=2&q=', 'local':"httplib2-0.7.4.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'DJANGO-OAUTH-PLUS': { 'setup': 'django-oauth-plus', 'url':'http://pypi.python.org/packages/source/d/django-oauth-plus/django-oauth-plus-2.0.tar.gz', 'local':"django-oauth-plus-2.0.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, @@ -43,6 +42,12 @@ 'WHOOSH': {'setup': 'whoosh', 'url':'https://bitbucket.org/mchaput/whoosh/get/tip.tar.gz', 'local':'whoosh-2.5.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'SETUPTOOLS_HG' : {'setup':'setuptools_hg', 'url':'http://pypi.python.org/packages/source/s/setuptools_hg/setuptools_hg-0.4.tar.gz', 'local': 'setuptools_hg-0.4.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'WSGIREF' : {'setup':'wsgiref', 'url':'http://pypi.python.org/packages/source/w/wsgiref/wsgiref-0.1.2.zip', 'local': 'wsgiref-0.1.2.zip', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + # dependencies for Tastypie : mimeparse>=0.1.3, python-dateutil>=2.1, lxml, PyYAML (not necessary but we never know), python-digest + 'MIMEPARSE' : {'setup':'mimeparse', 'url':'http://pypi.python.org/packages/source/m/mimeparse/mimeparse-0.1.3.tar.gz', 'local': 'mimeparse-0.1.3.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'PYTHON-DATEUTIL' : {'setup':'python-dateutil', 'url':'http://pypi.python.org/packages/source/p/python-dateutil/python-dateutil-2.1.tar.gz', 'local': 'python-dateutil-2.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'PYYAML' : {'setup':'pyyaml', 'url':'http://pypi.python.org/packages/source/P/PyYAML/PyYAML-3.10.tar.gz', 'local': 'PyYAML-3.10.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'PYTHON-DIGEST' : {'setup':'python-digest', 'url':'http://pypi.python.org/packages/source/p/python-digest/python-digest-1.7.tar.gz', 'local': 'python-digest-1.7.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'DJANGO-TASTYPIE' : {'setup':'django-tastypie', 'url':'http://pypi.python.org/packages/source/d/django-tastypie/django-tastypie-0.9.11.tar.gz', 'local': 'django-tastypie-0.9.11.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, } if system_str == 'Windows': diff -r dd8fe34c5abe -r 9eae65727f54 virtualenv/res/src/PyYAML-3.10.tar.gz Binary file virtualenv/res/src/PyYAML-3.10.tar.gz has changed diff -r dd8fe34c5abe -r 9eae65727f54 virtualenv/res/src/django-piston-7c90898072ce-modifed.tar.gz Binary file virtualenv/res/src/django-piston-7c90898072ce-modifed.tar.gz has changed diff -r dd8fe34c5abe -r 9eae65727f54 virtualenv/res/src/django-tastypie-0.9.11.tar.gz Binary file virtualenv/res/src/django-tastypie-0.9.11.tar.gz has changed diff -r dd8fe34c5abe -r 9eae65727f54 virtualenv/res/src/mimeparse-0.1.3.tar.gz Binary file virtualenv/res/src/mimeparse-0.1.3.tar.gz has changed diff -r dd8fe34c5abe -r 9eae65727f54 virtualenv/res/src/python-dateutil-2.1.tar.gz Binary file virtualenv/res/src/python-dateutil-2.1.tar.gz has changed diff -r dd8fe34c5abe -r 9eae65727f54 virtualenv/res/src/python-digest-1.7.tar.gz Binary file virtualenv/res/src/python-digest-1.7.tar.gz has changed diff -r dd8fe34c5abe -r 9eae65727f54 virtualenv/web/res/res_create_env.py --- a/virtualenv/web/res/res_create_env.py Sun Oct 21 22:48:17 2012 +0200 +++ b/virtualenv/web/res/res_create_env.py Mon Oct 29 12:04:20 2012 +0100 @@ -15,7 +15,6 @@ 'DJANGO-EXTENSIONS', 'DJANGO-REGISTRATION', 'DJANGO-TAGGING', - 'DJANGO-PISTON', 'HTTPLIB2', 'OAUTH2', 'SETUPTOOLS_HG', @@ -30,6 +29,11 @@ 'REQUESTS', 'PYELASTICSEARCH', 'WHOOSH', + 'MIMEPARSE', + 'PYTHON-DATEUTIL', + 'PYYAML', + 'PYTHON-DIGEST', + 'DJANGO-TASTYPIE', ] if system_str == "Linux": diff -r dd8fe34c5abe -r 9eae65727f54 web/ldtplatform/settings.py --- a/web/ldtplatform/settings.py Sun Oct 21 22:48:17 2012 +0200 +++ b/web/ldtplatform/settings.py Mon Oct 29 12:04:20 2012 +0100 @@ -93,7 +93,6 @@ 'django_openid_consumer.middleware.OpenIDMiddleware', 'ldt.ldt_utils.middleware.userprofile.LanguageMiddleware', 'ldt.security.middleware.SecurityMiddleware', - 'ldt.api.middleware.pistonput.PistonPutMiddleware', ) TEMPLATE_CONTEXT_PROCESSORS = ( @@ -143,11 +142,11 @@ 'ldt.indexation', 'oauth_provider', 'django_openid_consumer', - 'piston', 'social_auth', 'south', 'guardian', 'sorl.thumbnail', + 'tastypie', ) AUTH_PROFILE_MODULE = 'user.UserProfile'