IriSP.Model.List now inherits from Array new-model
authorveltr
Tue, 17 Apr 2012 15:03:40 +0200
branchnew-model
changeset 866 3bf7aa8216e5
parent 864 5e76a06b961c
child 868 a525cc2214e7
IriSP.Model.List now inherits from Array
sbin/build/client.xml
src/js/data.js
src/js/init.js
src/js/main.js
src/js/model.js
src/js/modules.js
src/js/players/player.allocine.js
src/js/serializers/CinecastSerializer.js
src/js/serializers/JSONSerializer.js
src/js/serializers/PlatformSerializer.js
src/js/widgets.js
test/integration/polemic.htm
--- a/sbin/build/client.xml	Mon Apr 16 19:10:32 2012 +0200
+++ b/sbin/build/client.xml	Tue Apr 17 15:03:40 2012 +0200
@@ -59,7 +59,7 @@
     	<filelist dir="../../build" files="compiled_templates.js" />
       
       <!-- core files -->
-    	<filelist dir="../../src/js" files="utils.js pop.js data.js defaults.js widgets.js modules.js layout.js init.js i18n.js" />
+    	<filelist dir="../../src/js" files="utils.js pop.js model.js defaults.js widgets.js modules.js layout.js init.js i18n.js" />
 
       <!-- players -->
 			<fileset dir="../../src/js/players" casesensitive="yes">
--- a/src/js/data.js	Mon Apr 16 19:10:32 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/* data.js - this file deals with how the players gets and sends data */
-
-IriSP.DataLoader = function() {
-  this._cache = {};
-  
-  /*
-    A structure to hold callbacks for specific urls. We need it because
-    ajax calls are asynchronous, so it means that sometimes we ask
-    multiple times for a ressource because the first call hasn't been
-    received yet.
-  */
-  this._callbacks = {};
-};
-
-IriSP.DataLoader.prototype.get = function(url, callback, force_reload) {
-  var base_url = url.split("&")[0];
-  if (typeof force_reload != "undefined" && force_reload && this._cache.hasOwnProperty(base_url)) {
-      delete this._cache[base_url]
-  }
-  if (this._cache.hasOwnProperty(base_url)) {
-    callback(this._cache[base_url]);
-  } else {  
-    if (!this._callbacks.hasOwnProperty(base_url)) {
-      this._callbacks[base_url] = [callback];
-      /* we need a closure because this gets lost when it's called back */
-  
-      // uncomment you don't want to use caching.
-      // IriSP.jQuery.get(url, callback);
-      
-      var func = function(data) {
-                  this._cache[base_url] = data;                                
-                  var i = 0;
-                  
-                  for (i = 0; i < this._callbacks[base_url].length; i++) {
-                    this._callbacks[base_url][i](this._cache[base_url]);                                  
-                  }
-                  delete this._callbacks[base_url];
-      };
-      
-      /* automagically choose between json and jsonp */
-      if (url.indexOf(document.location.hostname) === -1 &&
-          url.indexOf("http://") !== -1 /* not a relative url */ ) {
-        // we contacting a foreign domain, use JSONP
-
-        IriSP.jQuery.get(url, {}, IriSP.wrap(this, func), "jsonp");
-      } else {
-
-        // otherwise, hey, whatever rows your boat
-        IriSP.jQuery.get(url, IriSP.wrap(this, func));
-      }
-    
-    } else {
-      /* simply push the callback - it'll get called when the ressource
-         has been received */
-      
-      this._callbacks[base_url].push(callback);   
-   
-    }
-  }
-}
-
-/* the base abstract "class" */
-IriSP.Serializer = function(DataLoader, url) {
-  this._DataLoader = DataLoader;
-  this._url = url;
-  this._data = [];
-};
-
-IriSP.Serializer.prototype.serialize = function(data) { };
-IriSP.Serializer.prototype.deserialize = function(data) {};
-
-IriSP.Serializer.prototype.currentMedia = function() {  
-};
-
-IriSP.Serializer.prototype.getDuration = function() {  
-};
-
-IriSP.Serializer.prototype.sync = function(callback) {
-  this._DataLoader.get(this._url, callback, force_refresh);
-};
-
-IriSP.SerializerFactory = function(DataLoader) {
-  this._dataloader = DataLoader;
-};
-
-IriSP.SerializerFactory.prototype.getSerializer = function(metadataOptions) {
-  /* This function returns serializer set-up with the correct
-     configuration - takes a metadata struct describing the metadata source
-  */
-  
-  if (metadataOptions === undefined)
-    /* return an empty serializer */
-    return IriSP.Serializer("", "");
-            
-  switch(metadataOptions.type) {
-    case "json":
-      return new IriSP.JSONSerializer(this._dataloader, metadataOptions.src);
-      break;
-    
-    case "dummy": /* only used for unit testing - not defined in production */
-      return new IriSP.MockSerializer(this._dataloader, metadataOptions.src);
-      break;
-    
-    case "empty":
-      return new IriSP.Serializer("", "empty");
-      break;
-      
-    default:      
-      return undefined;
-  }
-};
--- a/src/js/init.js	Mon Apr 16 19:10:32 2012 +0200
+++ b/src/js/init.js	Tue Apr 17 15:03:40 2012 +0200
@@ -1,257 +1,205 @@
 /* init.js - initialization and configuration of Popcorn and the widgets
 exemple json configuration:
- 
- */
 
-/**
-    set up the IriSP.__dataloader instance - 
-    we need it because we have to get the metadata
-    about the video before that the widget have even
-    loaded.
 */
