Merge with eb9cc63ce7423fe953f6332fd7f28624e5840ef3
authorymh <ymh.work@gmail.com>
Sat, 11 May 2013 23:09:05 +0200
changeset 1180 54ef33bb4065
parent 1166 615d19953572 (diff)
parent 1178 eb9cc63ce742 (current diff)
child 1181 6ab716dd58f8
Merge with eb9cc63ce7423fe953f6332fd7f28624e5840ef3
.hgtags
src/ldt/ldt/__init__.py
src/ldt/ldt/ldt_utils/models.py
src/ldt/ldt/ldt_utils/templates/front/front_group.html
src/ldt/ldt/ldt_utils/templates/front/front_home.html
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_popup.html
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/projectslist.html
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/publishedprojectslist.html
src/ldt/ldt/ldt_utils/urls.py
src/ldt/ldt/ldt_utils/views/content.py
src/ldt/ldt/ldt_utils/views/front.py
src/ldt/ldt/ldt_utils/views/group.py
src/ldt/ldt/ldt_utils/views/lignesdetemps.py
src/ldt/ldt/ldt_utils/views/workspace.py
src/ldt/ldt/locale/fr/LC_MESSAGES/django.mo
src/ldt/ldt/locale/fr/LC_MESSAGES/django.po
src/ldt/ldt/management/commands/reindex.py
src/ldt/ldt/security/__init__.py
src/ldt/ldt/security/permissionchecker.py
src/ldt/ldt/security/utils.py
src/ldt/ldt/settings.py
src/ldt/ldt/static/ldt/css/embed_popup.css
src/ldt/ldt/static/ldt/css/front_group.css
src/ldt/ldt/static/ldt/js/embed_popup.js
src/ldt/ldt/static/ldt/js/projectscontents.js
src/ldt/ldt/static/ldt/metadataplayer/Annotation.js
src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.js
src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js
src/ldt/ldt/static/ldt/metadataplayer/Polemic.js
src/ldt/ldt/static/ldt/metadataplayer/Segments.js
src/ldt/ldt/static/ldt/metadataplayer/Tweet.js
src/ldt/ldt/static/ldt/swf/ldt/LignesDeTempsFlex.swf
--- a/.hgtags	Tue May 07 15:30:41 2013 +0200
+++ b/.hgtags	Sat May 11 23:09:05 2013 +0200
@@ -143,10 +143,8 @@
 c4d6ddd5f718d1e55441247aa4c4366a5d7be470 V01.43
 996bb5b1adbc920f8ecb49f9d7b45f51a8aa3c04 V01.44
 62be1eedf90855ab3cef1ab8a9f0c66130638673 V01.45
-ba7783d59d3fbee183ff2bc5ba1e8deed769928d V01.46.1
+e1b6be4d85a47f4cecce2cf6e88ff190301bd8dc V01.46
 1db1fa8c8076e791cfeedb8c2eb73d731656e034 V01.46.01
-ba7783d59d3fbee183ff2bc5ba1e8deed769928d V01.46.1
-0000000000000000000000000000000000000000 V01.46.1
 65712578e1f3adc7b441f5e853456442de4b7380 V01.46.02
 d0fdcae534a9826644e9f15c6a8c7888dad76c02 V01.46.03
 5647cbc32e53dafb824583ea8d0cbaf38ff38bb9 V01.46.04
@@ -160,3 +158,7 @@
 9e21c880c3ee2206a9150a46ea865bbc4a7ccccc V01.46.08
 8837650d6f629d0582169c6bda8432290a1680b0 V01.46.09
 af204bb19efa9dc45d09017968144bfb470acace V01.46.10
+86dbc665226d08c082a559b2c218efcd56105c69 V01.47
+56c6497c0785d20c3c17da90446d030eba3c78f3 V01.48
+e590a85b91cccd905ddd25db54357f4f584e83fa V01.49
+
--- a/.project	Tue May 07 15:30:41 2013 +0200
+++ b/.project	Sat May 11 23:09:05 2013 +0200
@@ -10,11 +10,6 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
-		<buildCommand>
-			<name>com.aptana.ide.core.unifiedBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>com.aptana.projects.webnature</nature>
--- a/.settings/org.eclipse.core.resources.prefs	Tue May 07 15:30:41 2013 +0200
+++ b/.settings/org.eclipse.core.resources.prefs	Sat May 11 23:09:05 2013 +0200
@@ -1,42 +1,47 @@
-eclipse.preferences.version=1
-encoding//src/ldt/ldt/core/migrations/0001_initial.py=utf-8
-encoding//src/ldt/ldt/core/migrations/0002_auto__del_owner.py=utf-8
-encoding//src/ldt/ldt/indexation/backends/elasticsearch_backend.py=utf-8
-encoding//src/ldt/ldt/indexation/highlighter.py=utf-8
-encoding//src/ldt/ldt/indexation/models.py=utf-8
-encoding//src/ldt/ldt/indexation/query_parser.py=utf-8
-encoding//src/ldt/ldt/indexation/search_indexes.py=utf-8
-encoding//src/ldt/ldt/indexation/tests.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0001_initial.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0002_auto__add_field_media_mimetype_field__chg_field_media_external_src_url.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0003_auto__chg_field_project_owner.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0004_auto__add_field_project_description.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0005_add_permissions.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0006_auto__add_field_media_image.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0007_auto__add_field_content_image__del_field_media_image.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0008_auto__add_field_project_image.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0009_auto__chg_field_content_image__chg_field_project_image.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0010_auto__add_annotationstat.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0011_gen_stat_annotation.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0012_auto__add_field_content_last_annotated.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0013_auto__add_field_content_front_project__chg_field_content_last_annotate.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0014_auto__del_annotationstat__chg_field_content_last_annotated.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0015_auto__add_contentstat__del_field_content_last_annotated__del_field_con.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0016_one_to_one_stat_annotation.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0017_correct_image_path.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0018_auto__chg_field_content_iri_id__chg_field_project_ldt_id__chg_field_au.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0019_recalculate_media_hash_src.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0020_auto__add_field_segment_id_hash__chg_field_segment_iri_id__chg_field_s.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0021_recalculate_segment_id_hash_script.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0022_auto__add_unique_media_src_hash__chg_field_segment_cutting_id__chg_fie.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0023_auto__add_field_segment_audio_src__add_field_segment_audio_href.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0024_auto__chg_field_tag_name.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/migrations/0025_chg_site_domain.py=utf-8
-encoding//src/ldt/ldt/ldt_utils/views/json.py=utf-8
-encoding//src/ldt/ldt/management/utils.py=utf-8
-encoding//src/ldt/ldt/test/test_runner.py=utf-8
-encoding//src/ldt/ldt/text/migrations/0001_initial.py=utf-8
-encoding//src/ldt/ldt/user/migrations/0001_initial.py=utf-8
-encoding//src/ldt/ldt/user/migrations/0008_auto__chg_field_groupprofile_image__chg_field_groupprofile_group__chg_.py=utf-8
-encoding//virtualenv/web/env/guardianenv/Lib/site-packages/guardian/migrations/0001_initial.py=utf-8
-encoding/<project>=UTF-8
+#Mon Apr 08 17:07:34 CEST 2013
+eclipse.preferences.version=1
+encoding//src/ldt/ldt/core/migrations/0001_initial.py=utf-8
+encoding//src/ldt/ldt/core/migrations/0002_auto__del_owner.py=utf-8
+encoding//src/ldt/ldt/indexation/backends/elasticsearch_backend.py=utf-8
+encoding//src/ldt/ldt/indexation/highlighter.py=utf-8
+encoding//src/ldt/ldt/indexation/models.py=utf-8
+encoding//src/ldt/ldt/indexation/query_parser.py=utf-8
+encoding//src/ldt/ldt/indexation/search_indexes.py=utf-8
+encoding//src/ldt/ldt/indexation/signals.py=utf-8
+encoding//src/ldt/ldt/indexation/tests.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/events.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0001_initial.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0002_auto__add_field_media_mimetype_field__chg_field_media_external_src_url.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0003_auto__chg_field_project_owner.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0004_auto__add_field_project_description.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0005_add_permissions.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0006_auto__add_field_media_image.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0007_auto__add_field_content_image__del_field_media_image.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0008_auto__add_field_project_image.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0009_auto__chg_field_content_image__chg_field_project_image.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0010_auto__add_annotationstat.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0011_gen_stat_annotation.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0012_auto__add_field_content_last_annotated.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0013_auto__add_field_content_front_project__chg_field_content_last_annotate.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0014_auto__del_annotationstat__chg_field_content_last_annotated.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0015_auto__add_contentstat__del_field_content_last_annotated__del_field_con.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0016_one_to_one_stat_annotation.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0017_correct_image_path.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0018_auto__chg_field_content_iri_id__chg_field_project_ldt_id__chg_field_au.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0019_recalculate_media_hash_src.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0020_auto__add_field_segment_id_hash__chg_field_segment_iri_id__chg_field_s.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0021_recalculate_segment_id_hash_script.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0022_auto__add_unique_media_src_hash__chg_field_segment_cutting_id__chg_fie.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0023_auto__add_field_segment_audio_src__add_field_segment_audio_href.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0024_auto__chg_field_tag_name.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0025_chg_site_domain.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/migrations/0026_set_relative_ldtproject.py=utf-8
+encoding//src/ldt/ldt/ldt_utils/views/json.py=utf-8
+encoding//src/ldt/ldt/management/commands/synciri.py=utf-8
+encoding//src/ldt/ldt/management/utils.py=utf-8
+encoding//src/ldt/ldt/test/test_runner.py=utf-8
+encoding//src/ldt/ldt/text/migrations/0001_initial.py=utf-8
+encoding//src/ldt/ldt/user/migrations/0001_initial.py=utf-8
+encoding//src/ldt/ldt/user/migrations/0008_auto__chg_field_groupprofile_image__chg_field_groupprofile_group__chg_.py=utf-8
+encoding//virtualenv/web/env/guardianenv/Lib/site-packages/guardian/migrations/0001_initial.py=utf-8
+encoding/<project>=UTF-8
--- a/src/ldt/ldt/__init__.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/__init__.py	Sat May 11 23:09:05 2013 +0200
@@ -1,4 +1,4 @@
-VERSION = (1, 46, 10, "final", 0)
+VERSION = (1, 49, 0, "final", 0)
 
 
 def get_version():
--- a/src/ldt/ldt/api/ldt/resources/annotation.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/api/ldt/resources/annotation.py	Sat May 11 23:09:05 2013 +0200
@@ -7,14 +7,16 @@
 from tastypie.exceptions import NotFound, BadRequest
 from tastypie.resources import Resource
 import logging #@UnresolvedImport
+from ldt.ldt_utils.contentindexer import add_segment
 
 
 class AnnotationObject(object):
-    def __init__(self, id="", project = "", type = "", type_title = "", media = "", begin = 0, end = 0, content = {"title":"", "description":""}, tags = [], meta = {"creator":"","created":""}):
+    def __init__(self, id="", project = "", type = "", type_title = "", ensemble="", media = "", begin = 0, end = 0, content = {"title":"", "description":""}, tags = [], meta = {"creator":"","created":""}):
         self.id = id
         self.project = project
         self.type = type
         self.type_title = type_title
+        self.ensemble = ensemble
         self.media = media
         self.begin = begin
         self.end = end
@@ -86,25 +88,44 @@
         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)
+        type_id, new_id, ensemble_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
         a['type'] = type_id
+        a['ensemble'] = ensemble_id
         a['id'] = new_id
         if not a['content'].has_key('audio') :
             a['content']['audio'] = {'src':audio_src, 'href':audio_href}
+        
+        #add segment
+        add_segment({
+            "project" : project,
+            "content" : content,
+            "ensemble_id" : ensemble_id,
+            "cutting_id" :  a['type'],            
+            "element_id" : new_id,
+            "title" : a['content']['title'],
+            "abstract" : a['content']['description'],
+            "tags" : ",".join(a['tags']),
+            "start_ts" : begin,
+            "duration" :  dur,
+            "author" : author,
+            "date" : date, 
+            "audio_src" : audio_src,            
+            "audio_href" : audio_href,
+            "polemics": adder.get_polemic_syntax(a['content']['title'])
+        })
             
         # We save the added annotation and reprotect the contents and projects
-        adder.save()
+        adder.save(must_reindex=False)
         protect_models()
         # We update the AnnotationObject for the returned datas to be correct.
-        bundle.obj = AnnotationObject(id = a["id"], project = a["project"], type = a["type"], type_title = a["type_title"], media = a["media"], begin = a["begin"], end = a["end"], content = a['content'], tags = a['tags'], meta = a['meta'])
+        bundle.obj = AnnotationObject(id = a["id"], project = a["project"], type = a["type"], type_title = a["type_title"], ensemble=a['ensemble'], media = a["media"], begin = a["begin"], end = a["end"], content = a['content'], tags = a['tags'], meta = a['meta'])
         return bundle
     
     def get_resource_uri(self, bundle_or_obj):
--- a/src/ldt/ldt/api/ldt/resources/content.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/api/ldt/resources/content.py	Sat May 11 23:09:05 2013 +0200
@@ -26,7 +26,7 @@
     class Meta:
         allowed_methods = ['get']
         resource_name = 'contents'
-        queryset = Content.objects.select_related('front_project').all()
+        queryset = Content.objects.select_related('front_project','media_obj').all()
         filtering = {
             'tags' : ALL_WITH_RELATIONS,
             'title' : ALL,
@@ -34,7 +34,7 @@
         ordering = ['title', 'creation_date', 'content_creation_date']
     
     def get_object_list(self, request):
-        return Content.safe_objects.all()
+        return Content.safe_objects.select_related('front_project', 'media_obj').all()
 
     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 
--- a/src/ldt/ldt/api/ldt/resources/segment.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/api/ldt/resources/segment.py	Sat May 11 23:09:05 2013 +0200
@@ -2,14 +2,16 @@
 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.indexation import get_results_list
 from ldt.ldt_utils.models import Content, Segment
 from ldt.ldt_utils.segmentserializer import SegmentSerializer
 from tastypie.constants import ALL
-from tastypie.http import HttpNotFound
+from tastypie.exceptions import BadRequest, NotFound
 from tastypie.resources import ModelResource
 from tastypie.utils import trailing_slash
+import logging
 
+logger = logging.getLogger(__name__)
 
 class SegmentResource(ModelResource):
     class Meta:
@@ -38,8 +40,9 @@
         self.method_check(request, allowed=['get'])
         # Do the query.
         search = request.GET.get('q', '')
+        if search=='':
+            raise BadRequest('The request needs a search query "q=" parameter.')
         field = "all"
-        content_list = None
         if u'author:' in search.lower() :
             sub = search[7:]
             sub = sub.upper()
@@ -48,22 +51,25 @@
             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))
