Front IDILL :
authorbastiena
Mon, 14 May 2012 17:20:35 +0200
changeset 32 4003f84cd349
parent 31 2c7fc855eba8
child 33 2d9b15f99b4e
Front IDILL : Player implemented and was mostly tested, still memory leaks.
.hgignore
front_idill/src/index.html
front_idill/src/mosaic/js/mosaic.js
front_idill/src/mosaic/mosaic/css/mosaic.anc.less
front_idill/src/mosaic/mosaic/css/mosaic.less
front_idill/src/mosaic/mosaic/css/reset.css
front_idill/src/mosaic/mosaic/js/localMosaic.js
front_idill/src/mosaic/mosaic/js/mosaic.js
front_idill/src/player/index.html
front_idill/src/player/json/videos.json
front_idill/src/player/metadataplayer/Timeline.js
--- a/.hgignore	Fri May 11 11:04:06 2012 +0200
+++ b/.hgignore	Mon May 14 17:20:35 2012 +0200
@@ -53,6 +53,25 @@
 front_idill/extern/fajran-npTuioClient/TestClient/TestClient.vcxproj.filters
 front_idill/src/snapshots-little/
 front_idill/src/snapshots/
+front_idill/src/player/markers/wheel.png
+front_idill/src/player/markers/wave.png
+front_idill/src/player/markers/updown.png
+front_idill/src/player/markers/swipe-down.png
+front_idill/src/player/markers/slow.png
+front_idill/src/player/markers/run.png
+front_idill/src/player/markers/right-angle.png
+front_idill/src/player/markers/pendulum.png
+front_idill/src/player/markers/knee-up.png
+front_idill/src/player/markers/jump.png
+front_idill/src/player/markers/join-hands.png
+front_idill/src/player/markers/hello.png
+front_idill/src/player/markers/cross.png
+front_idill/src/player/markers/circle.png
+front_idill/src/player/markers/bend.png
+front_idill/src/player/markers/beat.png
+front_idill/src/player/markers/arc.png
+front_idill/src/player/TODO player 11-05-12.txt
+front_idill/src/player/TODO player 02-05-12.txt
 syntax: regexp
 middleware/extern/.*/(bin|obj)
 middleware/src/bin/Debug/*
--- a/front_idill/src/index.html	Fri May 11 11:04:06 2012 +0200
+++ b/front_idill/src/index.html	Mon May 14 17:20:35 2012 +0200
@@ -66,22 +66,22 @@
             var lMos = new localMosaic(length, imagesToShow, zoomedMargin);
             mos.localMos = lMos;
             //Tableau d'images de test pour peupler la mosaïque.
-            var imgs = [];
+            /*var imgs = [];
             for(var i = 0 ; i < 42 ; i++)
 			{
                 imgs[i] = i + '.jpg';
-			}
+			}*/
             
             //Si on a changé les dimensions de la fenêtre, on raffraichit la mosaïque.
             $(window).resize(function ()
             {
-                mos.loadMosaic(imgs);
+                mos.loadMosaic();
             });
             
             //Si la page a chargé, on raffraichit la mosaïque.
             $(document).ready(function ()
             {
-                mos.loadMosaic(imgs);
+                mos.loadMosaic();
                 
                 $('.snapshotDivs').mouseenter(function ()
                 {
--- a/front_idill/src/mosaic/js/mosaic.js	Fri May 11 11:04:06 2012 +0200
+++ b/front_idill/src/mosaic/js/mosaic.js	Mon May 14 17:20:35 2012 +0200
@@ -32,6 +32,7 @@
         //Nombre d'images dans la mosaïque.
         this.imagesToShow = imgToShow;
         //Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
+        this.videos = [];
         this.urls = [];
         this.imgs = [];
         this.ids = [];
@@ -78,6 +79,10 @@
         this.neighboursIds = [];
         //ID du snapshot du milieu lors d'un zoom.
         this.centerId;
+		
+		this.player;
+		
+		this.loadFromJson('./player/json/videos.json');
     }
     else
     {
@@ -106,20 +111,30 @@
         }
     }
     
+	console.log(this.imagesToShow);
+	
     return str;
 }
 
 /*
  * Permet de raffraichir la mosaïque.
  */
-mosaic.prototype.loadMosaic = function(imgsTab)
+mosaic.prototype.loadMosaic = function()
 {
+	var createMosaic = this.createMosaic();
+	
+	if(createMosaic == '')
+	{
+		return;
+	}
+	
+	var _this = this;
+	
     //On affecte les chemins vers les images à la mosaïque.
-    this.imgs = imgsTab;
     this.previousZoomedSN;
     //this.width = 
     //On met à jour la mosaïque.
-    $('#mainPanel').html(this.createMosaic());
+    $('#mainPanel').html(createMosaic);
     //On récupère la taille des bordures.
     this.marginWidth = $('.snapshotDivs').css('margin-bottom');
     this.marginWidth = parseFloat(mos.marginWidth)*2;
@@ -134,6 +149,20 @@
     //On centre verticalement la mosaïque.
     this.MPTop_margin = ($(document).height() - $('#mainPanel').height())/2;
     $('#mainPanel').css('margin-top', this.MPTop_margin).css('margin-bottom', this.MPTop_margin);
+	
+	$('.snapshotDivs').mouseenter(function ()
+	{
+		//On effectue un prézoom dès qu'on va sur une image.
+		_this.preZoom($(this));
+	});
+	$('body').keypress(function (event)
+	{
+		//Si on a appuié sur la touche 'q' ou 'Q';
+		if(event.which == 113 || event.which == 81)
+		{
+		   _this.unzoom();
+		}
+	});
 }
 
 /*
@@ -377,10 +406,15 @@
 	IriSP.libFiles.defaultDir = "../lib/";
 	IriSP.widgetsDir = "./player/metadataplayer/"
 	
+	var videoToPlay = this.videos[this.centerId];
+	var currentMetadata = this.urls[this.centerId];
+	console.log('VIDEO[' + this.centerId + '] : ' + videoToPlay);
+	console.log('MD[' + this.centerId + '] : ' + currentMetadata);
+	
 	console.log(newZoomTop + " " + newZoomLeft);
 	
 	var _metadata = {
-		url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/7c912bce-66b8-11e1-80f6-00145ea4a2be?callback=?',
+		url: currentMetadata,
 		format: 'ldt'
 	};
 	var _config = {
@@ -400,7 +434,7 @@
 		},
 		player:{
 			type: 'html5', // player type
-			video: 'http://media.iri.centrepompidou.fr/video/ldtplatform/body_trail_cctv.mp4',
+			video: videoToPlay,
 			live: true,
 			height: newSnHeight,
 			width: newSnWidth,
@@ -419,8 +453,8 @@
 	});
 	
 	//On démarre le player.
-	var _myPlayer = new IriSP.Metadataplayer(_config, _metadata);
-	console.log(_myPlayer);
+	this.player = null;
+	this.player = new IriSP.Metadataplayer(_config, _metadata);
 }
 
 /*
@@ -556,7 +590,7 @@
 			'left': 0,
 			'width': $(this).width() - marginValue*2,
 			'height': $(this).height() - marginValue*2,
-			'background-image': 'url(' + $('img', $(this)).attr('src') + ')',
+			'background-image': 'url("' + $('img', $(this)).attr('src') + '")',
 			'background-size': $(this).width() + 'px ' + $(this).height() + 'px',
 			'background-position': -marginValue + 'px ' + -marginValue + 'px',
 			'opacity': '0.4'
@@ -734,4 +768,48 @@
         }
     }
     return true;
+}
+
+/*
+ * Charge les vidéos, les snapshots et les annotations depuis un fichier json.
+*/
+mosaic.prototype.loadFromJson = function(path)
+{
+	var _this = this;
+
+	$.getJSON(path, function(data)
+	{
+		$.each(data, function(key, val)
+		{
+			// console.log(val);
+			$.each(val, function(key_video, val_video)
+			{
+				$.getJSON(val_video.metadata, function(meta)
+				{
+					_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/'));
+					//console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/'));
+				});
+				
+				_this.imgs.push(val_video.snapshot);
+				_this.urls.push(val_video.metadata);
+			});
+		});
+		console.log('rdy');
+		_this.loadMosaic();
+	});
+}
+
+/*
+ * Affecte une vidéo au tableau des vidéos selon son id
+*/
+mosaic.prototype.affectVideoById = function(metadata_id, video)
+{
+	for (i = 0 ; i < this.urls.length ; i++)
+	{
+		if(this.urls[i] == metadata_id)
+		{
+			this.videos[i] = video;
+			break;
+		}
+	}
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/mosaic/mosaic/css/mosaic.anc.less	Mon May 14 17:20:35 2012 +0200
@@ -0,0 +1,107 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : mosaic.less
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les propriétés d'apparence des éléments de base de la mosaïque (les snapshots, la mosaïque en elle-même).
+ *
+ * Avertissement : Afin que ce fichier puisse compiler, il est nécessaire de lancer index.html depuis un chemin ne commencant pas par file:///.
+ * C'est pourquoi j'utilise WAMP pour le lancer.
+ */
+
+@mosaic-border-tickness: 1px;
+@mosaic-background-color: #202020;
+@mosaic-background-image-path: url("../../img/background.png");
+@selected-snapshot-background-image-path: url("../../img/selected_background.png");
+@snapshots-background-color: #8D8D8D;
+@snapshots-margin-value: 5px;
+@snapshots-margin: @snapshots-margin-value @snapshots-margin-value @snapshots-margin-value @snapshots-margin-value;
+@black: #000000;
+
+body
+{
+    overflow: hidden;
+    background-color: @black;
+}
+
+/*
+ * Il s'agit des propriétés de la mosaïque en elle même.
+ * On désactive les barres de défilement, on peut la placer à n'importe qu'elle position, elle doit être aussi large que la fenêtre du navigateur.
+ * Son fond se répète.
+ */
+#mainPanel
+{
+    overflow: hidden;
+    position: absolute;
+    width: 100%;
+    top: 0px;
+    left: 0px;
+    background-image: @mosaic-background-image-path;
+    background-repeat: repeat;
+}
+
+/*
+ * Les divs contenant les snapshots (ou les "voisins" aussi en cas de zoom total). Ils se positionnent par défaut de gauche à droite, à l'horizontale et wrap dès
+ * qu'ils ont atteint la bordure de fenêtre de droite.
+ */
+.snapshotDivs, .neighbourDivs
+{
+    background-color: @black;
+    margin: @snapshots-margin;
+    float: left;
+}
+
+/*
+ * Les snapshots sont des images, elles doivent remplir l'intégralité de leurs divs (snapshotDivs).
+ */
+.snapshots
+{
+    width: 100%;
+    height: 100%;
+}
+
+/*
+ * Ce sont des divs créés spécialement lors d'un prézoom. Leur fonction est d'afficher un clone du snapshot, superposé au précédent et de grandir un peu de manière
+ * à faire ressortir visuellement le snapshot pointé. Leur bordure est d'une couleur différente au fond, ce qui permet de les discerner plus facilement dans la mosaïque.
+ * au départ, lors de sa création, il est caché, mais apparaît dès que l'image est chargée.
+ */
+.prezoomContainers
+{
+    position: absolute;
+    display: none;
+    background-image: @selected-snapshot-background-image-path;
+    background-repeat: repeat;
+}
+
+/*
+ * Cette classe est attachée à des divs destinés à remplir les bordures d'une mosaïque locale.
+ */
+.blacks
+{
+    background-color: @black;
+    float: left;
+}
+
+/*
+ * C'est une classe appliquée aux divs "voisins", afin de les colorer lorsque l'utilisateur intéragit avec eux.
+ * Ils se positionnent exactement sur le voisin qu'ils représentent, à la manière du clone de prézoom (prezoomContainer), bien que celui-là n'est qu'un div simple
+ * ne contenant pas d'image.
+ * Au départ, l'opacité est à 0, ce qui signifie que ce div est invisible. L'opacité change lors d'intéractions avec cet objet. Le div apparaît alors.
+ */
+.cyan
+{
+    position: absolute;
+    background-color: #94C6C5;
+    opacity: 0;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/mosaic/mosaic/css/mosaic.less	Mon May 14 17:20:35 2012 +0200
@@ -0,0 +1,132 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : mosaic.less
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit les propriétés d'apparence des éléments de base de la mosaïque (les snapshots, la mosaïque en elle-même).
+ *
+ * Avertissement : Afin que ce fichier puisse compiler, il est nécessaire de lancer index.html depuis un chemin ne commencant pas par file:///.
+ * C'est pourquoi j'utilise WAMP pour le lancer.
+ */
+
+@mosaic-border-tickness: 1px;
+@mosaic-background-color: #202020;
+@mosaic-background-image-path: url("../../img/background.png");
+@selected-snapshot-background-image-path: url("../../img/selected_background.png");
+@snapshots-background-color: #8D8D8D;
+@snapshots-margin-value: 8px;
+@snapshots-margin: @snapshots-margin-value @snapshots-margin-value @snapshots-margin-value @snapshots-margin-value;
+@black: #000000;
+
+body
+{
+    //overflow: hidden;
+    background-color: @black;
+}
+
+/*
+ * Il s'agit des propriétés de la mosaïque en elle même.
+ * On désactive les barres de défilement, on peut la placer à n'importe qu'elle position, elle doit être aussi large que la fenêtre du navigateur.
+ * Son fond se répète.
+ */
+#mainPanel
+{
+    overflow: hidden;
+    position: absolute;
+    width: 100%;
+    top: 0px;
+    left: 0px;
+    background-image: @mosaic-background-image-path;
+    background-repeat: repeat;
+}
+
+/*
+ * Les divs contenant les snapshots (ou les "voisins" aussi en cas de zoom total). Ils se positionnent par défaut de gauche à droite, à l'horizontale et wrap dès
+ * qu'ils ont atteint la bordure de fenêtre de droite.
+ */
+.snapshotDivs, .neighbourDivs
+{
+    background-color: @black;
+    margin: @snapshots-margin;
+    float: left;
+}
+
+/*
+ * Les snapshots sont des images, elles doivent remplir l'intégralité de leurs divs (snapshotDivs).
+ */
+.snapshots
+{
+    width: 100%;
+    height: 100%;
+}
+
+/*
+ * Ce sont des divs créés spécialement lors d'un prézoom. Leur fonction est d'afficher un clone du snapshot, superposé au précédent et de grandir un peu de manière
+ * à faire ressortir visuellement le snapshot pointé. Leur bordure est d'une couleur différente au fond, ce qui permet de les discerner plus facilement dans la mosaïque.
+ * au départ, lors de sa création, il est caché, mais apparaît dès que l'image est chargée.
+ */
+.prezoomContainers
+{
+    position: absolute;
+    display: none;
+    background-image: @selected-snapshot-background-image-path;
+    background-repeat: repeat;
+}
+
+/*
+ * Cette classe est attachée à des divs destinés à remplir les bordures d'une mosaïque locale.
+ */
+.blacks
+{
+    background-color: @black;
+    float: left;
+}
+
+/*
+ * C'est une classe appliquée aux divs "voisins", afin de les colorer lorsque l'utilisateur intéragit avec eux.
+ * Ils se positionnent exactement sur le voisin qu'ils représentent, à la manière du clone de prézoom (prezoomContainer), bien que celui-là n'est qu'un div simple
+ * ne contenant pas d'image.
+ * Au départ, l'opacité est à 0, ce qui signifie que ce div est invisible. L'opacité change lors d'intéractions avec cet objet. Le div apparaît alors.
+ */
+.neighbourFrame
+{
+    position: absolute;
+    //background-color: #94C6C5;
+    //background-color: rgba(148, 198, 197, 1);
+	background-image: @selected-snapshot-background-image-path;
+    background-repeat: repeat;
+	opacity: 0;
+}
+
+/*
+ * 
+ */
+.neighbourImgBg
+{
+    position: absolute;
+	background-image: @mosaic-background-image-path;
+}
+
+/*
+ * 
+ */
+.neighbourImg
+{
+    position: absolute;
+}
+
+video
+{
+	//position: absolute;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/mosaic/mosaic/css/reset.css	Mon May 14 17:20:35 2012 +0200
@@ -0,0 +1,48 @@
+/* http://meyerweb.com/eric/tools/css/reset/ 
+   v2.0 | 20110126
+   License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+	margin: 0;
+	padding: 0;
+	border: 0;
+	font-size: 100%;
+	font: inherit;
+	vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure, 
+footer, header, hgroup, menu, nav, section {
+	display: block;
+}
+body {
+	line-height: 1;
+}
+ol, ul {
+	list-style: none;
+}
+blockquote, q {
+	quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+	content: '';
+	content: none;
+}
+table {
+	border-collapse: collapse;
+	border-spacing: 0;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/mosaic/mosaic/js/localMosaic.js	Mon May 14 17:20:35 2012 +0200
@@ -0,0 +1,106 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : localMosaic.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit la "classe" mosaïque locale (lors d'un zoom sur une mosaïque) et définit des fonctions d'intéractions.
+ */
+
+/*
+ * Classe définissant la mosaïque locale.
+ * Elle sera toujours de la forme 3x3, même si toutes les cases ne seront pas remplies par des snapshots (cas des bords et coins).
+*/
+function localMosaic(len, imgToShow, marginWidth)
+{
+    if(imgToShow % len == 0)
+    {
+        this.length = len;
+        this.imagesToShow = imgToShow;
+        this.centerId;
+        this.urls = [];
+        this.imgs = [];
+        this.ids = [];
+        this.width;
+        this.height;
+        this.marginWidth = marginWidth;
+        this.zoomed;
+        this.snapshotTop;
+        this.snapshotLeft;
+        this.snapshotWidth;
+        this.snapshotHeight;
+    }
+    else
+    {
+        //Affiche un message d'erreur.
+    }
+}
+
+/*
+ * Crée la mosaïque locale, qui est une partie de la mosaïque de mosaic.js.
+ * Il y a le snapshot sur lequel on a zoomé, et les 8 snapshots voisins.
+*/
+localMosaic.prototype.createLocalMosaic = function()
+{
+    var str = '';
+    
+    var t = this.coord1Dto2D(this.centerId);
+    var localId;
+    
+    for(var a = t[1] - 1 ; a < t[1] + 2 ; a++)
+        for(var b = t[0] - 1 ; b < t[0] + 2 ; b++)
+            if(a > -1 && a < this.imagesToShow / this.length && b > -1 && b < this.length)
+            {
+                localId = this.coord2Dto1D(a, b);
+                str += '<div class="snapshotDivs"><img id="snapshot-' + localId + '" class="snapshots" src="snapshots-little/' + this.imgs[localId] + '" /></div>';
+            }
+            else
+                str += '<div class="blacks"></div>';
+    
+    return str;
+}
+
+/*
+ * Permet de charger la mosaïque locale.
+*/
+localMosaic.prototype.loadLocalMosaic = function(snTop, snLeft, snWidth, snHeight, imgsTab, id)
+{
+    //On affecte les chemins vers les images à la mosaïque.
+    this.imgs = imgsTab;
+    this.centerId = id;
+    this.snapshotTop = snTop;//*(newPreMPHeight/initMPHeight) - this.zoomedMargin/2 + (initMPHeight - initMPHeight * this.zoomPercentage)/2 + 'px';
+    this.previousMPLeft = snLeft;
+    this.snapshotWidth = snWidth;
+    this.snapshotHeight = snHeight;
+    //On met à jour la mosaïque.
+    $('#mainPanel').html(this.createLocalMosaic(id));
+    $('.snapshotDivs').css('width', snWidth).css('height', snHeight).css('margin', this.marginWidth/2);
+    // var lMosTop = , newZoomLeft = -this.previousZoomedSN.position().left*(newPreMPWidth/initMPWidth) - this.zoomedMargin/2 + (initMPWidth - initMPWidth * this.zoomPercentage)/2 + 'px';
+    $('#mainPanel').css('top', 0).css('left', 0);
+}
+
+/*
+ * Change de 1 à 2 dimensions pour les coordonnées des snapshots dans la mosaïque.
+*/
+localMosaic.prototype.coord1Dto2D = function(i)
+{
+    return [i%length, Math.floor(i/this.length)];
+}
+
+/*
+ * Change de 2 à 1 dimension pour les coordonnées des snapshots dans la mosaïque.
+*/
+localMosaic.prototype.coord2Dto1D = function(i, j)
+{
+    return j * this.length + i;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/mosaic/mosaic/js/mosaic.js	Mon May 14 17:20:35 2012 +0200
@@ -0,0 +1,815 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : mosaic.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Définit la "classe" mosaïque et définit des fonctions d'intéractions.
+ */
+
+/*
+ * Classe définissant la mosaïque.
+ * Elle contient sa longueur, le nombre d'images total, une liste d'urls pour les vidéos, leurs snapshots principaux et leur position.
+ * Contient également les dimensions en px de la mosaïque.
+ */
+function mosaic(len, imgToShow, zoomPercentage, prezoomPercentage, zoomedMargin)
+{
+    //S'il s'agit d'un rectangle.
+    if(imgToShow % len == 0)
+    {
+        //Longueur horizontale.
+        this.length = len;
+        //Nombre d'images dans la mosaïque.
+        this.imagesToShow = imgToShow;
+        //Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque.
+        this.videos = [];
+        this.urls = [];
+        this.imgs = [];
+        this.ids = [];
+        //Dimensions de la mosaïque en pixels.
+        this.width;
+        this.height;
+        //Dimensions d'un snapshot en pixels.
+        this.snapshotWidth;
+        this.snapshotHeight;
+        //Espacement entre les snapshots en pixels.
+        this.marginWidth;
+        
+        //Temps d'intéractions/d'animations.
+        this.preZoomTime;
+        this.preUnzoomTime;
+        this.zoomTime;
+        this.unzoomTime;
+        this.timeNeighbourGlowing;
+        this.timeNeighbourUnglowing;
+        this.timeMovingToNeighbour;
+        
+        //Booléens permettant ou non certaines intéractions selon le contexte.
+        this.zoomed;
+        this.fullscreen;
+        this.canMoveToNeighbour;
+        
+        //Mode actuel.
+        this.currentMode;
+        //Snapshot sur lequel on a zoomé.
+        this.previousZoomedSN;
+        //Son ID.
+        this.previousId;
+        //Largeur de la marge pour le centrage vertical de la mosaïque.
+        this.MPTop_margin;
+        this.top_margin;
+        //Pourcentage d'agrandissement lors d'un prézoom et d'un zoom.
+        this.prezoomPercentage = prezoomPercentage;
+        this.zoomPercentage = zoomPercentage;
+        //Espacement des snapshots après un zoom.
+        this.zoomedMargin = zoomedMargin;
+        //Mosaïque locale.
+        this.localMos;
+        //Position des voisins lors d'un zoom.
+        this.neighboursIds = [];
+        //ID du snapshot du milieu lors d'un zoom.
+        this.centerId;
+		
+		this.player;
+		
+		this.loadFromJson('./player/json/videos.json');
+    }
+    else
+    {
+        //Affiche un message d'erreur.
+    }
+}
+
+/*
+ * Méthode d'affichage de la mosaïque.
+ * Génère une matrice de imgs.
+ */
+mosaic.prototype.createMosaic = function()
+{
+    this.previousZoomedSN = '';
+    this.previousPrezoomDiv = '';
+    this.fullscreen = false;
+    this.canMoveToNeighbour = false;
+    var str = '';
+    
+    if(this.imgs.length >= this.imagesToShow)
+    {
+        for(var i = 0 ; i < this.imagesToShow ; i++)
+        {
+            //On charge les images de petite taille pour ne pas surcharger la mosaïque lors de l'affichage global.
+            str += '<div id="snapshotDiv-' + i + '" class="snapshotDivs"><img id="snapshot-' + i + '" class="snapshots" src="snapshots-little/' + this.imgs[i] + '" /></div>';
+        }
+    }
+    
+	console.log(this.imagesToShow);
+	
+    return str;
+}
+
+/*
+ * Permet de raffraichir la mosaïque.
+ */
+mosaic.prototype.loadMosaic = function()
+{
+	var createMosaic = this.createMosaic();
+	
+	if(createMosaic == '')
+	{
+		return;
+	}
+	
+	var _this = this;
+	
+    //On affecte les chemins vers les images à la mosaïque.
+    this.previousZoomedSN;
+    //this.width = 
+    //On met à jour la mosaïque.
+    $('#mainPanel').html(createMosaic);
+    //On récupère la taille des bordures.
+    this.marginWidth = $('.snapshotDivs').css('margin-bottom');
+    this.marginWidth = parseFloat(mos.marginWidth)*2;
+    //On calcule la taille des divs contenant les snapshots.
+    this.width = $('#mainPanel').innerWidth();
+    //On ne calculera pas tout de suite la hauteur de la mosaique étant donnée qu'elle est calculée par la suite dynamiquement.
+    this.snapshotWidth = this.width / this.length - this.marginWidth;
+    this.snapshotHeight = this.snapshotWidth*9/16;
+    $('.snapshotDivs').css('width', this.snapshotWidth).css('height', this.snapshotHeight).css('margin', this.marginWidth/2);
+    
+    this.height = $('#mainPanel').innerHeight();
+    //On centre verticalement la mosaïque.
+    this.MPTop_margin = ($(document).height() - $('#mainPanel').height())/2;
+    $('#mainPanel').css('margin-top', this.MPTop_margin).css('margin-bottom', this.MPTop_margin);
+	
+	$('.snapshotDivs').mouseenter(function ()
+	{
+		//On effectue un prézoom dès qu'on va sur une image.
+		_this.preZoom($(this));
+	});
+	$('body').keypress(function (event)
+	{
+		//Si on a appuié sur la touche 'q' ou 'Q';
+		if(event.which == 113 || event.which == 81)
+		{
+		   _this.unzoom();
+		}
+	});
+}
+
+/*
+ * Zoom sur la position d'une image, 1ère partie. Durant le laps de temps de time ms, l'utilisateur a le choix de zoomer sur une autre image.
+ * Après ce laps de temps, l'image zoom complétement et il n'est plus possible de sélectionner une autre image par pointage.
+ */
+mosaic.prototype.preZoom = function(snapshot)
+{
+    if(this.fullscreen)
+	{
+        return;
+	}
+    //Mosaïque.
+    var mosaic = this;
+    //Dimensions de la mosaïque.
+    var h = this.height, w = this.width;
+    //Longueur en images, nombre d'images et taille de bordure de la mosaïque.
+    var len = this.length, imgs = this.imagesToShow, margin = this.marginWidth;
+    //Dimensions et position d'un snapshot dans la mosaïque.
+    var snHeight = this.snapshotHeight, snWidth = this.snapshotWidth;
+    var sTop = snapshot.position().top, sLeft = snapshot.position().left;
+    var prezoomPercentage = this.prezoomPercentage;
+    
+    //ID de l'image actuelle.
+    var currentId = $('img', snapshot).attr('id');
+    
+    //Si un zoom est déjà en cours, on ne zoom sur rien d'autre en attendant que ce snapshot ai dézoomé en cas de mouseleave.
+    if(this.zoomed)
+	{
+        if($('#preZoomContainer-' + currentId) != $(this) && this.previousZoomedSN != '' && this.previousId != '')
+		{
+            this.preUnzoom();
+		}
+        else
+		{
+            return;
+		}
+	}
+    
+    //On indique qu'on a zoomé et on spécifie le snapshot sur lequel on a zoomé.
+    this.zoomed = true;
+    this.previousZoomedSN = snapshot;
+    this.previousId = currentId;
+    
+    //On récupère les attributs de l'image.
+    var fakeImg = $('img', snapshot);
+    //On forme la balise de la fausse image et on passe son url pour les grands snapshots.
+    fakeImg = '<img id="fake-' + currentId + '" class="snapshots" src="' + fakeImg.attr('src').replace('-little/', '/') + '" />';
+    //On génère un faux snapshot identique au précédent et qu'on va coller dessus.
+    var fakeSnapshot = '<div id="prezoomContainer-' + currentId + '" class="prezoomContainers"><div id="prezoomSnapshot-' + currentId + '" class="snapshotDivs">' + fakeImg + '</div></div>';
+    
+    //On l'ajoute à la mosaïque.
+    $('#mainPanel').append(fakeSnapshot);
+    //On modifie ses attributs.
+    $('#fake-' + currentId).load(function()
+    {
+        $('#prezoomContainer-' + currentId).css('display', 'block');
+        $('#prezoomContainer-' + currentId).css('top', sTop).css('left', sLeft).css('width', (snWidth + margin)).css('height', (snHeight + margin));
+        $('#prezoomSnapshot-' + currentId).css('width', (snWidth)).css('height', (snHeight));
+        
+        //Dimensions et coordonnées initiales du div sur lequel on zoom.
+        var initialDivWidth = $('#prezoomContainer-' + currentId).width(), initialDivHeight = $('#prezoomContainer-' + currentId).height();
+        var initialDivTop = $('#prezoomContainer-' + currentId).position().top, initialDivLeft = $('#prezoomContainer-' + currentId).position().left;
+        //Dimensions et coordonnées finales du div.
+        var finalDivWidth = initialDivWidth * (prezoomPercentage+1), diffWidth = finalDivWidth - initialDivWidth, finalDivHeight = initialDivHeight + diffWidth;
+        var finalDivTop = (initialDivTop - (finalDivHeight - snHeight)/2), finalDivLeft = (initialDivLeft - (finalDivWidth - snWidth)/2);
+        
+        //CAS PARTICULIER pour la position du snapshot zoomé : les bordures.
+        if(finalDivTop < 0)
+		{
+            finalDivTop = -margin;
+		}
+        if(finalDivTop + finalDivHeight > h)
+		{
+            finalDivTop = h - finalDivHeight;
+		}
+        if(finalDivLeft < 0)
+		{
+            finalDivLeft = 0;
+		}
+        if(finalDivLeft + finalDivWidth + margin*2 > w)
+		{
+            finalDivLeft = w - finalDivWidth - margin*2;
+		}
+        
+        ////Code de debug.
+        ////CAUTION////
+        /*var red = '<div id="red"></div>';
+        if($('#red') != null || $('#red') != undefined)
+            $('body').append(red);
+        $('#red').css('background-color', '#FF0000').css('position', 'absolute').css('top', '0px').css('left', '0px').css('width', '100px').css('height', '100px');
+        $('#red').css('top', finalDivTop).css('left', finalDivLeft).css('width', finalDivWidth).css('height', finalDivHeight);*/
+        //alert("initial : " + initialDivWidth + " " + initialDivHeight + " ; final : " + finalDivWidth + " " + finalDivHeight);
+        ////CAUTION////
+        
+        //On prézoom le div en le centrant sur le milieu du snapshot pointé.
+        $('#prezoomSnapshot-' + currentId).animate(
+        {
+            width: finalDivWidth + margin,
+            height: finalDivHeight - margin*2,
+            top: finalDivTop + margin,
+            left: finalDivLeft + margin
+        }, this.preZoomTime);
+        $('#prezoomContainer-' + currentId).animate(
+        {
+            width: finalDivWidth + margin*2,
+            height: finalDivHeight - margin,
+            top: finalDivTop + margin,
+            left: finalDivLeft
+        }, this.preZoomTime);
+    });
+    
+    //Si on clique sur le snapshot prézoomé, on enclenche un zoom total sur ce snapshot.
+    $('#prezoomContainer-' + currentId).click(function ()
+    {
+        if(this.previousZoomedSN != '')
+		{
+            mosaic.zoom();
+		}
+    });
+}
+
+/*
+ * Dézoome sur la position de l'image. Il est à noter que ce dézoome diffère du dézoom global dans la mesure où celui-ci ne concerne que l'image sur laquelle on a zoomé.
+ */
+mosaic.prototype.preUnzoom = function()
+{
+    //Si on n'a pas zoomé, on quitte la fonction.
+    if(!this.zoomed)
+	{
+        return;
+	}
+    
+    //On spécifie la marge afin de centrer le prédézoom.
+    var margin = this.marginWidth;
+    //ID du snapshot précédemment pointé.
+    var id = this.previousId;
+    //On ne zoom plus.
+    this.zoomed = false;
+    //On rétrécit le snapshot de prézoom, puis on le supprime en donnant l'illusion qu'il s'agissait du véritable snapshot, alors qu'en fait c'était un clone.
+    $('#prezoomSnapshot-' + id).animate(
+    {
+        width: this.snapshotWidth,
+        height: this.snapshotHeight,
+        top: this.previousZoomedSN.position().top,
+        left: this.previousZoomedSN.position().left
+    }, this.preUnzoomTime);
+    $('#prezoomContainer-' + id).animate(
+    {
+        width: this.snapshotWidth + margin,
+        height: this.snapshotHeight + margin,
+        top: this.previousZoomedSN.position().top,
+        left: this.previousZoomedSN.position().left
+    }, this.preUnzoomTime, function(){ $(this).remove(); this.zoomed = false; });
+}
+
+
+/*
+ * Zoom d'un snapshot en plein écran.
+ */
+mosaic.prototype.zoom = function()
+{
+    var mos = this;
+    
+    //Si la mosaïque est en pleine écran, pas la peine de zoomer.
+    if(this.fullscreen)
+	{
+        return;
+	}
+    
+    //On prend les attributs nécessaires au calculs.
+    var margin = this.marginWidth, len = this.length, imgs = this.imagesToShow;
+    var initMPWidth = this.previousZoomedSN.width() * len + margin*len, initMPHeight = this.previousZoomedSN.height() * (imgs / len) + margin*(imgs / len);
+    var newMPWidth = initMPWidth * len + this.zoomedMargin * (len), newMPHeight = initMPHeight * (imgs / len) + this.zoomedMargin * ((imgs / len));
+    var newPreMPWidth = initMPWidth * len * this.zoomPercentage + this.zoomedMargin * (len), newPreMPHeight = initMPHeight * (imgs / len) * this.zoomPercentage + this.zoomedMargin * ((imgs / len));
+    
+    //Dimensions et coordonnées initiales du div sur lequel on zoom.
+    var initialDivWidth = this.previousZoomedSN.width(), initialDivHeight = this.previousZoomedSN.height();
+    var initialDivTop = this.previousZoomedSN.position().top, initialDivLeft = this.previousZoomedSN.position().left;
+    //Dimensions et coordonnées finales du div.
+    var finalDivWidth = initialDivWidth * (this.zoomPercentage+1), finalDivHeight = initialDivHeight * (this.zoomPercentage+1);
+    var newZoomTop = -this.previousZoomedSN.position().top*(newPreMPHeight/initMPHeight) - this.zoomedMargin/2 + (initMPHeight - initMPHeight * this.zoomPercentage)/2, newZoomLeft = -this.previousZoomedSN.position().left*(newPreMPWidth/initMPWidth) - this.zoomedMargin/2 + (initMPWidth - initMPWidth * this.zoomPercentage)/2;
+    var newSnWidth = initMPWidth * this.zoomPercentage, newSnHeight = initMPHeight * this.zoomPercentage;
+    
+    this.preUnzoom(this);
+    /*SINGULARITE*/
+    this.fullscreen = true;
+    
+    //On passe l'image du snapshot pointé en HD.
+    var zoomedImg = $('img', this.previousZoomedSN);
+    var src = zoomedImg.attr('src');
+    zoomedImg.attr('src', src.replace('-little/', '/'));
+    
+    //On récupère son ID.
+    var tab, zoomedImgId;
+    tab = mos.previousId.split('-');
+    zoomedImgId = tab[1];
+
+    //Les snapshots baissent alors en opacité, donnant l'impression qu'ils sont grisés.
+    $('.snapshotDivs').animate(
+    {
+        width: newSnWidth,
+        height: newSnHeight,
+        margin: this.zoomedMargin/2 + 'px',
+        opacity: '0.4'
+    }, this.zoomTime);
+    //Le snapshot du milieu revient à une opacité optimale, ce qui attire l'attention de l'utilisateur.
+    $(this.previousZoomedSN).animate(
+    {
+        opacity: '1'
+    }, this.zoomTime);
+    //On zoome sur la mosaïque.
+    $('#mainPanel').animate(
+    {
+        width: newPreMPWidth,
+        height: newPreMPHeight,
+        top: newZoomTop,
+        left: newZoomLeft
+    }, this.zoomTime, function()
+    {
+        //On charge les interactions avec les voisins.
+        mos.centerId = zoomedImgId;
+        mos.listenToNeighbours();
+        mos.currentMode = 'VIDEO';
+		
+		console.log('h : ' + -newZoomLeft + " " + zoomedImg.position().left);
+		
+		mos.loadPlayer((zoomedImg.position().top + newZoomTop + mos.MPTop_margin), (zoomedImg.position().left + newZoomLeft), newSnWidth + 1, newSnHeight + 1);
+		
+        /*mos.unload();
+        mos.localMos.loadLocalMosaic(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, mos.imgs, tab[1]);*/
+    });
+}
+
+/*
+ * Chargement du player basé sur le metadataplayer.
+*/
+mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight)
+{
+	//On configure les options de lancement.
+	IriSP.libFiles.defaultDir = "../lib/";
+	IriSP.widgetsDir = "./player/metadataplayer/"
+	
+	var videoToPlay = this.videos[this.centerId];
+	var currentMetadata = this.urls[this.centerId];
+	console.log('VIDEO[' + this.centerId + '] : ' + videoToPlay);
+	console.log('MD[' + this.centerId + '] : ' + currentMetadata);
+	
+	console.log(newZoomTop + " " + newZoomLeft);
+	
+	var _metadata = {
+		url: currentMetadata,
+		format: 'ldt'
+	};
+	var _config = {
+		gui: {
+			width: newSnWidth,
+			height: newSnHeight,
+			container: 'LdtPlayer',
+			default_options: {
+				metadata: _metadata
+			},
+			css:'./player/metadataplayer/LdtPlayer-core.css',
+			widgets: [
+				{
+					type: "Timeline"
+				}
+			]
+		},
+		player:{
+			type: 'html5', // player type
+			video: videoToPlay,
+			live: true,
+			height: newSnHeight,
+			width: newSnWidth,
+			autostart: true
+		}
+	};
+	
+	//On positionne le player.
+	$('.LdtPlayer').css(
+	{
+		//display: 'none',
+		position: 'absolute',
+		'background-color': '#000000',
+		top: newZoomTop,
+		left: newZoomLeft
+	});
+	
+	//On démarre le player.
+	this.player = null;
+	this.player = new IriSP.Metadataplayer(_config, _metadata);
+}
+
+/*
+ * Retour à la taille normale de la mosaïque.
+ */
+mosaic.prototype.unzoom = function()
+{
+    //Si on n'est pas en plein écran, on quitte.
+    if(!this.fullscreen)
+	{
+        return;
+	}
+    
+    //On charge les attributs nécessaires aux calculs.
+    var sWidth = this.snapshotWidth, sHeight = this.snapshotHeight;
+    var mpWidth = this.width, mpHeight = this.height;
+    var mos = this;
+    
+    //On passe le snapshot sur lequel on a zoomé en SD.
+    var zoomedImg = $('img', this.previousZoomedSN);
+    var src = zoomedImg.attr('src');
+    zoomedImg.attr('src', src.replace('snapshots/', 'snapshots-little/'));
+	
+	$('div').remove('.LdtPlayer');
+	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
+    
+    //On rend leur opacité aux snapshots. Qui ne sont alors plus grisés.
+    $('.snapshotDivs').animate(
+    {
+        width: sWidth,
+        height: sHeight,
+        margin: this.marginWidth/2 + 'px',
+        opacity: '1'
+    }, this.unzoomTime);
+    //On dézoom sur la mosaïque.
+    $('#mainPanel').animate(
+    {
+        width: mpWidth,
+        height: mpHeight,
+        top: '0px',
+        left: '0px'
+    }, this.unzoomTime, function()
+    {
+        //On n'est plus en plein écran, et on ne peut plus se déplacer vers le prochain voisin.
+        mos.fullscreen = false;
+        mos.canMoveToNeighbour = false;
+        //On revient en mode MOSAIC.
+        mos.currentMode = 'MOSAIC';
+        //On ne permet plus le déplacement vers les voisins.
+        $('.snapshotDivs').unbind('mouseenter', mos.selectNeighbour);
+    });
+}
+
+/*
+ * Affecte les listeners mouseenter aux voisins lors d'une vue en plein écran.
+ */
+mosaic.prototype.listenToNeighbours = function()
+{
+    ////TEST
+    //$('.test').empty();
+    this.canMoveToNeighbour = false;
+    var currentLine = Math.floor(this.centerId / this.length), currentColumn = this.centerId % this.length;
+    var zoomedImg = $('img', this.previousZoomedSN);
+    var mos = this;
+    
+    //On cherche l'ID des voisins.
+    //Si le voisin de gauche est sur la même ligne, on n'est pas sur la bordure de gauche.
+    this.neighboursIds[0] = (currentColumn > 0) ? (this.centerId - 1) : -1;
+    //Si le voisin de droite est sur la même ligne, on n'est pas sur la bordure de droite.
+    this.neighboursIds[1] = (currentColumn < this.length) ? (+this.centerId + 1) : -1;
+    //Si le voisin du haut est sur la même colonne, on n'est pas sur la bordure du haut.
+    this.neighboursIds[2] = (currentLine > 0) ? (this.centerId - this.length) : -1;
+    //Si le voisin du bas est sur la même colonne, on n'est pas sur la bordure du bas.
+    this.neighboursIds[3] = (currentLine < (this.imagesToShow / this.length)) ? (+this.centerId + this.length) : -1;
+    
+	//ID du cadre voisin.
+	var preId;
+	
+    for(var i = 0 ; i < this.neighboursIds.length ; i++)
+    {
+        if(this.neighboursIds[i] != -1)
+        {
+			preId = '#neighbourFrameBorder-' + this.neighboursIds[i];
+            //On permet le déplacement vers les voisins.
+            // $('#snapshotDiv-' + this.neighboursIds[i] + ', ' + preId + '-left,' + preId + '-right,' + preId + '-up,' + preId + '-down').mouseenter(mos.selectNeighbour);
+            $('#snapshotDiv-' + this.neighboursIds[i]).mouseenter(mos.selectNeighbour);
+        }
+    }
+}
+
+/*
+ * Change la coloration d'une bordure où on se positionne lors d'une vue en plein écran.
+ */
+mosaic.prototype.selectNeighbour = function()
+{
+    ////TEST
+    //$('.test').append(mos.currentMode + " " + $(this).attr('id') + " " + 'snapshotDiv-' + mos.centerId + ',');
+    
+    //Si on est en mode VIDEO (plein écran) ET si le snapshot pointé est un voisin.
+    if((mos.currentMode == 'VIDEO') && ($(this).attr('id') != 'snapshotDiv-' + mos.centerId))
+    {
+        //On crée le cadre qui va être superposé au voisin.
+        //On le colle au voisin.
+		var tab = $(this).attr('id').split('-');
+		var snapshotId = tab[1];
+        var neighbourFrame = '';
+		var marginValue = parseFloat($(this).css('margin'));
+		
+		neighbourFrame += '<div class="neighbourFrame" id="neighbourFrame-' + snapshotId + '"><div class="neighbourImgBg" id="neighbourImgBg-' + snapshotId + '"><div class="neighbourImg" id="neighbourImg-' + snapshotId + '"></div></div></div>';
+		
+        $('#mainPanel').append(neighbourFrame);
+		
+		//On positionne le div de background juste au niveau du voisin.
+        $('#neighbourFrame-' + snapshotId).css(
+		{
+			'top': (+$(this).position().top + marginValue),
+			'left': (+$(this).position().left + marginValue),
+			'width': $(this).width(),
+			'height': $(this).height()
+		});
+		//On positionne le div de background noir juste au niveau de l'image du voisin.
+        $('#neighbourImgBg-' + snapshotId).css(
+		{
+			'top': marginValue,
+			'left': marginValue,
+			'width': $(this).width() - marginValue*2,
+			'height': $(this).height() - marginValue*2,
+		});
+		//On met par dessus le div de l'image clonée du voisin.
+		$('#neighbourImg-' + snapshotId).css(
+		{
+			'top': 0,
+			'left': 0,
+			'width': $(this).width() - marginValue*2,
+			'height': $(this).height() - marginValue*2,
+			'background-image': 'url("' + $('img', $(this)).attr('src') + '")',
+			'background-size': $(this).width() + 'px ' + $(this).height() + 'px',
+			'background-position': -marginValue + 'px ' + -marginValue + 'px',
+			'opacity': '0.4'
+		});
+		
+		var fId = '#neighbourFrame-' + snapshotId;
+		
+		$(fId).animate(
+        {
+            //On le fait apparaître.
+            opacity: '1'
+        }, timeNeighbourGlowing, function()
+        {
+            //On peut désormais se déplacer vers ce voisin.
+            mos.canMoveToNeighbour = true;
+        });
+		//Lorsqu'on quitte un des snapshots (bien entendu le voisin en question), on retire le cadre.
+		$(fId).mouseleave(mos.deselectNeighbour)
+		//Si on clique sur le voisin ou son cadre, on passe au voisin suivant.
+		$(fId).click(mos.moveToNeighbour);
+    }
+}
+
+/*
+ * Change la coloration d'une bordure quittée lors d'une vue en plein écran.
+ */
+mosaic.prototype.deselectNeighbour = function()
+{
+    ////TEST
+    //$('.test').append('un,');
+	
+    //On ne peut plus se déplacer vers les voisins.
+    mos.canMoveToNeighbour = false;
+    
+	//On récupère le voisin.
+	var neighbourFrame = $(this);
+	
+    //Si on est en mode VIDEO.
+    if(mos.currentMode == 'VIDEO')
+    {
+        //On le fait disparaître progressivement.
+        neighbourFrame.animate(
+        {
+            opacity: '0'
+        }, timeNeighbourUnglowing, function()
+        {
+            //Une fois invisible, on le supprime.
+            neighbourFrame.remove();
+        });
+    }
+}
+
+/*
+ * Lors d'une vue en plein écran, on se déplace vers le voisin dont l'id a été spécifié dans la fonction appelante.
+ */
+mosaic.prototype.moveToNeighbour = function()
+{
+    //Si on ne peut pas se déplacer vers les voisins, on quitte.
+    if(!mos.canMoveToNeighbour)
+	{
+        return;
+	}
+    
+    //On obtient l'ID de destination.
+    var tab = $(this).attr('id').split('-');
+    var destinationId = tab[1];
+    
+    //On charge les attributs nécessaires aux calculs.
+    var MPCurrentTop = $('#mainPanel').position().top, MPCurrentLeft = $('#mainPanel').position().left;
+    var divideCoeffTop = Math.floor(destinationId / mos.length) == 0 ? 1 : Math.floor(destinationId / mos.length);
+    var divideCoeffLeft = destinationId % mos.length == 0 ? 1 : destinationId % mos.length;
+    var neighbourFrameTop = $('#snapshotDiv-' + destinationId).position().top, neighbourFrameLeft = $('#snapshotDiv-' + destinationId).position().left;
+    
+    //On définit pour le déplacement vertical s'il est nécessaire de se déplacer en haut ou en bas.
+    if(mos.previousZoomedSN.position().top > neighbourFrameTop)
+        MPCurrentTop += Math.abs(neighbourFrameTop - mos.previousZoomedSN.position().top);
+    else if(mos.previousZoomedSN.position().top < neighbourFrameTop)
+        MPCurrentTop -= Math.abs(neighbourFrameTop - mos.previousZoomedSN.position().top);
+    //On définit pour le déplacement horizontal s'il est nécessaire de se déplacer à gauche ou à droite.
+    if(mos.previousZoomedSN.position().left > neighbourFrameLeft)
+        MPCurrentLeft += Math.abs(neighbourFrameLeft - mos.previousZoomedSN.position().left);
+    else if(mos.previousZoomedSN.position().left < neighbourFrameLeft)
+        MPCurrentLeft -= Math.abs(neighbourFrameLeft - mos.previousZoomedSN.position().left);
+    
+    //On passe le snapshot de destination en HD.
+    var destinationImg = $('#snapshot-' + destinationId);
+    var destinationImgSrc = destinationImg.attr('src');
+    destinationImg.attr('src', destinationImgSrc.replace('snapshots-little/', 'snapshots/'));
+    
+    //On passe l'ancien snapshot en SD.
+    var currentImgSrc = $('img', mos.previousZoomedSN).attr('src');
+    $('img', mos.previousZoomedSN).attr('src', currentImgSrc.replace('snapshots/', 'snapshots-little/'));
+    
+    //On obtient l'ID du div de coloration du snapshot vers lequel on se déplace afin de le supprimer.
+    var neighbourFrame = $(this);
+    var tab = neighbourFrame.attr('id').split('-');
+    mos.centerId = tab[1];
+    $(this).css('opacity', '0');
+    neighbourFrame.remove();
+    
+	$('div').remove('.LdtPlayer');
+	$('body').append('<div class="LdtPlayer" id="LdtPlayer"></div>');
+	
+    //On grise le snapshot qu'on vient de quitter.
+    mos.previousZoomedSN.animate(
+    {
+        opacity: '0.4'
+    });
+    
+    //On se déplace.
+    $('#mainPanel').animate(
+    {
+        top: MPCurrentTop,
+        left: MPCurrentLeft
+    }, timeMovingToNeighbour, function()
+    {
+        //On fait apparaître le snapshot vers lequel on s'est déplacé.
+        $('#snapshotDiv-' + destinationId).animate(
+        {
+            opacity: '1'
+        }, mos.zoomTime, function()
+        {
+            //On recharge les voisins.
+            $('.snapshotDivs').unbind('mouseenter', mos.selectNeighbour);
+            mos.previousZoomedSN = $('#snapshotDiv-' + mos.centerId);
+            mos.listenToNeighbours();
+			
+			mos.loadPlayer((destinationImg.position().top + MPCurrentTop + mos.MPTop_margin), (destinationImg.position().left + MPCurrentLeft), destinationImg.width(), destinationImg.height());
+        });
+    });
+}
+
+/*
+ * Déchargement du contenu de la mosaïque pour le chargement de la mosaïque locale.
+ */
+mosaic.prototype.unload = function()
+{
+    //On supprime les event listeners des objets de la mosaïque.
+    $('.snapshotDivs').unbind();
+    $('.snapshots').unbind();
+    $('.prezoomContainers').unbind();
+    //On supprime physiquement les objets.
+    $('#mainPanel').empty();
+}
+
+/*
+ * Centre verticalement un snapshot.
+ */
+/*function verticalCenterImg(mosaic, img)
+{
+    //On récupère sa hauteur.
+    var image_height = img.height();
+    //Calcule la marge du haut de chaque div pour le centrage.
+    if(mosaic.top_margin == undefined)
+        mosaic.top_margin = (mosaic.snapshotHeight > image_height) ? (mosaic.snapshotHeight - image_height)/2 : (image_height - mosaic.snapshotHeight)/2;
+    //On centre le snapshot.
+    img.css('margin-top', mosaic.top_margin).css('margin-bottom', mosaic.top_margin);
+}*/
+
+/*
+ * Permet de tester l'égalité des éléments de deux objets.
+ * Pour ce faire on compare les éléments définissant ces objets.
+ */
+$.fn.equals = function(compareTo)
+{
+    if (!compareTo || !compareTo.length || this.length!=compareTo.length)
+    {
+        return false;
+    }
+    for (var i=0; i<this .length; i++)
+    {
+        if (this[i]!==compareTo[i])
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+/*
+ * Charge les vidéos, les snapshots et les annotations depuis un fichier json.
+*/
+mosaic.prototype.loadFromJson = function(path)
+{
+	var _this = this;
+
+	$.getJSON(path, function(data)
+	{
+		$.each(data, function(key, val)
+		{
+			// console.log(val);
+			$.each(val, function(key_video, val_video)
+			{
+				$.getJSON(val_video.metadata, function(meta)
+				{
+					_this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/'));
+					//console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/'));
+				});
+				
+				_this.imgs.push(val_video.snapshot);
+				_this.urls.push(val_video.metadata);
+			});
+		});
+		console.log('rdy');
+		_this.loadMosaic();
+	});
+}
+
+/*
+ * Affecte une vidéo au tableau des vidéos selon son id
+*/
+mosaic.prototype.affectVideoById = function(metadata_id, video)
+{
+	for (i = 0 ; i < this.urls.length ; i++)
+	{
+		if(this.urls[i] == metadata_id)
+		{
+			this.videos[i] = video;
+			break;
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/player/index.html	Mon May 14 17:20:35 2012 +0200
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html dir="ltr" xml:lang="fr" xmlns="http://www.w3.org/1999/xhtml" lang="fr">
+
+<head>
+	<title>Metadataplayer - Polemic tweet integration test</title>
+	<meta http-equiv='cache-control' content='no-cache'>
+	<meta http-equiv='expires' content='0'>
+	<meta http-equiv='pragma' content='no-cache'>
+	<!--<script type="text/javascript" src="libs/jquery-1.7.2.min.js" type="text/javascript"></script>   -->
+</head>
+
+<body bgcolor="#FFFFFF">
+
+  <!--<div style="width:650px;font-family: 'Trebuchet MS', 'Helvetica', 'Arial',  'Verdana', 'sans-serif';">
+  <h1>MetaDataPlayer</h1>
+  Polemic tweet integration test - using Popcorn, jwplayer and the <a href="http://polemictweet.com">PolemicTweet</a> widget.<br>
+  </div>-->
+  
+  
+ <!-- START Integration  ###################################### -->
+ <!-- SIMPLE PLAYER EXPERIMENTATION -->
+  <script type="text/javascript" src="metadataplayer/LdtPlayer-core.js" type="text/javascript"></script>   
+  
+  <div id="video"></div>
+  <div id="LdtPlayer"></div>
+  
+  <script  type="text/javascript">
+  IriSP.libFiles.defaultDir = "../../lib/";
+  IriSP.widgetsDir = "metadataplayer/"
+  //IriSP.jwplayer_swf_path = "libs/player.swf";
+    var _metadata = {
+        //url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/13b0aa52-336b-11e0-b233-00145ea49a02?callback=?',
+        //url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/f1a17368-2bc8-11e1-b21a-00145ea49a02?callback=?', enmi
+        //url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/d726e86a-684f-11e1-a087-00145ea4a2be?callback=?', //webze
+        //url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/a972dbcc-26ff-11e1-8869-00145ea49a02?callback=?',
+        //url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/3f1f08e6-66b9-11e1-80f6-00145ea4a2be?callback=?', //stronger
+        url: 'http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/cljson/id/7c912bce-66b8-11e1-80f6-00145ea4a2be?callback=?', //stronger
+        format: 'ldt'
+    };
+    var _config = {            
+        gui: {
+            width:620,
+            //height:800,
+			//timelineBorderLength: 10,
+            container:'LdtPlayer',
+			default_options: {
+				metadata: _metadata
+			},
+            css:'metadataplayer/LdtPlayer-core.css',
+            widgets: [
+				{
+					type: "Timeline"
+				}
+            ]
+        },
+        player:{
+            type:'html5', // player type
+			video:'http://media.iri.centrepompidou.fr/video/ldtplatform/body_trail_cctv.mp4',
+            live: true, 
+			height: 350, 
+            width: 620, 
+			autostart: true
+            //provider: "rtmp" 
+        }
+    };
+	
+    var _myPlayer = new IriSP.Metadataplayer(_config, _metadata);
+	
+	//var playerTop = $('#LdtPlayer').position().top, playerLeft = $('#LdtPlayer').position().left;
+  </script>
+  
+  
+ </body>
+ <div id="AnnotationsListContainer" style="position: absolute; width: 400px; left: 660px; top: 105px;"></div>
+ </html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/player/json/videos.json	Mon May 14 17:20:35 2012 +0200
@@ -0,0 +1,560 @@
+{
+	"videos" : [
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/23256da6-66b9-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "mue.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/076230fe-66b9-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "deep end dance.png",
+			"gestures": [
+				{
+					"gesture_name": "circle",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "jump",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "contact",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "updown",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "wave",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/b411a6dc-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "-s-pression.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/98517ca6-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "i am my mother.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/9e92ebdc-66b7-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "hannah.png",
+			"gestures": [
+				{
+					"gesture_name": "wave",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "run",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/82cd7e30-66b7-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "vrtti.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/0d8f65f6-66b8-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "palms.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/f1cee904-66b7-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "fenella.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/2f8b92b6-66b7-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "patria.png",
+			"gestures": [
+				{
+					"gesture_name": "circle",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "updown",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "slow",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/3f1f08e6-66b9-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "stronger.png",
+			"gestures": [
+				{
+					"gesture_name": "jump",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "circle",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "contact",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "beat",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/ba4d888c-66b7-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "50 shots.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/7c912bce-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "body trail cctv.png",
+			"gestures": [
+				{
+					"gesture_name": "screw",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "contact",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/f80bd9fe-66b6-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "encontro cotidianos.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/d610e47e-66b7-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "instrument.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/dc8c4d62-66b6-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "jeu de societe.png",
+			"gestures": [
+				{
+					"gesture_name": "wave",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "run",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/e2b5b9e8-562c-11e1-b3c3-00145ea49a02?callback=?",
+			"snapshot": "joudance 2 in asakusa_stage1.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/cfd63004-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "nid de lune.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/4b4aa85c-66b7-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "molecule no.1.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/eba1967a-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "mine.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/60d03074-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "you are you.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/c66bfa64-66b6-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "new under the sun.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/294f727c-66b8-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "sliced.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/670c5054-66b7-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "field n.8.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/23256da6-66b9-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "mue.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/076230fe-66b9-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "deep end dance.png",
+			"gestures": [
+				{
+					"gesture_name": "circle",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "jump",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "contact",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "updown",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "wave",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/b411a6dc-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "-s-pression.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/98517ca6-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "i am my mother.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/9e92ebdc-66b7-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "hannah.png",
+			"gestures": [
+				{
+					"gesture_name": "wave",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "run",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/82cd7e30-66b7-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "vrtti.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/0d8f65f6-66b8-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "palms.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/f1cee904-66b7-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "fenella.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/2f8b92b6-66b7-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "patria.png",
+			"gestures": [
+				{
+					"gesture_name": "circle",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "updown",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "slow",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/3f1f08e6-66b9-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "stronger.png",
+			"gestures": [
+				{
+					"gesture_name": "jump",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "circle",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "contact",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "beat",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/ba4d888c-66b7-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "50 shots.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/7c912bce-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "body trail cctv.png",
+			"gestures": [
+				{
+					"gesture_name": "screw",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "contact",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/f80bd9fe-66b6-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "encontro cotidianos.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/d610e47e-66b7-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "instrument.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/dc8c4d62-66b6-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "jeu de societe.png",
+			"gestures": [
+				{
+					"gesture_name": "wave",
+					"snapshot": ""
+				},
+				{
+					"gesture_name": "run",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/e2b5b9e8-562c-11e1-b3c3-00145ea49a02?callback=?",
+			"snapshot": "joudance 2 in asakusa_stage1.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/cfd63004-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "nid de lune.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/4b4aa85c-66b7-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "molecule no.1.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/eba1967a-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "mine.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/60d03074-66b8-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "you are you.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/c66bfa64-66b6-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "new under the sun.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/294f727c-66b8-11e1-91ba-00145ea4a2be?callback=?",
+			"snapshot": "sliced.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		},
+		{
+			"metadata": "http://ldt.iri.centrepompidou.fr//ldtplatform/ldt/cljson/id/670c5054-66b7-11e1-80f6-00145ea4a2be?callback=?",
+			"snapshot": "field n.8.png",
+			"gestures": [
+				{
+					"gesture_name": "",
+					"snapshot": ""
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
--- a/front_idill/src/player/metadataplayer/Timeline.js	Fri May 11 11:04:06 2012 +0200
+++ b/front_idill/src/player/metadataplayer/Timeline.js	Mon May 14 17:20:35 2012 +0200
@@ -20,10 +20,45 @@
 	this.top_epsilon = 0;
 	this.imgDir = "player/img/";
 	this.markersDir = "player/markers/";
+	
+	this.gestures = ["swipe-down", "jump", "circle", "screw", "bend", "join-hands", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "beat", "cross", "wheel", "contact", "run"];
+	
+	this.annotations = this.annotationsFilter(this.source.getAnnotations(), this.gestures, this.isGesture);
+	
+	// for(var a = 0 ; a < this.annotations.length ; a++)
+		// console.log("A : " + this.annotations[a].annotationType.contents.title);
 };
 
 IriSP.Widgets.Timeline.prototype = new IriSP.Widgets.Widget();
 
+IriSP.Widgets.Timeline.prototype.isGesture = function(element, index, array)
+{
+	return ($.inArray(element.annotationType.contents.title, array) > -1);
+}
+
+//Fonction de filtrage de tableaux
+IriSP.Widgets.Timeline.prototype.annotationsFilter = function(annotations, gestures, fun /*, thisp*/)
+{
+	var len = annotations.length;
+	if (typeof fun != "function")
+		throw new TypeError();
+
+	var res = new Array();
+	var thisp = arguments[1];
+	for (var i = 0; i < len; i++)
+	{
+		if (i in annotations)
+		{
+			var val = annotations[i]; // in case fun mutates this
+			if (fun.call(thisp, val, i, gestures))
+			{
+				res.push(val);
+			}
+		}
+	}
+	return res;
+};
+
 IriSP.Widgets.Timeline.prototype.defaults = {
     minimized_height : 44,
     maximized_height : 44,
@@ -133,13 +168,12 @@
 */
 IriSP.Widgets.Timeline.prototype.processMarkers = function() {
 	var _this = this;
-	var annotations = this.source.getAnnotations();
 	var markers = "";
 	var timelineMiddleTop = this.$timelineMiddle.position().top;
 	
-	for(var i = 0 ; i < annotations.length ; i++)
+	for(var i = 0 ; i < this.annotations.length ; i++)
 	{
-		markers += "<div class='Ldt-Marker' id='" + annotations[i].id.replace(":", "_") + "'></div>";
+		markers += "<div class='Ldt-Marker' id='" + this.annotations[i].id.replace(":", "_") + "'></div>";
 		// console.log(annotations[i].begin.milliseconds);
 	}
 	
@@ -147,12 +181,12 @@
 	var markerHeight = IriSP.jQuery(".Ldt-Marker").height();
 	IriSP.jQuery(".Ldt-Marker").css("z-align", "150");
 	
-	for(var i = 0 ; i < annotations.length ; i++)
+	for(var i = 0 ; i < this.annotations.length ; i++)
 	{
-		IriSP.jQuery("#" + annotations[i].id.replace(":", "_")).css(
+		IriSP.jQuery("#" + this.annotations[i].id.replace(":", "_")).css(
 		{
 			top: timelineMiddleTop + "px",
-			left: Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), annotations[i].begin/1000) + this.$timeline.position().left) + "px",
+			left: Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), this.annotations[i].begin/1000) + this.$timeline.position().left) + "px",
 			"margin-top": (-_this.$timeline.height()/2 - markerHeight/2) - this.top_epsilon + "px"
 		});
 	}
@@ -174,9 +208,8 @@
 		//On supprime le marqueur précédemment affiché si c'est le cas.
 		if(this.previousMarkerIdx > -1)
 		{
-			var annotations = this.source.getAnnotations();
 			// console.log("EXT hide idx " + this.previousMarkerIdx);
-			var previousMarker = IriSP.jQuery("#" + annotations[this.previousMarkerIdx].id.replace(":", "_"));
+			var previousMarker = IriSP.jQuery("#" + this.annotations[this.previousMarkerIdx].id.replace(":", "_"));
 			this.hideMarkerBig(previousMarker);
 			// console.log("EXT hide " + this.previousMarkerIdx);
 		}
@@ -382,7 +415,6 @@
 IriSP.Widgets.Timeline.prototype.onTimeupdate = function() {
     var _time = this.player.popcorn.currentTime();
 	var arrowLeft = Math.floor(+this.scaleIntervals(0, this.source.getDuration().getSeconds(), 0, this.$timeline.width(), _time) + this.$timeline.position().left) - IriSP.jQuery("#TL_ArrowUp").width()/2 + "px";
-	var annotations = this.source.getAnnotations();
 	
     this.$timeline.slider("value",_time*1000);
 	IriSP.jQuery(".TL_Arrows").css("display", "block");
@@ -391,19 +423,19 @@
 	// this.player.popcorn.trigger("IriSP.Arrow.updatePosition",{widget: this.type, time: 1000 * _time});
 	//Si on a une distance de 500 ms à un marqueur, on l'affiche.
 	var nearestMarkerIdx = 0;
-	for(var i = 0 ; i < annotations.length ; i++)
+	for(var i = 0 ; i < this.annotations.length ; i++)
 	{
 		//S'il existe des marqueurs dans l'intervalle de temps actuel (ici 500ms).
-		if(Math.abs(_time*1000 - annotations[i].begin.milliseconds) <= 250)
+		if(Math.abs(_time*1000 - this.annotations[i].begin.milliseconds) <= 250)
 		{
 			// console.log("1) i = " + i + " " + Math.abs(_time*1000 - annotations[i].begin.milliseconds));
 			
 			//On sélectionne le plus proche marqueur (dans les cas où il en existe plusieurs dans l'intervalle des 1s) ou bien le premier marqueur.
-			if(Math.abs(_time*1000 - annotations[i].begin.milliseconds) < Math.abs(_time*1000 - annotations[nearestMarkerIdx].begin.milliseconds) || i == nearestMarkerIdx)
+			if(Math.abs(_time*1000 - this.annotations[i].begin.milliseconds) < Math.abs(_time*1000 - this.annotations[nearestMarkerIdx].begin.milliseconds) || i == nearestMarkerIdx)
 			{
 				// console.log("2) " + Math.abs(_time*1000 - annotations[i].begin.milliseconds) + " < " + Math.abs(_time*1000 - annotations[nearestMarkerIdx].begin.milliseconds));
 				//Si le prochain marqueur se situe après le curseur de lecture, on passe donc au marqueur le plus proche.
-				if(_time*1000 < annotations[i].begin.milliseconds)
+				if(_time*1000 < this.annotations[i].begin.milliseconds)
 				{
 					// console.log("3) " + _time*1000 + " < " + annotations[i].begin.milliseconds);
 					// console.log("4) " + "nearest = " + i);
@@ -412,18 +444,18 @@
 					//S'il y a un changement de marqueur (marqueur actuel différent du précédent).
 					if(nearestMarkerIdx != this.previousMarkerIdx)
 					{
-						var currentMarker = IriSP.jQuery("#" + annotations[nearestMarkerIdx].id.replace(":", "_"));
+						var currentMarker = IriSP.jQuery("#" + this.annotations[nearestMarkerIdx].id.replace(":", "_"));
 						//S'il existe un marqueur précédent, on le cache.
 						if(this.previousMarkerIdx > -1)
 						{
 							// console.log("hide idx " + this.previousMarkerIdx);
-							var previousMarker = IriSP.jQuery("#" + annotations[this.previousMarkerIdx].id.replace(":", "_"));
+							var previousMarker = IriSP.jQuery("#" + this.annotations[this.previousMarkerIdx].id.replace(":", "_"));
 							this.hideMarkerBig(previousMarker);
 							// console.log("5a) hide " + this.previousMarkerIdx);
 						}
 						
 						// console.log("5b) show " + nearestMarkerIdx);
-						this.showMarkerBig(currentMarker, annotations[nearestMarkerIdx].annotationType.contents.title);
+						this.showMarkerBig(currentMarker, this.annotations[nearestMarkerIdx].annotationType.contents.title);
 						//Mise à jour du marqueur précédent s'il y a un changement.
 						this.previousMarkerIdx = nearestMarkerIdx;
 						// console.log("MAJ : " + this.previousMarkerIdx);
@@ -540,7 +572,20 @@
 	
 	var _this = this;
 	
-	var markerTop = marker.position().top, markerLeft = marker.position().left, markerWidth = marker.width(), markerHeight = marker.height();
+	var markerTop, markerLeft;
+	
+	if(marker.position() == null)
+	{
+		markerTop = 0;
+		markerLeft = 0;
+	}
+	else
+	{
+		markerTop = marker.position().top;
+		markerLeft = marker.position().left;
+	}
+	
+	var markerWidth = marker.width(), markerHeight = marker.height();
 	
 	this.markerBigShown = true;
 	var markerBig = "<div class='TL_MarkersBig' id='MB_Text'>" + type + "<div class='TL_MarkersBig' id='MB_Spike'></div></div><div class='TL_MarkersBig' id='MB_Pic'></div>";
@@ -611,16 +656,15 @@
 	var _this = this;
 	
 	//On récupère les annotations.
-	var annotations = this.source.getAnnotations();
 	var markersSearch = "", markersPicSearch = "";
 	//Pour chaque annotation, on ajoute un double.
-	for(var i = 0 ; i < annotations.length ; i++)
+	for(var i = 0 ; i < this.annotations.length ; i++)
 	{
 		//Si elle correspond à la recherche.
-		if(annotations[i].annotationType.contents.title == type)
+		if(this.annotations[i].annotationType.contents.title == type)
 		{
 			//On récupère le marqueur associé à l'annotation.
-			var markerId = annotations[i].id.replace(":", "_");
+			var markerId = this.annotations[i].id.replace(":", "_");
 			
 			markersSearch += "<div class='search_Marker' id='search_Marker_" + markerId + "'></div>";
 			markersPicSearch += "<div class='search_MBPic' id='search_Pic_" + markerId + "'></div>";
@@ -630,12 +674,12 @@
 	this.$.append(markersSearch + markersPicSearch);
 	
 	//On place chaque double.
-	for(var i = 0 ; i < annotations.length ; i++)
+	for(var i = 0 ; i < this.annotations.length ; i++)
 	{
 		//Si elle correspond à la recherche.
-		if(annotations[i].annotationType.contents.title == type)
+		if(this.annotations[i].annotationType.contents.title == type)
 		{
-			var markerId = annotations[i].id.replace(":", "_"), marker = IriSP.jQuery("#" + markerId);
+			var markerId = this.annotations[i].id.replace(":", "_"), marker = IriSP.jQuery("#" + markerId);
 			var markerTop = marker.position().top, markerLeft = marker.position().left, markerWidth = marker.width(), markerHeight = marker.height();
 			var markerBigPicWidth = parseFloat(IriSP.jQuery(".search_MBPic").css("width")), markerBigPicHeight = parseFloat(IriSP.jQuery(".search_MBPic").css("height")), markerBigPicTop = +parseFloat(marker.css("margin-top")) + markerHeight, markerBigPicLeft = (markerLeft - markerBigPicWidth/2 + markerWidth/2);