-IriSP.setupDataLoader = function() {
-  /* we set it up separately because we need to
-     get data at the very beginning, for instance when
-     setting up the video */
-  IriSP.__dataloader = new IriSP.DataLoader();
-};
 
 /** do some magic to configure popcorn according to the options object passed.
-    Works for html5, jwplayer and youtube videos 
-*/
-IriSP.configurePopcorn = function (layoutManager, options) {
+ Works for html5, jwplayer and youtube videos
+ */
+IriSP.configurePopcorn = function(layoutManager, options) {
     var pop;
-    var ret = layoutManager.createDiv(); 
+    var ret = layoutManager.createDiv();
     var containerDiv = ret[0];
     var spacerDiv = ret[1];
-    
-    /* insert one pixel of margin between the video and the first widget, using the 
-       spacer.
-    */
+
+    /* insert one pixel of margin between the video and the first widget, using the
+     spacer.
+     */
     IriSP.jQuery("#" + spacerDiv).css("height", "1px");
-    
+
     switch(options.type) {
-      /*
-        todo : dynamically create the div/video tag which
-        will contain the video.
-      */
-      case "html5":
-           var tmpId = Popcorn.guid("video"); 
-           IriSP.jQuery("#" + containerDiv).append("<video src='" + options.file + "' id='" + tmpId + "'></video>");
-
-           if (options.hasOwnProperty("width"))
-             IriSP.jQuery("#" + containerDiv).css("width", options.width);
-           
-           if (options.hasOwnProperty("height"))
-             IriSP.jQuery("#" + containerDiv).css("height", options.height);
+        /*
+         todo : dynamically create the div/video tag which
+         will contain the video.
+         */
+        case "html5":
+            var tmpId = Popcorn.guid("video");
+            IriSP.jQuery("#" + containerDiv).append("<video src='" + options.video + "' id='" + tmpId + "'></video>");
 
-           pop = Popcorn("#" + tmpId);
-        break;
-        
-      case "jwplayer":
-          var opts = IriSP.jQuery.extend({}, options);
-          delete opts.container;
-          delete opts.type;
+            if(options.hasOwnProperty("width"))
+                IriSP.jQuery("#" + containerDiv).css("width", options.width);
 
-          
-          /* Try to guess options.file and options.streamer only if file and streamer
-             are not already defined in the configuration */
-          if (options.provider === "rtmp" && !opts.hasOwnProperty("file") && !opts.hasOwnProperty("streamer")) {
-            /* exit if we can't access the metadata */
-            if (typeof(IriSP.__jsonMetadata) === "undefined") {
-                break;
-            };
+            if(options.hasOwnProperty("height"))
+                IriSP.jQuery("#" + containerDiv).css("height", options.height);
+            pop = Popcorn("#" + tmpId);
+            break;
 
-            // the json format is totally illogical
-            //opts.streamer = IriSP.__jsonMetadata["medias"][0]["meta"]["item"]["value"];
-            //var source = IriSP.__jsonMetadata["medias"][0]["href"];
+        case "jwplayer":
+            var opts = IriSP.jQuery.extend({}, options);
+            delete opts.container;
+            delete opts.type;
+            opts.file = opts.video;
+            delete opts.video;
 
-            // the source if a full url but jwplayer wants an url relative to the
-            // streamer url, so we've got to remove the common part.
-            //opts.file = source.slice(opts.streamer.length);
-            
-            /* sometimes we get served a file with a wrong path and streamer.
-               as a streamer is of the form rtmp://domain/path/ and the media is
-               the rest, we uglily do this :
-            */
-            opts.file = "";
-            opts.streamer = "";
-            var fullPath = IriSP.get_aliased(IriSP.__jsonMetadata["medias"][0], ["href","url"]);
-            
-            if (fullPath === null) {
-              console.log("no url or href field defined in the metadata.");
+            if(!options.hasOwnProperty("flashplayer")) {
+                opts.flashplayer = IriSP.jwplayer_swf_path;
             }
-            
-            var pathSplit = fullPath.split('/');
-            
-            for (var i = 0; i < pathSplit.length; i++) {
-              if (i < 4) {
-                 opts.streamer += pathSplit[i] + "/";
-              } else {
-                 opts.file += pathSplit[i];
-                 /* omit the last slash if we're on the last element */
-                 if (i < pathSplit.length - 1)
-                  opts.file += "/";
-              }
-            }            
-          } else {
-            /* other providers type, video for instance -
-               pass everything as is */
-          }
+
+            if(!options.hasOwnProperty("controlbar.position")) {
+                opts["controlbar.position"] = "none";
+            }
+            pop = new IriSP.PopcornReplacement.jwplayer("#" + containerDiv, opts);
+            break;
 
-          if (!options.hasOwnProperty("flashplayer")) {
-            opts.flashplayer = IriSP.jwplayer_swf_path;
-          }
-
-          if (!options.hasOwnProperty("controlbar.position")) {
-            opts["controlbar.position"] = "none";
-          }
+        case "youtube":
+            var opts = IriSP.jQuery.extend({}, options);
+            delete opts.container;
+            opts.controls = 0;
+            opts.autostart = false;
+            // Popcorn.youtube wants us to specify the size of the player in the style attribute of its container div.
+            IriSP.jQuery("#" + containerDiv).css({
+                width : opts.width + "px",
+                height : opts.height + "px"
+            })
+            pop = Popcorn.youtube("#" + containerDiv, opts.video, opts);
+            break;
 
-          pop = new IriSP.PopcornReplacement.jwplayer("#" + containerDiv, opts);
-        break;
-      
-      case "youtube":
-          var opts = IriSP.jQuery.extend({}, options);
-          delete opts.container;
-          opts.controls = 0;
-          opts.autostart = false;
-          templ = "width: {{width}}px; height: {{height}}px;";
-          var str = Mustache.to_html(templ, {width: opts.width, height: opts.height});    
-          // Popcorn.youtube wants us to specify the size of the player in the style attribute of its container div.
-          IriSP.jQuery("#" + containerDiv).attr("style", str);
-          
-          pop = Popcorn.youtube("#" + containerDiv, opts.video, opts);
-        break;
-      
-    case "dailymotion":
-        pop = new IriSP.PopcornReplacement.dailymotion("#" + containerDiv, options);
-        break;
-             
-      case "allocine":
-          /* pass the options as-is to the allocine player and let it handle everything */
-          pop = new IriSP.PopcornReplacement.allocine("#" + containerDiv, options);
-          break;
-          
-      default:
-        pop = undefined;
+        case "dailymotion":
+            pop = new IriSP.PopcornReplacement.dailymotion("#" + containerDiv, options);
+            break;
+
+        case "allocine":
+            /* pass the options as-is to the allocine player and let it handle everything */
+            pop = new IriSP.PopcornReplacement.allocine("#" + containerDiv, options);
+            break;
+
+        default:
+            pop = undefined;
     };
-    
+
     return pop;
 };
-
 /** Configure the gui and instantiate the widgets passed as parameters
-    @param guiOptions the gui object as seen in the examples.
+ @param guiOptions the gui object as seen in the examples.
  */
-IriSP.configureWidgets = function (popcornInstance, layoutManager, guiOptions) {
- 
-  var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader);
-  var params = {width: guiOptions.width, height: guiOptions.height};
+IriSP.configureWidgets = function(popcornInstance, layoutManager, guiOptions) {
+
+    var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader);
+    var params = {
+        width : guiOptions.width,
+        height : guiOptions.height
+    };
 
-  var default_options = guiOptions.default_options;
-  if (IriSP.null_or_undefined(default_options))
-    default_options = {};
-  
-  var ret_widgets = [];
-  var index;
-  
-  for (index = 0; index < guiOptions.widgets.length; index++) {    
-    var widget = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, guiOptions.widgets[index], default_options);
-   
-    ret_widgets.push(widget);   
-  };
+    var default_options = guiOptions.default_options;
+    if(IriSP.null_or_undefined(default_options))
+        default_options = {};
+
+    var ret_widgets = [];
+    var index;
 
-  return ret_widgets;
+    for( index = 0; index < guiOptions.widgets.length; index++) {
+        var widget = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, guiOptions.widgets[index], default_options);
+
+        ret_widgets.push(widget);
+    };
+
+    return ret_widgets;
 };
-
 /** configure modules. @see configureWidgets */