-
+        
+        results = get_results_list(field, search, False)
+        # get_results_list returns a SearchQuerySet, we load_all() to get all real Segment objects 
+        all_segments = results.load_all()
+        paginator = Paginator(all_segments, request.GET.get("limit") or 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.")
-
+            raise NotFound("Sorry, no results on that page.")
+        
         objects = []
-
-        for segment in page.object_list:
-            bundle = self.build_bundle(obj=segment, request=request)
+        
+        for search_res in page.object_list:
+            # search_res is a SearchResult, search_res.object is the real Segment Object thanks to results.load_all()
+            bundle = self.build_bundle(obj=search_res.object, request=request)
             bundle = self.full_dehydrate(bundle)
             objects.append(bundle)
-
+        
         object_list = {
             'objects': objects,
         }
@@ -78,22 +84,22 @@
         returns segments about content iri_id between timecodes begin and end
         """
         if not begin:
-            return HttpNotFound("begin timecode argument is missing.")
+            raise NotFound("begin timecode argument is missing.")
         if not end:
-            return HttpNotFound("end timecode argument is missing.")
+            raise NotFound("end timecode argument is missing.")
         begin = int(begin)
         end = int(end)
         
-        content = Content.objects.filter(iri_id=iri_id)
+        content = Content.objects.filter(iri_id=iri_id).select_related('media_obj', 'stat_annotation')
         if not content:
-            return HttpNotFound("Content does not exist or id is not correct.")
+            raise NotFound("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
-                    )
+                    ).select_related("project_obj")
         
         a = SegmentSerializer(content, segments)
         return self.create_response(request, a.serialize_to_cinelab())
--- a/src/ldt/ldt/indexation/__init__.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/indexation/__init__.py	Sat May 11 23:09:05 2013 +0200
@@ -1,5 +1,7 @@
+from .backends import elasticsearch_backend as ldt_elasticsearch_backend
 from django.conf import settings
-
+from haystack import connections
+from haystack.constants import DEFAULT_ALIAS
 from haystack.query import SearchQuerySet
 from ldt.indexation.highlighter import LdtHighlighter as Highlighter
 from ldt.indexation.query_parser import QueryParser
@@ -7,6 +9,7 @@
 from ldt.text.models import Annotation
 import re
 import sys
+
  
 def get_results_with_context(field, query, content_list=None, highlight=True):
     
@@ -82,6 +85,62 @@
                 
     return results_list
 
+def object_delete(model, **kwargs):
+    
+    
+    kwargs_filter = kwargs.copy()
+    kwargs_filter.pop('using', None)
+    
+    # here we do a poor man transaction management.
+    # the is no clear transaction management in Haystack.
+    # therefore, we give priority to the database and delete there first.
+    # if there is an error there, the index will not be updated.
+      
+    objs = list(model.objects.filter(**kwargs_filter))    
+    
+    model.objects.filter(**kwargs_filter).delete()
+    
+    using = None
+    if 'using' in kwargs:
+        using = kwargs.get('using', None)
+    if not using:
+        using = DEFAULT_ALIAS        
+    
+    conn = connections[using]
+    
+    if isinstance(conn, ldt_elasticsearch_backend.ElasticsearchSearchEngine):
+        conn.get_backend().remove(objs, commit=True)
+    else:
+        for o in objs:
+            conn.get_backend().remove(o, commit=True)
+
+def object_insert(model, object_list, func_key, using = None):
+    
+    if not object_list:
+        return
+
+    model.objects.bulk_create(object_list)
+    
+    obj_dict = dict(model.objects.filter(**{func_key+'__in':[getattr(o, func_key) for o in object_list]}).values_list(func_key,"id"))
+
+    for o in object_list:
+        o.id = obj_dict[getattr(o,func_key)]
+
+    if not using:
+        using = DEFAULT_ALIAS        
+    
+    conn = connections[using]
+    
+    backend = conn.get_backend()
+    unified_index = conn.get_unified_index()
+    
+    index = unified_index.get_index(model)
+    
+    backend.update(index, object_list)
+    
+    
+
+
 class SimpleSearch(object):
 
     def query(self, field, query):
--- a/src/ldt/ldt/indexation/backends/elasticsearch_backend.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/indexation/backends/elasticsearch_backend.py	Sat May 11 23:09:05 2013 +0200
@@ -7,8 +7,21 @@
 from django.db.models.loading import get_model
 from haystack.backends import BaseEngine, SearchResult, elasticsearch_backend
 from haystack.constants import DJANGO_CT, DJANGO_ID
+from haystack.exceptions import MissingDependency
+from haystack.utils import get_identifier
 from ldt.ldt_utils.models import Segment
+import collections
 import datetime
+try:
+    import requests
+except ImportError:
+    raise MissingDependency("The 'elasticsearch' backend requires the installation of 'requests'.")
+try:
+    import pyelasticsearch
+except ImportError:
+    raise MissingDependency("The 'elasticsearch' backend requires the installation of 'pyelasticsearch'. Please refer to the documentation.")
+
+
 
 class ElasticsearchSearchBackend(elasticsearch_backend.ElasticsearchSearchBackend):
 
@@ -110,6 +123,27 @@
             'facets': facets,
             'spelling_suggestion': spelling_suggestion,
         }
+        
+    def remove(self, obj_or_string, commit=True):
+        
+        if not self.setup_complete:
+            try:
+                self.setup()
+            except (requests.RequestException, pyelasticsearch.ElasticHttpError), e:
+                if not self.silently_fail:
+                    raise
+
+                self.log.error("Failed to remove document '%s' from Elasticsearch: %s", repr(obj_or_string), e)
+                return
+
+        if isinstance(obj_or_string, collections.Iterable) and not isinstance(obj_or_string, basestring):
+            ids = [get_identifier(elt) for elt in obj_or_string]
+            if not ids:
+                return
+            q = {'ids' : {'values' : ids}}
+            self.conn.delete_by_query(self.index_name, 'modelresult', q)
+        else: 
+            return super(ElasticsearchSearchBackend, self).remove(obj_or_string, commit=commit) 
 
 
 class ElasticsearchSearchEngine(BaseEngine):
--- a/src/ldt/ldt/indexation/query_parser.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/indexation/query_parser.py	Sat May 11 23:09:05 2013 +0200
@@ -7,10 +7,13 @@
 
 #TODO: unitest for 
 
-from whoosh.qparser import SimpleParser, FieldsPlugin, OperatorsPlugin, PhrasePlugin, SingleQuotePlugin, GroupPlugin, PrefixPlugin, GtLtPlugin, RangePlugin
-from whoosh.query import Term, And, AndMaybe, Or, AndNot, Not, Phrase, Prefix, TermRange
+from django.conf import settings
 from haystack.query import SQ
-from django.conf import settings
+from whoosh.qparser import (SimpleParser, FieldsPlugin, OperatorsPlugin, 
+    PhrasePlugin, SingleQuotePlugin, GroupPlugin, PrefixPlugin, GtLtPlugin, 
+    RangePlugin)
+from whoosh.query import (Term, And, AndMaybe, Or, AndNot, Not, Phrase, Prefix, 
+    TermRange)
 
 HAYSTACK_DEFAULT_OPERATOR = getattr(settings,'HAYSTACK_DEFAULT_OPERATOR','AND')
 
@@ -158,16 +161,16 @@
         current_node, current_connector = self.current_node_stack[-1]
         current_node.add(new_node, current_connector)
 
-    def __convert_nb(self, str):        
+    def __convert_nb(self, str_nb):        
         try:
-            res = int(str)
+            res = int(str_nb)
             return res
         except ValueError:
             try:
-                res = float(str)
+                res = float(str_nb)
                 return res
             except ValueError:
-                return str
+                return str_nb
         
         
         
\ No newline at end of file
--- a/src/ldt/ldt/indexation/search_indexes.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/indexation/search_indexes.py	Sat May 11 23:09:05 2013 +0200
@@ -6,10 +6,10 @@
 '''
 
 from haystack import indexes
-from ldt.ldt_utils.models import Segment 
+from ldt.ldt_utils.models import Segment
 from ldt.text.models import Annotation
 
-class SegmentIndex(indexes.RealTimeSearchIndex, indexes.Indexable):
+class SegmentIndex(indexes.SearchIndex, indexes.Indexable):
     text = indexes.CharField(document=True, use_template=True)
     iri_id = indexes.CharField(model_attr='iri_id', indexed=False, stored=True)
     project_id = indexes.CharField(model_attr='project_id', indexed=False, stored=True, null=True)
@@ -27,7 +27,7 @@
     def get_model(self):
         return Segment
     
-class AnnotationIndex(indexes.RealTimeSearchIndex, indexes.Indexable):
+class AnnotationIndex(indexes.SearchIndex, indexes.Indexable):
     text = indexes.CharField(document=True, use_template=True)
     tags = indexes.CharField(model_attr='tags', indexed=True, stored=False)
     title = indexes.CharField(model_attr='title', indexed=True, stored=True)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/indexation/signals.py	Sat May 11 23:09:05 2013 +0200
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+'''
+Created on Feb 22, 2013
+
+@author: ymh
+'''
+from django.db import models
+from haystack import signals
+from ldt.ldt_utils.models import Segment
+from ldt.text.models import Annotation
+
+class LdtSignalProcessor(signals.BaseSignalProcessor):
+    
+    def __connect_signals(self, klass):
+        models.signals.post_save.connect(self.handle_save, sender=klass)
+        models.signals.post_delete.connect(self.handle_delete, sender=klass)        
+
+    def __disconnect_signals(self, klass):
+        models.signals.post_save.disconnect(self.handle_save, sender=klass)
+        models.signals.post_delete.disconnect(self.handle_delete, sender=klass)
+
+    
+    def setup(self):        
+        self.__connect_signals(Segment)
+        self.__connect_signals(Annotation)
+
+
+
+    def teardown(self):
+        self.__disconnect_signals(Annotation)
+        self.__disconnect_signals(Segment)
+        
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/__init__.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/__init__.py	Sat May 11 23:09:05 2013 +0200
@@ -1,2 +0,0 @@
-#initialize 
-from ldt.ldt_utils import contentindexer
--- a/src/ldt/ldt/ldt_utils/contentindexer.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/contentindexer.py	Sat May 11 23:09:05 2013 +0200
@@ -1,15 +1,16 @@
-from django.db.models.signals import post_save
+from StringIO import StringIO
 from django.dispatch import receiver
 from ldt import settings
+from ldt.indexation import object_delete, object_insert
+from ldt.ldt_utils.events import post_project_save
 from ldt.ldt_utils.models import Segment, Content, Project
-from ldt.ldt_utils.stat import update_stat_project
+from ldt.ldt_utils.stat import update_stat_project, add_annotation_to_stat
 from ldt.ldt_utils.utils import reduce_text_node
+from ldt.utils.url import request_with_auth
 from tagging import settings as tagging_settings
 import logging
 import lxml.etree #@UnresolvedImport
 import tagging.utils
-from ldt.utils.url import request_with_auth
-from StringIO import StringIO
 
 logger = logging.getLogger(__name__)
 
@@ -19,8 +20,11 @@
 
 class LdtIndexer(object):
     
-    def __init__(self, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
-            self.__decoupage_blacklist = decoupage_blackList
+    def __init__(self, object_list, decoupage_blackList=settings.DECOUPAGE_BLACKLIST, callback=None):
+        self.__object_list = object_list
+        self.__decoupage_blacklist = decoupage_blackList
+        self.__callback = callback
+        self.__segment_cache = []
         
     @Property
     def decoupage_blacklist(): #@NoSelf
@@ -40,7 +44,23 @@
         return locals()
     
     def index_all(self):
-        raise NotImplemented
+        for i,obj in enumerate(self.__object_list):
+            if self.__callback:
+                self.__callback(i,obj)
+            self.index_object(obj)
+    
+    
+    def index_object(self, obj):
+        
+        self._do_index_object(obj)
+        
+        if self.__segment_cache:
+            object_insert(Segment, self.__segment_cache, 'id_hash')
+            self.__segment_cache = []
+
+
+    def _do_index_object(self, obj):
+        raise NotImplementedError()
     
     def index_ensemble(self, ensemble, content, project=None):
         ensembleId = ensemble.get(u"id", None)
@@ -97,7 +117,7 @@
                     audio_src = audio_node[0].get(u"source", u"")
                     audio_href = audio_node[0].text
 
-                seg = Segment(content=content,
+                seg = Segment.create(content=content,
                               iri_id=content.iri_id,
                               ensemble_id=ensembleId,
                               cutting_id=decoupId,
@@ -114,55 +134,41 @@
                               audio_src=audio_src,
                               audio_href=audio_href)
                 seg.polemics = seg.get_polemic(polemics)
-                seg.save()
+                if settings.LDT_INDEXATION_INSERT_BATCH_SIZE < 2:
+                    seg.save()
+                else:
+                    self.__segment_cache.append(seg)
+                    if not (len(self.__segment_cache)%settings.LDT_INDEXATION_INSERT_BATCH_SIZE):
+                        object_insert(Segment, self.__segment_cache)
+                        self.__segment_cache = []
 
 
 class ContentIndexer(LdtIndexer):
         
-    def __init__(self, contentList, decoupage_blackList=settings.DECOUPAGE_BLACKLIST, callback=None):
-        super(ContentIndexer, self).__init__(decoupage_blackList)
-        self.__contentList = contentList
-        self.__callback = callback
-                                   
-    def index_all(self):
-        for i,content in enumerate(self.__contentList):
-            if self.__callback:
-                self.__callback(i,content)
-            self.index_content(content)
-            
-    def index_content(self, content):        
+    def _do_index_object(self, obj):
+        
+        content = obj 
         url = content.iri_url()
         _, file_content = request_with_auth(url)
         doc = lxml.etree.parse(StringIO(file_content)) #@UndefinedVariable
        
-        Segment.objects.filter(iri_id=content.iri_id).delete() #@UndefinedVariable
+        object_delete(Segment, iri_id=content.iri_id, project_id='')
         
         res = doc.xpath("/iri/body/ensembles/ensemble")
 
         for ensemble in res:                
             self.index_ensemble(ensemble, content)
-                    
+                            
             
 class ProjectIndexer(LdtIndexer):
+                              
+    def _do_index_object(self, obj):
 
-    def __init__(self, projectList, decoupage_blackList=settings.DECOUPAGE_BLACKLIST, callback=None):
-        super(ProjectIndexer, self).__init__(decoupage_blackList)                
-        self.__projectList = projectList
-        self.__callback = callback
-                              
-    def index_all(self):
-        for i,project in enumerate(self.__projectList):
-            if self.__callback:
-                self.__callback(i,project)
-
-            self.index_project(project)
-
-    def index_project(self, project):
-
+        project = obj
         # pocketfilms.utils.log.debug("Indexing project : "+str(project.iri_id))
         doc = lxml.etree.fromstring(project.ldt_encoded) #@UndefinedVariable
 
-        Segment.objects.filter(project_obj__ldt_id=project.ldt_id).delete() #@UndefinedVariable
+        object_delete(Segment, project_obj__ldt_id=project.ldt_id)
        
         res = doc.xpath("/iri/annotations/content")
 
@@ -177,14 +183,66 @@
             for ensemble in content.getchildren():
                 self.index_ensemble(ensemble, content_obj, project)
 
-@receiver(post_save, sender=Project)
-def index_project(sender, **kwargs):
-    if settings.AUTO_INDEX_AFTER_SAVE:
+@receiver(post_project_save)
+def index_project(**kwargs):
+    must_reindex = kwargs.get("must_reindex", True)
+    if must_reindex and settings.AUTO_INDEX_AFTER_SAVE:
         instance = kwargs['instance']
-        if instance.state != 2:
-            Segment.objects.filter(project_obj__ldt_id=instance.ldt_id).delete() #@UndefinedVariable
+        if instance.state != Project.PUBLISHED:
+            object_delete(Segment, project_obj__ldt_id=instance.ldt_id)
             update_stat_project(instance)
         else:
             projectIndexer = ProjectIndexer([instance])
             projectIndexer.index_all()
             update_stat_project(instance)
+
+
+
+def add_segment(params):
+                                
+    project = params.get("project",None)
+    content = params.get("content",None)
+    ensemble_id = params.get("ensemble_id", "")
+    cutting_id = params.get("cutting_id", "")
+    element_id = params.get("element_id", "")
+    title = params.get("title", "")
+    abstract = params.get("abstract", "")
+    tags_str = params.get("tags", "")
+    start_ts = params.get("start_ts", 0)
+    duration = params.get("duration", 0)
+    author = params.get("author", "")
+    date_str = params.get("date", "")
+    audio_src = params.get("audio_src", "")
+    audio_href = params.get("audio_href", "")
+    polemics = params.get("polemics", "")
+    
+    seg = Segment.create(content=content,
+              iri_id=content.iri_id if content is not None else "",
+              ensemble_id=ensemble_id,
+              cutting_id=cutting_id,
+              element_id=element_id,
+              tags=tags_str,
+              title=title,
+              abstract=abstract,
+              duration=duration,
+              author=author,
+              start_ts=start_ts,
+              date=date_str,
+              project_obj=project,
+              project_id=project.ldt_id if project is not None else "",
+              audio_src=audio_src,
+              audio_href=audio_href)
+    seg.polemics = seg.get_polemic(polemics)
+    seg.save()
+    add_annotation_to_stat(seg.content, seg.start_ts, seg.start_ts+seg.duration)
+
+
+def delete_segment(project, project_id, iri_id, ensemble_id, cutting_id, element_id):
+
+    # delete Segment
+    for seg in Segment.objects.filter(project_id=project_id, iri_id=iri_id, ensemble_id=ensemble_id, cutting_id=cutting_id, element_id=element_id):        
+        seg.delete()
+        add_annotation_to_stat(seg.content, seg.start_ts, seg.start_ts+seg.duration)
+    
+    
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/events.py	Sat May 11 23:09:05 2013 +0200
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+'''
+Created on Jan 22, 2013
+
+@author: ymh
+'''
+import django.dispatch
+
+post_project_save = django.dispatch.Signal(["instance","must_reindex"])
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/fixtures/user_data.json	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/fixtures/user_data.json	Sat May 11 23:09:05 2013 +0200
@@ -17,50 +17,86 @@
     }
   },
   {
-    "pk": 1, 
-    "model": "oauth_provider.resource", 
+    "pk": 7, 
+    "model": "ldt_utils.media", 
     "fields": {
-      "url": "/api/1.0/text/delete/", 
-      "name": "delete", 
-      "is_readonly": true
-    }
-  },
-  {
-    "pk": 2, 
-    "model": "oauth_provider.resource", 
-    "fields": {
-      "url": "/api/1.0/text/create/", 
-      "name": "create", 
-      "is_readonly": true
+      "external_permalink": "", 
+      "src_hash": "f4a5afb24467cbf18825ea6b90bc2bcc78e68610d6650625296ae70b2e981d9bad6619a3b4ff22431e74177dcc264ffb0c9471bc625a6229b7cdbeb2e372468f", 
+      "videopath": "", 
+      "update_date": "2012-11-26T15:48:12", 
+      "external_publication_url": "", 
+      "external_src_url": "", 
+      "creator": null, 
+      "creation_date": "2012-11-26T15:48:12", 
+      "media_creation_date": null, 
+      "mimetype_field": "", 
+      "duration": null, 
+      "title": "", 
+      "src": "http://dvvsyrlsr21oz.cloudfront.net/01-Kristina-HD.mp4", 
+      "external_id": "", 
+      "description": ""
     }
   },
   {
-    "pk": 3, 
-    "model": "oauth_provider.resource", 
+    "pk": 48, 
+    "model": "ldt_utils.media", 
     "fields": {
-      "url": "/api/1.0/text/update/", 
-      "name": "update", 
-      "is_readonly": true
+      "external_permalink": "", 
+      "src_hash": "79d1ada053cae7e6e49329645fc55f7ffb5341112134e70f55ea91b2c3e647e8e319525c6117ccfaea61039bf701a3ed8fd4921ac7bf2ef89e2e2f2233b29898", 
+      "videopath": "", 
+      "update_date": "2012-11-26T16:06:45", 
+      "external_publication_url": "", 
+      "external_src_url": "", 
+      "creator": null, 
+      "creation_date": "2012-11-26T16:06:45", 
+      "media_creation_date": null, 
+      "mimetype_field": "", 
+      "duration": null, 
+      "title": "", 
+      "src": "http://dvvsyrlsr21oz.cloudfront.net/INTERNATIONALE-CHANT_1-HD.mp4", 
+      "external_id": "", 
+      "description": ""
     }
-  },
+  }, 
   {
-    "pk": 4, 
-    "model": "oauth_provider.resource", 
+    "pk": 49, 
+    "model": "ldt_utils.media", 
     "fields": {
-      "url": "", 
-      "name": "all", 
-      "is_readonly": true
+      "external_permalink": "", 
+      "src_hash": "64460e021df13d4bc558e5672393539241f846065ec48862b89f43aadbcd278bc311c16782f43e68a0c83ed3357d0ca4d2082204bc4169af23985fa420a56bee", 
+      "videopath": "", 
+      "update_date": "2012-11-26T16:07:09", 
+      "external_publication_url": "", 
+      "external_src_url": "", 
+      "creator": null, 
+      "creation_date": "2012-11-26T16:07:09", 
+      "media_creation_date": null, 
+      "mimetype_field": "", 
+      "duration": null, 
+      "title": "", 
+      "src": "http://dvvsyrlsr21oz.cloudfront.net/NIDIEU-CHANT-2-HD.mp4", 
+      "external_id": "", 
+      "description": ""
     }
-  },
+  }, 
   {
-    "pk": 1, 
-    "model": "oauth_provider.consumer", 
+    "pk": 50, 
+    "model": "ldt_utils.media", 
     "fields": {
-      "status": 1, 
-      "name": "example.com", 
-      "secret": "kd94hf93k423kf44", 
-      "user": 2, 
-      "key": "dpf43f3p2l4k3l03", 
+      "external_permalink": "", 
+      "src_hash": "1cfb8cdec8da988eca4992b07f7d1bc4ef5c6a3f0a175c9941646c1e3a0abcd1eae6cae35b575b66738ef272ed87c2814fb9c8db3192d1f43c3fb5d7043db766", 
+      "videopath": "", 
+      "update_date": "2012-11-26T16:07:29", 
+      "external_publication_url": "", 
+      "external_src_url": "", 
+      "creator": null, 
+      "creation_date": "2012-11-26T16:07:29", 
+      "media_creation_date": null, 
+      "mimetype_field": "", 
+      "duration": null, 
+      "title": "", 
+      "src": "http://dvvsyrlsr21oz.cloudfront.net/MARSEILLAISE-CHANT_3-HD.mp4", 
+      "external_id": "", 
       "description": ""
     }
   }
--- a/src/ldt/ldt/ldt_utils/forms.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/forms.py	Sat May 11 23:09:05 2013 +0200
@@ -84,7 +84,7 @@
         
     class Media:
         css = {
-            'all' : ('admin/css/forms.css', 'admin/css/base.css', 'admin/css/widgets.css')
+            'all' : ('admin/css/forms.css', 'admin/css/widgets.css')
                }
         
 class MediaForm(forms.ModelForm):
@@ -100,7 +100,7 @@
     
     class Media:
         css = {
-            'all' : ('admin/css/forms.css', 'admin/css/base.css', 'admin/css/widgets.css')
+            'all' : ('admin/css/forms.css', 'admin/css/widgets.css')
                }
         
 class GroupAddForm(ShareForm):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/migrations/0026_set_relative_ldtproject.py	Sat May 11 23:09:05 2013 +0200
@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+from django.core.management import call_command
+from south.v2 import DataMigration
+
+
+class Migration(DataMigration):
+
+    def forwards(self, orm):
+        call_command('setprojectldtiri')
+
+    def backwards(self, orm):
+        #do nothing
+        pass
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'ldt_utils.author': {
+            'Meta': {'object_name': 'Author'},
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+            'firstname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lastname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.content': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Content'},
+            'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Author']", 'symmetrical': 'False', 'blank': 'True'}),
+            'content_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'front_project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/contents/content_default_icon.png'", 'max_length': '200'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'default': "u'75d885e1-4446-11e2-a1e1-00161798aedb'", 'unique': 'True', 'max_length': '255'}),
+            'iriurl': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'media_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Media']", 'null': 'True', 'blank': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.contentstat': {
+            'Meta': {'object_name': 'ContentStat'},
+            'annotation_volume_str': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'content': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'stat_annotation'", 'unique': 'True', 'to': "orm['ldt_utils.Content']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_annotated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'blank': 'True'}),
+            'nb_annotations': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}),
+            'polemics_volume_str': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.media': {
+            'Meta': {'object_name': 'Media'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'external_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_permalink': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_publication_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'external_src_url': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'media_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'mimetype_field': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'src': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'src_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'videopath': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
+        },
+        'ldt_utils.project': {
+            'Meta': {'ordering': "['title']", 'object_name': 'Project'},
+            'changed_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'contents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Content']", 'symmetrical': 'False'}),
+            'created_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}),
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/projects/project_default_icon.png'", 'max_length': '200'}),
+            'ldt': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'ldt_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'modification_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'state': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
+        },
+        'ldt_utils.segment': {
+            'Meta': {'object_name': 'Segment'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'audio_href': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'audio_src': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Content']"}),
+            'cutting_id': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}),
+            'date': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'element_id': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}),
+            'ensemble_id': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'id_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
+            'iri_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+            'polemics': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}),
+            'project_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'project_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True'}),
+            'start_ts': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['ldt_utils']
+    symmetrical = True
--- a/src/ldt/ldt/ldt_utils/models.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/models.py	Sat May 11 23:09:05 2013 +0200
@@ -24,7 +24,7 @@
 import uuid
 from shutil import move
 from django.core.files.storage import default_storage
-#from ldt.core.models import Document, Owner
+from .events import post_project_save
 
 
 class Author(SafeModel):
@@ -43,22 +43,20 @@
                        )
 
 
-
 class MediaManager(SafeManager):
     
     def __init__(self):
         super(MediaManager, self).__init__(check_perm=False)
-    
+        
     def get_by_natural_key(self, src_hash):
         return self.get(src_hash=src_hash)
 
 
-
 class Media(SafeModel):
     objects = MediaManager()
     external_id = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_id'))
-    external_permalink = models.URLField(max_length=1024, verify_exists=False, null=True, blank=True, verbose_name=_('media.external_permalink'))
-    external_publication_url = models.URLField(max_length=1024, verify_exists=True, null=True, blank=True, verbose_name=_('media.external_publication_url'))
+    external_permalink = models.URLField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_permalink'))
+    external_publication_url = models.URLField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_publication_url'))
     external_src_url = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_src_url'))
     creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('media.creation_date'))
     media_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('media.media_creation_date'))
@@ -247,7 +245,7 @@
 
     def get_duration(self):
         if self.duration is None:
-            doc = lxml.etree.parse(self.iri_file_path())
+            doc = lxml.etree.parse(self.iri_file_path()) #@UndefinedVariable
             res = doc.xpath("/iri/body/medias/media[@id='video']/video")
             if len(res) > 0:
                 try:
@@ -326,6 +324,10 @@
             if not url_utils.is_absolute(res_url):
                 res_url = unicode(web_url) + res_url
             return res_url 
+        
+    def relative_iri_url(self): #this function is called when we create a project 
+        res_url =  u"ldt/" + unicode(self.iriurl)
+        return res_url 
     
     def iri_file_path(self):
         return os.path.join(os.path.join(os.path.join(settings.MEDIA_ROOT, "ldt"), self.iri_id), os.path.basename(self.iriurl))
@@ -582,17 +584,22 @@
         return locals()
     
     polemics_volume = property(**polemics_volume())
-
-
     
     
-class Project(Document, SafeModel):  
+class Project(Document, SafeModel):
+    
+    EDITION = 1
+    PUBLISHED = 2
+    MODERATED = 3
+    REJECTED = 4
+    DELETED = 5
+      
     STATE_CHOICES = (
-    (1, 'edition'),
-    (2, 'published'),
-    (3, 'moderated'),
-    (4, 'rejected'),
-    (5, 'deleted')
+    (EDITION, 'edition'),
+    (PUBLISHED, 'published'),
+    (MODERATED, 'moderated'),
+    (REJECTED, 'rejected'),
+    (DELETED, 'deleted')
     )
     ldt_id = models.CharField(max_length=255, unique=True)
     ldt = models.TextField(null=True)
@@ -628,7 +635,7 @@
     def get_description(self, doc=None):
         
         if doc is None:
-            doc = lxml.etree.fromstring(self.ldt)
+            doc = lxml.etree.fromstring(self.ldt) #@UndefinedVariable
         
         res = doc.xpath("/iri/project")
         if len(res) > 0:
@@ -660,7 +667,15 @@
         return locals()
     
     stream_mode = property(**stream_mode())
-
+    
+    def save(self, *args, **kwargs):
+        
+        must_reindex = kwargs.pop("must_reindex", True)
+        super(Project, self).save(*args, **kwargs)
+        
+        post_project_save.send(self, instance=self, must_reindex = must_reindex)
+            
+            
     @staticmethod
     def create_project(user, title, contents, description='', groups=[], set_icon=True, cuttings=[]):
 #        owner = Owner.objects.get(user=user) #@UndefinedVariable
@@ -740,7 +755,7 @@
         
     def has_annotations(self):
         nb_annot = 0
-        doc = lxml.etree.fromstring(self.ldt)
+        doc = lxml.etree.fromstring(self.ldt) #@UndefinedVariable
         res = doc.xpath("/iri/annotations/content/ensemble/decoupage")
         for r in res:
             nb_annot = nb_annot + r.find('elements').__len__()
@@ -790,6 +805,11 @@
     audio_src = models.CharField(max_length=255, unique=False, null=True, blank=True)
     audio_href = models.CharField(max_length=512, unique=False, null=True, blank=True)
     
+    @classmethod
+    def create(cls, **kwargs):
+        seg = cls(**kwargs)
+        seg.set_hash()
+        return seg
     
     # All combinations of polemic hashtags can be represented by a combination of 
     # 4 bits, 1 if the hashtag is in the tweet, 0 else. We use the order OK, KO, Q, REF
@@ -801,7 +821,7 @@
             'Q': set([2,3,6,7,10,11,14,15]),
             'REF': set([1,3,5,7,9,11,13,15]),
             }
-    
+        
     def is_polemic(self, polemic_keyword): # OK, KO, Q, REF 
         if self.polemics in self.mask[polemic_keyword]:
             return True
@@ -818,14 +838,25 @@
             
         return value.pop()
     
+    def set_hash(self):
+        try:
+            self.id_hash = generate_hash(self.__unicode__())
+        except AttributeError:
+            self.id_hash = None
+            
+    def __unicode__(self):
+        return "/".join((
+            unicode(self.project_id if self.project_id is not None else ""),
+            unicode(self.iri_id if self.iri_id is not None else ""),
+            unicode(self.ensemble_id if self.ensemble_id is not None else ""),
+            unicode(self.cutting_id if self.cutting_id is not None else ""),
+            unicode(self.element_id if self.element_id is not None else "")
+            ))
+            
     def save(self, *args, **kwargs):
-        self.id_hash = generate_hash(self.__unicode__())
-                
+        self.set_hash()                
         super(Segment, self).save(*args, **kwargs)
-
     
-    def __unicode__(self):
-        return "/".join((unicode(self.project_id), unicode(self.iri_id), unicode(self.ensemble_id), unicode(self.cutting_id), unicode(self.element_id)))
     
     class Meta:
         permissions = (
--- a/src/ldt/ldt/ldt_utils/projectserializer.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/projectserializer.py	Sat May 11 23:09:05 2013 +0200
@@ -1,17 +1,17 @@
+from datetime import datetime
 from django.conf import settings
-from datetime import datetime
+from django.contrib.contenttypes.models import ContentType
 from django.utils.datastructures import SortedDict
-from ldt.ldt_utils.models import Content
+from ldt.ldt_utils.models import Content, User, Project
+from ldt.ldt_utils.stat import get_string_from_buckets
 from ldt.ldt_utils.utils import reduce_text_node
-from ldt.ldt_utils.models import User, Project
-from ldt.ldt_utils.stat import get_string_from_buckets
-from ldt.security.utils import use_forbidden_url
 import logging
 import lxml.etree
 import uuid
 
 DATE_FORMATS = ["%d/%m/%Y", "%Y-%m-%d"]
 
+logger = logging.getLogger(__name__)
 
 """
 Serialize a project object to a cinelab compatible array
@@ -40,6 +40,7 @@
         
         
     def __parse_views(self, display_node_list):
+        logger.debug("__parse_views start")
         for display_node in display_node_list:
             display_id = display_node.get(u"id", None)
             if not display_id:
@@ -90,11 +91,13 @@
                 new_display['annotation_types'] = [new_display['annotation_types'][0]] 
             
             self.views_dict[display_id] = new_display
-            
+        logger.debug("__parse_views done")        
     
     def __parse_ensemble(self, ensemble_node, content, cutting_only=None):
+                
+        ensemble_id = ensemble_node.attrib[u"id"]
+        logger.debug("__parse_ensemble %s start" % ensemble_id)
         
-        ensemble_id = ensemble_node.attrib[u"id"]
         ensemble_author = ensemble_node.attrib[u"author"]
         ensemble_title = ensemble_node.attrib[u"title"]
         ensemble_description = ensemble_node.attrib[u"abstract"]
@@ -280,10 +283,13 @@
         if not list_items:
             new_list["items"] = None
         self.lists_dict[ensemble_id] = new_list
+        
+        logger.debug("__parse_ensemble %s done" % ensemble_id)
 
 
     def __parse_ldt(self):
         
+        logger.debug("__parse_ldt start")
         self.ldt_doc = lxml.etree.fromstring(self.project.ldt_encoded)
         
         if self.from_display:
@@ -293,20 +299,35 @@
             
             self.__parse_views(self.ldt_doc.xpath(xpath_str))
         
+        #getting all contents at once
+        contents_iri_id = list(
+            set(self.ldt_doc.xpath("/iri/medias/media/@id")) |
+            set(self.ldt_doc.xpath("/iri/annotations/content/@id")) |
+            (set(self.ldt_doc.xpath('/iri/annotations/content[ensemble/decoupage/@id=\'%s\']/@id' % self.first_cutting)) if self.first_cutting and self.first_cutting not in self.display_cuttings_list else set())
+        )
+        
+        logger.debug(contents_iri_id)
+        
+        contents =  dict([ (c.iri_id, c) for c in Content.objects.filter(iri_id__in=contents_iri_id).select_related('media_obj', 'stat_annotation').prefetch_related("authors")])
+        m_cls = ContentType.objects.get(model='media')
+        m_cls = m_cls.model_class()
+        medias = dict([ (m.id, m) for m in m_cls.safe_objects.filter(id__in = [c.media_obj.id for c in contents.values() if c.media_obj])])
+          
+        
         res = self.ldt_doc.xpath("/iri/medias/media")
         for mediaNode in res:
             iri_id = mediaNode.attrib[u"id"]
             if self.from_display and iri_id not in self.display_contents_list:
                 continue
-            content = Content.objects.get(iri_id=iri_id) #@UndefinedVariable
-            self.__parse_content(content)
+            content = contents[iri_id]#Content.objects.get(iri_id=iri_id) #@UndefinedVariable
+            self.__parse_content(content, medias)
             
         res = self.ldt_doc.xpath("/iri/annotations/content")
         for content_node in res:
             content_id = content_node.attrib[u"id"]
             if self.from_display and content_id not in self.display_contents_list:
                 continue
-            content = Content.objects.get(iri_id=content_id) #@UndefinedVariable
+            content = contents[content_id]#Content.objects.get(iri_id=content_id) #@UndefinedVariable
             for ensemble_node in content_node:
                 if ensemble_node.tag != "ensemble" :
                     continue
@@ -320,7 +341,7 @@
             ensemble_node = cutting_node.xpath('..')[0]
             content_node = ensemble_node.xpath('..')[0]
             iri_id = content_node.get("id")
-            content = Content.objects.get(iri_id=iri_id)
+            content = contents[iri_id]#Content.objects.get(iri_id=iri_id)
             self.__parse_ensemble(ensemble_node, content, cutting_only=[cutting_node])
             
         
@@ -341,9 +362,11 @@
         self.__parse_edits()
                                
         self.parsed = True
+        logger.debug("__parse_ldt done")
         
     
     def __parse_edits(self):
+        logger.debug("__parse_edits start")
         editings = self.ldt_doc.xpath("/iri/edits/editing")
         if not editings:
             return False
@@ -378,10 +401,11 @@
                 }
             }
             self.lists_dict[e_id] = new_list
-        
+        logger.debug("__parse_edits done")    
     
-    def __parse_content(self, content):
+    def __parse_content(self, content, medias):
         
+        logger.debug("__parse_content %s start" % content.iri_id)
         doc = lxml.etree.parse(content.iri_file_path())
         
         authors = content.authors.all()
@@ -412,7 +436,7 @@
         url = ""
         meta_item_value = ""
         
-        if use_forbidden_url(content):   
+        if content.media_obj and content.media_obj.id not in medias:   
             url = settings.FORBIDDEN_STREAM_URL
         elif content.videopath:
             url = content.videopath.rstrip('/') + "/" + content.src
@@ -459,15 +483,20 @@
             res = doc.xpath("/iri/body/ensembles/ensemble")
             for ensemble_node in res:
                 self.__parse_ensemble(ensemble_node, content)
+                
+        logger.debug("__parse_content %s done" % content.iri_id)
 
     
     def serialize_to_cinelab(self):
     
         res = {}
-        
+
+        logger.debug("serialize_to_cinelab before parse ldt")
+                
         if not self.parsed:
             self.__parse_ldt()    
 
+            logger.debug("serialize_to_cinelab parse ldt done")
         
         project_main_media = ""
         if len(self.medias_dict) > 0:
--- a/src/ldt/ldt/ldt_utils/searchutils.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/searchutils.py	Sat May 11 23:09:05 2013 +0200
@@ -3,7 +3,9 @@
 from ldt.ldt_utils.utils import LdtUtils
 from ldt.security.utils import set_forbidden_stream
 import base64
+import logging
 
+logger = logging.getLogger(__name__)
 
 def search_generate_ldt(request, field, query, query_encoded=True): 
     
@@ -28,13 +30,21 @@
         id_list = ids.keys()
         projId_list = projIds.keys()
         typesId_list = typesIds.keys()
-            
-        contentList = Content.objects.filter(iri_id__in=id_list)        #@UndefinedVariable
-        projectList = Project.safe_objects.filter(ldt_id__in=projId_list)    
+        
+        logger.debug("search_generate_ldt : getting content list")    
+        contentList = Content.objects.filter(iri_id__in=id_list).select_related("front_project", "media_obj")        #@UndefinedVariable
+        logger.debug("search_generate_ldt : getting project list")
+        projectList = Project.safe_objects.filter(ldt_id__in=projId_list)
+        
+        
           
     ldtgen = LdtUtils()
     #            generate_ldt(contentList, title=u"", author=u"IRI Web", web_url=u"", startSegment=None, projects=None):
+    logger.debug("search_generate_ldt : generate ldt")
     doc = ldtgen.generate_ldt(contentList, title=u"Recherche : " + queryStr, projects=projectList, types_id_list=typesId_list)
+    
+    logger.debug("search_generate_ldt : set forbidden streams")
     doc = set_forbidden_stream(doc, request.user)
     
+    logger.debug("search_generate_ldt : done")
     return doc, results
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/segmentserializer.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/segmentserializer.py	Sat May 11 23:09:05 2013 +0200
@@ -3,9 +3,12 @@
 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 logging
 import lxml.etree
 import uuid
 