-IriSP.configureModules = function (popcornInstance, modulesList) {
-  if (IriSP.null_or_undefined(modulesList))
-    return;
-  
-  var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader);
-  var ret_modules = [];
-  var index;
-  
-  for (index = 0; index < modulesList.length; index++) {    
-    var moduleConfig = modulesList[index];
-    
-    var serializer = serialFactory.getSerializer(moduleConfig.metadata);
-    var module = new IriSP[moduleConfig.type](popcornInstance, moduleConfig, serializer);    
-    ret_modules.push(module);
-  };
+IriSP.configureModules = function(popcornInstance, modulesList) {
+/*    if(IriSP.null_or_undefined(modulesList))
+        return;
+
+    var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader);
+    var ret_modules = [];
+    var index;
+
+    for( index = 0; index < modulesList.length; index++) {
+        var moduleConfig = modulesList[index];
 
-  return ret_modules;
-};
+        var serializer = serialFactory.getSerializer(moduleConfig.metadata);
+        var module = new IriSP[moduleConfig.type](popcornInstance, moduleConfig, serializer);
+        ret_modules.push(module);
+    };
 
-/** instantiate a widget - only called by configureWidgets, never by the user. Handles widget 
-    dependencies.
-    @param popcornInstance popcorn instance the widget will user
-    @param serialFactory serializer factory to instantiate the widget with
-    @param layoutManager layout manager
-    @param widgetConfig configuration options for the widget
-    @param defaultOptions a dictionnary with some options defined for every widget.
+    return ret_modules; */
+};
+/** instantiate a widget - only called by configureWidgets, never by the user. Handles widget
+ dependencies.
+ @param popcornInstance popcorn instance the widget will user
+ @param serialFactory serializer factory to instantiate the widget with
+ @param layoutManager layout manager
+ @param widgetConfig configuration options for the widget
+ @param defaultOptions a dictionnary with some options defined for every widget.
  */
 IriSP.instantiateWidget = function(popcornInstance, serialFactory, layoutManager, widgetConfig, defaultOptions) {
 
-    if (IriSP.null_or_undefined(defaultOptions))
-      defaultOptions = {};
-    
+    if(IriSP.null_or_undefined(defaultOptions))
+        defaultOptions = {};
     widgetConfig = IriSP.underscore.defaults(widgetConfig, defaultOptions);
 
     var arr = IriSP.jQuery.extend({}, widgetConfig);
-    
+
     /* create a div for those widgets who didn't already specify a container; */
-    if (!arr.hasOwnProperty("container")) {
-      /* create div returns us a container for the widget and a spacer */    
-      var ret = layoutManager.createDiv(widgetConfig.type);        
-      var container = ret[0];
-      var spacer = ret[1];           
-      arr.container = container;
-      arr.spacer = spacer;
-      arr.layoutManager = layoutManager;
+    if(!arr.hasOwnProperty("container")) {
+        /* create div returns us a container for the widget and a spacer */
+        var ret = layoutManager.createDiv(widgetConfig.type);
+        var container = ret[0];
+        var spacer = ret[1];
+        arr.container = container;
+        arr.spacer = spacer;
+        arr.layoutManager = layoutManager;
     }
-    var serializer = serialFactory.getSerializer(widgetConfig.metadata);    
-    
-    if (typeof serializer == "undefined")   
-      debugger;
-    
+    var serializer = serialFactory.getSerializer(widgetConfig.metadata);
+
+    if( typeof serializer == "undefined")
+        debugger;
+
     // instantiate the object passed as a string
-    var widget = new IriSP[widgetConfig.type](popcornInstance, arr, serializer);    
-    
-    if (widgetConfig.hasOwnProperty("requires")) {
-      // also create the widgets this one depends on.
-      // the dependency widget is available in the parent widget context as
-      // this.WidgetName (for instance, this.TipWidget);
-      
-      var i = 0;
-      for(i = 0; i < widgetConfig.requires.length; i++) {
-        var widgetName = widgetConfig.requires[i]["type"],
-            _configobj = IriSP.jQuery.extend({}, widgetConfig.requires[i]),
-            _div = document.createElement('div'),
-            _container = IriSP.guid(arr.container + '_' + widgetName + '_');
-        _configobj.container = _container;
-        _div.id = _container;
-        widget.selector.append(_div);
-        widget[widgetName] = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, _configobj, defaultOptions);
-      }
-    }       
-     
-    serializer.sync(IriSP.wrap(widget, function() { this.draw(); }));
+    var widget = new IriSP[widgetConfig.type](popcornInstance, arr, serializer);
+
+    if(widgetConfig.hasOwnProperty("requires")) {
+        // also create the widgets this one depends on.
+        // the dependency widget is available in the parent widget context as
+        // this.WidgetName (for instance, this.TipWidget);
+
+        var i = 0;
+        for( i = 0; i < widgetConfig.requires.length; i++) {
+            var widgetName = widgetConfig.requires[i]["type"], _configobj = IriSP.jQuery.extend({}, widgetConfig.requires[i]), _div = document.createElement('div'), _container = IriSP.guid(arr.container + '_' + widgetName + '_');
+            _configobj.container = _container;
+            _div.id = _container;
+            widget.selector.append(_div);
+            widget[widgetName] = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, _configobj, defaultOptions);
+        }
+    }
+
+    serializer.sync(IriSP.wrap(widget, function() {
+        this.draw();
+    }));
     return widget;
 };
-
 /** single point of entry for the metadataplayer */
-IriSP.initPlayer = function(config, metadata_url) {
+IriSP.initPlayer = function(config, metadata_url, format) {
     document.getElementById(config.gui.container).innerHTML = IriSP.templToHTML(IriSP.loading_template, config.gui);
-    IriSP.loadLibs(config, metadata_url,
-      function() {   
-              
-              var layoutManager = new IriSP.LayoutManager(config.gui);
+    IriSP.loadLibs(config, metadata_url, format, function() {
 
-              var pop = IriSP.configurePopcorn(layoutManager, config.player);
-              
-              IriSP._widgets = IriSP.configureWidgets(pop, layoutManager, config.gui); 
-              IriSP._modules = IriSP.configureModules(pop, config.modules); 
-              IriSP.jQuery('#Ldt-loader').detach();
-      });
-};
\ No newline at end of file
+        var layoutManager = new IriSP.LayoutManager(config.gui);
+        
+        if (typeof IriSP._videoData !== "undefined" && typeof config.player.video === "undefined") {
+            var _media = IriSP._videoData.currentMedia;
+            if (typeof _media !== "undefined") {
+                config.player.video = _media.video;
+                if (typeof _media.streamer !== "undefined") {
+                    config.player.streamer = _media.streamer;
+                    config.player.video = _media.video.replace(_media.streamer,'');
+                }
+            }
+            
+        }
+        
+        var pop = IriSP.configurePopcorn(layoutManager, config.player);
+
+        IriSP._widgets = IriSP.configureWidgets(pop, layoutManager, config.gui);
+        IriSP.jQuery('#Ldt-loader').detach();
+    });
+};
--- a/src/js/main.js	Mon Apr 16 19:10:32 2012 +0200
+++ b/src/js/main.js	Tue Apr 17 15:03:40 2012 +0200
@@ -1,20 +1,20 @@
 /* main file */
 // Why is it called main ? It only loads the libs !
 
-if ( window.IriSP === undefined && window.__IriSP === undefined ) { 
-  /**
-    @class
-    the object under which everything goes.        
-  */
-	IriSP = {}; 
-  
-  /** Alias to IriSP for backward compatibility */
-	__IriSP = IriSP;
+if(window.IriSP === undefined && window.__IriSP === undefined) {
+    /**
+     @class
+     the object under which everything goes.
+     */
+    IriSP = {};
+
+    /** Alias to IriSP for backward compatibility */
+    __IriSP = IriSP;
 }
 
-/* underscore comes bundled with the player and we need 
-   it ASAP, so load it that way
-*/
+/* underscore comes bundled with the player and we need
+ it ASAP, so load it that way
+ */
 
 IriSP._ = window._.noConflict();
 IriSP.underscore = IriSP._;
@@ -35,73 +35,65 @@
     )
 }
 