+logger = logging.getLogger(__name__)
+
 DATE_FORMATS = ["%d/%m/%Y", "%Y-%m-%d"]
 
 class SegmentSerializer(object):
@@ -30,13 +33,11 @@
                
         self.xml_docs = {}
         
-    def __get_cutting_title(self, project_id, content_id, ensemble_id, cutting_id):
+    def __get_cutting_title(self, project_id, content_id, ensemble_id, cutting_id, project):
         
         if not self.xml_docs.has_key(project_id):
-            project = Project.objects.filter(ldt_id=project_id)
             if not project:
                 return None
-            project = project[0]
             doc = lxml.etree.fromstring(project.ldt_encoded)
             self.xml_docs[project_id] = doc
         else:
@@ -74,7 +75,7 @@
 
         annotation_types = []        
         for seg in self.segments:
-            title = self.__get_cutting_title(seg.project_id, seg.iri_id, seg.ensemble_id, seg.cutting_id)
+            title = self.__get_cutting_title(seg.project_id, seg.iri_id, seg.ensemble_id, seg.cutting_id, seg.project_obj)
             annotation_types.append({'id': seg.cutting_id, 'title': title})
         
         for a in annotation_types:
@@ -98,7 +99,8 @@
         
         url = ""
         meta_item_value = ""
-            
+         
+        logger.debug("__parse_content start")   
         if use_forbidden_url(self.content):
             url = settings.FORBIDDEN_STREAM_URL
         elif self.content.videopath:
@@ -107,6 +109,8 @@
         else:
             url = self.content.src
         
+        logger.debug("__parse_content url %s " % url)
+        
         media = {
              "http://advene.liris.cnrs.fr/ns/frame_of_reference/ms" : "o=0",
              "id" : self.content.iri_id,
@@ -192,12 +196,16 @@
     
     def serialize_to_cinelab(self):
         
+        logger.debug("serialize_to_cinelab start")
         if not self.segments:
             return None
         
         self.__parse_content()
+        logger.debug("serialize_to_cinelab parse content done")
         self.__parse_segments()
+        logger.debug("serialize_to_cinelab parse segments done")
         self.__parse_views()
+        logger.debug("serialize_to_cinelab parse views done")
         
         res = {}
         res['views'] = self.views 
@@ -207,5 +215,7 @@
         res['annotations'] = self.annotations
         res['annotation-types'] = self.annotation_types
         
+        logger.debug("serialize_to_cinelab done")
+        
         return res
     
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/templates/front/front_group.html	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_group.html	Sat May 11 23:09:05 2013 +0200
@@ -14,17 +14,17 @@
 {% block js_declaration %}
 {{block.super}}
 <script type="text/javascript">
-$(document).ready(function () {
-    $("#home_tag_cloud").toggle(false);
-    $("#hide_tag_cloud").toggle(false);
-    $("#show_tag_cloud").toggle(true);
-    $("#tag_cloud_link").click(function(){
-        $("#home_tag_cloud").slideToggle("fast");
-        $("#hide_tag_cloud").toggle();
-        $("#show_tag_cloud").toggle();         
+    $(document).ready(function () {
+        $("#home_tag_cloud").toggle(false);
+        $("#hide_tag_cloud").toggle(false);
+        $("#show_tag_cloud").toggle(true);
+        $("#tag_cloud_link").click(function(){
+            $("#home_tag_cloud").slideToggle("fast");
+            $("#hide_tag_cloud").toggle();
+            $("#show_tag_cloud").toggle();         
         });
-});
-</script>
+    });
+</script> 
 {% endblock %}
 
 {% block body %}
--- a/src/ldt/ldt/ldt_utils/templates/front/front_home.html	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_home.html	Sat May 11 23:09:05 2013 +0200
@@ -112,7 +112,7 @@
             <a href="{% url ldt.ldt_utils.views.front.group_info group.id %}">{% thumbnail group.get_profile.image "54x40" format="PNG" crop="center" as im %}<img src="{{ im.url }}" class="img_media" width="{{ im.width }}" height="{{ im.height }}" alt="{% trans 'group picture' %}" title="{% trans 'view more infos on this group'%}">{% endthumbnail %}</a>
         </div>
         <div class="txt_groupes_actifs">
-            <div class="bulle_people" title="{% blocktrans count nb=group.user_set.count %}{{nb}} user in this group{% plural %}{{nb}} users in this group{% endblocktrans %}">{{ group.user_set.count }}</div>
+            <div class="bulle_people" title="{% blocktrans count nb=group.nb_users %}{{nb}} user in this group{% plural %}{{nb}} users in this group{% endblocktrans %}">{{ group.nb_users }}</div>
             <p><a href="{% url ldt.ldt_utils.views.front.group_info group.id %}" class="under" title="{% trans 'view more infos on this group'%}"><b>{{group.name}}</b></a></p>
             <p>{% if group.get_profile.description|striptags|length > 69 %}{{group.get_profile.description|striptags|slice:":69"}}...{% else %}{{group.get_profile.description|striptags}}{% endif %}</p>
         </div>
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html	Sat May 11 23:09:05 2013 +0200
@@ -10,13 +10,12 @@
 	{{ block.super }}
     <script type="text/javascript" src="{{ADMIN_MEDIA_PREFIX}}js/core.js" ></script>
     <script type="text/javascript" src="{{ADMIN_MEDIA_PREFIX}}js/jquery.init.js"></script>
-    <script type="text/javascript" src="{{ADMIN_MEDIA_PREFIX}}js/jquery.min.js"></script>
+    <script type="text/javascript" src='{% absstatic "ldt/js/jquery.min.js" %}'></script>
+    <script type="text/javascript" src="{% url ldt.jsi18n packages='ldt' %}" ></script>	
     <script type="text/javascript" src="{% absurl ldt.jsi18n packages='ldt' %}" ></script>
     <script type="text/javascript" src='{% absstatic "ldt/js/projectscontents.js" %}'></script>
     <script type="text/javascript" src='{% absstatic "ldt/js/jquery.textchange.min.js" %}'></script>
     <script type="text/javascript" src='{% absstatic "ldt/js/jquery-ui.min.js" %}'></script>
-    <script type="text/javascript" src='{% absstatic "ldt/js/swfupload/swfupload.js" %}'></script>
-	
 	{{ content_form.media.js }}
 {% endblock %}
 
@@ -29,27 +28,58 @@
 		post_added_params = {"csrfmiddlewaretoken" : "{{csrf_token}}",
                     		"{{cookie_name}}" : "{{session_key}}"};
 		
-		onCreateContentReady("{% url ldt.ldt_utils.views.content.upload %}",
-							"{% absstatic 'ldt' %}",
-							post_added_params,
-							"{% trans 'Browse' %}",
-							"{% trans 'File uploaded' %}",
-							"{% trans 'Please wait, the upload is not finished yet' %}",
-							"{% trans 'Cancel upload' %",
-							"{% url ldt.ldt_utils.views.content.remove_temp_file %}",
-							"{% url ldt.ldt_utils.views.content.get_duration %}");
-		
+	     onCreateContentReady("{% url ldt.ldt_utils.views.content.upload %}",
+	    	     "{% absstatic 'ldt' %}",
+	    	     post_added_params,
+	    	     "{% trans 'Browse' %}",
+	    	     "{% trans 'File uploaded' %}",
+	    	     "{% trans 'Please wait, the upload is not finished yet' %}",
+	    	     "{% trans 'Cancel upload' %",
+	    	     "{% url ldt.ldt_utils.views.content.remove_temp_file %}",
+	    	     "{% url ldt.ldt_utils.views.content.get_duration %}");
 	});
 	// the function stopRKey prevents from the validation of the form if the user tape enter button while entering a field 
 	function stopRKey(evt) {
 		  var evt = (evt) ? evt : ((event) ? event : null);
 		  var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
 		  if ((evt.keyCode == 13) && (node.type=="text"))  {return false;}
-		}
+	}
 
 	document.onkeypress = stopRKey;
 
+	chunked_uploads_endpoints = {
+		upload_url: '{{WEB_URL}}{% url upload %}',
+		done_url: '{{WEB_URL}}{% url upload_done uuid='00000000-0000-0000-0000-000000000000' %}',
+    };
 	
+	$(function() {		
+    	//gets video_url and returns it to the "scr" field
+    	chunked_uploads_video_url = function(video_url) {
+    		$('#id_content-media_input_type').val("create");
+    		$('#id_media-src').val(video_url);
+    		$('#id_media-src').attr('readOnly', true);
+    		$(".media_fields").hide();
+       		$("#media_field_create").show();
+    		$('#upload_url').append(video_url);
+	    };
+	    
+	    //callback of chunked upload start
+		chunked_uploads_start = function(){
+		};
+		
+		//callback of chunked upload stop
+		chunked_uploads_stop = function(){
+		};
+		
+		//callback of chunked upload error
+		chunked_uploads_error = function(){
+			alert("The upload failed. Please reload the page, and try again.");
+		};
+		
+		//callback of chunked upload complete
+		chunked_uploads_complete = function(){
+		};
+    });
     </script>
 {% endblock %}
 
@@ -60,8 +90,6 @@
 {% endblock %}
 
 {% block content %}
-
-	
 	{% if media_form.errors %}
 	<div id="media-form-error">
 		<p>{% trans "The operation could not be performed because one or more error(s) occurred.<br />Please resubmit the media form after making the following changes:" %}</p>
@@ -108,15 +136,14 @@
 		<div>{{ content_form.media_input_type.errors }}{{ content_form.media_input_type.label_tag }}{{content_form.media_input_type}}</div>
 		<div id="media_fields_div">
 			<div id="media_field_link" class="media_fields">{{ content_form.media_obj.errors }}{{ content_form.media_obj.label_tag }}{{content_form.media_obj}}</div>
+			
 			<div id="media_field_upload" class="media_fields">
-				{{ media_form.media_file.errors }}
-				{% comment %}{{ media_form.media_file.label_tag }}{{media_form.media_file}}{% endcomment %}
-				<div id="upload_btn"></div>
-				<input type="text" name="media-local_file_name" id="id_media-local_file_name" readonly/>
-				<div id="upload_progress_bar"></div>
-				<div id="upload_progress_info"></div>
+				<!-- refers to chunked_upload template -->
+				{% include "chunked_uploads.html"%}
 			</div>
+			
 			<div id="media_field_url" class="media_fields">{{ media_form.external_src_url.errors }}{{ media_form.external_src_url.label_tag }}{{ media_form.external_src_url }}</div>
+			
 			<div id="media_field_create" class="media_fields">{{ media_form.src.errors }}{{ media_form.src.label_tag }}{{ media_form.src }}</div>
 		</div>
 	</div>	 
@@ -132,7 +159,6 @@
 		{% endif %}
 	{% include "ldt/ldt_utils/partial/picture.html"%}
 	{% include "ldt/ldt_utils/partial/permissions.html" %}
-
 		
 	<div id="submitcontent" class="span-18 last">
 		<div id="submitcontent-loader" class="span-10">
@@ -149,4 +175,8 @@
 	
 	</form>
 	</div>
+	<script type="text/javascript" src='{% absstatic "chunked_uploads/js/jquery.ui.widget.js" %}'></script>
+	<script type="text/javascript" src='{% absstatic "chunked_uploads/js/jquery.iframe-transport.js" %}'></script>
+	<script type="text/javascript" src='{% absstatic "chunked_uploads/js/jquery.fileupload.js" %}'></script>
+	<script type="text/javascript" src='{% absstatic "chunked_uploads/js/jquery.chunked_uploads.js" %}'></script>
 {% endblock %}
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_iframe.html	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_iframe.html	Sat May 11 23:09:05 2013 +0200
@@ -70,7 +70,7 @@
 			                    },
 			            {% endif %}
 			            height: '{{ player_height }}',
-			            autostart: true
+			            autostart: {% if autostart %} true {% else %} false {% endif %}
 			        }  {% if polemic == 'all' or polemic == 'tweet' %},
 			        {
 			            type: "Polemic",
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_popup.html	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_popup.html	Sat May 11 23:09:05 2013 +0200
@@ -59,16 +59,16 @@
 
 	{% block content %}
 		<div id='ldt_id'>
-		  <p>{% trans 'Share the project' %} : <span class="large_text">{{ project.title }}</span></p>
-		  <p class="margin0">{% trans "List of the project's contents" %}:<br/>
-		     <ul>
-		     {% for c in contents %}
-		      <li>{{ c.title }} - <span class="middle_text">{% trans 'Link to the Metadata Player' %} : <a href="{% url ldt.ldt_utils.views.front.annot_content c.iri_id ldt_id %}" target="_blank">{% trans 'See' %}</a> - </span><span class="click_to_select">{% trans 'Select' %}</span> : <input id="" class="copy_input" value="{% absurl ldt.ldt_utils.views.front.annot_content c.iri_id ldt_id %}"/></li>
-		     {% endfor %}
-		    </ul>
-		  </p>
-		  <div>{% trans 'project id' %} <span id="project_id_select" class="click_to_select">({% trans 'Select' %})</span> : <input id="project_id_input" class="copy_input" value="{{ldt_id}}"/></div>
-		  <div>{% trans 'The project in Lignes de Temps' %} : <span class="middle_text"><a href="{% url index_project_full ldt_id %}" target="_blank">{% trans 'See' %}</a> - </span><span class="click_to_select">{% trans 'Select' %}</span> : <input id="" class="copy_input" value="{% absurl index_project_full ldt_id %}"/></div>
+          <p>{% trans 'Share the project' %} : <span class="large_text">{{ project.title }}</span></p>
+          <p class="margin0">{% trans "List of the project's contents" %}:<br/>
+             <ul>
+             {% for c in contents %}
+              <li>{{ c.title }} - <span class="middle_text">{% trans 'Link to the Metadata Player' %} : <a href="{% url ldt.ldt_utils.views.front.annot_content c.iri_id ldt_id %}" target="_blank">{% trans 'See' %}</a> - </span><span class="click_to_select">{% trans 'Select' %}</span> : <input id="" class="copy_input" value="{% absurl ldt.ldt_utils.views.front.annot_content c.iri_id ldt_id %}"/></li>
+             {% endfor %}
+            </ul>
+          </p>
+          <div>{% trans 'project id' %} <span id="project_id_select" class="click_to_select">({% trans 'Select' %})</span> : <input id="project_id_input" class="copy_input" value="{{ldt_id}}"/></div>
+          <div>{% trans 'The project in Lignes de Temps' %} : <span class="middle_text"><a href="{% url index_project_full ldt_id %}" target="_blank">{% trans 'See' %}</a> - </span><span class="click_to_select">{% trans 'Select' %}</span> : <input id="" class="copy_input" value="{% absurl index_project_full ldt_id %}"/></div>
         </div>
 		<br>
 		<div id="button_row">
@@ -84,7 +84,6 @@
 		
 		<div style="float: left;">
 			<div id="links_code" class="ldt_player_code">{% include "ldt/ldt_utils/partial/embed_links.html" %}</div>
-			
 			<div id="ldt_iframe_code">
                 <textarea id="ldt_iframe_id_code" readonly="readonly" class="ldt_player_code" >{% autoescape off %}<iframe src='{% absurl embed_ldt ldt_id %}' width='1005' height='635' seamless='seamless'></iframe>{% endautoescape %}</textarea>
             </div>
@@ -124,6 +123,9 @@
 							<span class="title">{% trans 'Create your own configuration' %}</span>
 						</a><br>
 							<div id="embed_personnalisation" class="embedPersonnalisation">
+								<input type="checkbox" id="autostart_checkbox" value="autostart" onClick="put_new_code()">
+									<span class="infostooltip title" data-title="AutoStart" data-desc="{% trans 'The video starts automatically' %}">Autostart</span>	
+								</input><br>
 								<div id="createannotation_block">
 									<input type="checkbox" id="createannotation_checkbox" value="createannotation" onClick="put_new_code(); display_createannotation();" > 
 										<span class="infostooltip title" data-title="createAnnotation" data-desc="{% trans 'Displays a form to create a new annotation' %}">CreateAnnotation</span>
@@ -228,7 +230,7 @@
 					<textarea id="player_id_code" readonly="readonly" class="ldt_player_code" onClick="select_code();"></textarea>
 				</div>
 			</div>
-          <a id="displayPlayer" href="javascript:toggle();">{% trans 'Show Player' %}</a>
+            <a id="displayPlayer" href="javascript:toggle();">{% trans 'Show Player' %}</a>
 		</div>
         <div id="player_div" style="display:none">
 	  		<button type="button" class="refresh_button" id="refresh_player_button" title="Rafraichir le player" >
@@ -237,4 +239,4 @@
 			<div class="ldt_player" id="wrapper_{{player_id}}"></div>
 		</div>
 	{% endblock %}
-	{% analytics %}
+	{% analytics %}
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/projectslist.html	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/projectslist.html	Sat May 11 23:09:05 2013 +0200
@@ -21,20 +21,27 @@
         {% url ldt.ldt_utils.views.json.project_json_id project.ldt_id as json_url_id %}
         {% if is_gecko %}
             <td class="cellimg"><div class="cellimgdiv"><a  href="{% url index_project_full project.ldt_id %}">
-            {% if project.change and project.state != 2 %}
+            {% if project.change or project.owner == user %}
+              {% if project.state != 2 %}
                 <img src='{% absstatic "ldt/img/page_edit.png" %}' alt="{% trans 'open ldt' %}" title="{% trans 'open ldt' %}"/>
+              {% else %}
+                <img src='{% absstatic "ldt/img/page_eye.png" %}' alt="{% trans 'open ldt' %}" title="{% trans 'open ldt' %}"/>
+              {% endif %}
             {% else %}
                 <img src='{% absstatic "ldt/img/page_eye.png" %}' alt="{% trans 'open ldt' %}" title="{% trans 'open ldt' %}"/>
             {% endif %}
             </a></div></td>
         {% else %}
             <td class="cellimg"><div class="cellimgdiv"><a href="{% url index_project project.ldt_id %}" class="ldt_link_open_ldt">
-            {% if project.change and project.state != 2 %}
+            {% if project.change or project.owner == user %}
+              {% if project.state != 2 %}
                 <img src='{% absstatic "ldt/img/page_edit.png" %}' alt="{% trans 'open ldt' %}" title="{% trans 'open ldt' %}"/>
+              {% else %}
+                <img src='{% absstatic "ldt/img/page_eye.png" %}' alt="{% trans 'open ldt' %}" title="{% trans 'open ldt' %}"/>
+              {% endif %}
             {% else %}
                 <img src='{% absstatic "ldt/img/page_eye.png" %}' alt="{% trans 'open ldt' %}" title="{% trans 'open ldt' %}"/>
             {% endif %}
-            
             </a></div></td>
         {% endif %}
         
@@ -50,9 +57,9 @@
         </td>
         <td class="cellimg">
         {% ifequal project.state 2 %}
-        <img src='{% absstatic "ldt/img/icon-yes.gif" %}' {% if project.change %} alt="{% trans 'Project published, click to unpublish' %}" title="{% trans 'Project published, click to unpublish' %}" class="publishedproject qtiplink" {% else %} class="qtiplink" title="{% trans "You are not allowed to change this project" %}"{% endif %} id="project_{{project.ldt_id}}" /></div>
+        <img src='{% absstatic "ldt/img/icon-yes.gif" %}' {% if project.change or project.owner == user %} alt="{% trans 'Project published, click to unpublish' %}" title="{% trans 'Project published, click to unpublish' %}" class="publishedproject qtiplink" {% else %} class="qtiplink" title="{% trans "You are not allowed to change this project" %}"{% endif %} id="project_{{project.ldt_id}}" /></div>
         {% else %}
-        <img src='{% absstatic "ldt/img/icon-no.gif" %}' {% if project.change %} alt="{% trans 'Project not published, click to publish' %}" title="{% trans 'Project not published, click to publish' %}" class="unpublishedproject qtiplink" {% else %} class="qtiplink" title="{% trans "You are not allowed to change this project" %}"{% endif %}id="project_{{project.ldt_id}}" />
+        <img src='{% absstatic "ldt/img/icon-no.gif" %}' {% if project.change or project.owner == user %} alt="{% trans 'Project not published, click to publish' %}" title="{% trans 'Project not published, click to publish' %}" class="unpublishedproject qtiplink" {% else %} class="qtiplink" title="{% trans "You are not allowed to change this project" %}"{% endif %}id="project_{{project.ldt_id}}" />
         {% endifequal %}
         </td>
         <td>{% thumbnail project.image "50x50" crop="center" format="PNG" as im %}<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />{% empty %}&nbsp;{% endthumbnail %}</td>
@@ -60,7 +67,7 @@
         {% if project.state == 2 %}
         <span class="projecttitlelink infostooltip" data-title="{{ project.title }}" data-desc="{{ project.description|linebreaksbr }}" >{% if show_username %}{{ project.owner.username }} : {% endif %}{{ project.title }}</span>
         {% else %}
-        	{% if project.change %}
+        	{% if project.change or project.owner == user %}
         	<a class="projecttitlelink" href="{% url ldt.ldt_utils.views.project.update_project ldt_id=project.ldt_id %}"><span class="infostooltip" data-title="{{ project.title }}" data-desc="{{ project.description|linebreaksbr }}" >{% if show_username %}{{ project.owner.username }} : {% endif %}{{ project.title }}</span></a>
         	{% else %}
         	<a class="projecttitlelink"><span class="qtiplink" title="{% trans "You are not allowed to change this project" %}">{% if show_username %}{{ project.owner.username }} : {% endif %}{{ project.title }}</span></a>
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/publishedprojectslist.html	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/publishedprojectslist.html	Sat May 11 23:09:05 2013 +0200
@@ -29,7 +29,8 @@
           <a href='{% url ldt.ldt_utils.views.workspace.popup_embed %}?json_url={{WEB_URL}}{{json_url_id}}&player_id=player_project_{{project.ldt_id}}&ldt_id={{project.ldt_id}}'>
            <img src='{% absstatic "ldt/img/plugin.png" %}' id="player_project_{{project.ldt_id}}" class="ldt_link_embed" alt="{% trans 'link json by id' %}" title="{% trans 'link json by id' %}"/>
           </a>
-         </div></td>
+         </div>
+        </td>
         <td class="cellimg">
         <img src='{% absstatic "ldt/img/icon-yes.gif" %}' alt="{% trans 'Project published' %}" id="project_{{project.ldt_id}}" />
         </td>
--- a/src/ldt/ldt/ldt_utils/tests/content_tests.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/tests/content_tests.py	Sat May 11 23:09:05 2013 +0200
@@ -5,19 +5,13 @@
 Replace these with more appropriate tests for your application.
 """
 
-from ldt.test.testcases import OAuthWebTestCase, TestCase
 from django.conf import settings
-from django.test import TestCase
-from ldt.ldt_utils.models import User, Project, Content, Media
-from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from django.utils._os import WindowsError
+from ldt.ldt_utils.models import User, Content, Media
 from ldt.test.client import Client
-import lxml.etree
-import tempfile
-import unittest
-import uuid
+from ldt.test.testcases import TestCase
 import logging
 import os
-import exceptions
 
 class ContentTest(TestCase):
     
@@ -27,7 +21,7 @@
         self.client = Client()
         User.objects.create_superuser('blop', 'blop@blop.com', 'blop')
         
-        client = self.client.login(username='blop', password='blop')
+        _ = self.client.login(username='blop', password='blop')
         
         self.user = User()
         self.user.username = 'blop'
--- a/src/ldt/ldt/ldt_utils/tests/ldt_tests.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/tests/ldt_tests.py	Sat May 11 23:09:05 2013 +0200
@@ -5,17 +5,15 @@
 Replace these with more appropriate tests for your application.
 """
 
-from ldt.test.testcases import OAuthWebTestCase, TestCase
-from django.conf import settings
-from django.test import TestCase
-from ldt.ldt_utils.models import User, Project, Content, Media
-from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from ldt.ldt_utils.models import User, Project, Content
+from ldt.ldt_utils.utils import (LdtUtils, LdtAnnotation, create_ldt, 
+    create_empty_iri, copy_ldt)
 from ldt.test.client import Client
+from ldt.test.testcases import TestCase
+import base64
 import lxml.etree
 import tempfile
-import unittest
 import uuid
-import logging
 
 class UtilsTest(TestCase):
     
@@ -25,7 +23,7 @@
         self.client = Client()
         User.objects.create_superuser('blop', 'blop@blop.com', 'blop')
         
-        client = self.client.login(username='blop', password='blop')
+        _ = self.client.login(username='blop', password='blop')
         
         self.user = User()
         self.user.username = 'blop'
@@ -77,11 +75,14 @@
         self.cont4.iri_id = "id4"
         self.cont4.save()
         
+        search=''
+        field='all'
+        query = base64.urlsafe_b64encode(search.encode('utf8'))
+
         self.project.contents.add(self.cont3, self.cont4)
-        ldoc = self.LU.generate_init([], 'ldt.ldt_utils.views.search_ldt')
+        ldoc = self.LU.generate_init([field, query], 'ldt.ldt_utils.views.lignesdetemps.search_ldt', 'ldt.ldt_utils.views.lignesdetemps.search_segments')
         self.assertEqual(ldoc.xpath("/iri/files/init")[0].tag, "init")
-        self.assertEqual(ldoc.xpath("/iri/files/library")[0].tag, "library")
-    
+        self.assertEqual(ldoc.xpath("/iri/files/library")[0].tag, "library")    
     def test_create_ldt(self):
         self.cont5 = Content(iriurl="id5/iriurl5", duration=111)
         self.cont5.iri_id = "id5"
@@ -97,7 +98,7 @@
         ldt = lxml.etree.fromstring(self.project.ldt_encoded)
         self.assertEqual(ldt.xpath("/iri")[0].tag, "iri")
         self.assertEqual(ldt.xpath("/iri/project")[0].get("title"), self.project.title)
-        self.assertEqual(ldt.xpath("/iri/medias/media")[0].get("src"), self.cont5.iri_url())
+        self.assertEqual(ldt.xpath("/iri/medias/media")[0].get("src"), self.cont5.relative_iri_url())
         self.assertEqual(ldt.xpath("/iri/medias/media")[1].get("id"), self.cont6.iri_id)
 
     def test_copy_ldt(self):
--- a/src/ldt/ldt/ldt_utils/tests/media_tests.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/tests/media_tests.py	Sat May 11 23:09:05 2013 +0200
@@ -5,18 +5,9 @@
 Replace these with more appropriate tests for your application.
 """
 
-from ldt.test.testcases import OAuthWebTestCase, TestCase
-from django.conf import settings
-from django.test import TestCase
-from ldt.ldt_utils.models import User, Project, Content, Media
-from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from ldt.ldt_utils.models import User, Media
 from ldt.test.client import Client
-from django.core.exceptions import ObjectDoesNotExist
-import lxml.etree
-import tempfile
-import unittest
-import uuid
-import logging
+from ldt.test.testcases import TestCase
 
 class MediaTest(TestCase):
     
@@ -26,13 +17,13 @@
         self.client = Client()
         User.objects.create_superuser('blop', 'blop@blop.com', 'blop')
         
-        client = self.client.login(username='blop', password='blop')
+        _ = self.client.login(username='blop', password='blop')
         
         self.user = User()
         self.user.username = 'blop'
     
     def test_create_media(self):
-        self.media1, created = Media.objects.get_or_create(src = "http://www.youtube.com/watch?v=O2G-PEtyKSY")
+        self.media1, _ = Media.objects.get_or_create(src = "http://www.youtube.com/watch?v=O2G-PEtyKSY")
         self.media1.id = 1
         self.media1.save()        
         
--- a/src/ldt/ldt/ldt_utils/tests/project_tests.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/tests/project_tests.py	Sat May 11 23:09:05 2013 +0200
@@ -5,17 +5,14 @@
 Replace these with more appropriate tests for your application.
 """
 
-from ldt.test.testcases import OAuthWebTestCase, TestCase
-from django.conf import settings
-from django.test import TestCase
-from ldt.ldt_utils.models import User, Project, Content, Media
-from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from django.core.management import call_command
+from ldt.ldt_utils.models import User, Project, Content
+from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt
 from ldt.test.client import Client
+from ldt.test.testcases import TestCase
 import lxml.etree
-import tempfile
-import unittest
 import uuid
-import logging
+
 
 class ProjectTest(TestCase):
     
@@ -25,14 +22,29 @@
         self.client = Client()
         User.objects.create_superuser('blop', 'blop@blop.com', 'blop')
         
-        client = self.client.login(username='blop', password='blop')
-        
+        _ = self.client.login(username='blop', password='blop')
         self.user = User()
         self.user.username = 'blop'
+        self.LU = LdtUtils()
+        self.project = Project(title="titleproj1", owner=self.user)
+        self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+        self.project.id = "11321"
+        self.project.ldt_id = str(uuid.uuid1())
+        self.project.description = "proj1description"
+        self.project.save()
         
-    def test_create_project(self):       
+    def test_create_project(self):   
+        self.cont1 = Content(iriurl="cont1_id/iriurl1", duration=123)
+        self.cont1.iri_id = "cont1_id"
+        self.cont1.save()
+        
+        self.cont2 = Content(iriurl="cont2_id/iriurl2", duration=100)
+        self.cont2.iri_id = "cont2_id"
+        self.cont2.save()
+        
         self.project2 = Project(title="titleproj2", owner=self.user)
-        self.project2.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a212" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+    
+        self.project2.ldt = self.LU.generate_ldt(Content.objects.all())    
         self.project2.ldt_id = str(uuid.uuid1())
         self.project2.description = "proj2description"
         self.project2.save()
@@ -41,8 +53,12 @@
         
     #test deletion of project without annotation
     def test_del_project_v1(self):
+        self.cont3 = Content(iriurl="cont3_id/iriurl3", duration=100)
+        self.cont3.iri_id = "cont3_id"
+        self.cont3.save()
+        
         self.project3 = Project(title="titleproj3", owner=self.user)
-        self.project3.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a333" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+        self.project3.ldt = self.LU.generate_ldt(Content.objects.all())  
         self.project3.id = "333"
         self.project3.ldt_id = str(uuid.uuid1())
         self.project3.description = "proj3description"
@@ -55,9 +71,12 @@
     
     #test deletion of project with annotations  
     def test_del_project_v2(self):
+        self.cont4 = Content(iriurl="cont4_id/iriurl4", duration=100)
+        self.cont4.iri_id = "cont4_id"
+        self.cont4.save()
         
-        self.project4 = Project(title="titleproj3", owner=self.user)
-        self.project4.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a333" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+        self.project4 = Project(title="titleproj4", owner=self.user)
+        self.project4.ldt=self.LU.generate_ldt(Content.objects.all())  
         self.project4.id = "444"
         self.project4.ldt_id = str(uuid.uuid1())
         self.project4.description = "proj4description"
@@ -74,4 +93,76 @@
         self.project4.delete()
 
         with self.assertRaises(Project.DoesNotExist):
-            Project.objects.get(ldt_id=self.project4.ldt_id)
\ No newline at end of file
+            Project.objects.get(ldt_id=self.project4.ldt_id)
+    
+    def test_clean_database_project(self) :
+        self.cont5 = Content(iriurl="cont5_id/iriurl5", duration=123)
+        self.cont5.iri_id = "cont5_id"
+        self.cont5.save()
+        
+        self.cont6 = Content(iriurl="cont6_id/iriurl6", duration=100)
+        self.cont6.iri_id = "cont6_id"
+        self.cont6.save()
+        
+        self.cont7 = Content(iriurl="cont7_id/iriurl7", duration=100)
+        self.cont7.iri_id = "cont7_id"
+        self.cont7.save()
+        
+        self.project.contents.add(self.cont5, self.cont6)
+    
+        doc = self.LU.generate_ldt(Content.objects.all())
+        
+        #project5 : valid project
+        self.project5 = Project(title="titleproj5", owner=self.user)
+        ldt = lxml.etree.tostring(doc, pretty_print = False)
+        self.project5.ldt = ldt
+        self.project5.id = "555"
+        self.project5.ldt_id = str(uuid.uuid1())
+        self.project5.description = "proj5description"
+        self.project5.save()
+        
+        #project6 : project with empty ldt
+        self.project6 = Project(title="titleproj5", owner=self.user)
+        self.project6.id = "666"
+        self.project6.ldt_id = str(uuid.uuid1())
+        self.project6.description = "proj6description"
+        self.project6.save()
+        
+        #project7 : project with a non-existing media
+        
+        self.project7 = Project(title="titleproj7", owner=self.user)
+        self.project7.id = "777"
+        self.project7.ldt_id = str(uuid.uuid1())
+        self.project7.ldt = '<iri><project id="a18ec3de-49c1-11e2-8e5d-00161798aedb" title="" user="IRI Web" abstract=""/><medias><media id="non_existing_media" src="ldt/non_existing_media/non_existing_media_iri_url" video="%(stream_url)s" pict="" extra=""/></medias><annotations/><displays><display id="0" title="generated" idsel="cont5_id" tc="0"><content id="cont5_id"/><content id="cont6_id"/><content id="cont7_id"/></display></displays><edits/></iri>'
+        self.project7.description = "proj7description"
+        self.project7.save()
+        
+        #project8 : project with multiple medias some valid and some that don't exist
+        self.project8 = Project(title="titleproj8", owner=self.user)
+        self.project8.id = "888"
+        self.project8.ldt_id = str(uuid.uuid1())
+        self.project8.ldt = '<iri><project id="a18ec3de-49c1-11e2-8e5d-00161798aedb" title="" user="IRI Web" abstract=""/><medias><media id="cont5_id" src="ldt/cont5_id/iriurl5" video="%(stream_url)s" pict="" extra=""/><media id="non_existing_media" src="ldt/non_existing_media/non_existing_media_iri_url" video="%(stream_url)s" pict="" extra=""/><media id="cont6_id" src="ldt/cont6_id/iriurl6" video="%(stream_url)s" pict="" extra=""/><media id="cont7_id" src="ldt/cont7_id/iriurl7" video="%(stream_url)s" pict="" extra=""/></medias><annotations/><displays><display id="0" title="generated" idsel="cont5_id" tc="0"><content id="cont5_id"/><content id="cont6_id"/><content id="cont7_id"/></display></displays><edits/></iri>'
+        self.project8.description = "proj8description"
+        self.project8.save()
+        
+        #project9 : project without any media
+        self.project9 = Project(title="titleproj9", owner=self.user)
+        self.project9.id = "999"
+        self.project9.ldt_id = str(uuid.uuid1())
+        self.project9.ldt = '<iri><project id="a18ec3de-49c1-11e2-8e5d-00161798aedb" title="" user="IRI Web" abstract=""/><medias></medias><annotations/><displays><display id="0" title="generated" idsel="cont5_id" tc="0"><content id="cont5_id"/><content id="cont6_id"/><content id="cont7_id"/></display></displays><edits/></iri>'
+        self.project9.description = "proj9description"
+        self.project9.save()
+        
+        call_command('set_projectldtiri')
+
+        with self.assertRaises(Project.DoesNotExist):
+            Project.objects.get(ldt_id=self.project6.ldt_id)
+        
+        with self.assertRaises(Project.DoesNotExist):
+            Project.objects.get(ldt_id=self.project7.ldt_id)
+        
+        with self.assertRaises(Project.DoesNotExist):
+            Project.objects.get(ldt_id=self.project9.ldt_id)
+        
+        self.assertEqual(ldt, self.project5.ldt)    
+        
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/tests/view_tests.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/tests/view_tests.py	Sat May 11 23:09:05 2013 +0200
@@ -5,17 +5,8 @@
 Replace these with more appropriate tests for your application.
 """
 
-from ldt.test.testcases import OAuthWebTestCase, TestCase
-from django.conf import settings
-from django.test import TestCase
-from ldt.ldt_utils.models import User, Project, Content, Media
-from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
-from ldt.test.client import Client
-import lxml.etree
-import tempfile
+from ldt.ldt_utils.models import Project, Content
 import unittest
-import uuid
-import logging
 
 class ViewsTest(unittest.TestCase):
     def setUp(self):
--- a/src/ldt/ldt/ldt_utils/urls.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/urls.py	Sat May 11 23:09:05 2013 +0200
@@ -1,4 +1,4 @@
-from django.conf.urls.defaults import patterns, url
+from django.conf.urls.defaults import patterns, url, include
 from ldt.management import test_ldt
 
 # Uncomment the next two lines to enable the admin:
@@ -28,11 +28,11 @@
     url(r'^cljson/idcutting/(?P<id>.*)/(?P<cutting_id>.*)$', 'views.json.project_json_cutting_id'),
     url(r'^rdf/id/(?P<ldt_id>.*)$', 'views.rdf.project_annotations_rdf'),
     url(r'^workspace/?$', "views.workspace.home", name="root-view"),
-    url(r'^filterprojects/_(?P<filter>[\w\%\_\-\+]*?)/(?P<is_owner>true|false)/(?P<status>\d)$', "views.project.projects_filter",),
-    url(r'^filterprojects/_(?P<filter>[\w\%\_\-\+]*?)/(?P<is_owner>true|false)/(?P<status>\d)/(?P<id_group>.*)$', "views.project.projects_filter",),
-    url(r'^filtercontents/_(?P<filter_c>[\w\%\_\-\+]*?)/$', "views.content.contents_filter",),
-    url(r'^filtergroups/_(?P<filter>[\w\%\_\-\+]*?)/$', "views.group.groups_filter",),
-    url(r'filtershare/_(?P<filter>[\w\%\_\-\+]*?)/(?P<use_groups>true|false)$', "views.workspace.share_filter"),
+    url(r'^filterprojects/_(?P<filter>[\w \%\_\-\+]*?)/(?P<is_owner>true|false)/(?P<status>\d)$', "views.project.projects_filter",),
+    url(r'^filterprojects/_(?P<filter>[\w \%\_\-\+]*?)/(?P<is_owner>true|false)/(?P<status>\d)/(?P<id_group>.*)$', "views.project.projects_filter",),
+    url(r'^filtercontents/_(?P<filter_c>[\w \%\_\-\+]*?)/$', "views.content.contents_filter",),
+    url(r'^filtergroups/_(?P<filter>[\w \%\_\-\+]*?)/$', "views.group.groups_filter",),
+    url(r'filtershare/_(?P<filter>[\w \%\_\-\+]*?)/(?P<use_groups>true|false)$', "views.workspace.share_filter"),
     url(r'^embedpopup/?$', "views.workspace.popup_embed"),
     url(r'^embediframe/?$', "views.workspace.iframe_embed", name="embediframe_page"),
     url(r'^embedldt/(?P<id>.*)$', 'views.lignesdetemps.embed_ldt', name='embed_ldt'),
@@ -78,5 +78,5 @@
         url(r'^space/upload/$', 'views.content.upload'),
         url(r'^space/removetempfile/$', 'views.content.remove_temp_file'),
         url(r'^space/getduration/$', 'views.content.get_duration'),
-
+        url(r'^chunked_uploads/', include('chunked_uploads.urls')),
 )
--- a/src/ldt/ldt/ldt_utils/utils.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/utils.py	Sat May 11 23:09:05 2013 +0200
@@ -8,7 +8,6 @@
 import uuid
 from ldt.utils.url import request_with_auth
 from ldt.utils.url import absurl_norequest
-import logging
 
 __BOOLEAN_DICT = {
     'false':False,
@@ -58,7 +57,7 @@
                 videopath = unicode(content.videopath)
             media = lxml.etree.SubElement(medias, "media")
             media.set(u"id", content.iri_id)
-            media.set(u"src", content.iri_url(web_url))
+            media.set(u"src", content.relative_iri_url())
             media.set(u"video", videopath)
             media.set(u"pict", u"")
             media.set(u"extra", u"")
@@ -277,12 +276,12 @@
             tag_node = lxml.etree.SubElement(tags, 'tag')
             tag_node.text = tag
         
-        return cutting_id, id_annotation
+        return cutting_id, id_annotation, ensemble_id
     
-    def save(self):
+    def save(self, must_reindex=True):
         if self.to_add:
             self.project.ldt = lxml.etree.tostring(self.ldtdoc, pretty_print=True)
-            self.project.save()
+            self.project.save(must_reindex=must_reindex)
        
     def get_polemic_syntax(self, text):
         polemics = []
@@ -322,7 +321,7 @@
             idsel = content.iri_id
         elementMedia = lxml.etree.SubElement(elementMedias, 'media')
         elementMedia.set('id', content.iri_id)
-        elementMedia.set('src', content.iri_url())
+        elementMedia.set('src', content.relative_iri_url())
         
         if content.videopath != None :
             elementMedia.set('video', content.videopath)
--- a/src/ldt/ldt/ldt_utils/views/content.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/views/content.py	Sat May 11 23:09:05 2013 +0200
@@ -123,7 +123,6 @@
             
             
         except Exception as inst:
-            logging.debug("write_content_base : POST error when processing file:" + str(inst)) #@UndefinedVariable
             form_status = "error"
             #set error for form
             if media_input_type == "url":
@@ -171,9 +170,8 @@
 @transaction.commit_manually
 def write_content_base(request, iri_id=None):
     if iri_id:
-        instance_content = Content.safe_objects.get(iri_id=iri_id) #@UndefinedVariable
+        instance_content = Content.safe_objects.select_related('media_obj','front_project').get(iri_id=iri_id) #@UndefinedVariable
         instance_media = instance_content.media_obj
-        logging.debug("write_content_base : valid form: for instance : media -> " + repr(instance_media) + " content : for instance : " + repr(instance_content)) #@UndefinedVariable
     else:
         logging.debug("No iri_id") #@UndefinedVariable
         instance_content = None
@@ -234,7 +232,6 @@
                             picture_form.cleaned_data["image"]=File(img_temp) 
                     except Exception as inst:
                         logging.debug("couldn't download video thumbnail from image_link : " + str(image_link))
-            logging.debug("write_content_base : valid form: for instance : " + repr(instance_media) + " -> media " + str(media_valid) + " content : for instance : " + repr(instance_content) + " : " + str(content_valid) + "picture : valid :" +str(picture_valid)) #@UndefinedVariable
             
             if media_valid and content_valid and picture_valid:
     
@@ -297,7 +294,7 @@
         except Exception, e:
             transaction.rollback()
             __, value, traceback = sys.exc_info()
-            return False, False, False, False, False, e, traceback
+            return False, False, False, False, False, False, e, traceback
             
     else:
         form_status = 'empty'
@@ -326,9 +323,9 @@
     except Exception, e:
         transaction.rollback()
         __, __, traceback = sys.exc_info()
-        return False, False, False, False, False, e, traceback
+        return False, False, False, False, False, False, e, traceback
         
-    return content_form, media_form, picture_form, form_status, current_front_project, "", ""
+    return content_form, media_form, picture_form, form_status, instance_content, current_front_project, "", ""
 
 @login_required
 def write_content(request, iri_id=None):  
@@ -370,7 +367,7 @@
         return render_to_response('ldt/ldt_utils/reset_confirm.html', {'errors':errors, 'message':message, 'title': title}, context_instance=RequestContext(request))
     elif submit_action == "reset":
         #TODO : verifier index de la recherche maj
-        content = Content.objects.get(iri_id=iri_id)
+        content = Content.objects.get(iri_id=iri_id).select_related('front_project')
         project_temp = content.front_project
         content.create_front_project()
         content.save()
@@ -379,9 +376,9 @@
     elif submit_action=="close":
         return redirect("root-view")
     else:
-        content_form, media_form, picture_form, form_status, current_front_project, e, traceback = write_content_base(request, iri_id)        
+        content_form, media_form, picture_form, form_status, content_temp, current_front_project, e, traceback = write_content_base(request, iri_id)        
         if iri_id: 
-            content_temp = Content.objects.get(iri_id=iri_id)
+            #content_temp = Content.objects.select_related('media_obj').get(iri_id=iri_id)
             media_temp = content_temp.media_obj
             if media_temp:
                 member_list, admin_list = get_userlist_model(media_temp, request.user)
--- a/src/ldt/ldt/ldt_utils/views/front.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/views/front.py	Sat May 11 23:09:05 2013 +0200
@@ -3,6 +3,7 @@
 from django.contrib.auth.models import Group, User
 from django.core.paginator import Paginator, InvalidPage, EmptyPage
 from django.core.urlresolvers import reverse
+from django.db.models import Count
 from django.shortcuts import render_to_response
 from django.template import RequestContext
 from ldt.ldt_utils.models import Content, Project
@@ -13,23 +14,24 @@
 from tagging.models import TaggedItem
 from ldt.utils.url import absstatic
 
+import logging
+logger = logging.getLogger(__name__)
 
 
 def front_home(request):
     # Get the 3 last annotated contents
-    last_contents = Content.safe_objects.order_by('-stat_annotation__last_annotated').exclude(stat_annotation__nb_annotations=0)[:3]
+    last_contents = Content.safe_objects.order_by('-stat_annotation__last_annotated').select_related('stat_annotation').exclude(stat_annotation__nb_annotations=0)[:3]
     # Get the most annotated contents
-    most_contents = Content.safe_objects.order_by('-stat_annotation__nb_annotations')[:8]
+    most_contents = Content.safe_objects.order_by('-stat_annotation__nb_annotations').select_related('stat_annotation')[:8]
     # Get the active groups
-    active_groups = Group.objects.exclude(name=settings.PUBLIC_GROUP_NAME)[:5]
+    active_groups = Group.objects.select_related("profile").annotate(nb_users=Count("user")).exclude(name=settings.PUBLIC_GROUP_NAME)[:5]
     # Get the main tag list
     front_tags = settings.FRONT_TAG_LIST
     # Get the all tags list
     tag_cloud = get_content_tags()
-
     
     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, 'front_tags':front_tags,
                                'tag_cloud': tag_cloud, 'is_gecko': is_gecko},
@@ -48,9 +50,10 @@
                                'is_gecko': is_gecko},
                               context_instance=RequestContext(request))
 
-
 @login_required
 def group_info(request, group_id):
+    
+    # Get the active group
     group = Group.objects.select_related("profile").get(id=group_id)
     proj_title = request.GET.get("title")
     # Get the projects for this group
@@ -70,7 +73,7 @@
         results = paginator.page(page)
     except (EmptyPage, InvalidPage):
         results = paginator.page(paginator.num_pages)
-
+    
     # Group's users
     users = User.objects.filter(groups__in=[group]).exclude(is_superuser=True)
     
@@ -94,11 +97,11 @@
         tag_label = request.GET.get("tag")
         # Get all the public contents group
         if tag_label is None :
-            content_list = Content.safe_objects.all()
+            content_list = Content.safe_objects.all().select_related('stat_annotation')
         else :
-            content_list = TaggedItem.objects.get_by_model(Content.safe_objects.all(), '"'+tag_label+'"')
+            content_list = TaggedItem.objects.get_by_model(Content.safe_objects.all().select_related('stat_annotation'), '"'+tag_label+'"')
     else :
-        content_list = Content.safe_objects.filter(title__icontains=media_title)
+        content_list = Content.safe_objects.filter(title__icontains=media_title).select_related('stat_annotation')
     
     
     nb = settings.LDT_FRONT_MEDIA_PER_PAGE
@@ -187,7 +190,6 @@
             content_list = TaggedItem.objects.get_by_model(Content.objects.all(), '"'+content_tag+'"')
         results, nb, nb_segment = get_search_results(request, search, field, page, content_list)
 
-
     return render_to_response('front/front_search_results.html', {'results': results, 'nb_results' : nb, 'nb_segment':nb_segment, 'search' : search, 'field': field, 'tag_label':content_tag, 'colorurl': colorurl, 'i18nurl': i18nurl, 'language': language_code, 'baseurl': baseurl}, context_instance=RequestContext(request))
 
 
--- a/src/ldt/ldt/ldt_utils/views/group.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/views/group.py	Sat May 11 23:09:05 2013 +0200
@@ -13,8 +13,7 @@
 
 @login_required
 def get_group_projects_view(request):
-
-    # Get group, user and project_list
+    
     grp_id = request.POST["id_group"]
     project_list = get_group_projects(request.user, grp_id)
     
@@ -31,15 +30,15 @@
     # Get group, user and project_list
     if grp_id == "-1":
         if exclude_owner:
-            project_list = get_objects_for_user(user, 'ldt_utils.view_project', use_groups=False).exclude(owner=user)
+            project_list = get_objects_for_user(user, 'ldt_utils.view_project', use_groups=False).exclude(owner=user).select_related("owner")
         else:
-            project_list = get_objects_for_user(user, 'ldt_utils.view_project', use_groups=False)
+            project_list = get_objects_for_user(user, 'ldt_utils.view_project', use_groups=False).select_related("owner")
     else:
         grp = Group.objects.get(id=grp_id)
         if exclude_front:
-            project_list = get_objects_for_group(grp, 'ldt_utils.view_project').exclude(title__startswith='front')
+            project_list = get_objects_for_group(grp, 'ldt_utils.view_project').exclude(title__startswith='front').select_related("owner")
         else:
-            project_list = get_objects_for_group(grp, 'ldt_utils.view_project')
+            project_list = get_objects_for_group(grp, 'ldt_utils.view_project').select_related("owner")
     project_list = add_change_attr(user, project_list)
     
     return project_list
--- a/src/ldt/ldt/ldt_utils/views/json.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/views/json.py	Sat May 11 23:09:05 2013 +0200
@@ -14,6 +14,8 @@
 import lxml.etree
 import logging
 
+logger = logging.getLogger(__name__)
+
 
 def project_json_id(request, id): 
     
@@ -96,7 +98,6 @@
     # do we remove annotations from mashup if the have duration=0 ? (yes by default)
     remove_zero_dur_str = request.REQUEST.get("removezeroduration")
     remove_zero_dur = True
-    logging.debug("CC 1 " + str(remove_zero_dur))
     if remove_zero_dur_str:
         remove_zero_dur = {'true': True, 'false': False, "0": False, "1": True}.get(remove_zero_dur_str.lower())
     
@@ -106,14 +107,23 @@
     if s:
         # We get the projects with all the segments
         project_xml, results = search_generate_ldt(request, "tags", s, False)
+        
+        logger.debug("mashup_by_tag : search_generate_ldt done")
+        
         project = Project()
         project.ldt = lxml.etree.tostring(project_xml, pretty_print=True)
         # Needed datas for jsonification
         now = datetime.now()
         project.modification_date = project.creation_date = now
         #return HttpResponse(lxml.etree.tostring(project_xml, pretty_print=True), mimetype="text/xml;charset=utf-8")
+        logger.debug("mashup_by_tag : serialize_to_cinelab prepare")
+        
         ps = ProjectJsonSerializer(project, from_contents=False)
+        logger.debug("mashup_by_tag : serialize_to_cinelab serializer ready")        
         mashup_dict = ps.serialize_to_cinelab()
+
+        logger.debug("mashup_by_tag : serialize_to_cinelab done")
+        
         # Now we build the mashup with the good segments (the ones between in and out)
         if results:
             tc_in = 0
@@ -178,6 +188,8 @@
                     cur_out = cur_in + dur
                     if tc_in<=cur_in and cur_out<=tc_out and ((not remove_zero_dur) or (remove_zero_dur and dur>0.0)):
                         mashup_list["items"].append(res["element_id"])
+            if mashup_dict["lists"] is None:
+                mashup_dict["lists"] = []
             mashup_dict["lists"].append(mashup_list)
     
             # If asked, we remove the annotations not used in the mashup.
@@ -202,8 +214,6 @@
         json_str = "%s(%s)" % (callback, json_str)
     
     resp = HttpResponse(mimetype="application/json; charset=utf-8")
-    resp['Cache-Control'] = 'no-cache, must-revalidate'
-    resp['Pragma'] = 'no-cache'
     resp.write(json_str)
     
     return resp
--- a/src/ldt/ldt/ldt_utils/views/lignesdetemps.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/views/lignesdetemps.py	Sat May 11 23:09:05 2013 +0200
@@ -4,21 +4,22 @@
 from django.http import HttpResponse, HttpResponseRedirect
 from django.shortcuts import render_to_response, get_object_or_404
 from django.template import RequestContext
+from ldt.indexation import SimpleSearch
 from ldt.ldt_utils.models import Content, Project, Media
+from ldt.ldt_utils.searchutils import search_generate_ldt
+from ldt.ldt_utils.stat import update_stat_project
 from ldt.ldt_utils.utils import LdtUtils, clean_description
-from ldt.indexation import SimpleSearch
 from ldt.security.permissionchecker import check_object_perm_for_user
 from ldt.security.utils import set_forbidden_stream
-from ldt.ldt_utils.stat import update_stat_project
-from ldt.ldt_utils.searchutils import search_generate_ldt
+from ldt.utils.projectldt_parser import absolute_src_xml, relative_src_xml
 from ldt.utils.url import absstatic, absurl
 from ldt.utils.web_url_management import get_web_url
 import base64
+import logging
 import lxml.etree
 
-import logging
 logger = logging.getLogger(__name__)
-  
+
 def search_index_get(request, field, query):
     
     language_code = request.LANGUAGE_CODE[:2]
@@ -44,6 +45,7 @@
     
     resp = HttpResponse(mimetype="text/xml")
     doc, _ = search_generate_ldt(request, field, query)
+    doc = absolute_src_xml(doc)
     doc.write(resp, pretty_print=True)
     
     return resp
@@ -101,7 +103,6 @@
     
     ldtgen = LdtUtils()
     doc = ldtgen.generate_init([project_id, content_id, ensemble_id, cutting_id, segment_id], 'ldt.ldt_utils.views.lignesdetemps.ldt_segment', 'ldt.ldt_utils.views.lignesdetemps.highlight_segment')
-    
     return HttpResponse(lxml.etree.tostring(lxml.etree.ElementTree(doc), pretty_print=True), mimetype="text/xml;charset=utf-8")
 
 def highlight_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id):
@@ -131,6 +132,7 @@
     if project_id and project_id != "_" :
         project = Project.safe_objects.get(ldt_id=project_id) #@UndefinedVariable
         ldtdoc = lxml.etree.fromstring(project.ldt_encoded)
+        ldtdoc = absolute_src_xml(ldtdoc)
         ldtdoc = set_forbidden_stream(ldtdoc, request.user)
         displays_node = ldtdoc.find("displays")
         if not displays_node:
@@ -176,6 +178,7 @@
         }        
         
         doc = ldtgen.generate_ldt(content_list, "segment : ", author=username, startSegment=start_segment)
+        doc = absolute_src_xml(doc)
         doc = set_forbidden_stream(doc, request.user)
         doc.write(resp, pretty_print=('DEBUG' in dir(settings) and settings.DEBUG))
         
@@ -184,7 +187,7 @@
    
 @login_required    
 def index_project(request, id, full=False): 
-    
+
     urlStr = absurl(request, "ldt.ldt_utils.views.lignesdetemps.init", args=['ldt_project', id])
     posturl = absurl(request, "ldt.ldt_utils.views.lignesdetemps.save_ldt_project")
     language_code = request.LANGUAGE_CODE[:2]
@@ -212,13 +215,12 @@
     else:
         template_path = 'ldt/ldt_utils/init_ldt.html'
     
-    return render_to_response(template_path, 
-                              {'colorurl': colorurl, 'i18nurl': i18nurl, 'language': language_code, 
-                               'baseurl': baseurl, 'url': urlStr, 'posturl': posturl, 
-                               'id': id, 'readonly': readonly, 'audio_record_url': audio_record_url}, 
+    return render_to_response(template_path,
+                              {'colorurl': colorurl, 'i18nurl': i18nurl, 'language': language_code,
+                                'baseurl': baseurl, 'url': urlStr, 'posturl': posturl,
+                                'id': id, 'readonly': readonly},
                               context_instance=RequestContext(request))
-
-
+    
 
 def embed_ldt(request, id): 
     # Almost identical to index_project but without login_required and less parameters
@@ -275,6 +277,7 @@
     
     doc = lxml.etree.fromstring(project.ldt_encoded)
     doc = set_forbidden_stream(doc, request.user)
+    doc = absolute_src_xml(doc)
     resp.write(lxml.etree.tostring(doc, pretty_print=True, xml_declaration=True, encoding="utf-8")) 
 
     return resp
@@ -284,10 +287,12 @@
 def save_ldt_project(request):
     if request.method == "POST":
         ldt = request.POST['ldt']
-        id = request.POST['id']
-        ldtproject = Project.safe_objects.select_related().get(ldt_id=id) #@UndefinedVariable
-
+        ldt_id = request.POST['id']
+        ldtproject = Project.safe_objects.select_related().get(ldt_id=ldt_id) #@UndefinedVariable
+        ldtxml=lxml.etree.fromstring(ldt)
         #save xml ldt
+        ldt, _, _ = relative_src_xml(ldtxml)
+        ldt = lxml.etree.tostring(ldt, pretty_print=True)          
         ldtproject.ldt = ldt
         
         doc = lxml.etree.fromstring(ldtproject.ldt_encoded)
@@ -300,11 +305,11 @@
         new_contents = []
         result = doc.xpath("/iri/medias/media")
         for medianode in result:
-            id = medianode.get("id")
-            new_contents.append(id)
+            media_id = medianode.get("id")
+            new_contents.append(media_id)
             #Put back the video fied from "forbidden_stream_url" to the video url
             if medianode.get("video") == settings.FORBIDDEN_STREAM_URL:
-                content = Content.objects.get(iri_id=id)
+                content = Content.objects.get(iri_id=media_id)
                 media = Media.objects.get(id=content.media_obj.id)
                 medianode.set('video', media.videopath)
                 ldtproject.ldt = lxml.etree.tostring(doc, pretty_print=True)
@@ -325,7 +330,7 @@
             if c not in contents_id:
                 content = Content.objects.get(iri_id=c)
                 ldtproject.contents.add(content)
-        
+         
         update_stat_project(ldtproject)
         
         #remove html tags added by flash
@@ -338,7 +343,7 @@
             ldtproject.ldt = lxml.etree.tostring(doc, pretty_print=True)
         
         ldtproject.description = new_desc if new_desc else description
-        
+    
         #set a new icon for this project
         if check_icon_project:
             ldtproject.set_icon()
@@ -349,7 +354,7 @@
         ldt = ''
         new_contents = []
     
-    return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':id, 'title':ldtproject.title, 'contents': new_contents}, context_instance=RequestContext(request))
+    return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':ldt_id, 'title':ldtproject.title, 'contents': new_contents}, context_instance=RequestContext(request))
     
 
 def index(request, url):
@@ -372,6 +377,7 @@
     ldtgen = LdtUtils()
     doc = ldtgen.generate_ldt(contentList, title=contentList[0].title, startSegment=startSegment)
     doc = set_forbidden_stream(doc, request.user)
+    doc = absolute_src_xml(doc)
     doc.write(resp, pretty_print=True)
 
     return resp
--- a/src/ldt/ldt/ldt_utils/views/project.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/views/project.py	Sat May 11 23:09:05 2013 +0200
@@ -235,21 +235,21 @@
     if id_group > 0:    # Search inside a group
         grp = Group.objects.get(id=id_group)
         project_list = get_objects_for_group(grp, 'ldt_utils.view_project').filter(query)
+        project_list = add_change_attr(request.user, project_list)
     elif id_group == -1:# Search inside projects shared with a specific user
         project_list = get_objects_for_user(request.user, 'ldt_utils.view_project', use_groups=False).exclude(owner=request.user)
+        project_list = add_change_attr(request.user, project_list)
     else:
         # We paginate in these cases : user's project or published
         if status==2:
-            project_list = Project.safe_objects.filter(query).exclude(title__startswith='front')
+            project_list = Project.safe_objects.filter(query).select_related("owner").exclude(title__startswith='front')
         else:
-            project_list = Project.safe_objects.filter(query)
+            project_list = Project.safe_objects.filter(query).select_related("owner")
         project_nb = float(project_list.count()) #@UndefinedVariable
         nb_pj_pages = int(math.ceil(project_nb / settings.LDT_MAX_PROJECTS_PER_PAGE))
         project_list = project_list[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)] #@UndefinedVariable
         show_username = False
 
-    project_list = add_change_attr(request.user, project_list)
-    
     if status == 2:
         url_templ = "ldt/ldt_utils/partial/publishedprojectslist.html"
     else:
@@ -281,7 +281,8 @@
 def get_projects_page(num_page, user):
     project_nb = float(Project.safe_objects.filter(owner=user).count()) #@UndefinedVariable
     nb_pj_pages = int(math.ceil(project_nb / settings.LDT_MAX_PROJECTS_PER_PAGE))
-    project_list = add_change_attr(user, Project.safe_objects.filter(owner=user)[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)]) #@UndefinedVariable
+    # add_change_attr is not useful because user and project's owner are the same
+    project_list = Project.safe_objects.filter(owner=user).select_related("owner")[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)] #@UndefinedVariable
     return project_nb, nb_pj_pages, project_list
 
 
--- a/src/ldt/ldt/ldt_utils/views/workspace.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/ldt_utils/views/workspace.py	Sat May 11 23:09:05 2013 +0200
@@ -3,7 +3,9 @@
 from django.contrib.auth.models import Group
 from django.core.paginator import Paginator, InvalidPage, EmptyPage
 from django.core.urlresolvers import reverse #, resolve
-from django.http import HttpResponseForbidden, HttpResponseNotFound, HttpResponseRedirect
+from django.db import transaction
+from django.http import (HttpResponseForbidden, HttpResponseNotFound, 
+    HttpResponseRedirect)
 from django.shortcuts import render_to_response
 from django.template import RequestContext
 from django.template.loader import render_to_string
@@ -12,13 +14,14 @@
 from django.utils.translation import ugettext as _
 from itertools import groupby
 from ldt.indexation import get_results_with_context, highlight_documents
+from ldt.ldt_utils import contentindexer
 from ldt.ldt_utils.forms import SearchForm
 from ldt.ldt_utils.models import Content, Project, Segment
 from ldt.ldt_utils.projectserializer import ProjectJsonSerializer
 from ldt.ldt_utils.utils import boolean_convert
 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.ldt_utils.views.project import (get_projects_page, 
+    get_published_projects_page)
 from ldt.security.utils import add_change_attr, get_userlist
 from ldt.utils.url import absstatic, absurl
 from ldt.utils.web_url_management import get_web_url
@@ -160,7 +163,10 @@
         else:
             rend_dict["polemic_qColor"] = "036aae"
             
-
+    if request.GET.has_key("autostart"):
+        rend_dict["autostart"] = {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("autostart").lower())
+    else : 
+        rend_dict["autostart"] = True
     if request.GET.has_key("createannotation"):
         rend_dict["createannotation"] = {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("createannotation").lower())
     if request.GET.has_key("show_mic_record"):
@@ -242,7 +248,7 @@
     LANGUAGE_CODE = settings.LANGUAGE_CODE
     ps = ProjectJsonSerializer(project, from_contents=True, from_display=True)
     annotations = ps.get_annotations(first_cutting=True)
-    rend_dict = {'project':project, 'contents':project_contents, 'json_url':json_url, 'player_id':player_id, 'annotations':annotations, 'ldt_id': ldt_id, 'stream_mode': stream_mode, 
+    rend_dict = {'project':project, 'contents':project_contents, 'json_url':json_url, 'player_id':player_id, 'annotations':annotations, 'ldt_id': ldt_id, 'stream_mode': stream_mode,  
                 'external_url': external_url,
                  'polemic':False, 'show_mic_record':False, 'annotations_list':False, 'iframe_url':iframe_url, 'WEB_URL':WEB_URL,
                 'LANGUAGE_CODE':LANGUAGE_CODE}
@@ -278,6 +284,7 @@
 def search_index(request):
     language_code = request.LANGUAGE_CODE[:2]
     nb = 0
+    nb_segment=0
     results = []
     search = ''
     field = 'all'
@@ -313,25 +320,26 @@
     results = get_results_with_context(field, search, content_list)
     all_segments = Segment.objects.filter(element_id__in=[e['element_id'] for e in results])
     all_projects = Project.objects.filter(ldt_id__in=[e['project_id'] for e in results], state=2)
-    all_contents = Content.objects.filter(iri_id__in=[e['iri_id'] for e in results])
+    all_contents = Content.objects.filter(iri_id__in=[e['iri_id'] for e in results]).select_related('stat_annotation')
     viewable_projects_id = [p.ldt_id for p in all_projects]
     nb_segment=0       
     complete_results = []           
     results.sort(key=lambda k: k['iri_id'])
            
     for iri_id, item in groupby(results, itemgetter('iri_id')):
-        content=[]
+        content=None
         content_filter = filter(lambda e: e.iri_id == iri_id, all_contents)
         if len(content_filter)>0:
-            content = filter(lambda e: e.iri_id == iri_id, all_contents)[0]
+            content = content_filter[0]
             if content.description is None:
                 content.description = ''
-                    
+        if content is None:
+            continue
         all_related_segments = list(item)
                 
         valid_segments = []
         for s in all_related_segments:
-            array_of_segs = [seg for seg in all_segments if seg.element_id == s['element_id'] and seg.project_id == s['project_id'] and seg.iri_id == s['iri_id'] and seg.cutting_id == s['cutting_id'] and seg.ensemble_id == s['ensemble_id'] ]
+            array_of_segs = [seg for seg in all_segments if (seg.element_id == s['element_id'] and seg.project_id == s['project_id'] and seg.iri_id == s['iri_id'] and seg.cutting_id == s['cutting_id'] and seg.ensemble_id == s['ensemble_id']) ]
             if len(array_of_segs)>0:
                 segment = array_of_segs[0]
                     
@@ -379,6 +387,7 @@
     return render_to_response('ldt/ldt_utils/loading.html', context_instance=RequestContext(request))
    
 
+@transaction.commit_on_success
 def delete_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id):
     if project_id and project_id != "_" :
         project = Project.safe_objects.get(ldt_id=project_id) #@UndefinedVariable
@@ -395,7 +404,9 @@
                 el = element[0]
                 el.getparent().remove(el)
                 project.ldt = lxml.etree.tostring(ldtdoc)
-                project.save()
+                project.save(must_reindex=False)
+                contentindexer.delete_segment(project, project_id, content_id, ensemble_id, cutting_id, segment_id)                
+                
                 return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
             else:
                 return HttpResponseNotFound(_("Annotation not found"))
--- a/src/ldt/ldt/management/commands/initsitedomain.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/management/commands/initsitedomain.py	Sat May 11 23:09:05 2013 +0200
@@ -1,8 +1,5 @@
 from django.core.management.base import BaseCommand
-from ldt.ldt_utils.models import Content, Project
-from ldt.ldt_utils.contentindexer import ContentIndexer, ProjectIndexer
 from django.conf import settings
-from django.db import models
 from django.contrib.sites.models import Site
 
 class Command(BaseCommand):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/management/commands/setprojectldtiri.py	Sat May 11 23:09:05 2013 +0200
@@ -0,0 +1,33 @@
+from django.core.management.base import BaseCommand
+from ldt.ldt_utils.models import Project
+from ldt.utils.projectldt_parser import relative_src_xml
+import lxml.etree
+from ..utils import show_progress
+
+class Command(BaseCommand):
+    help = 'set the .iri src in relative url'
+    
+    def handle(self, *args, **options):
+        
+        writer = None
+        
+        project_list = list(Project.objects.all())
+        
+        for i,p in enumerate(project_list): #we check all the project in the database
+            
+            writer = show_progress(i+1, len(project_list), "Processing project %s" % p.title, 80, writer)
+            no_more_media = False
+            modif = False
+            try : 
+                iri = lxml.etree.fromstring(p.ldt)
+            except :
+                iri = None
+                p.delete()
+            if iri is not None :
+                new_ldt, modif, no_more_media = relative_src_xml(iri)
+                if modif and not no_more_media:
+                    new_ldt = lxml.etree.tostring(new_ldt, pretty_print=True)
+                    p.ldt= new_ldt #we write the the new xml 
+                    p.save(must_reindex=False)
+                if no_more_media :
+                    p.delete()
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/management/commands/synciri.py	Sat May 11 23:09:05 2013 +0200
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+'''
+Created on Jan 22, 2013
+
+@author: ymh
+'''
+
+from django.core.management.base import NoArgsCommand
+from ..utils import show_progress
+from ldt.ldt_utils.models import Content
+
+class Command(NoArgsCommand):
+    
+    def handle_noargs(self, **options):
+        
+        content_list = list(Content.objects.all())
+        writer = None
+        for i,c in enumerate(content_list):
+            writer = show_progress(i+1, len(content_list), "Processing content %s" % c.title, 80, writer)
+            c.sync_iri_file()
+        
\ No newline at end of file
--- a/src/ldt/ldt/security/__init__.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/security/__init__.py	Sat May 11 23:09:05 2013 +0200
@@ -1,7 +1,7 @@
 from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.auth.models import User
-from django.core.signals import request_started 
+from django.core.signals import request_started
 from ldt.security.permissionchecker import check_object_perm_for_user
 
 try:
@@ -98,7 +98,7 @@
             # use our check_object_perm_for_user instead of not optimized guardian has_perm
             if self.pk and not check_object_perm_for_user(self, 'change_%s' % cls_name, user):
                 raise AttributeError('User %s is not allowed to change object %s' % (user, self))
-            
+      
             return func(self, *args, **kwargs)
         return wrapped    
     return wrapper
--- a/src/ldt/ldt/security/utils.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/security/utils.py	Sat May 11 23:09:05 2013 +0200
@@ -5,6 +5,7 @@
 from cache import get_cached_userlist, cached_assign
 from ldt.security import change_security
 import types
+
   
 def unprotect_instance(instance):
     if hasattr(instance, 'old_save'):
@@ -27,24 +28,28 @@
     cls = ContentType.objects.get(model='content')
     cls = cls.model_class()
     
+    m_cls = ContentType.objects.get(model='media')
+    m_cls = m_cls.model_class()
+    
+    content_ids = xml.xpath('/iri/medias/media/@id')
+    contents = dict( [(c.iri_id, c) for c in cls.safe_objects.filter(iri_id__in=content_ids).select_related("media_obj")])
+    
+    medias = dict([(m.id,m) for m in m_cls.safe_objects.filter(id__in=[c.media_obj.id for c in contents.values()])])
+            
     for elem in xml.xpath('/iri/medias/media'):
-        content = cls.safe_objects.filter(iri_id=elem.get('id'))
-        if content and use_forbidden_url(content[0]) :
+        content = contents.get(elem.get('id'), None)
+        if content and (content.media_obj and content.media_obj.id not in medias) :
             elem.set('video', settings.FORBIDDEN_STREAM_URL)
     return xml
 
 def use_forbidden_url(content):
-    c_cls = ContentType.objects.get(model='content')
-    c_cls = c_cls.model_class()
     m_cls = ContentType.objects.get(model='media')
     m_cls = m_cls.model_class()
     
-    new_content = c_cls.safe_objects.filter(iri_id=content.iri_id)
-    if new_content:
-        if new_content[0].media_obj:
-            media = m_cls.safe_objects.filter(id=new_content[0].media_obj.id)
-            if not media:
-                return True
+    if content.media_obj:
+        media = m_cls.safe_objects.filter(id=content.media_obj.id)
+        if not media:
+            return True
     return False
 
 def add_change_attr(user, obj_list):
@@ -54,11 +59,9 @@
     """
     if len(obj_list) == 0:
         return []
-    
     model_name = obj_list[0].__class__.__name__.lower()
     ctype = ContentType.objects.get(model=model_name)
     cls = ctype.model_class()
-    
     # We don't use obj.values_list('pk', flat=True) because the full queryset will be calculated and used after anyway.
     pk_list = [item.pk for item in obj_list]
     if model_name in [cls_name.lower() for cls_name in settings.USE_GROUP_PERMISSIONS] or model_name == 'group':
@@ -67,13 +70,13 @@
         change_list = get_objects_for_user(user, '%s.change_%s' % (cls._meta.app_label, model_name)).filter(pk__in=pk_list)
     else:
         to_check = False
-        
+    
     for obj in obj_list:
         if not to_check or obj in change_list:
             obj.change = True
         else:
             obj.change = False
-            
+    
     return obj_list
 
 def assign_perm_to_obj(object, read_list, write_list, owner):
--- a/src/ldt/ldt/settings.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/settings.py	Sat May 11 23:09:05 2013 +0200
@@ -10,7 +10,7 @@
 #DEFAULT_FROM_EMAIL = "admin@domain.com"
 #SERVER_EMAIL = "admin@domain.com"
 
-INSTALLED_APPS = (
+INSTALLED_APPS = getattr(settings, 'INSTALLED_APPS', (
     'django_extensions',
     'django.contrib.auth',
     'django.contrib.contenttypes',
@@ -35,9 +35,10 @@
     'guardian',
     'sorl.thumbnail',
     'tastypie',
-)
+    'chunked_uploads',
+))
 
-MIDDLEWARE_CLASSES = (
+MIDDLEWARE_CLASSES = getattr(settings, 'MIDDLEWARE_CLASSES', (
     'django.middleware.cache.UpdateCacheMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.cache.FetchFromCacheMiddleware',
@@ -49,7 +50,7 @@
     'django.contrib.messages.middleware.MessageMiddleware',
     'django_openid_consumer.middleware.OpenIDMiddleware',
     'ldt.ldt_utils.middleware.userprofile.LanguageMiddleware',
-)
+))
 
 
 
@@ -78,26 +79,27 @@
 
 ACCOUNT_ACTIVATION_DAYS = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', 7)
 LDT_MEDIA_PREFIX = getattr(settings, 'LDT_MEDIA_PREFIX', MEDIA_URL + 'ldt/')
-LDT_MAX_SEARCH_NUMBER = 50
-LDT_MAX_FRAGMENT_PER_SEARCH = 3
-LDT_RESULTS_PER_PAGE = 1
-LDT_JSON_DEFAULT_INDENT = 2
-LDT_MAX_CONTENTS_PER_PAGE = 10
-LDT_MAX_PROJECTS_PER_PAGE = 10
-LDT_FRONT_MEDIA_PER_PAGE = 9
-LDT_FRONT_PROJECTS_PER_PAGE = 12
+LDT_MAX_SEARCH_NUMBER = getattr(settings, 'LDT_MAX_SEARCH_NUMBER', 50)
+LDT_MAX_FRAGMENT_PER_SEARCH = getattr(settings, 'LDT_MAX_FRAGMENT_PER_SEARCH', 3)
+LDT_RESULTS_PER_PAGE = getattr(settings, 'LDT_RESULTS_PER_PAGE', 1)
+LDT_JSON_DEFAULT_INDENT = getattr(settings, 'LDT_JSON_DEFAULT_INDENT', 2)
+LDT_MAX_CONTENTS_PER_PAGE = getattr(settings, 'LDT_MAX_CONTENTS_PER_PAGE', 10)
+LDT_MAX_PROJECTS_PER_PAGE = getattr(settings, 'LDT_MAX_PROJECTS_PER_PAGE', 10)
+LDT_FRONT_MEDIA_PER_PAGE = getattr(settings, 'LDT_FRONT_MEDIA_PER_PAGE', 9)
+LDT_FRONT_PROJECTS_PER_PAGE = getattr(settings, 'LDT_FRONT_PROJECTS_PER_PAGE', 12)
 
 AUTO_INDEX_AFTER_SAVE = getattr(settings, 'AUTO_INDEX_AFTER_SAVE', True)
+LDT_INDEXATION_INSERT_BATCH_SIZE = getattr(settings, 'LDT_INDEXATION_INSERT_BATCH_SIZE', 5000)
 
 WEB_VERSION = getattr(settings, 'WEB_VERSION', '')
-ANONYOUS_USER_ID = -1
-USE_GROUP_PERMISSIONS = ['Project', 'Content'] 
-PUBLIC_GROUP_NAME = 'everyone'
+ANONYOUS_USER_ID = getattr(settings, 'ANONYMOUS_USER_ID',-1)
+USE_GROUP_PERMISSIONS = getattr(settings, 'USE_GROUP_PERMISSIONS', ['Project', 'Content']) 
+PUBLIC_GROUP_NAME = getattr(settings, 'PUBLIC_GROUP_NAME','everyone')
 
-DEFAULT_CONTENT_ICON = "thumbnails/contents/content_default_icon.png"
-DEFAULT_PROJECT_ICON = "thumbnails/projects/project_default_icon.png"
-DEFAULT_USER_ICON = "thumbnails/users/user_default_icon.png"
-DEFAULT_GROUP_ICON = "thumbnails/groups/group_default_icon.png"
+DEFAULT_CONTENT_ICON = getattr(settings, 'DEFAULT_CONTENT_ICON', "thumbnails/contents/content_default_icon.png")
+DEFAULT_PROJECT_ICON = getattr(settings, 'DEFAULT_PROJECT_ICON', "thumbnails/projects/project_default_icon.png")
+DEFAULT_USER_ICON = getattr(settings, 'DEFAULT_USER_ICON', "thumbnails/users/user_default_icon.png")
+DEFAULT_GROUP_ICON = getattr(settings, 'DEFAULT_GROUP_ICON', "thumbnails/groups/group_default_icon.png")
 
 # force settings value
 if(not hasattr(settings, 'MAX_TAG_LENGTH') or getattr(settings, 'MAX_TAG_LENGTH') > 255):
@@ -105,9 +107,11 @@
 
 EXTERNAL_STREAM_SRC = getattr(settings, 'EXTERNAL_STREAM_SRC', ['youtube.com', 'dailymotion.com', 'vimeo.com'])
 
-HAYSTACK_CONNECTIONS = {
+HAYSTACK_CONNECTIONS = getattr(settings, 'HAYSTACK_CONNECTIONS', {
     'default': {
         'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
     },
-}
+})
 
+HAYSTACK_SIGNAL_PROCESSOR = getattr(settings, 'HAYSTACK_SIGNAL_PROCESSOR', 'ldt.indexation.signals.LdtSignalProcessor')
+
--- a/src/ldt/ldt/static/ldt/css/front_group.css	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/static/ldt/css/front_group.css	Sat May 11 23:09:05 2013 +0200
@@ -38,9 +38,8 @@
 .li_membre_groupe p {
     margin-left: 45px;
 }
-
 /* media title search input*/
- #search_title{
+#search_title{
     background : url(../img/search.gif) no-repeat;
     border: none;
     height: 16px;
@@ -52,7 +51,8 @@
     background: transparent;
     margin: 0px 7px 10px 0px;
 }