-IriSP.loadLibs = function( config, metadata_url, callback ) {
+IriSP.loadLibs = function(config, metadata_url, format, callback) {
     // Localize jQuery variable
-		IriSP.jQuery = null;
-    var $L = $LAB.script(IriSP.getLib("jQuery")).script(IriSP.getLib("swfObject")).wait()
-                .script(IriSP.getLib("jQueryUI"));
-                                   
-    if (config.player.type === "jwplayer" || config.player.type === "allocine") {
-      // load our popcorn.js lookalike
-      $L.script(IriSP.getLib("jwplayer"));
+    IriSP.jQuery = null;
+    var $L = $LAB.script(IriSP.getLib("jQuery")).script(IriSP.getLib("swfObject")).wait().script(IriSP.getLib("jQueryUI"));
+
+    if(config.player.type === "jwplayer" || config.player.type === "allocine") {
+        // load our popcorn.js lookalike
+        $L.script(IriSP.getLib("jwplayer"));
     } else {
-      // load the real popcorn
-      $L.script(IriSP.getLib("popcorn")).script(IriSP.getLib("popcorn.code"));
-      if (config.player.type === "youtube") {
-        $L.script(IriSP.getLib("popcorn.youtube"));
-      } 
-      if (config.player.type === "vimeo")
-        $L.script(IriSP.getLib("popcorn.vimeo"));
-      
-      /* do nothing for html5 */
-    }       
-    
+        // load the real popcorn
+        $L.script(IriSP.getLib("popcorn")).script(IriSP.getLib("popcorn.code"));
+        if(config.player.type === "youtube") {
+            $L.script(IriSP.getLib("popcorn.youtube"));
+        }
+        if(config.player.type === "vimeo")
+            $L.script(IriSP.getLib("popcorn.vimeo"));
+
+        /* do nothing for html5 */
+    }
+
     /* widget specific requirements */
-    for (var idx in config.gui.widgets) {
-      if (config.gui.widgets[idx].type === "PolemicWidget" ||
-          config.gui.widgets[idx].type === "StackGraphWidget" ||
-          config.gui.widgets[idx].type === "SparklineWidget") {        
-        $L.script(IriSP.getLib("raphael"));
-      }
-      if (config.gui.widgets[idx].type === "TraceWidget") {
-          $L.script(IriSP.getLib("tracemanager"))
-      }
+    for(var idx in config.gui.widgets) {
+        if(config.gui.widgets[idx].type === "PolemicWidget" || config.gui.widgets[idx].type === "StackGraphWidget" || config.gui.widgets[idx].type === "SparklineWidget") {
+            $L.script(IriSP.getLib("raphael"));
+        }
+        if(config.gui.widgets[idx].type === "TraceWidget") {
+            $L.script(IriSP.getLib("tracemanager"))
+        }
     }
-    
-    // same for modules
-    /*
-    for (var idx in config.modules) {
-      if (config.modules[idx].type === "PolemicWidget")
-        $L.script(IriSP.getLib("raphaelJs"));
-    }
-    */
+
 
     $L.wait(function() {
-      IriSP.jQuery = window.jQuery.noConflict( true );
-      
-      var css_link_jquery = IriSP.jQuery( "<link>", { 
-        rel: "stylesheet", 
-        type: "text/css", 
-        href: IriSP.getLib("cssjQueryUI"),
-        'class': "dynamic_css"
-      } );
-      var css_link_custom = IriSP.jQuery( "<link>", { 
-        rel: "stylesheet", 
-        type: "text/css", 
-        href: config.gui.css,
-        'class': "dynamic_css"
-      } );
-      
-      css_link_jquery.appendTo('head');
-      css_link_custom.appendTo('head');
-          
-      IriSP.setupDataLoader();
-      IriSP.__dataloader.get(metadata_url, 
-          function(data) {
-            /* save the data so that we could re-use it to
-               configure the video
-            */
-            IriSP.__jsonMetadata = data;
-            callback.call(window) });
+        IriSP.jQuery = window.jQuery.noConflict(true);
+
+        var css_link_jquery = IriSP.jQuery("<link>", {
+            rel : "stylesheet",
+            type : "text/css",
+            href : IriSP.getLib("cssjQueryUI"),
+            'class' : "dynamic_css"
+        });
+        var css_link_custom = IriSP.jQuery("<link>", {
+            rel : "stylesheet",
+            type : "text/css",
+            href : config.gui.css,
+            'class' : "dynamic_css"
+        });
+
+        css_link_jquery.appendTo('head');
+        css_link_custom.appendTo('head');
+
+        IriSP._directory = new IriSP.Model.Directory();
+        IriSP._videoData = _directory.remoteSource({
+            url : metadata_url,
+            namespace : "metadataplayer",
+            serializer : IriSP.serializers[format]
+        });
+        if (typeof callback !== "undefined") {
+            IriSP._videoData.onLoad(callback);
+        }
+        
     });
-};
\ No newline at end of file
+};
--- a/src/js/model.js	Mon Apr 16 19:10:32 2012 +0200
+++ b/src/js/model.js	Tue Apr 17 15:03:40 2012 +0200
@@ -47,63 +47,59 @@
 /* */
 
 IriSP.Model.List = function(_directory) {
-    this.contents = [];
+    Array.call(this);
     this.directory = _directory;
+    this.idIndex = [];
     if (typeof _directory == "undefined") {
         throw("Error : new IriSP.Model.List(directory): directory is undefined");
     }
 }
 
-IriSP.Model.List.prototype.toString = function() {
-    return 'List of Elements, length=' + this.length();
-}
-
-IriSP.Model.List.prototype.length = function() {
-    return this.contents.length;
-}
+IriSP.Model.List.prototype = new Array();
 
 IriSP.Model.List.prototype.getElement = function(_id) {
-    return this.directory.getElement(_id);
-}
-
-IriSP.Model.List.prototype.getElementAt = function(_pos) {
-    if (_pos >= 0 && _pos < this.length()) {
-        return this.getElement(this.contents[_pos]);
+    if (this.hasId(_id)) {
+        return this;
     }
 }
 
 IriSP.Model.List.prototype.hasId = function(_id) {
-    return (IriSP._(this.contents).indexOf(_id) !== -1);
+    return (IriSP._(this.idIndex).indexOf(_id) !== -1);
 }
 
-IriSP.Model.List.prototype.each = function(_callback) {
-    var _this = this;
-    IriSP._(this.contents).each(function(_id) {
-        _callback.call(_this, _this.getElement(_id), _id);
-    });
+if (typeof Array.prototype.forEach === "undefined") {
+    IriSP.Model.List.prototype.forEach = function(_callback) {
+        var _this = this;
+        IriSP._(this).forEach(function(_value, _key) {
+            _callback(_value, _key, _this);
+        });
+    }
 }
 
-IriSP.Model.List.prototype.map = function(_callback) {
-    var _this = this;
-    return IriSP._(this.contents).map(function(_id) {
-        return _callback.call(_this, _this.getElement(_id), _id);
-    });
+if (typeof Array.prototype.map === "undefined") {
+    IriSP.Model.List.prototype.map = function(_callback) {
+        var _this = this;
+        return IriSP._(this).map(function(_value, _key) {
+            return _callback(_value, _key, _this);
+        });
+    }
 }
 
+/* We override Array's filter function because it doesn't return an IriSP.Model.List */
 IriSP.Model.List.prototype.filter = function(_callback) {
     var _this = this,
         _res = new IriSP.Model.List(this.directory);
-    _res.contents = IriSP._(this.contents).filter(function(_id) {
-        return _callback.call(_this, _this.getElement(_id), _id);
-    });
+    _res.addElements(IriSP._(this).filter(function(_value, _key) {
+        return _callback(_value, _key, _this);
+    }));
     return _res;
 }
 
 IriSP.Model.List.prototype.sortBy = function(_callback) {
     var _this = this,
         _res = new IriSP.Model.List(this.directory);
-    _res.contents = IriSP._(this.contents).sortBy(function(_id) {
-        return _callback.call(_this, _this.getElement(_id), _id);
+    _res.contents = IriSP._(this).sortBy(function(_value, _key) {
+        return _callback(_value, _key, _this);
     });
     return _res;
 }
@@ -130,24 +126,35 @@
 }
 
 IriSP.Model.List.prototype.addId = function(_id) {
-    if (!this.hasId(_id)) {
-        this.contents.push(_id);
+    var _el = this.directory.getElement(_id)
+    if (!this.hasId(_id) && typeof _el !== "undefined") {
+        this.idIndex.push(_id);
+        Array.prototype.push.call(this, _el);
     }
 }
 
-IriSP.Model.List.prototype.addElement = function(_el) {
-    this.addId(_el.id);
+IriSP.Model.List.prototype.push = function(_el) {
+    if (typeof this.directory.getElement(_el.id) === "undefined") {
+        this.directory.addElement(_el);
+    }
+    this.idIndex.push(_el.id);
+    Array.prototype.push.call(this, _el);
 }
 
-IriSP.Model.List.prototype.addIdsFromArray = function(_array) {
-    var _l = _array.length;
-    for (var _i = 0; _i < _l; _i++) {
-        this.addId(_array[_i]);
-    }
+IriSP.Model.List.prototype.addIds = function(_array) {
+    var _l = _array.length,
+        _this = this;
+    IriSP._(_array).forEach(function(_id) {
+        _this.addId(_id);
+    });
 }
 
-IriSP.Model.List.prototype.addIdsFromList = function(_list) {
-    this.addIdsFromArray(_list.contents);
+IriSP.Model.List.prototype.addElements = function(_array) {
+    var _l = _array.length,
+        _this = this;
+    IriSP._(_array).forEach(function(_el) {
+        _this.push(_el);
+    });
 }
 
 /* */
@@ -197,7 +204,7 @@
     if (typeof _idRef === "object") {
         this.isList = true;
         this.contents = new IriSP.Model.List(this.source.directory);
-        this.contents.addIdsFromArray(IriSP._(_idRef).map(function(_id) {
+        this.contents.addIds(IriSP._(_idRef).map(function(_id) {
             return _source.getNamespaced(_id).fullname;
         }));
     } else {
@@ -259,7 +266,7 @@
     IriSP.Model.Element.call(this, _id, _source);
     this.elementType = 'media';
     this.duration = new IriSP.Model.Time();
-    this.url = '';
+    this.video = '';
 }
 
 IriSP.Model.Media.prototype = new IriSP.Model.Element();
@@ -348,7 +355,7 @@
     this.status = IriSP.Model.SOURCE_STATUS_EMPTY;
     if (typeof _config !== "undefined") {
         var _this = this;
-        IriSP._(_config).each(function(_v, _k) {
+        IriSP._(_config).forEach(function(_v, _k) {
             _this[_k] = _v;
         })
         this.callbackQueue = [];
@@ -389,7 +396,7 @@
     if (typeof this.contents[_listId] === "undefined") {
         this.contents[_listId] = new IriSP.Model.List(this.directory);
     }
-    this.contents[_listId].addIdsFromList(_contents);
+    this.contents[_listId].addElements(_contents);
 }
 
 IriSP.Model.Source.prototype.getList = function(_listId) {
@@ -402,27 +409,26 @@
     }
 }
 
-IriSP.Model.Source.prototype.each = function(_callback) {
+IriSP.Model.Source.prototype.forEach = function(_callback) {
     var _this = this;
-    IriSP._(this.contents).each(function(_value, _key) {
+    IriSP._(this.contents).forEach(function(_value, _key) {
         _callback.call(_this, _value, _key);
     })
 }
 
-IriSP.Model.Source.prototype.getElement = function(_listId, _elId) {
-    var _list = this.getList(_listId);
-    return (typeof _list !== "undefined" ? _list.getElement(_elId) : undefined);
+IriSP.Model.Source.prototype.getElement = function(_elId) {
+    return this.directory.getElement(_elId);
 }
 
 IriSP.Model.Source.prototype.setCurrentMediaId = function(_idRef) {
     if (typeof _idRef !== "undefined") {
-        this.currentMedia = this.getNamespaced(_idRef).fullname;
+        this.currentMedia = this.getMedias().getElement(this.getNamespaced(_idRef).fullname);
     }
 }
 
 IriSP.Model.Source.prototype.setDefaultCurrentMedia = function() {
-    if (typeof this.currentMedia === "undefined") {
-        this.currentMedia = this.getList("media").getElementAt(0);
+    if (typeof this.currentMedia === "undefined" && this.getMedias().length) {
+        this.currentMedia = this.getMedias()[0];
     }
 }
 
@@ -430,9 +436,9 @@
     var _this = this,
         _nsls = [],
         _excludeSelf = (typeof _excludeSelf !== "undefined" && _excludeSelf);
-    this.each(function(_list) {
-        IriSP._(_list.contents).each(function(_id) {
-            var _ns = _id.replace(/:.*$/,'');
+    this.forEach(function(_list) {
+        IriSP._(_list).forEach(function(_el) {
+            var _ns = _el.id.replace(/:.*$/,'');
             if (IriSP._(_nsls).indexOf(_ns) === -1 && (!_excludeSelf || _ns !== _this.namespace)) {
                 _nsls.push(_ns);
             }
@@ -445,7 +451,7 @@
     this.status = IriSP.Model.SOURCE_STATUS_READY;
     var _this = this;
     if (_this.callbackQueue.length) {
-        IriSP._.each(_this.callbackQueue, function(_callback) {
+        IriSP._(_this.callbackQueue).forEach(function(_callback) {
             _callback.call(_this);
         });
     }
@@ -456,7 +462,7 @@
     return this.serializer.serialize(this);
 }
 
-IriSP.Model.Source.prototype.addCallback = function(_callback) {
+IriSP.Model.Source.prototype.onLoad = function(_callback) {
     if (this.status === IriSP.Model.SOURCE_STATUS_READY) {
         callback.call(this);
     } else {
@@ -478,13 +484,16 @@
 
 IriSP.Model.Source.prototype.getAnnotationTypeByTitle = function(_title) {
     var _res = this.getAnnotationTypes().searchByTitle(_title);
-    if (_res.length() > 0) {
-        return _res.getElementAt(0);
+    if (_res.length) {
+        return _res[0];
     }
 }
 
 IriSP.Model.Source.prototype.getDuration = function() {
-    return this.currentMedia.duration;
+    var _m = this.currentMedia;
+    if (typeof _m !== "undefined") {
+        return this.currentMedia.duration;
+    }
 }
 
 /* */
@@ -501,7 +510,7 @@
     IriSP.jQuery.getJSON(this.url, function(_result) {
         _this.serializer.deSerialize(_result, _this);
         if (_this.callbackQueue.length) {
-            IriSP._.each(_this.callbackQueue, function(_callback) {
+            IriSP._(_this.callbackQueue).forEach(function(_callback) {
                 _callback.call(_this);
             });
         }
@@ -542,7 +551,7 @@
 
 IriSP.Model.Directory.prototype.getGlobalList = function() {
     var _res = new IriSP.Model.List(this);
-    _res.addIdsFromArray(IriSP._(this.elements).keys());
+    _res.addIds(IriSP._(this.elements).keys());
     return _res;
 }
 
--- a/src/js/modules.js	Mon Apr 16 19:10:32 2012 +0200
+++ b/src/js/modules.js	Tue Apr 17 15:03:40 2012 +0200
@@ -1,5 +1,7 @@
 /* modules are non-graphical entities, similar to widgets */
 
+// TODO: Unify widgets and modules
+
 IriSP.Module = function(Popcorn, config, Serializer) {
 
   if (config === undefined || config === null) {
--- a/src/js/players/player.allocine.js	Mon Apr 16 19:10:32 2012 +0200
+++ b/src/js/players/player.allocine.js	Tue Apr 17 15:03:40 2012 +0200
@@ -36,11 +36,6 @@
     window.onAllocineStateChange = IriSP.wrap(this, this.stateHandler);
     window.onTime = IriSP.wrap(this, this.progressHandler);
     
-    var _videoUrl = (
-        typeof options.directVideoPath == "string"
-        ? options.directVideoPath
-        : IriSP.get_aliased(IriSP.__jsonMetadata["medias"][0], ["href","url"])
-    );
     var _flashVars = {
         "streamFMS" : true,
         "adVast" : false,
@@ -48,7 +43,7 @@
         "autoPlay" : options.autoPlay,
         "directVideoTitle" : "",
         "urlAcData" : options.urlAcData,
-        "directVideoPath" : _videoUrl,
+        "directVideoPath" : options.video,
         "host" : "http://allocine.fr"
     }
     
--- a/src/js/serializers/CinecastSerializer.js	Mon Apr 16 19:10:32 2012 +0200
+++ b/src/js/serializers/CinecastSerializer.js	Tue Apr 17 15:03:40 2012 +0200
@@ -9,7 +9,7 @@
             model_name : "media",
             deserializer : function(_data, _source) {
                 var _res = new IriSP.Model.Media(_data.id, _source);
-                _res.url = _data.href;
+                _res.video = _data.url;
                 _res.title = _data.meta.title;
                 _res.description = _data.meta.synopsis;
                 _res.setDuration(_data.meta.duration);
@@ -18,7 +18,7 @@
             serializer : function(_data, _source) {
                 return {
                     id : _source.unNamespace(_data.id),
-                    url : _data.url,
+                    url : _data.video,
                     meta : {
                         title : _data.title,
                         synopsis : _data.description,
@@ -97,7 +97,7 @@
                             .replace(/[^A-Za-z0-9_]/g,''),
                             _tag = new IriSP.Model.Tag(_id, _source);
                         _tag.title = _t;
-                        _source.contents.tag.addElement(_tag);
+                        _source.contents.tag.push(_tag);
                         return _id;
                     }
                 }));
@@ -143,7 +143,7 @@
                })
            } 
         }
-        _source.each(function(_list, _typename) {
+        _source.forEach(function(_list, _typename) {
             if (typeof _this.types[_typename] !== "undefined") {
                 _res[_this.types[_typename].serialized_name] = _list.map(function(_el) {
                     return _this.types[_typename].serializer(_el, _source);
@@ -154,28 +154,28 @@
     },
     deSerialize : function(_data, _source) {
         if (typeof _data.imports !== "undefined") {
-            IriSP._(_data.imports).each(function(_import) {
+            IriSP._(_data.imports).forEach(function(_import) {
                 _source.directory.namespaces[_import.id] = _import.url;
             })
         }
-        IriSP._(this.types).each(function(_type, _typename) {
+        IriSP._(this.types).forEach(function(_type, _typename) {
             var _listdata = _data[_type.serialized_name];
             if (typeof _listdata !== "undefined") {
                 var _list = new IriSP.Model.List(_source.directory);
                 if (_listdata.hasOwnProperty("length")) {
                     var _l = _listdata.length;
                     for (var _i = 0; _i < _l; _i++) {
-                        _list.addElement(_type.deserializer(_listdata[_i], _source));
+                        _list.push(_type.deserializer(_listdata[_i], _source));
                     }
                 } else {
-                    _list.addElement(_type.deserializer(_listdata, _source));
+                    _list.push(_type.deserializer(_listdata, _source));
                 }
                 _source.addList(_typename, _list);
             }
         });
         
         if (typeof _data.meta !== "undefined" && typeof _data.meta.main_media !== "undefined" && typeof _data.meta.main_media["id-ref"] !== "undefined") {
-            _source.setCurrentMediaId(_data.meta.main_media["id-ref"]);
+            _source.setCurrentMediaId(_data.meta.id);
         }
         _source.setDefaultCurrentMedia();
     }
--- a/src/js/serializers/JSONSerializer.js	Mon Apr 16 19:10:32 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,443 +0,0 @@
-/** @class This class implement a serializer for the JSON-Cinelab format
-    @params DataLoader a dataloader reference
-    @url the url from which to get our cinelab
- */
-IriSP.JSONSerializer = function(DataLoader, url) {
-  IriSP.Serializer.call(this, DataLoader, url);
-};
-
-IriSP.JSONSerializer.prototype = new IriSP.Serializer();
-
-/** serialize data */
-IriSP.JSONSerializer.prototype.serialize = function(data) {
-  return JSON.stringify(data);
-};
-
-/** deserialize data */
-IriSP.JSONSerializer.prototype.deserialize = function(data) {
-  return JSON.parse(data);
-};
-
-/** load JSON-cinelab data and also sort the annotations by start time
-    @param callback function to call when the data is ready.
- */
-IriSP.JSONSerializer.prototype.sync = function(callback, force_refresh) {
-  /* we don't have to do much because jQuery handles json for us */
-
-  var self = this;
-
-  var fn = function(data) {
-	  //TODO: seems taht data can be null here
-	  if (data !== null) {
-		  self._data = data;  
-	      if (typeof(self._data["annotations"]) === "undefined" ||
-	          self._data["annotations"] === null)
-	          self._data["annotations"] = [];
-	      
-	      // sort the data too       
-	      self._data["annotations"].sort(function(a, b) 
-	          { var a_begin = +a.begin;
-	            var b_begin = +b.begin;
-	            return a_begin - b_begin;
-	          });
-	  }     
-      callback(data);      
-  };
-  this._DataLoader.get(this._url, fn, force_refresh);
-};
-
-/** @return the metadata about the media being read FIXME: always return the first media. */
-IriSP.JSONSerializer.prototype.currentMedia = function() {  
-  return (typeof this._data.medias == "object" && this._data.medias.length) ? this._data.medias[0] : IriSP.__jsonMetadata.medias[0];
-};
-
-IriSP.JSONSerializer.prototype.getDuration = function() {
-    var _m = this.currentMedia();
-    if (_m === null || typeof _m.meta == "undefined") {
-        return 0;
-    }
-    return +(IriSP.get_aliased(_m.meta, ["dc:duration", "duration"]) || 0);
-}
-
-
-/** searches for an annotation which matches title, description and keyword 
-   "" matches any field. 
-   Note: it ignores tweets.
-   @return a list of matching ids.
-*/    
-IriSP.JSONSerializer.prototype.searchAnnotations = function(title, description, keyword) {
-    /* we can have many types of annotations. We want search to only look for regular segments */
-    /* the next two lines are a bit verbose because for some test data, _serializer.data.view is either
-       null or undefined.
-    */
-    var view;
-
-    if (typeof(this._data.views) !== "undefined" && this._data.views !== null)
-       view = this._data.views[0];
-
-    var searchViewType = "";
-
-    if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) {
-            searchViewType = view.annotation_types[0];
-    }
-
-    var filterfn = function(annotation) {
-      if( searchViewType  != "" && 
-          typeof(annotation.meta) !== "undefined" && 
-          typeof(annotation.meta["id-ref"]) !== "undefined" &&
-          annotation.meta["id-ref"] !== searchViewType) {
-        return true; // don't pass
-      } else {
-          return false;
-      }
-    };
-
-    return this.searchAnnotationsFilter(title, description, keyword, filterfn);
-
-};
-
-/* only look for tweets */
-IriSP.JSONSerializer.prototype.searchTweets = function(title, description, keyword) {
-    /* we can have many types of annotations. We want search to only look for regular segments */
-    /* the next two lines are a bit verbose because for some test data, _serializer.data.view is either
-       null or undefined.
-    */
-    
-    var searchViewType = this.getTweets();
-    if (typeof(searchViewType) === "undefined") {
-      var view;
-      
-      if (typeof(this._data.views) !== "undefined" && this._data.views !== null)
-         view = this._data.views[0];    
-
-      if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) {
-              searchViewType = view.annotation_types[0];
-      }
-    }
-    var filterfn = function(annotation) {
-      if( searchViewType  != "" && 
-          typeof(annotation.meta) !== "undefined" && 
-          typeof(annotation.meta["id-ref"]) !== "undefined" &&
-          annotation.meta["id-ref"] === searchViewType) {
-        return false; // pass
-      } else {
-          return true;
-      }
-    };
-
-    return this.searchAnnotationsFilter(title, description, keyword, filterfn);
-
-};
-
-/**
-  search an annotation according to its title, description and keyword
-  @param filter a function to filter the results with. Used to select between annotation types.
- */    
-IriSP.JSONSerializer.prototype.searchAnnotationsFilter = function(title, description, keyword, filter) {
-
-    var rTitle;
-    var rDescription;
-    var rKeyword;
-    /* match anything if given the empty string */
-    if (title == "")
-      title = ".*";
-    if (description == "")
-      description = ".*";
-    if (keyword == "")
-      keyword = ".*";
-    
-    rTitle = new RegExp(title, "i");  
-    rDescription = new RegExp(description, "i");  
-    rKeyword = new RegExp(keyword, "i");  
-    
-    var ret_array = [];
-    
-    var i;
-    for (i in this._data.annotations) {
-      var annotation = this._data.annotations[i];
-      
-      /* filter the annotations whose type is not the one we want */
-      if (filter(annotation)) {
-          continue;
-      }
-      
-      if (rTitle.test(annotation.content.title) && 
-          rDescription.test(annotation.content.description)) {
-          /* FIXME : implement keyword support */
-          ret_array.push(annotation);
-      }
-    }
-    
-    return ret_array;
-};
-
-/** breaks a string in words and searches each of these words. Returns an array
-   of objects with the id of the annotation and its number of occurences.
-   
-   @param searchString a string of words.
-   FIXME: optimize ? seems to be n^2 in the worst case.
-*/
-IriSP.JSONSerializer.prototype.searchOccurences = function(searchString) {
-  var ret = { };
-  var keywords = searchString.split(/\s+/);
-  
-  for (var i in keywords) {
-    var keyword = keywords[i];
-    
-    // search this keyword in descriptions and title
-    var found_annotations = []
-    found_annotations = found_annotations.concat(this.searchAnnotations(keyword, "", ""));
-    found_annotations = found_annotations.concat(this.searchAnnotations("", keyword, ""));
-    
-    for (var j in found_annotations) {
-      var current_annotation = found_annotations[j];
-      
-      if (!ret.hasOwnProperty(current_annotation.id)) {
-        ret[current_annotation.id] = 1;
-      } else {
-        ret[current_annotation.id] += 1;
-      }
-      
-    }
-
-  };
-  
-  return ret;
-};
-
-/** breaks a string in words and searches each of these words. Returns an array
-   of objects with the id of the annotation and its number of occurences.
-   
-   FIXME: optimize ? seems to be n^2 in the worst case.
-*/
-IriSP.JSONSerializer.prototype.searchTweetsOccurences = function(searchString) {
-  var ret = { };
-  var keywords = searchString.split(/\s+/);
-  
-  for (var i in keywords) {
-    var keyword = keywords[i];
-    
-    // search this keyword in descriptions and title
-    var found_annotations = []
-    found_annotations = found_annotations.concat(this.searchTweets(keyword, "", ""));
-    found_annotations = found_annotations.concat(this.searchTweets("", keyword, ""));
-    
-    for (var j in found_annotations) {
-      var current_annotation = found_annotations[j];
-      
-      if (!ret.hasOwnProperty(current_annotation.id)) {
-        ret[current_annotation.id] = 1;
-      } else {
-        ret[current_annotation.id] += 1;
-      }
-      
-    }
-
-  };
-  
-  return ret;
-};
-
-/** returns all the annotations that are displayable at the moment 
-   NB: only takes account the first type of annotations - ignores tweets 
-   currentTime is in seconds.
-   
-   @param currentTime the time at which we search.
-   @param (optional) the if of the type of the annotations we want to get.
- */
-
-IriSP.JSONSerializer.prototype.currentAnnotations = function(currentTime, id) {
-  var view;
-  var currentTimeMs = 1000 * currentTime;
-
-  if (typeof(id) === "undefined") {
-      var legal_ids = this.getNonTweetIds();
-  } else {
-      legal_ids = [id];
-  }
-  
-  var ret_array = [];
-  
-  var i;
-  
-  for (i in this._data.annotations) {
-    var annotation = this._data.annotations[i];
-    
-    if (IriSP.underscore.include(legal_ids, annotation.meta["id-ref"]) && 
-        annotation.begin <= currentTimeMs &&
-        annotation.end >= currentTimeMs)
-          ret_array.push(annotation);
-  }
- 
-  if (ret_array == []) {
-    console.log("ret_array empty, ", legal_ids);
-  }
-  
-  return ret_array;
-};
-
-/** return the current chapitre
-    @param currentTime the current time, in seconds.
-*/
-IriSP.JSONSerializer.prototype.currentChapitre = function(currentTime) {
-  return this.currentAnnotations(currentTime, this.getChapitrage())[0];
-};
-
-/** returns a list of ids of tweet lines (aka: groups in cinelab) */
-IriSP.JSONSerializer.prototype.getTweetIds = function() {
-  if (IriSP.null_or_undefined(this._data.lists) || IriSP.null_or_undefined(this._data.lists) ||
-      IriSP.null_or_undefined(this._data.views) || IriSP.null_or_undefined(this._data.views[0]))
-    return [];
-
-  
-  /* Get the displayable types
-     We've got to jump through a few hoops because the json sometimes defines
-     fields with underscores and sometimes with dashes
-  */
-  var annotation_types = IriSP.get_aliased(this._data.views[0], ["annotation_types", "annotation-types"]);
-  if (annotation_types === null) {
-      console.log("neither view.annotation_types nor view.annotation-types are defined");      
-      return;
-  }
-
-  var available_types = IriSP.get_aliased(this._data, ["annotation_types", "annotation-types"]);    
-  if (available_types === null) {
-      console.log("neither view.annotation_types nor view.annotation-types are defined");      
-      return;
-  }
-  
-  var potential_types = [];
-  
-  // Get the list of types which contain "Tw" in their content
-  for (var i = 0; i < available_types.length; i++) {
-    if (/Tw/i.test(IriSP.get_aliased(available_types[i], ['dc:title', 'title']))) {
-      potential_types.push(available_types[i].id);
-    }
-  }
-  
-  // Get the intersection of both.
-  var tweetsId = IriSP.underscore.intersection(annotation_types, potential_types);
-  
-  return tweetsId;
-};
-
-/** this function returns a list of lines which are not tweet lines */
-IriSP.JSONSerializer.prototype.getNonTweetIds = function() {
-  if (IriSP.null_or_undefined(this._data.lists) || IriSP.null_or_undefined(this._data.lists) ||
-      IriSP.null_or_undefined(this._data.views) || IriSP.null_or_undefined(this._data.views[0]))
-    return [];
-
-  /* Get the displayable types
-     We've got to jump through a few hoops because the json sometimes defines
-     fields with underscores and sometimes with dashes
-  */
-  var annotation_types = IriSP.get_aliased(this._data.views[0], ["annotation_types", "annotation-types"]);
-  if (annotation_types === null) {
-      console.log("neither view.annotation_types nor view.annotation-types are defined");      
-      return;
-  }
-
-  var available_types = IriSP.get_aliased(this._data, ["annotation_types", "annotation-types"]);    
-  if (available_types === null) {
-      console.log("neither view.annotation_types nor view.annotation-types are defined");      
-      return;
-  }
-
-  var potential_types = [];
-  
-  // Get the list of types which do not contain "Tw" in their content
-  for (var i = 0; i < available_types.length; i++) {
-    if (!(/Tw/i.test(IriSP.get_aliased(available_types[i], ['dc:title', 'title'])))) {
-      potential_types.push(available_types[i].id);
-    }
-  }
-
-  // Get the intersection of both.
-  var nonTweetsId = IriSP.underscore.intersection(annotation_types, potential_types);
-  
-  return nonTweetsId;
-  
-};
-
-/** return the id of the ligne de temps which contains name
-    @param name of the ligne de temps
-*/
-IriSP.JSONSerializer.prototype.getId = function(name) {
-   var available_types = IriSP.get_aliased(this._data, ["annotation_types", "annotation-types"]);  
-   
-  if (available_types == null)
-    return;
-
-  name = name.toUpperCase();
-  var e;  
-  e = IriSP.underscore.find(available_types, 
-    function(entry) {
-        if (IriSP.get_aliased(entry, ['dc:title', 'title']) === null)
-          return false;
-        return (entry["dc:title"].toUpperCase().indexOf(name) !== -1);
-    });
-  
-  if (typeof(e) === "undefined")
-    return;
-    
-  var id = e.id;
-
-  return id;
-};
-
-/** return the list of id's of the ligne de temps which contains name
-    @param name of the ligne de temps
-*/
-IriSP.JSONSerializer.prototype.getIds = function(name) {
-   var available_types = IriSP.get_aliased(this._data, ["annotation_types", "annotation-types"]);  
-   
-  if (available_types == null)
-    return;
-
-  name = name.toUpperCase();
-  var e = [];  
-  e = IriSP.underscore.filter(available_types, 
-                                  function(entry) { return (IriSP.get_aliased(entry, ['dc:title', 'title']).toUpperCase().indexOf(name) !== -1) });
-  return IriSP.underscore.pluck(e, "id");  
-};
-
-/** return the id of the ligne de temps named "Chapitrage" */
-IriSP.JSONSerializer.prototype.getChapitrage = function() {
-  var val = this.getId("Chapitrage");
-  if (typeof(val) === "undefined")
-    val = this.getId("Chapter");   
-  if (typeof(val) === "undefined")
-    val = this.getId("Chapit");
-  if (typeof(val) === "undefined")
-    val = this.getId("Chap");
-    
-  return val;
-};
-
-/** return the id of the ligne de temps named "Tweets" */
-IriSP.JSONSerializer.prototype.getTweets = function() {
-  var val = this.getId("Tweets");
-  if (typeof(val) === "undefined")
-    val = this.getId("Tweet");
-  if (typeof(val) === "undefined")
-    val = this.getId("Twitter");
-  if (typeof(val) === "undefined")
-    val = this.getId("twit");
-  if (typeof(val) === "undefined")
-    val = this.getId("Polemic");
-  
-  return val;
-};
-
-/** return the id of the ligne de temps named "Contributions" */
-IriSP.JSONSerializer.prototype.getContributions = function() {
-  var val = this.getId("Contribution");
-  if (typeof(val) === "undefined")
-    val = this.getId("Particip");   
-  if (typeof(val) === "undefined")
-    val = this.getId("Contr");
-  if (typeof(val) === "undefined")
-    val = this.getId("Publ");
-    
-  return val;
-};
\ No newline at end of file
--- a/src/js/serializers/PlatformSerializer.js	Mon Apr 16 19:10:32 2012 +0200
+++ b/src/js/serializers/PlatformSerializer.js	Tue Apr 17 15:03:40 2012 +0200
@@ -9,7 +9,18 @@
             model_name : "media",
             deserializer : function(_data, _source) {
                 var _res = new IriSP.Model.Media(_data.id, _source);
-                _res.url = _data.href;
+                _res.video = (
+                    typeof _data.url !== "undefined"
+                    ? _data.url
+                    : (
+                        typeof _data.href !== "undefined"
+                        ? _data.href
+                        : null
+                    )
+                );
+                if (typeof _data.meta.item !== "undefined" && _data.meta.item.name === "streamer") {
+                    _res.streamer = _data.meta.item.value;
+                }
                 _res.title = _data.meta["dc:title"];
                 _res.description = _data.meta["dc:description"];
                 _res.setDuration(_data.meta["dc:duration"]);
@@ -18,7 +29,7 @@
             serializer : function(_data, _source) {
                 return {
                     id : _source.unNamespace(_data.id),
-                    href : _data.url,
+                    url : _data.video,
                     meta : {
                         "dc:title" : _data.title,
                         "dc:description" : _data.description,
@@ -105,7 +116,7 @@
     serialize : function(_source) {
         var _res = {},
             _this = this;
-        _source.each(function(_list, _typename) {
+        _source.forEach(function(_list, _typename) {
             if (typeof _this.types[_typename] !== "undefined") {
                 _res[_this.types[_typename].serialized_name] = _list.map(function(_el) {
                     return _this.types[_typename].serializer(_el, _source);
@@ -115,17 +126,17 @@
         return _res;
     },
     deSerialize : function(_data, _source) {
-        IriSP._(this.types).each(function(_type, _typename) {
+        IriSP._(this.types).forEach(function(_type, _typename) {
             var _listdata = _data[_type.serialized_name];
             if (typeof _listdata !== "undefined") {
                 var _list = new IriSP.Model.List(_source.directory);
                 if (_listdata.hasOwnProperty("length")) {
                     var _l = _listdata.length;
                     for (var _i = 0; _i < _l; _i++) {
-                        _list.addElement(_type.deserializer(_listdata[_i], _source));
+                        _list.push(_type.deserializer(_listdata[_i], _source));
                     }
                 } else {
-                    _list.addElement(_type.deserializer(_listdata, _source));
+                    _list.push(_type.deserializer(_listdata, _source));
                 }
                 _source.addList(_typename, _list);
             }
--- a/src/js/widgets.js	Mon Apr 16 19:10:32 2012 +0200
+++ b/src/js/widgets.js	Tue Apr 17 15:03:40 2012 +0200
@@ -61,13 +61,7 @@
   var _this = this;
   
   if (typeof config.type == "string" && typeof IriSP.widgetsDefaults[config.type] == "object") {
-      IriSP._(IriSP.widgetsDefaults[config.type]).each(function(_v, _k) {
-          if (typeof config[_k] != "undefined") {
-              _this[_k] = config[_k];
-          } else {
-              _this[_k] = _v;
-          }
-      });
+      config = IriSP._.defaults(IriSP.widgetsDefaults[config.type]);
   }
   
 };
--- a/test/integration/polemic.htm	Mon Apr 16 19:10:32 2012 +0200
+++ b/test/integration/polemic.htm	Tue Apr 17 15:03:40 2012 +0200
@@ -45,32 +45,10 @@
               width: 180,
               height: 160,
              }],
-            }, */
+            }, 
             {type: "StackGraphWidget",
              height: 150,
             streamgraph: true,
-/*            tags : [
-            {
-                "keywords" : [ "#ilReste" ],
-                "description" : "#ilReste",
-                "color" : "#1D973D"
-            },
-            {
-                "keywords" : [ "#ilPart" ],
-                "description" : "#ilPart",
-                "color" : "#CE0A15"
-            },
-            {
-                "keywords" : [ "#change2ton" ],
-                "description" : "#change2ton",
-                "color" : "#C5A62D"  
-            },
-            {
-                "keywords" : [ "#cQui" ],
-                "description" : "#cQui",
-                "color" : "#036AAE"
-            } 
-        ],*/
              requires: [{
               type: "TooltipWidget",
               width: 180,
@@ -98,7 +76,7 @@
             excludeWords: ['#museoweb']},
             {type: "AnnotationsListWidget",
             container: "AnnotationsListContainer",
-            ajax_mode: false},
+            ajax_mode: false}, */
 //            {type: "TraceWidget"}
             ]
         },
@@ -110,12 +88,12 @@
           provider: "rtmp" 
       },
       modules: [
-               { type: "MediaFragment",
+           /*    { type: "MediaFragment",
                             metadata:{
                            format:'cinelab',
                              src:file,
                              type:'json'}
-                        }]
+                        }*/]
 
     };