+
 #result_pagination {
     border: 0 none;
     margin: 5px 0;
-}
+}
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/css/ldtform.css	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/static/ldt/css/ldtform.css	Sat May 11 23:09:05 2013 +0200
@@ -1,10 +1,26 @@
 @charset "UTF-8";
 
+input, textarea, select, .form-row p {
+    margin: 2px 0;
+    padding: 2px 3px;
+    vertical-align: middle;
+    font-family: "Lucida Grande", Verdana, Arial, sans-serif;
+    font-weight: normal;
+    font-size: 11px;
+}
+
+textarea {
+    vertical-align: top !important;
+}
+
+input[type=text], input[type=password], textarea, select, .vTextField {
+    border: 1px solid #ccc;
+}
 body {
 	min-width: 0;
 }
 
-#add_content, #add_contribution, #add_group {
+#add_contribution, #add_group {
 	padding: 10px;	
 }
 
@@ -147,7 +163,7 @@
 }
 
 #media_fields_div {
-	width : 338px;
+	width : 300px;
 	height : 50px;
 	margin-top: 10px 0px;
 	padding-left: 10px;
--- a/src/ldt/ldt/static/ldt/js/projectscontents.js	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/static/ldt/js/projectscontents.js	Sat May 11 23:09:05 2013 +0200
@@ -412,17 +412,11 @@
     	var h = $(element).innerHeight() + 10;
     	var w = $(element).innerWidth() + 10;
 	}
-        
+    
     nm.sizes.minH = h + 10;
     nm.sizes.minW = w;
     iframe.height(h);
     iframe.width(w);
-    
-    if ($.browser.mozilla && createcontent) {
-    	$(".nyroModalCont", parent.window.document).height(h+10);
-    } else {
-    	nm.resize(true);
-    }
 }
 
 //
@@ -438,7 +432,8 @@
     $("#close_button").click(function (e) {
         e.preventDefault();
         parent.$.nmTop().close();
-    });    
+    });
+    
     $("#submit_button_write").click(function(e) {
         $(".submitcontent-loader-content").show();
         resize_modal_window($("#add_content"), true);
@@ -456,103 +451,22 @@
     $('#my_form').bind('submit', function() {
         window.submit_asked = true;
         if($('#id_content-media_input_type').val()=="upload"){
-            if(window.upload_from_local_done==false){
-                // The form has sent but the uploading has not ended.
-                if($('#upload_progress_info').children().size()>0){
-                    $('#progress_info').remove();
-                }
-                $('#upload_progress_info').append('<p id="progress_info"><font color="red"><strong>' + wait_label + '.</strong></font><br/><a href="javascript:cancelSwfUpload()">' + cancel_label + '.</a></p>');
-                return false;
+            /*if(chunked_upload_complete == true){
+                return true;
             }
             else{
-                return true;
-            }
+                return false;
+            }*/
+        	return false;
         }
         else{
-            //alert("2. " + $('#id_content-media_input_type').val());
             return true;
         }
     });
     
-    $("#upload_progress_bar").css({ width:"90%", height:"10" });
-    
     $('#media_fields_div').height(80);
-    
-    // We init the swfupload object
-    swfupload = new SWFUpload({
-        debug: false,
-        
-        upload_url: url_upload,
-        flash_url: media_prefix+"swf/swfupload.swf",
-        
-        post_params: post_added_params,
-        
-        button_placeholder_id: "upload_btn",
-        button_width: "60",
-        button_height: "16",
-        button_cursor: SWFUpload.CURSOR.HAND,
-        button_text : '<span class="btnText">' + btn_label + '</span>',
-        button_text_style : ".btnText { font-size: 12; font-family: Arial; }",
-        
-        file_types : "*.flv;*.f4v;*.mp4;*.mov;*.mp3",
-        file_types_description : "Media Files (flv, f4v, mov H264, mp4, mp3)",
-        file_upload_limit : "1",
-        file_queue_limit : "1",
-        
-        upload_error_handler : uploadError,
-        upload_start_handler : function(file) {
-            try {
-                if($('#upload_progress_info').children().size()>0){
-                    $('#progress_info').remove();
-                }
-                $('#upload_progress_info').append('<p id="progress_info"><a href="javascript:cancelSwfUpload()">' + cancel_label + '.</a></p>');
-            }
-            catch (ex) {
-                //this.debug(ex);
-            }
-        },
-        upload_progress_handler : uploadProgress,
-        upload_success_handler : function() {
-                try {
-                    if($('#upload_progress_info').children().size()>0){
-                        $('#progress_info').remove();
-                    }
-                    $('#upload_progress_info').append('<p id="progress_info">' + success_label + '.</p>');
-                    $("#upload_progress_bar > div").css({ 'background': '#90ffa8' });
-                    window.upload_from_local_done = true;
-                    // Now that the file is uploaded, we submit the form if asked
-                    if(window.submit_asked==true){
-                        $('#my_form').submit();
-                    }
-                    else{
-                        // We ask the uploaded media's duration
-                        if(window.ask_duration_url){
-                            $.ajax({
-                                type: "GET",
-                                url: window.ask_duration_url,
-                                data: "filename="+ $('#id_media-local_file_name').val(),
-                                cache: false,
-                                success: function(data, status, request){
-                                    if(data && data!=""){
-                                        $('#id_content-duration').val(data);
-                                    }
-                                }
-                            });
-                        }
-                    }
-                }
-                catch (ex) {
-                    //this.debug(ex);
-                }
-            },
-        file_queued_handler : displayUploadPath,
-        file_dialog_complete_handler: function() { 
-            window.submit_asked = false;
-            this.startUpload();
-        }
-        //upload_complete_handler: function() { this.startUpload(); },
-    });
 }
+
 function displayUploadPath(file) {
     try {
         $('#id_media-local_file_name').val(file.name);
@@ -561,62 +475,6 @@
         //this.debug(ex);
     }
 }
-function startLocalUpload(){
-    swfupload.startUpload();
-}
-function uploadProgress(file, bytesLoaded, bytesTotal) {
-    try {
-        var percent = Math.ceil((bytesLoaded / bytesTotal) * 100);
-        $("#upload_progress_bar").progressbar({ value: percent });
-    }
-    catch (ex) {
-        //this.debug(ex);
-    }
-}
-function cancelSwfUpload(){
-    swfupload.cancelUpload();
-    if($('#media_field_upload').has($('#cancelupload')).length==0){
-        $('#cancelupload').remove();
-    }
-}
-function uploadError(file, errorCode, message) {
-    try {
-        if($('#upload_progress_info').children().size()>0){
-            $('#progress_info').remove();
-        }
-        switch (errorCode) {
-        case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
-            $('#upload_progress_info').append('<p id="progress_info">' + "Error Code: HTTP Error, File name: " + file.name + ", Message: " + message + '</p>');
-            break;
-        case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
-            $('#upload_progress_info').append('<p id="progress_info">' + "Error Code: Upload Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message + '</p>');
-            break;
-        case SWFUpload.UPLOAD_ERROR.IO_ERROR:
-            $('#upload_progress_info').append('<p id="progress_info">' + "Error Code: IO Error, File name: " + file.name + ", Message: " + message + '</p>');
-            break;
-        case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
-            $('#upload_progress_info').append('<p id="progress_info">' + "Error Code: Security Error, File name: " + file.name + ", Message: " + message + '</p>');
-            break;
-        case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
-            $('#upload_progress_info').append('<p id="progress_info">' + "Error Code: Upload Limit Exceeded, File name: " + file.name + ", File size: " + file.size + ", Message: " + message + '</p>');
-            break;
-        case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
-            $('#upload_progress_info').append('<p id="progress_info">' + "Error Code: File Validation Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message + '</p>');
-            break;
-        case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
-            $('#upload_progress_info').append('<p id="progress_info">' + "Error Code: FILE_CANCELLED" + '</p>');
-            break;
-        case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
-            $('#upload_progress_info').append('<p id="progress_info">' + "STOPPED" + '</p>');
-            break;
-        default:
-            $('#upload_progress_info').append('<p id="progress_info">' + "unhandled error: File name: " + file.name + ", File size: " + file.size + ", Message: " + message + '</p>');
-            break;
-        }
-    } catch (ex) {
-        //this.debug(ex);
-    }
-}
 
 // Test the value of the URL from the form to load a picture in case it is a youtube video
 function testUrlValue(e){
--- a/src/ldt/ldt/static/ldt/metadataplayer/Segments.js	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Segments.js	Sat May 11 23:09:05 2013 +0200
@@ -102,11 +102,11 @@
 	    	var url = (typeof _annotation.url !== "undefined" 
 	                ? _annotation.url
 	                : (document.location.href.replace(/#.*$/,'') + '#id='  + _annotation.id));
-	        	e.originalEvent.dataTransfer.setData("text/x-iri-title",_annotation.title);
-	        	e.originalEvent.dataTransfer.setData("text/x-iri-description",_annotation.description);
-	        	e.originalEvent.dataTransfer.setData("text/x-iri-uri",url);
-	        	if (typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail) {
-	        		e.originalEvent.dataTransfer.setData("text/x-iri-image",_annotation.thumbnail);
+	            e.originalEvent.dataTransfer.setData("text/x-iri-title",_annotation.title);
+	            e.originalEvent.dataTransfer.setData("text/x-iri-description",_annotation.description);
+	            e.originalEvent.dataTransfer.setData("text/x-iri-uri",url);
+                if (typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail) {
+	        	    e.originalEvent.dataTransfer.setData("text/x-iri-image",_annotation.thumbnail);
 	        	}
 	        })
             .appendTo(list_$)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/utils/projectldt_parser.py	Sat May 11 23:09:05 2013 +0200
@@ -0,0 +1,40 @@
+from ldt.utils.url import absolute_media_url, is_absolute
+from ldt.ldt_utils.models import Content
+
+def absolute_src_xml(doc):
+    media_list = doc.xpath("/iri/medias/media")
+    for element in media_list:
+        src = element.get("src") #we split to hate two parts, one with the src
+        if not is_absolute(src):
+            new_src = absolute_media_url()+src
+            element.set('src', new_src) #we replace the old value by the new one
+    return doc
+
+def relative_src_xml(ldt):
+    modif = False
+    no_more_media=False
+    media_list = ldt.xpath("/iri/medias/media")
+    if len(media_list) == 0 :
+        no_more_media = True
+    if not no_more_media :
+        for element in media_list:
+            src = element.get("src")
+            id_content=element.get("id")
+            content_list = Content.objects.filter(iri_id=id_content)
+            if len(content_list) == 0:
+                element.getparent().remove(element)
+                modif = True
+                for content_elem in ldt.xpath("/iri/annotations/content[@id=\"%s\"]" % id_content):
+                    content_elem.getparent().remove(content_elem)
+                media_list = ldt.xpath("/iri/medias/media")
+                if len(media_list) == 0 :
+                    no_more_media =  True
+            else:
+                content = content_list[0]
+                right_src = content.relative_iri_url()
+                if not src == right_src: #we will modify only the project that have an absolute url
+                    modif = True
+                    new_src = right_src
+                    element.set('src', new_src) #we replace the old value by the new one
+
+    return ldt, modif, no_more_media
\ No newline at end of file
--- a/src/ldt/ldt/utils/url.py	Tue May 07 15:30:41 2013 +0200
+++ b/src/ldt/ldt/utils/url.py	Sat May 11 23:09:05 2013 +0200
@@ -2,15 +2,22 @@
 from django.core.urlresolvers import reverse
 from ldt.utils.web_url_management import get_web_url
 from ldt import settings
+from django.conf import settings as djangosettings
 import httplib2
 import re
 import urlparse
+import logging
 
 def absstatic(request, path):
     domain=get_web_url(request)
     new_path = staticfiles_storage.url(path)
     return urlparse.urljoin(domain, new_path)
 
+def absolute_media_url():
+    domain=get_web_url()
+    
+    return urlparse.urljoin(domain, djangosettings.MEDIA_URL)
+
 def absurl(request, viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None):
     domain=get_web_url(request)
     path=reverse(viewname, urlconf, args, kwargs, prefix, current_app)