diff -r 03ea3d7ddbe1 -r 277c94533395 front_idill/src/mosaic/js/mosaic.js --- a/front_idill/src/mosaic/js/mosaic.js Mon Jul 23 10:52:41 2012 +0200 +++ b/front_idill/src/mosaic/js/mosaic.js Mon Jul 23 16:59:35 2012 +0200 @@ -21,291 +21,584 @@ * 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. + * Est appelé dans : + * la page d'index, afin de créer la mosaique. */ -function mosaic(config, default_conf) +function Mosaic(config, default_conf) { - //Interactions souris/kinect. - this.mouseInteractions = true; - //Interactions avec/sans préphase. - this.prephaseEnabled = true; - - this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run", "up-down", "grand-jete"]; + this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run", "up-down", "grand-jete"]; - //Chemin du fichier de configuration. - this.config_path = config; - //Configuration par défaut en cas de valeur erronnée. - this.default_config = default_conf; - this.config = new Object(); - //Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque. - this.videos = []; - this.urls = []; - this.sources = []; - this.imgs = []; - this.opacities = []; - this.timeToGoAt = []; - this.ids = []; - this.fillingIds = []; - this.currentRandomVideoIdx = 0; - - //Dictionnaire pour les courbes de recherche. - this.dictionary = []; - - //Dernières positions des pointeurs. - this.mainPointerLastX; - this.mainPointerLastY; - this.secondPointerLastX; - this.secondPointerLastY; - //Dernières positions avant le lancement de la fonction d'idle. - this.mainPointerIdleStartX; - this.mainPointerIdleStartY; - this.secondPointerIdleStartX; - this.secondPointerIdleStartY; - - //Coordonnées de la souris dans le mode d'interaction souris. - this.mousePosX; - this.mousePosY; - //Coordonnées précédentes de la souris dans le mode d'interaction souris. - this.mousePosLastX; - this.mousePosLastY; - //Valeur du déplacement entre un mouse up et un mouse down. - this.mouseUpDownDelta = 0; - - //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; - - //Booléens permettant ou non certaines intéractions selon le contexte. - this.zoomed = false; - this.fullscreen = false; - this.canMoveToNeighbour = false; - this.mainPointerExitBorder = false; - this.secondPointerExitBorder = false; - this.isMainPointerDisplayed = false; - this.isSecondPointerDisplayed = false; - this.helpDisplayed = false; - //Indique si l'utilisateur a manuellement pausé la vidéo. - this.userPaused = false; - //Indique si on est en train de se déplacer vers un voisin. - this.currentlyMoving = false; - //Indique si on est en train de dézoomer vers la mosaïque. - this.currentlyUnzooming = false; - //Indique si on peut s'approcher de kinect. - this.canStart = false; - //Indique si on est actuellement sur un snapshot. - this.isOnASnapshot = false; - //Indique si l'idle des pointeurs est disponible (deux mains détectées). - this.pointersIdleAvailable = false; - //Indique si le timeout pour l'idle des pointeurs à besoin d'être lancé. - this.pointersIdleNeedLaunch = false; - //Indique si les deux mains sont là. - this.areBothPointersHere = false; - //Indique si le timeout pour la détection de deux pointeurs a été lancé. - this.areBothPointersTimeoutLaunched = false; - //Indique si la mosaïque a été filtrée. - this.isMosaicFiltered = false; - //Indique si on est actuellement dans une recherche par gesture. - this.isCurrentlyInASearchByGesture = false; - //Indique si un pointeur est déjà sur une notification de recherche par gesture. - this.alreadyOnNotification = false; - //Si on a fait un swipe. - this.isSwipe = false; - //On peut swiper. - this.canSwipe = false; - //On passe vers une autre video automatiquement à la fin d'une lecture. - this.autoMove = false; - //Si l'utilisateur a demandé à sélectionner la TL. - this.isTLRequested = false; - //Le pointeur gauche a sélectionné la TL. - this.isTLSelectedBySecondPointer = false; - //Le pointeur droit a sélectionné la TL. - this.isTLSelectedByMainPointer = false; - //On peut afficher l'aide. - this.canNotifyHelp = false; - //Indique si la mosaique est en train d'être filtrée. - this.isMosaicFiltering = false; - this.arrowLeftLoading = false; - this.arrowRightLoading = false; - this.arrowUpLoading = false; - this.arrowDownLoading = false; - //On est dans une recherche par courbes. - this.isSearchByCurvesOn = false; - this.canDrawNextCurve = false; - //Dans le mode d'interaction souris, indique si on se situe actuellement sur un snapshot entièrement prézoomé. - this.isOnAPrezoomSN = false; - //Indique si une courbe de recherche donne au moins un résultat. - this.curvesGesturesFound = false; - //Indique si on souhaite supprimer la recherche en cours. - this.gestureDelRequested = false; - //Code de gesture actuellement calculé par les détecteurs de courbes. - this.actualCode = ''; - //Indique si l'utilisateur est entré dans la zone de recherche. - this.isUserInSearchZone = false; - - //Timeout (attente) pour le zoom après un préZoom. - this.zoomTimeout = null; - //Timeout (attente) pour le passage vers un voisin. - this.moveToNeighbourTimeout = null; - this.mainPointerExitBorderTimeout = null; - this.secondPointerExitBorderTimeout = null; - //Idle time pour les pointeurs afin d'informer le front qu'on souhaite faire une recherche. - this.pointersSearchIdleTimeout = null; - //Vérifie toutes les N ms que les deux pointeurs sont détectés. - this.areBothPointersHereTimeout = null; - //Délai de suppression d'une notification de recherche par gesture. - this.removeNotificationByGestureTimeout = null; - //Délai de suppression d'une notification de recherche par gesture infructueuse. - this.removeFailedNotificationByGestureTimeout = null; - //Délai avant la suppression de notification swipe. - this.notifySwipeTimeout = null; - //Délai pour la sélection de la TL. - this.selectTLTimeout = null; - //Délai pour slider sur la TL. - this.canSlideInTLTimeout = null; - //Délai pour afficher l'aide. - this.canNotifyHelpTimeout = null; - this.arrowLeftTimeout = null; - this.arrowRightTimeout = null; - this.arrowUpTimeout = null; - this.arrowDownTimeout = null; - - this.arrowSpinnerTimeout = null; - this.nouserTimeout = null; - this.nextDrawCurveTimeout = null; - - //Dernier message INCOMING (pour éviter d'effectuer n fois la même action. - this.lastIncomingMessage = ''; - - //Type de marqueur recherché dans la mosaïque (en mode filter). - this.filterSearchedType = ""; - - //Mode actuel. - this.currentMode = "NO-USER"; - //Snapshot sur lequel on a zoomé. - this.previousZoomedSN = null; - //Snapshot sur lequel on a prezoomé. - this.previousPrezoomDiv = null; - //Son ID. - this.previousId = null; - //Dernier snapshot prézoomé non null. - this.lastNonNullSN = null; - //Largeur de la marge pour le centrage vertical de la mosaïque. - this.MPTop_margin; - this.top_margin; - - //Gestures actuellement cherchées dans les vidéos. - this.currentSearchGesture = []; - - //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; - - //Voisins sélectionnés par les pointeurs. - this.mainPointerNeighbourSelectedId = null; - this.secondPointerNeighbourSelectedId = null; - - //Snapshots a afficher. - this.snapshotsToShow = 1; - - //Lecteur. - this.player = null; - //Si le lecteur est prêt. - this.playerIsReady = false; - - //Annotations (pour les marqueurs los d'un filtrage). - this.annotations = []; - - //Client websocket pour recevoir les notifications du Middleware. - this.client; - - //Coordonnées et dimensions d'un snapshot zoomé. - this.snTop = 0; - this.snLeft = 0; - this.snWidth = 0; - this.snHeight = 0; - - this.searchCanvas; - //Position actuelle de la vidéo zoomée. - this.notifyTopVideo; - this.notifyLeftVideo; - this.loadParameters(this.config_path); + //Chemin du fichier de configuration. + this.config_path = config; + //Configuration par défaut en cas de valeur erronnée. + this.default_config = default_conf; + this.config = new Object(); + //Tableaux des urls des vidéos, des snapshots et de leur position dans la mosaïque. + this.videos = []; + this.urls = []; + this.sources = []; + this.imgs = []; + this.opacities = []; + this.timeToGoAt = []; + this.ids = []; + this.fillingIds = []; + this.currentRandomVideoIdx = 0; + + //Dictionnaire pour les courbes de recherche. + this.dictionary = []; + + //Dernières positions des pointeurs. + this.mainPointerLastX = null; + this.mainPointerLastY = null; + this.secondPointerLastX = null; + this.secondPointerLastY = null; + //Dernières positions avant le lancement de la fonction d'idle. + this.mainPointerIdleStartX = null; + this.mainPointerIdleStartY = null; + this.secondPointerIdleStartX = null; + this.secondPointerIdleStartY = null; + + //Coordonnées de la souris dans le mode d'interaction souris. + this.mousePosX = null; + this.mousePosY = null; + //Coordonnées précédentes de la souris dans le mode d'interaction souris. + this.mousePosLastX = null; + this.mousePosLastY = null; + //Valeur du déplacement entre un mouse up et un mouse down. + this.mouseUpDownDelta = 0; + //Coordonnées de la souris au dernier mouse down. + this.mouseDownPosX = null; + this.mouseDownPosY = null; + + //Dimensions de la mosaïque en pixels. + this.width = null; + this.height = null; + //Dimensions d'un snapshot en pixels. + this.snapshotWidth = null; + this.snapshotHeight = null; + //Espacement entre les snapshots en pixels. + this.marginWidth = null; + + //Booléens permettant ou non certaines intéractions selon le contexte. + this.zoomed = false; + this.fullscreen = false; + this.canMoveToNeighbour = false; + this.mainPointerExitBorder = false; + this.secondPointerExitBorder = false; + this.isMainPointerDisplayed = false; + this.isSecondPointerDisplayed = false; + this.helpDisplayed = false; + //Indique si l'utilisateur a manuellement pausé la vidéo. + this.userPaused = false; + //Indique si on est en train de se déplacer vers un voisin. + this.currentlyMoving = false; + //Indique si on est en train de dézoomer vers la mosaïque. + this.currentlyUnzooming = false; + //Indique si on peut s'approcher de kinect. + this.canStart = false; + //Indique si on est actuellement sur un snapshot. + this.isOnASnapshot = false; + //Indique si l'idle des pointeurs est disponible (deux mains détectées). + this.pointersIdleAvailable = false; + //Indique si le timeout pour l'idle des pointeurs à besoin d'être lancé. + this.pointersIdleNeedLaunch = false; + //Indique si les deux mains sont là. + this.areBothPointersHere = false; + //Indique si le timeout pour la détection de deux pointeurs a été lancé. + this.areBothPointersTimeoutLaunched = false; + //Indique si la mosaïque a été filtrée. + this.isMosaicFiltered = false; + //Indique si on est actuellement dans une recherche par gesture. + this.isCurrentlyInASearchByGesture = false; + //Indique si un pointeur est déjà sur une notification de recherche par gesture. + this.alreadyOnNotification = false; + //Si on a fait un swipe. + this.isSwipe = false; + //On peut swiper. + this.canSwipe = false; + //On passe vers une autre video automatiquement à la fin d'une lecture. + this.autoMove = false; + //Si l'utilisateur a demandé à sélectionner la TL. + this.isTLRequested = false; + //Le pointeur gauche a sélectionné la TL. + this.isTLSelectedBySecondPointer = false; + //Le pointeur droit a sélectionné la TL. + this.isTLSelectedByMainPointer = false; + //On peut afficher l'aide. + this.canNotifyHelp = false; + //Indique si la mosaique est en train d'être filtrée. + this.isMosaicFiltering = false; + this.arrowLeftLoading = false; + this.arrowRightLoading = false; + this.arrowUpLoading = false; + this.arrowDownLoading = false; + //On est dans une recherche par courbes. + this.isSearchByCurvesOn = false; + this.canDrawNextCurve = false; + //Dans le mode d'interaction souris, indique si on se situe actuellement sur un snapshot entièrement prézoomé. + this.isOnAPrezoomSN = false; + //Indique si une courbe de recherche donne au moins un résultat. + this.curvesGesturesFound = false; + //Indique si on souhaite supprimer la recherche en cours. + this.gestureDelRequested = false; + //Code de gesture actuellement calculé par les détecteurs de courbes. + this.actualCode = ''; + //Indique si l'utilisateur est entré dans la zone de recherche. + this.isUserInSearchZone = false; + this.isMouseDown = false; + //Indique si on est en train de prézoomer. + this.isPrezooming = false; + + //Timeout (attente) pour le zoom après un préZoom. + this.zoomTimeout = null; + //Timeout (attente) pour le passage vers un voisin. + this.moveToNeighbourTimeout = null; + this.mainPointerExitBorderTimeout = null; + this.secondPointerExitBorderTimeout = null; + //Idle time pour les pointeurs afin d'informer le front qu'on souhaite faire une recherche. + this.pointersSearchIdleTimeout = null; + //Vérifie toutes les N ms que les deux pointeurs sont détectés. + this.areBothPointersHereTimeout = null; + //Délai de suppression d'une notification de recherche par gesture. + this.removeNotificationByGestureTimeout = null; + //Délai de suppression d'une notification de recherche par gesture infructueuse. + this.removeFailedNotificationByGestureTimeout = null; + //Délai avant la suppression de notification swipe. + this.notifySwipeTimeout = null; + //Délai pour la sélection de la TL. + this.selectTLTimeout = null; + //Délai pour slider sur la TL. + this.canSlideInTLTimeout = null; + //Délai pour afficher l'aide. + this.canNotifyHelpTimeout = null; + this.arrowLeftTimeout = null; + this.arrowRightTimeout = null; + this.arrowUpTimeout = null; + this.arrowDownTimeout = null; + + this.arrowSpinnerTimeout = null; + this.nouserTimeout = null; + this.nextDrawCurveTimeout = null; + + //Dernier message INCOMING (pour éviter d'effectuer n fois la même action. + this.lastIncomingMessage = ''; + + //Type de marqueur recherché dans la mosaïque (en mode filter). + this.filterSearchedType = ""; + + //Mode actuel. + this.currentMode = "NO-USER"; + //Snapshot sur lequel on a zoomé. + this.previousZoomedSN = null; + //Snapshot sur lequel on a prezoomé. + this.previousPrezoomDiv = null; + //Son ID. + this.previousId = null; + //Dernier snapshot prézoomé non null. + this.lastNonNullSN = null; + //Largeur de la marge pour le centrage vertical de la mosaïque. + this.MPTop_margin = null; + this.top_margin = null; + + //Gestures actuellement cherchées dans les vidéos. + this.currentSearchGesture = []; + + //Position des voisins lors d'un zoom. + this.neighboursIds = []; + //ID du snapshot du milieu lors d'un zoom. + this.centerId = null; + + //Voisins sélectionnés par les pointeurs. + this.mainPointerNeighbourSelectedId = null; + this.secondPointerNeighbourSelectedId = null; + + //Snapshots a afficher. + this.snapshotsToShow = 1; + + //Lecteur. + this.player = null; + //Si le lecteur est prêt. + this.playerIsReady = false; + + //Annotations (pour les marqueurs los d'un filtrage). + this.annotations = []; + + //Client websocket pour recevoir les notifications du Middleware. + this.client = null; + + //Coordonnées et dimensions d'un snapshot zoomé. + this.snTop = 0; + this.snLeft = 0; + this.snWidth = 0; + this.snHeight = 0; + + this.searchCanvas = null; + //Position actuelle de la vidéo zoomée. + this.notifyTopVideo = null; + this.notifyLeftVideo = null; + this.loadParameters(this.config_path); } /* * Méthode d'affichage de la mosaïque. * Génère une matrice de imgs. + * Est appelé dans le fichier : + * mosaic > fonction loadMosaic, afin de créer les éléments visuels de la mosaique. */ -mosaic.prototype.createMosaic = function() +Mosaic.prototype.createMosaic = function() { - // console.log('CREATE'); - // this.currentMode = "NO-USER"; - var initPanel = '
'; - var mp = $('#mainPanel'); - mp.append(initPanel); - $('#initPanel').css( + var _this = this; + + //On ajoute le player au body pour le lancer la première fois qu'on zoom. + $('body').append('
'); + + //On recharge la fenêtre si sa taille a changé. + $(window).resize(function() { - background: 'transparent', - width: mp.width(), - height: mp.height(), - top: mp.position().top, - left: mp.position().left, - 'margin-top': this.MPTop_margin + _.debounce(window.location.reload(), _this.config.timeReloadAfterResize); }); - var len = this.config['length'], imgs = this.config['imagesToShow'], imgsTotal = this.config['imagesTotal']; - - //S'il s'agit d'un rectangle. + var initPanel = '
'; + var mp = $('#mainPanel'); + mp.append(initPanel); + $('#initPanel').css( + { + background: 'transparent', + width: mp.width(), + height: mp.height(), + top: mp.position().top, + left: mp.position().left, + 'margin-top': this.MPTop_margin + }); + + var len = this.config.length, imgs = this.config.imagesToShow, imgsTotal = this.config.imagesTotal; + + //S'il s'agit d'un rectangle. if(imgs % len == 0) { - this.lastIncomingMessage = 'INCOMING-0'; - - var str = ''; - - if(this.imgs.length >= imgs) - { - for(var i = 0 ; i < imgs ; i++) - { - //On charge les images de petite taille pour ne pas surcharger la mosaïque lors de l'affichage global. - str += '
'; - //Au départ aucune vidéo n'a de gesture de recherche. - this.currentSearchGesture[i] = ''; - } - } - - return str + '
'; - } - else + this.lastIncomingMessage = 'INCOMING-0'; + + var str = ''; + + if(this.imgs.length >= imgs) + { + for(var i = 0 ; i < imgs ; i++) + { + //On charge les images de petite taille pour ne pas surcharger la mosaïque lors de l'affichage global. + str += '
'; + //Au départ aucune vidéo n'a de gesture de recherche. + this.currentSearchGesture[i] = ''; + } + } + + return str + '
'; + } + else + { + alert("Le nombre d'images a afficher doit être divisible par la longueur de la mosaïque !"); + } +} + +/* + * Fonction appelée lors d'un mouse down en mode d'interaction souris. + * Est appelé dans le fichier : + * mosaic > fonction loadMosaic, attachée à l'événement jQuery mousedown. +*/ +Mosaic.prototype.onMouseDown = function(e) +{ + this.isMouseDown = true; + + //On met à jour les coordonnées de la souris au dernier mouse down. + this.mouseDownPosX = e.pageX; + this.mouseDownPosY = e.pageY; + + //Si on est sur une notification de gesture de recherche. + this.removeSearchNotificationIfOnIt(e.pageX, e.pageY); + this.isUserInSearchZone = true; + + //Si on est en mode de tracé de courbes, on indique qu'on a commencé à tracer au canvas. + if(this.isSearchByCurvesOn) { - alert("Le nombre d'images a afficher doit être divisible par la longueur de la mosaïque !"); + this.searchCanvas.onPointerIn(this.mousePosX, this.mousePosY, null, null); } } /* - * Permet de raffraichir la mosaïque. - */ -mosaic.prototype.loadMosaic = function() + * Fonction appelée lors d'un mouse move en mode d'interaction souris. + * Est appelé dans le fichier : + * mosaic > fonction loadMosaic, attachée à l'événement jQuery mousemove. +*/ +Mosaic.prototype.onMouseMove = function(e) { - // console.log('LOAD'); - var createMosaic = this.createMosaic(); - - if(createMosaic == '') + //Si on n'a pas appuyé sur la souris avant, on part. + if(!this.isMouseDown) { return; } var _this = this; + //Si on est en mode de tracé de courbes, on met à jour la courbe. + if(this.isSearchByCurvesOn) + { + this.searchCanvas.onPointerMove(this.mousePosX, this.mousePosY - this.MPTop_margin, null, null); + } + + //On met à jour l'ancienne position de la souris si elle est nulle. + if(!this.mousePosLastX && this.mousePosLastX != 0) + { + this.mousePosLastX = this.mousePosX; + } + if(!this.mousePosLastY && this.mousePosLastY != 0) + { + this.mousePosLastY = this.mousePosY; + } + + //Le delta s'accroît si la souris bouge. + this.mouseUpDownDelta += Math.floor(Math.sqrt((this.mousePosLastX - e.pageX) * (this.mousePosLastX - e.pageX) + (this.mousePosLastY - e.pageY) * (this.mousePosLastY - e.pageY))); + + //On met à jour l'ancienne position de la souris. + if(this.mousePosLastX != this.mousePosX) + { + this.mousePosLastX = this.mousePosX; + } + if(this.mousePosLastY != this.mousePosY) + { + this.mousePosLastY = this.mousePosY; + } + + //Si la souris a parcouru une trop grande distance, on entre en recherche. + if(this.mouseUpDownDelta > this.config.mouseUpDownDeltaTreshold) + { + //Si on est en mosaique, on entre en filtrage. + if(this.currentMode == "MOSAIC") + { + this.preUnzoom(); + this.currentMode = "FILTER"; + this.isMosaicFiltered = true; + } + //Si on est en mode de filtrage, mais qu'on n'est pas en tracé de courbes. + else if(this.currentMode == "FILTER" && !this.isSearchByCurvesOn && this.isUserInSearchZone) + { + //On lance une nouvelle recherche pas courbes. + this.preUnzoom(); + } + //Si on est dans une vidéo, on entre en recherche. + else if(this.currentMode == "VIDEO" || this.currentMode == "TIMELINE") + { + this.currentMode = "SEARCH"; + } + //Si on est en mode recherche dans une vidéo, mais qu'on n'est pas en tracé de courbes. + /*else if(this.currentMode == "SEARCH" && !this.isSearchByCurvesOn) + { + //On lance une nouvelle recherche pas courbes. + }*/ + + if(this.currentMode != "NO-USER" && this.currentMode.indexOf("INCOMING") == -1 && !this.isSearchByCurvesOn) + { + this.isSearchByCurvesOn = true; + this.startSearch(); + this.searchCanvas.onPointerIn(this.mousePosX, this.mousePosY - this.MPTop_margin, null, null); + } + + //S'il n'est pas possible d'afficher l'aide. + if(!this.canNotifyHelp) + { + //On rend son affichage possible après un certain délai. + this.canNotifyHelpTimeout = setTimeout(function() + { + _this.canNotifyHelp = true; + }, this.config.timeoutCanNotifyHelp); + } + } +} + +/* + * Fonction appelée lors d'un mouse up en mode d'interaction souris. + * Est appelé dans le fichier : + * mosaic > fonction loadMosaic, attachée à l'événement jQuery mousemove. +*/ +Mosaic.prototype.onMouseUp = function() +{ + this.isMouseDown = false; + + //Si on était en train de tracer une courbe. + if(this.isSearchByCurvesOn) + { + //On quitte la zone de recherche. + this.isUserInSearchZone = false; + + //On regarde si ce qu'on a tracé correspond à une courbe en particulier. + var gesture_match = this.gestureWithSameCode(this.actualCode); + this.actualCode = ''; + + //Si oui. + if(gesture_match.length > 0) + { + //Si on est en mode recherche dans une vidéo et que le player est prêt. + if(this.currentMode == "SEARCH" && this.playerIsReady) + { + //On effectue une recherche dans cette vidéo. + this.player.widgets[0].searchByGesture(gesture_match); + this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture; + + //On va au premier marqueur trouvé. + if(this.player && this.player.widgets[0] && this.timeToGoAt[this.centerId] === 0 && this.player.widgets[0].atLeastOneSearchMarker(this.currentSearchGesture[this.centerId])) + { + this.player.widgets[0].goToFirstSearchedMarker(this.currentSearchGesture[this.centerId]); + } + + //On affiche la notification de gesture de recherche. + this.removeNotifications(); + this.currentSearchGesture[this.centerId] = gesture_match; + this.searchGesture(gesture_match, 'valid'); + this.curvesGesturesFound = false; + } + //Si on est en mode de filtrage de mosaique. + else if(this.currentMode == "FILTER") + { + if(this.isMosaicFiltered) + { + //On notifie la recherche par filtrage. + this.removeNotifications(); + this.filterSearchedType = gesture_match; + this.filterGesture(gesture_match, 'valid'); + //On filtre la mosaique. + this.searchFilter(gesture_match); + this.curvesGesturesFound = false; + } + } + } + //Si aucune gesture ne matche dans le dictionnaire. + else + { + //Si on était en mode filtrage de la mosaïque et qu'aucune gesture de filtrage n'avait été détectée avant ca, on revient en mode mosaïque. + if(this.currentMode == "FILTER" && this.filterSearchedType == "") + { + this.currentMode = "MOSAIC"; + this.isMosaicFiltered = false; + } + //Sinon si on était en mode recherche dans une video et qu'aucune gesture n'avait été détectée avant ca, on revient en mode video. + if(this.currentMode == "SEARCH" && this.currentSearchGesture[this.centerId] == "") + { + this.currentMode = "VIDEO"; + } + } + //On dit au module de recherche qu'on arrête de tracer des courbes. + this.searchCanvas.onPointerOut(); + } + + this.mousePosLastX = null; + this.mousePosLastY = null; + + //Si la distance parcourue par la souris entre le mouse down et le mouse up est inférieure ou égale au seuil. + if(this.mouseUpDownDelta <= this.config.mouseUpDownDeltaTreshold) + { + //Si on est sur un snapshot prézoomé. + if(this.isOnAPrezoomSN && this.previousZoomedSN != '' && (this.currentMode == 'MOSAIC' || this.currentMode == 'FILTER') && !this.isPrezooming) + { + this.zoom(); + } + } + + //On réinitialise le delta, on quitte la recherche par courbes. + this.mouseUpDownDelta = 0; + this.isSearchByCurvesOn = false; + this.leaveSearch(); + + //Si on est en mode de filtrage et qu'on a une gesture de filtrage trouvée. + if(this.currentMode == 'FILTER' && this.filterSearchedType != '') + { + //On notifie. + this.removeNotifications(); + this.filterGesture(this.filterSearchedType, 'valid'); + } +} + +/* + * Fonction appelée lors d'un clic en mode d'interaction souris. + * Est appelé dans le fichier : + * mosaic > fonction loadMosaic. +*/ +Mosaic.prototype.onClick = function(x, y) +{ + //Si la position de la souris entre le mouse down et le mouse up change de plus de 10px, on part. + if(!this.mouseDownPosX || !this.mouseDownPosY || Math.sqrt((this.mouseDownPosX - x) * (this.mouseDownPosX - x) + (this.mouseDownPosY - y) * (this.mouseDownPosY - y)) > 10) + { + return; + } + + //Si on est dans un mode autre qu'un mode zoomé et qu'on n'affiche pas l'aide, on part. + if(this.currentMode != "VIDEO" && this.currentMode != "SEARCH" && this.currentMode != "TIMELINE" && !this.helpDisplayed) + { + return; + } + + //Si on clique en dehors de la video centrale, alors on dézoome. + var TL = $('.Ldt-Timeline'); + var TLwidth = TL.width(), TLheight = TL.height(); + var Ptop = $('.LdtPlayer').position().top, Pleft = $('.LdtPlayer').position().left; + var Pheight = $('.LdtPlayer').height(); + var MPx = this.mousePosX, MPy = this.mousePosY; + + //On regarde si on a cliqué sur un snapshot. + var SN = this.pointerPositionToSN(MPx - this.notifyLeftVideo, MPy - this.notifyTopVideo, true); + var SNId; + if(SN) + { + SNId = parseInt(SN.attr('id').replace('snapshotDiv-', '')); + } + + //Si on n'a pas demandé à supprimé la notification de gesture. + if(!this.gestureDelRequested && !this.helpDisplayed) + { + //Si non, ou s'il ne fait pas partie des voisins. + if(!SNId || !_.include(this.neighboursIds, SNId)) + { + //Si le clic a lieu en dehors du player et que l'aide n'est pas affichée, on dezoom. + if(MPx < Pleft || MPx > (+Pleft + TLwidth) || MPy < Ptop || MPy > (+Ptop + Pheight - TLheight)) + { + this.unzoom(); + } + } + //Si on se trouve sur un voisin, on bouge. + else if(SNId && _.include(this.neighboursIds, SNId) && this.canMoveToNeighbour) + { + this.moveToNeighbour($('#snapshotDiv-' + SNId)); + } + } + //Si on l'a demandé, on enlève la demande de suppression. + else + { + this.gestureDelRequested = false; + } + + //Si l'aide est affichée, un clic la ferme. + if(this.helpDisplayed) + { + this.removeHelp(); + } +} + +/* + * Permet de raffraichir la mosaïque. + * Est appelé dans le fichier : + * mosaic > fonction loadFromJson, afin de charger la mosaique une fois que les fichiers de métadonnées ont été lus. + */ +Mosaic.prototype.loadMosaic = function() +{ + // console.log('LOAD'); + var createMosaic = this.createMosaic(); + + if(createMosaic == '') + { + return; + } + + var _this = this; + //On affecte les chemins vers les images à la mosaïque. this.previousZoomedSN; - //this.width = - // console.log(createMosaic); //On met à jour la mosaïque. $('#mainPanel').html(createMosaic); //On récupère la taille des bordures. @@ -314,7 +607,7 @@ //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.config['length'] - this.marginWidth; + this.snapshotWidth = this.width / this.config.length - this.marginWidth; this.snapshotHeight = this.snapshotWidth*9/16; $('.snapshotDivs').css('width', this.snapshotWidth).css('height', this.snapshotHeight).css('margin', this.marginWidth/2); @@ -322,936 +615,774 @@ //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); - - //On fait coincider le background du body avec celui de la mosaïque. - $('body').css('background-position', '0px ' + this.MPTop_margin + 'px'); - - /*$('.snapshotDivs').mouseover(function () - { - //On effectue un prézoom dès qu'on va sur une image. - _this.preZoom($(this)); - });*/ - - this.addPointers(); - - //Si dans le metadata player _ n'est pas déclaré, on le déclare. - if(typeof _ !== "undefined" && typeof IriSP._ === "undefined") - { - IriSP._ = _; - } - - if(typeof $ !== "undefined" && typeof IriSP.jQuery === "undefined") - { - IriSP.jQuery = $; - } - - //On charge les marqueurs. - var sourceManager = new IriSP.Model.Directory(), - globalAnnotations = new IriSP.Model.List(sourceManager), - nbFichiers = _this.urls.length, - fichiersCharges = 0; - - for (var i = 0; i < nbFichiers; i++) - { - // console.log('url : ' + _this.urls[i]); - _this.sources[i] = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt}); - _this.sources[i].onLoad(function() + + //On fait coincider le background du body avec celui de la mosaïque. + $('body').css('background-position', '0px ' + this.MPTop_margin + 'px'); + + this.addPointers(); + + //Si dans le metadata player _ n'est pas déclaré, on le déclare. + if(typeof _ !== "undefined" && typeof IriSP._ === "undefined") + { + IriSP._ = _; + } + + if(typeof $ !== "undefined" && typeof IriSP.jQuery === "undefined") + { + IriSP.jQuery = $; + } + + //On charge les marqueurs. + var sourceManager = new IriSP.Model.Directory(), + globalAnnotations = new IriSP.Model.List(sourceManager), + nbFichiers = _this.urls.length, + fichiersCharges = 0; + + //Récupère les annotations. + for (var i = 0; i < nbFichiers; i++) + { + _this.sources[i] = sourceManager.remoteSource({url: _this.urls[i], serializer: IriSP.serializers.ldt}); + _this.sources[i].onLoad(function() + { + var source = this; + globalAnnotations.addElements(source.getAnnotations()); + fichiersCharges++; + if (fichiersCharges == nbFichiers) + { + //Instructions à exécuter quand tout est chargé. + _this.annotations = globalAnnotations; + // console.log(_this.annotations.length + ' annotations loaded from ' + nbFichiers + ' files.'); + + //Si on gère les interactions à la souris. + if(_this.config.mouseInteractions) + { + //On met à jour la position estimée de la souris. + $(window).mousemove(function(e) + { + // _this.refreshPointers(e.pageX, e.pageY, _this, true); + _this.refreshPointers(e.pageX, e.pageY, true); + _this.mousePosX = e.pageX; + _this.mousePosY = e.pageY; + }); + } + + //Si on a activé la préphase mais qu'on est en mode Kinect. + if(_this.config.noUserModeEnabled && !_this.config.mouseInteractions) + { + //On active la préphase. + _this.init(); + _this.showNImages(0); + _this.currentMode = "NO-USER"; + } + else + { + //Sinon on affiche directement la mosaique. + _this.showNImages(20); + _this.currentMode = "MOSAIC"; + } + + //Le premier snapshot sur lequel on zoom en préphase. + _this.previousZoomedSN = $('#snapshotDiv-' + _this.fillingIds[0]); + } + }); + } + + //Si on est en mode d'intéraction souris. + if(this.config.mouseInteractions) + { + //Si on fait un mouse down sur le body, on vérifie enregistre le déplacement de la souris jusqu'au prochain mouse up. + $(window).mousedown(function (e) + { + _this.onMouseDown(e); + return false; + }); + + //On écoute le déplacement de la souris. + $(window).mousemove(function(e) { - var source = this; - // console.log(source); - globalAnnotations.addElements(source.getAnnotations()); - // console.log(source.url + ' ' + source.getAnnotations().length); - fichiersCharges++; - if (fichiersCharges == nbFichiers) + _this.onMouseMove(e); + return false; + }); + + //Si on fait un mouse up après ce mouse down. + $(window).mouseup(function() + { + _this.onMouseUp(); + return false; + }); + + //Si on fait un clic. + $(window).click(function(e) + { + _this.onClick(e.pageX, e.pageY); + _this.removeSearchNotificationIfOnIt(e.pageX, e.pageY); + return false; + }); + + $(window).on('mousewheel', function(event, delta, deltaX, deltaY) + { + //Si on est dans un mode autre qu'on mode zoomé ou que l'aide est affichée, on part. + if(_this.currentMode != "VIDEO" && _this.currentMode != "SEARCH" && _this.currentMode != "TIMELINE" || _this.helpDisplayed) { - // instructions à exécuter quand tout est chargé - _this.annotations = globalAnnotations; - // console.log(_this.annotations.length + ' ' + nbFichiers); - console.log(_this.annotations.length + ' annotations loaded from ' + nbFichiers + ' files.'); - - //Si on gère les interactions à la souris. - if(_this.mouseInteractions) - { - $(window).mousemove(function(e) - { - _this.refreshMainPointer(e.pageX, e.pageY, _this); - _this.mousePosX = e.pageX; - _this.mousePosY = e.pageY; - }); - } - - if(_this.prephaseEnabled && !_this.mouseInteractions) - { - _this.init(); - _this.showNImages(0); - _this.currentMode = "NO-USER"; - } - else - { - _this.showNImages(20); - _this.currentMode = "MOSAIC"; - } - - // /!\ // - // _this.currentMode = "FILTER"; - // _this.showNImages(20); - //_this.isSearchByCurvesOn = true; - // _this.startSearch(); - // console.log('CANVAS READY'); - // /!\ // - - _this.previousZoomedSN = $('#snapshotDiv-' + _this.fillingIds[0]); - } - }); - } - - if(this.mouseInteractions) - { - //Si on fait un mouse down sur le body, on vérifie enregistre le déplacement de la souris jusqu'au prochain mouse up. - $(window).mousedown(function (e) - { - _this.removeSearchNotificationIfOnIt(e.pageX, e.pageY); - - _this.isUserInSearchZone = true; - if(_this.isSearchByCurvesOn) - { - _this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY, null, null); + return; } - console.log('mdown'); - //On écoute le déplacement de la souris. - $(window).mousemove(function(e) - { - if(_this.isSearchByCurvesOn) - { - _this.searchCanvas.onPointerMove(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null); - } - - //On met à jour l'ancienne position de la souris si elle est nulle. - if(!_this.mousePosLastX && _this.mousePosLastX != 0) - { - _this.mousePosLastX = _this.mousePosX; - } - if(!_this.mousePosLastY && _this.mousePosLastY != 0) - { - _this.mousePosLastY = _this.mousePosY; - } - - //Le delta s'accroît si la souris bouge. - _this.mouseUpDownDelta += Math.floor(Math.sqrt((_this.mousePosLastX - e.pageX) * (_this.mousePosLastX - e.pageX) + (_this.mousePosLastY - e.pageY) * (_this.mousePosLastY - e.pageY))); - - // console.log(_this.mouseUpDownDelta, _this.mousePosLastX, e.pageX); - - if(_this.mousePosLastX != _this.mousePosX) - { - _this.mousePosLastX = _this.mousePosX; - } - if(_this.mousePosLastY != _this.mousePosY) - { - _this.mousePosLastY = _this.mousePosY; - } - - //Si la souris a parcouru une trop grande distance, on entre en recherche. - if(_this.mouseUpDownDelta > _this.config['mouseUpDownDeltaTreshold']) - { - //Si on est en mosaique, on entre en filtrage. - if(_this.currentMode == "MOSAIC") - { - _this.preUnzoom(); - _this.currentMode = "FILTER"; - _this.isMosaicFiltered = true; - - console.log(_this.date() + ' - ENTRE EN MODE FILTRAGE'); - - _this.isSearchByCurvesOn = true; - _this.startSearch(); - - /*if(!_this.curvesGesturesFound) - { - this.removeNotifications(); - _this.filterSearch(); - }*/ - - _this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null); - } - else if(_this.currentMode == "FILTER" && !_this.isSearchByCurvesOn && _this.isUserInSearchZone) - { - console.log('after search'); - _this.preUnzoom(); - _this.isSearchByCurvesOn = true; - _this.startSearch(); - _this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null); - } - //Si on est dans une vidéo, on entre en recherche. - else if(_this.currentMode == "VIDEO" || _this.currentMode == "TIMELINE") - { - _this.currentMode = "SEARCH"; - - console.log(_this.date() + ' - ENTRE EN MODE RECHERCHE'); - - _this.isSearchByCurvesOn = true; - _this.startSearch(); - - /*if(!_this.curvesGesturesFound) - { - this.removeNotifications(); - _this.searchSearch(); - }*/ - - _this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null); - } - else if(_this.currentMode == "SEARCH" && !_this.isSearchByCurvesOn) - { - _this.isSearchByCurvesOn = true; - _this.startSearch(); - _this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null); - } - - //Il est possible d'afficher l'aide. - if(!_this.canNotifyHelp) - { - _this.canNotifyHelpTimeout = setTimeout(function() - { - _this.canNotifyHelp = true; - }, _this.config['timeoutCanNotifyHelp']); - } - } - }); - - //Si on fait un mouse up après ce mouse down. - $(window).mouseup(function() - { - console.log('mup'); - - if(_this.isSearchByCurvesOn) - { - _this.isUserInSearchZone = false; - - var gesture_match = _this.gestureWithSameCode(_this.actualCode); - _this.actualCode = ''; - - if(gesture_match.length > 0) - { - if(_this.currentMode == "SEARCH" && _this.playerIsReady) - { - _this.player.widgets[0].searchByGesture(gesture_match); - _this.isCurrentlyInASearchByGesture = _this.player.widgets[0].isCurrentlyInASearchByGesture; - - if(_this.player && _this.player.widgets[0] && _this.timeToGoAt[_this.centerId] === 0 && _this.player.widgets[0].atLeastOneSearchMarker(_this.currentSearchGesture[_this.centerId])) - { - _this.player.widgets[0].goToFirstSearchedMarker(_this.currentSearchGesture[_this.centerId]); - } - - _this.removeNotifications(); - _this.currentSearchGesture[_this.centerId] = gesture_match; - _this.searchGesture(gesture_match, 'valid'); - _this.curvesGesturesFound = false; - } - else if(_this.currentMode == "FILTER") - { - if(_this.isMosaicFiltered) - { - _this.removeNotifications(); - _this.filterSearchedType = gesture_match; - _this.filterGesture(gesture_match, 'valid'); - _this.searchFilter(gesture_match); - _this.curvesGesturesFound = false; - } - } - } - - _this.searchCanvas.onPointerOut(); - } - - //On unbind ce qui a été bindé après le mouse up. - $(window).unbind('mousemove'); - $(window).unbind('mouseup'); - //On rebind le mousemove principal du body, car ils ont tous été unbindés. - $(window).mousemove(function(e) - { - _this.refreshMainPointer(e.pageX, e.pageY, _this); - _this.mousePosX = e.pageX; - _this.mousePosY = e.pageY; - }); - - _this.mousePosLastX = null; - _this.mousePosLastY = null; - - //Si la distance parcourue par la souris entre le mouse down et le mouse up est inférieure ou égale au seuil. - if(_this.mouseUpDownDelta <= _this.config['mouseUpDownDeltaTreshold']) - { - //Si on est sur un snapshot prézoomé. - if(_this.isOnAPrezoomSN && _this.previousZoomedSN != '' && (_this.currentMode == 'MOSAIC' || _this.currentMode == 'FILTER')) - { - _this.zoom(); - } - } - - _this.mouseUpDownDelta = 0; - _this.isSearchByCurvesOn = false; - _this.leaveSearch(); - - if(_this.currentMode == 'FILTER' && _this.filterSearchedType != '') - { - _this.removeNotifications(); - _this.filterGesture(_this.filterSearchedType, 'valid'); - } - }); - }); - } + //Quand on "tire" la molette vers soi, on dezoom. + if (delta < 0) + { + _this.unzoom(); + } + }); + } } /* * Charge les paramètres du Front. Local (true/false) est le mode de chargement des données. + * Est appelé dans le fichier : + * mosaic > fonction Mosaic, est appelée dans le constructeur de manière à charger les paramètres de configuration avant la création de la mosaique. */ -mosaic.prototype.loadParameters = function(file_path) +Mosaic.prototype.loadParameters = function(file_path) { - var _this = this; - - var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'zoomTime', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeANFade', 'timeFilling', 'zoomedMargin', 'timeoutZoom', 'timeoutUnzoom', 'timeoutMoveToNeighbour', 'timeoutPointersIdle', 'timeoutAreBothPointersHere', 'timeoutRemoveNotificationByGesture', 'timeoutRemoveFailedNotificationByGesture', 'timeoutNotifySwipe', 'timeoutSelectTL', 'timeoutSlideTL', 'timeoutCanNotifyHelp', 'timeoutRemoveSpinner', 'timeoutNouser', 'timeoutNextDrawCurve', 'mouseUpDownDeltaTreshold']; - var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage']; - - $.getJSON(file_path, function(data) - { - for(key in data) - { - var val = data[key]; - - if(_.include(supposedToBeInt, key)) - { - var intVal = parseInt(val); - if(isNaN(intVal)) - { - // console.log(_this.default_config); - _this.config[key] = _this.default_config[key]; - console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Int). Valeur par défaut " + _this.default_config[key] + " chargée à la place."); - } - else - { - _this.config[key] = intVal; - } - } - else if(_.include(supposedToBeFloat, key)) - { - var floatVal = parseFloat(val); - if(isNaN(floatVal)) + var _this = this; + + //Variables censées être des ints. + var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timeReloadAfterResize', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'zoomTime', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeANFade', 'timeFilling', 'zoomedMargin', 'timeoutZoom', 'timeoutUnzoom', 'timeoutMoveToNeighbour', 'timeoutPointersIdle', 'timeoutAreBothPointersHere', 'timeoutRemoveNotificationByGesture', 'timeoutRemoveFailedNotificationByGesture', 'timeoutNotifySwipe', 'timeoutSelectTL', 'timeoutSlideTL', 'timeoutCanNotifyHelp', 'timeoutRemoveSpinner', 'timeoutNouser', 'timeoutNextDrawCurve', 'mouseUpDownDeltaTreshold']; + //Variables censées êtres des floats. + var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage']; + + //On lit le fichier de configuration. + $.getJSON(file_path, function(data) + { + //Pour chaque ligne du fichier. + for(key in data) + { + var val = data[key]; + + //Si la valeur est prise pour un int. + if(_.include(supposedToBeInt, key)) + { + //On la parse et s'il y a une erreur, on l'indique dans la console avant d'affecter la valeur par défaut. + //Sinon on lui affecte la valeur lue. + var intVal = parseInt(val); + if(isNaN(intVal)) + { + _this.config[key] = _this.default_config[key]; + console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Int). Valeur par défaut " + _this.default_config[key] + " chargée à la place."); + } + else + { + _this.config[key] = intVal; + } + } + //Si la valeur est prise pour un float. + else if(_.include(supposedToBeFloat, key)) + { + //On la parse et s'il y a une erreur, on l'indique dans la console avant d'affecter la valeur par défaut. + //Sinon on lui affecte la valeur lue. + var floatVal = parseFloat(val); + if(isNaN(floatVal)) + { + _this.config[key] = _this.default_config[key]; + console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Float). Valeur par défaut " + _this.default_config[key] + " chargée à la place."); + } + else + { + _this.config[key] = floatVal; + } + } + else + { + //S'il s'agit de la langue, on met par défaut si la valeur est nulle. + if(key == 'lang' && val == '') { _this.config[key] = _this.default_config[key]; - console.log("param[" + key + "] : Valeur " + val + " incorrecte (non Float). Valeur par défaut " + _this.default_config[key] + " chargée à la place."); } + //Sinon si c'est une string, on l'affecte. else { - _this.config[key] = floatVal; + _this.config[key] = val; } - } - else - { - _this.config[key] = val; - } - } - - //On remplit le tableau d'ids. - for(var i = 0 ; i < _this.config['totalImages'] ; i++) - _this.ids.push(i); - //On les mélange. - _this.ids.sort(function() - { - return 0.5 - Math.random() - }); - - //On remplit le tableau d'ids destiné à afficher les snapshots au fur et à mesure. - for(var i = 0 ; i < _this.config['imagesToShow'] ; i++) - _this.fillingIds.push(i); - //On les mélange. - _this.fillingIds.sort(function() - { - return 0.5 - Math.random() - }); - - if(_this.config['local'] == 'true') - { - // console.log("Loading local metadata."); - _this.loadFromJson('./player/json/local_videos.json'); - } - else - { - // console.log("Loading online metadata."); - _this.loadFromJson('./player/json/online_videos.json'); - } - - //On initialise le client. - if(!_this.mouseInteractions) - { - _this.client = new client(_this.config['host'], _this.config['port'], _this); - } - - _this.getDictionary(); - _this.getLang(); - }); + } + } + + //On remplit le tableau d'ids. + for(var i = 0 ; i < _this.config.totalImages ; i++) + _this.ids.push(i); + //On les mélange. + _this.ids = _.shuffle(_this.ids); + + //On remplit le tableau d'ids destiné à afficher les snapshots au fur et à mesure. + for(var i = 0 ; i < _this.config.imagesToShow ; i++) + _this.fillingIds.push(i); + //On les mélange. + _this.fillingIds = _.shuffle(_this.fillingIds); + + //Si la config spécifie le chargement comme étant local/en ligne, on charge le fichier des vidéos approprié. + if(_this.config.local) + { + _this.loadFromJson(_this.config.videoConfigFileLocal); + } + else + { + _this.loadFromJson(_this.config.videoConfigFileOnline); + } + + //On initialise le client dans le cas d'intéractions Kinect. + if(!_this.config.mouseInteractions) + { + _this.client = new Client(_this.config.host, _this.config.port, _this); + } + + //On prend le dictionnaire stockant les codes des courbes de recherche. + _this.getDictionary(); + //On charge le fichier des langues. + _this.getLang(); + }); } /* * Phase principale (utilisateur non détecté). Une vidéo se lance aléatoirement. * L'interface est identique à celle du zoom, mais sans interaction possible avec les voisins, ni les controles timeline. * Lors de la fin d'une lecture, on dézoome vers la mosaïque, puis on rezoome vers un autre snapshot (aléatoire). + * Est appelé dans les fichiers : + * mosaic > fonction loadMosaic. + * zoomInteractions > fonction unzoom. */ -mosaic.prototype.init = function() +Mosaic.prototype.init = function() { - var _this = this; - - if(this.currentRandomVideoIdx > this.config['imagesToShow']) - { - this.currentRandomVideoIdx = 0; - } - - - this.previousZoomedSN = $('#snapshotDiv-' + this.fillingIds[this.currentRandomVideoIdx]); - this.previousId = $('img', this.previousZoomedSN).attr('id'); - - // console.log('CURRENT MODE : ' + _this.currentMode); - // console.log('ids', this.fillingIds[this.currentRandomVideoIdx]); - - this.previousZoomedSN.fadeTo(this.config['timePrezoom'], 1, function() - { - // console.log('CURRENT MODE : ' + _this.currentMode); - _this.zoom(); - _this.currentRandomVideoIdx++; - }); + var _this = this; + + //Si l'index de lecture des vidéos en mode sans utilisateur excède le nombre maximal de vidéos, il est remis à 0 pour tourner en boucle. + if(this.currentRandomVideoIdx > this.config.imagesToShow) + { + this.currentRandomVideoIdx = 0; + } + + //Le snapshot sur lequel on doit zoomé a pour id le tableau de lecture aléatoire à l'index de lecture. + this.previousZoomedSN = $('#snapshotDiv-' + this.fillingIds[this.currentRandomVideoIdx]); + this.previousId = $('img', this.previousZoomedSN).attr('id'); + + //On fait apparaître le snapshot avant de zoomer dessus. + this.previousZoomedSN.fadeTo(this.config.timePrezoom, 1, function() + { + _this.zoom(); + _this.currentRandomVideoIdx++; + }); } /* * Remplissage de la mosaïque en fonction du nombre d'images à afficher. + * Est appelé dans le fichier : + * mosaic > fonctions loadMosaic et manageControlEvents. */ -mosaic.prototype.showNImages = function(n) +Mosaic.prototype.showNImages = function(n) +{ + //Si on bouge vers un voisin, on n'utilise pas cette fonction. + if(this.currentlyMoving) + { + return; + } + + //Si il y a plus d'un snapshot à afficher, on entre dans le mode INCOMING avec en paramètre le nombre à afficher. + if(n > 1 && n < this.config.imagesToShow) + { + //On met en mode incoming avec le nombre de snapshots à afficher. + this.currentMode = "INCOMING-" + n; + //On dézoom. + this.unzoom(); + + //On initialise les gestures de recherche. + for(var i = 0 ; i < this.config.imagesToShow ; i++) + { + this.currentSearchGesture[i] = ''; + } + + //On enlève les notifications. + this.removeNotifications(); + //On annule les recherches. + this.isMosaicFiltered = false; + this.isCurrentlyInASearchByGesture = false; + //On masque les pointeurs. + $('#mainPointer').fadeTo(this.config.timePrezoom, 0); + $('#secondPointer').fadeTo(this.config.timePrezoom, 0); + //On enlève le spinner. + $('#spinner').remove(); + //On déselectionne tous les voisins. + this.deselectAllNeighbours(); + //On enlève tous les prézooms en cours. + $('.prezoomContainers').remove(); + } + + //Si on doit afficher la mosaique complète. + if(n >= this.config.imagesToShow) + { + //Si on est en mode sans utilisateur ou bien en mode d'utilisateur approchant. + if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING-") > -1) + { + //Si on est en intéractions Kinect. + if(!this.config.mouseInteractions) + { + //On met le mode à jour. + this.currentMode = "INCOMING-20"; + //On dézoom. + this.unzoom(); + } + + //On passe en mode mosaique. + this.currentMode = "MOSAIC"; + //On enlève les notifications, et on met les notifications de sélection et de recherche. + this.removeNotifications(); + this.mosaicSelectionAndSearch(); + //On retarde le mécanisme de redémarrage. + clearTimeout(this.nouserTimeout); + } + } + + //Pour les snapshots à afficher. + for(var i = 0 ; i < n ; i++) + { + //Si les snapshots ne sont pas affichés. + if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') < 1) + { + //On les fait apparaître. + $('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config.timeFilling, '1'); + } + } + //Pour ceux à masquer. + for(var i = n ; i < this.config.imagesToShow ; i++) + { + //Si les snapshots ne sont pas masqués et qu'il ne s'agit pas du dernier snapshot en lecture aléatoire (mode NO-USER). + if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') > 0 && this.fillingIds[i] != this.currentRandomVideoIdx) + { + //On les masque. + $('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config.timeFilling, '0'); + } + } +} + +/* + * Gère les événements de contrôle dans la mosaïque. + * Est appelé dans le fichier : + * client > fonction processMsg. +*/ +Mosaic.prototype.manageControlEvents = function(event) { - if(this.currentlyMoving) + var _this = this; + + if(typeof event === 'undefined') + { + return; + } + + var gestureReceived = ''; + + //Si l'utilisateur arrive et qu'on a la préphase activée. + if(event.indexOf("INCOMING-") != -1 && this.config.noUserModeEnabled) + { + //Si on peut démarrer. + if(this.canStart) + { + //Si on veut afficher plus de snapshots que disponibles, on affiche le maximum. + if(this.snapshotsToShow > this.config.imagesToShow) + { + this.snapshotsToShow = this.config.imagesToShow; + } + else + { + //On récupère le nombre de snapshots à afficher. + var params = event.split('-'); + this.snapshotsToShow = params[1]; + } + + //Si la position de l'utilisateur a changé. + if(event != this.lastIncomingMessage) + { + //On la met à jour et on affiche la mosaique en conséquence. + this.lastIncomingMessage = event; + this.showNImages(this.snapshotsToShow); + } + } + + //On retarde le mécanisme de redémarrage. + clearTimeout(this.nouserTimeout); + + //Après un délai d'absence de l'utilisateur on redémarre. + this.nouserTimeout = setTimeout(function() + { + window.location.reload(); + }, this.config.timeoutNouser); + } + //S'il n'y a qu'un snapshot à afficher et qu'on est en préphase, on redémarre. + else if((event == "NO-USER" || event == "INCOMING-0" || event == "INCOMING-1") && this.config.noUserModeEnabled) + { + window.location.reload(); + } + //Si on a fait un swipe. + else if(event.indexOf("SWIPE") != -1) + { + //Si le player est près et qu'on n'est pas en train de faire un swipe. + if(this.player && this.player.widgets && this.playerIsReady && !this.isSwipe) + { + //On est en train de faire un swipe. + this.isSwipe = true; + + //Si on est en mode de recherche, que la mosaique est filtrée et qu'on est arrivé au dernier marqueur. + if(this.currentMode == 'SEARCH' && this.isMosaicFiltered && !this.player.widgets[0].isAMarkerAhead(this.currentSearchGesture[this.centerId])) + { + //On passe à la prochaine vidéo qui contient des résultats. + this.playNextVideo(); + } + + //On spécifie s'il s'agit d'un swipe left ou right. + var swipeType = ((event.indexOf("LEFT") != -1) ? 'left' : 'right'); + var isSwipeLeft = ((event.indexOf("LEFT") != -1) ? true : false); + + //On passe au marqueur suivant/précédent en fonction du type de swipe. + this.player.widgets[0].switchToMarker(isSwipeLeft, this.currentSearchGesture[this.centerId]); + //Si on est en mode vidéo. + if(this.currentMode == 'VIDEO') + { + //On affiche la notification. + this.removeNotifications(); + this.videoSwipe(swipeType); + } + //Si on est en mode recherche dans une vidéo et qu'on n'a pas de gesture de recherche. + else if(this.currentMode == 'SEARCH' && this.currentSearchGesture[this.centerId] == '') + { + //On affiche la notification. + this.removeNotifications(); + this.searchSearchAndSwipe(swipeType); + } + //Si on est en mode recherche dans une vidéo et qu'on a une gesture de recherche. + else if(this.currentMode == 'SEARCH' && this.currentSearchGesture[this.centerId] != '') + { + //On affiche la notification. + this.removeNotifications(); + this.searchGestureAndSwipe(this.currentSearchGesture[this.centerId], 'valid', swipeType); + } + + //On le fait disparaitre au bout d'un certain temps. + this.notifySwipeTimeout = setTimeout(function() + { + _this.isSwipe = false; + _this.removeNotifications(); + + //Si on est en mode de recherche dans une vidéo et qu'aucune gesture n'est recherchée. + if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] == '') + { + _this.searchSearch(); + } + //Si on est en mode de recherche dans une vidéo et qu'on a une recherche par gesture. + else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId] != '') + { + _this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid'); + } + + }, this.config.timeoutNotifySwipe); + } + } + //Si on reçoit l'instruction correspondant à une des quatre gestures de recherche corporelle. + else if(event.indexOf("BEND") != -1 || event.indexOf('KNEE-UP') != -1 || event.indexOf('FALL') != -1 || event.indexOf('JUMP') != -1) + { + //On la met en minuscule. + gestureReceived = event.toLowerCase(); + //On met à jour la gesture recherchée. + this.currentSearchGesture[centerId] = gestureReceived; + } + //Si on a effectué un hello, qu'on peut notifier l'aide et que les deux mains ne sont pas dans la zone de recherche. + else if(event.indexOf("HELLO") != -1 && this.canNotifyHelp && !this.areBothPointersHere) + { + //On affiche différentes aides en fonction de si on se trouve dans une vidéo ou non. + if(this.currentMode == 'SEARCH') + { + this.notifyHelp(false); + } + else if(this.currentMode == 'FILTER') + { + this.notifyHelp(true); + } + } + + //Si on a reçu une gesture. + if(gestureReceived != '') + { + //Si on est en mode recherche et que le player est prêt. + if(this.currentMode == "SEARCH" && this.playerIsReady) + { + //On recherche dans la vidéo. + this.player.widgets[0].searchByGesture(gestureReceived); + this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture; + //On notifie. + this.removeNotifications(); + this.searchGesture(gestureReceived, 'valid'); + } + //Si on est dans un filtrage. + else if(this.currentMode == "FILTER") + { + if(this.isMosaicFiltered) + { + //On notifie et on filtre. + this.removeNotifications(); + this.filterGesture(gestureReceived, 'valid'); + this.searchFilter(gestureReceived); + } + } + + //Si l'aide est affichée, on l'enlève. + if(this.helpDisplayed) + { + this.removeHelp(); + } + } +} + +/* + * Fonction qui s'exécute lorsque le player a chargé. + * Est appelé dans le fichier : + * mosaic > fonction loadPlayer. +*/ +Mosaic.prototype.onPlayerLoad = function() +{ + var _this = this; + + if(this.currentMode == 'NO-USER') { - return; + //On peut s'approcher de la kinect. + this.canStart = true; } - // console.log('INCOMING ----- ' + n); - //Si il y a plus d'un snapshot à afficher, on entre dans le mode INCOMING avec en paramètre le nombre à afficher. - if(n > 1 && n < this.config['imagesToShow']) + //Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline). + if(this.player.popcorn) { - this.currentMode = "INCOMING-" + n; - this.unzoom(); - - for(var i = 0 ; i < this.config['imagesToShow'] ; i++) + this.player.popcorn.listen('pause', function() { - this.currentSearchGesture[i] = ''; - } + //Si la pause est naturelle (fin de la timeline, dézoom, déplacement vers un voisin). + if(!_this.userPaused) + { + //Si c'est en mode sans utilisateur. + if(_this.currentMode == 'NO-USER') + { + //On dézoome. + _this.unzoom(); + } + //Sinon, si ce n'est pas causé par un déplacement ou un dézoom. + else if(!_this.currentlyMoving && !_this.currentlyUnzooming) + { + //Si on est en mode timeline et qu'on est en pause, c'est probablement que l'user a placé le curseur à la fin. + if(_this.currentMode != 'TIMELINE') + { + _this.playNextVideo(); + } + } + } + }); - this.removeNotifications(); - this.isMosaicFiltered = false; - this.isCurrentlyInASearchByGesture = false; - $('#mainPointer').fadeTo(this.config['timePrezoom'], 0); - $('#secondPointer').fadeTo(this.config['timePrezoom'], 0); - $('#spinner').remove(); - this.deselectAllNeighbours(); - $('.prezoomContainers').remove(); + //Si les marqueurs ont été chargés. + this.player.popcorn.on("markersready", function() + { + _this.onMarkersReady(); + }); } - // console.log('n : ' + n); - if(n >= this.config['imagesToShow']) +} + +/* + * Fonction qui s'exécute lorsque les marqueurs d'une video on été placés. + * Est appelé dans le fichier : + * mosaic > fonction onPlayerLoad. +*/ +Mosaic.prototype.onMarkersReady = function() +{ + var _this = this; + + //Le player est prêt. + this.playerIsReady = true; + + if(this.player.widgets[0]) { - // this.unzoom(); - if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING-") > -1) + //On spécifie à la timeline dans quel mode d'intéraction on est. + this.player.widgets[0].setMouseInteractions(this.config.mouseInteractions); + //Idem pour la langue. + if(this.gesturesText.length > 0) { - if(!this.mouseInteractions) - { - this.currentMode = "INCOMING-20"; - this.unzoom(); - } - - this.currentMode = "MOSAIC"; - this.removeNotifications(); - this.mosaicSelectionAndSearch(); - clearTimeout(this.nouserTimeout); - console.log('OK'); + this.player.widgets[0].setLang(this.gesturesText); } - //On affiche les notifications. - // this.notifySelectionSearchMosaicFull(); - - //$('#mainPointer').fadeTo(this.config['timePrezoom'], 1); - //$('#secondPointer').fadeTo(this.config['timePrezoom'], 1); } - //Pour les snapshots à afficher. - for(var i = 0 ; i < n ; i++) + //Si on est en mode video ou recherche ou timeline. + if(this.currentMode == 'VIDEO' || this.currentMode == 'SEARCH' || this.currentMode == 'TIMELINE') + { + //On peut faire des swipes. + this.canSwipe = true; + } + + //Si aucune recherche par gesture n'est effectuée. + if(this.currentSearchGesture[this.centerId] == '') { - //Si les snapshots ne sont pas affichés. - if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') < 1) + //On enlève le filtre. + this.removeFilter(); + } + //Sinon. + else + { + //On entre en mode recherche dans une vidéo. + this.currentMode = 'SEARCH'; + //On recherche la gesture. + this.player.widgets[0].searchByGesture(this.currentSearchGesture[this.centerId]); + this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture; + + //On va au premier marqueur trouvé. + if(this.timeToGoAt[this.centerId] === 0 && this.player.widgets[0].atLeastOneSearchMarker(this.currentSearchGesture[this.centerId])) { - //On les fait apparaître. - $('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config['timeFilling'], '1'); + this.player.widgets[0].goToFirstSearchedMarker(this.currentSearchGesture[this.centerId]); } - } - //Pour ceux à masquer. - for(var i = n ; i < this.config['imagesToShow'] ; i++) - { - //Si les snapshots ne sont pas masqués et qu'il ne s'agit pas du dernier snapshot en lecture aléatoire (mode NO-USER). - if($('#snapshotDiv-' + this.fillingIds[i]).css('opacity') > 0 && this.fillingIds[i] != this.currentRandomVideoIdx) + //Si aucun marqueur n'est trouvé. + else { - //On les masque. - $('#snapshotDiv-' + this.fillingIds[i]).fadeTo(this.config['timeFilling'], '0'); + //On va juste là où on était la dernière fois qu'on a joué la vidéo. + this.player.popcorn.currentTime(this.timeToGoAt[this.centerId]); } } } /* - * Gère les événements de contrôle dans la mosaïque. + * Chargement du player basé sur le metadataplayer. + * Est appelé dans les fichiers : + * neighbours > fonction moveToNeighbour. + * zoomInteractions > zoom. */ -mosaic.prototype.manageControlEvents = function(event) +Mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft, timeToGo) { - // console.log('manage'); - - var _this = this; - - if(typeof event === 'undefined') - { - return; - } - - var gestureReceived = ''; - - if(event.indexOf("INCOMING-") != -1 && this.prephaseEnabled) - { - // console.log(this.date() + ' ' + event); - // console.log('CAN START : ' + this.canStart); - if(this.canStart) - { - if(this.snapshotsToShow > this.config['imagesToShow']) - { - this.snapshotsToShow = this.config['imagesToShow']; - } - else - { - var params = event.split('-'); - // console.log(event); - this.snapshotsToShow = params[1]; - } - - //Si la position de l'utilisateur a changé. - if(event != this.lastIncomingMessage) - { - console.log(this.snapshotsToShow); - this.lastIncomingMessage = event; - this.showNImages(this.snapshotsToShow); - } - } - - clearTimeout(this.nouserTimeout); - this.nouserTimeout = setTimeout(function() - { - /*_this.showNImages(0); - _this.init(); - _this.canStart = false; - _this.currentMode = "NO-USER";*/ - - window.location.reload(); - // mos = new mosaic('./config.json', default_parameters); - - console.log('NOUSER'); - }, this.config['timeoutNouser']); - } - else if((event == "NO-USER" || event == "INCOMING-0" || event == "INCOMING-1") && this.prephaseEnabled) - { - /*this.showNImages(0); - this.init(); - this.canStart = false; - this.currentMode = "NO-USER";*/ - - window.location.reload(); - // mos = new mosaic('./config.json', default_parameters); - - console.log('NOUSER'); - - /*this.currentMode = "NO-USER"; - this.showNImages(0); - this.canStart = false; - this.init();*/ - } - // /!\/!\ // - else if(event.indexOf("SWIPE") != -1) - { - if(this.player && this.player.widgets && this.playerIsReady && !this.isSwipe) - { - this.isSwipe = true; - - if(this.currentMode == 'SEARCH' && this.isMosaicFiltered && !this.player.widgets[0].isAMarkerAhead(this.currentSearchGesture[this.centerId])) - { - this.playNextVideo(); - } - - //L'utilisateur a fait un swipe left. - if(event.indexOf("LEFT") != -1) - { - this.player.widgets[0].switchToMarker(true, this.currentSearchGesture[this.centerId]); - if(this.currentMode == 'VIDEO') - { - this.removeNotifications(); - this.videoSwipe('left'); - } - else if(this.currentMode == 'SEARCH' && !this.currentSearchGesture[this.centerId]) - { - this.removeNotifications(); - this.searchSearchAndSwipe('left'); - } - else if(this.currentMode == 'SEARCH' && this.currentSearchGesture[this.centerId]) - { - this.removeNotifications(); - this.searchGestureAndSwipe(this.currentSearchGesture[this.centerId], 'valid', 'left'); - } - } - //L'utilisateur a fait un swipe right. - else if(event.indexOf("RIGHT") != -1) - { - this.player.widgets[0].switchToMarker(false, this.currentSearchGesture[this.centerId]); - if(this.currentMode == 'VIDEO') - { - this.removeNotifications(); - this.videoSwipe('right'); - } - else if(this.currentMode == 'SEARCH' && !this.currentSearchGesture[this.centerId]) - { - this.removeNotifications(); - this.searchSearchAndSwipe('right'); - } - else if(this.currentMode == 'SEARCH' && this.currentSearchGesture[this.centerId]) - { - this.removeNotifications(); - this.searchGestureAndSwipe(this.currentSearchGesture[this.centerId], 'valid', 'right'); - } - } - - //On le fait disparaitre au bout d'un certain temps. - this.notifySwipeTimeout = setTimeout(function() - { - _this.isSwipe = false; - - // /!\ // - _this.removeNotifications(); - - if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture[_this.centerId]) - { - _this.searchSearch(); - } - else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture[_this.centerId]) - { - _this.searchGesture(_this.currentSearchGesture[_this.centerId], 'valid'); - } - - }, this.config['timeoutNotifySwipe']); - } - } - else if(event.indexOf("BEND") != -1 || event.indexOf('KNEE-UP') != -1 || event.indexOf('FALL') != -1 || event.indexOf('JUMP') != -1) - { - gestureReceived = event.toLowerCase(); - gestureReceived = gestureReceived.replace('wave', 'hello'); - this.currentSearchGesture[centerId] = gestureReceived; - } - else if(event.indexOf("HELLO") != -1 && this.canNotifyHelp && !this.areBothPointersHere) - { - if(this.currentMode == 'SEARCH') - { - this.notifyHelp(false); - } - else if(this.currentMode == 'FILTER') - { - this.notifyHelp(true); - } - } - - if(gestureReceived != '') - { - if(this.currentMode == "SEARCH" && this.playerIsReady) - { - this.player.widgets[0].searchByGesture(gestureReceived); - this.isCurrentlyInASearchByGesture = this.player.widgets[0].isCurrentlyInASearchByGesture; - - this.removeNotifications(); - this.searchGesture(gestureReceived, 'valid'); - } - else if(this.currentMode == "FILTER") - { - if(this.isMosaicFiltered) - { - // console.log('FILTER !!!'); - // this.notifySearch1Gesture(gestureReceived, 'valid'); - this.removeNotifications(); - this.filterGesture(gestureReceived, 'valid'); - this.searchFilter(gestureReceived); - } - } - - if(this.helpDisplayed) - { - this.removeHelp(); - } - } - // /!\/!\ // -} - -/* - * Chargement du player basé sur le metadataplayer. -*/ -mosaic.prototype.loadPlayer = function(newZoomTop, newZoomLeft, newSnWidth, newSnHeight, zoomTop, zoomLeft, timeToGo) -{ - var _this = this; - - //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]; - - var _metadata = { - url: currentMetadata, - format: 'ldt' - }; - - var _config = { - gui: { - zoomTop: zoomTop - this.marginWidth*2, - zoomLeft: zoomLeft, - 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); - - this.player.onLoad(function() - { - if(_this.currentMode == 'NO-USER') - { - //On peut s'approcher de la kinect. - _this.canStart = true; - console.log('CAN START !'); - // console.log(_this.player); - // console.log(_this.player.popcorn); - } - - //Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline). - if(_this.player.popcorn) - { - _this.player.popcorn.listen('pause', function() - { - //Si l'utilisateur a mis en pause. - if(_this.userPaused) - { - - } - //Si la pause est naturelle (fin de la timeline, dézoom, déplacement vers un voisin). - else - { - //Si c'est en mode sans utilisateur. - if(_this.currentMode == 'NO-USER') - { - //On dézoome. - _this.unzoom(); - } - //Sinon. - else - { - //Si ce n'est pas causé par un déplacement ou un dézoom. - if(!_this.currentlyMoving && !_this.currentlyUnzooming) - { - //On réinitialise la position du curseur à la prochaine lecture de la vidéo. - console.log('REINIT'); - //On passe a la video suivante. - console.log('AUTOMOVE'); - - //Si on est en mode timeline et qu'on est en pause, c'est probablement que l'user a placé le curseur à la fin. - if(_this.currentMode != 'TIMELINE') - { - _this.playNextVideo(); - } - //_this.timeToGoAt[parseInt(_this.centerId)] = 0; - console.log('time to go at to 0'); - // return; - } - } - } - }); - // console.log('mosaic filtered : ' + _this.isMosaicFiltered); - - _this.player.popcorn.on("markersready", function() - { - _this.playerIsReady = true; - - if(_this.player.widgets[0]) - { - _this.player.widgets[0].setMouseInteractions(_this.mouseInteractions); - if(_this.gesturesText.length > 0) - { - _this.player.widgets[0].setLang(_this.gesturesText); - } - } - - if(_this.currentMode == 'VIDEO' || _this.currentMode == 'SEARCH' || _this.currentMode == 'TIMELINE') - { - _this.canSwipe = true; - } - - console.log('TIME TO GO AT : ' + _this.timeToGoAt[_this.centerId], _this.centerId, _this.imgs[_this.centerId]); - - // if(_this.isMosaicFiltered) - // { - if(_this.currentSearchGesture[_this.centerId] == '') - { - _this.removeFilter(); - } - else - { - _this.currentMode = 'SEARCH'; - // console.log(_this.currentSearchGesture); - _this.player.widgets[0].searchByGesture(_this.currentSearchGesture[_this.centerId]); - _this.isCurrentlyInASearchByGesture = _this.player.widgets[0].isCurrentlyInASearchByGesture; - - if(_this.timeToGoAt[_this.centerId] === 0 && _this.player.widgets[0].atLeastOneSearchMarker(_this.currentSearchGesture[_this.centerId])) - { - _this.player.widgets[0].goToFirstSearchedMarker(_this.currentSearchGesture[_this.centerId]); - } - else - { - _this.player.popcorn.currentTime(_this.timeToGoAt[_this.centerId]); - } - } - // } - // /!\ // - /*else - { - if(_this.player.popcorn) - { - _this.player.popcorn.currentTime(_this.timeToGoAt[_this.centerId]); - } - }*/ - }); - } - }); -} - -/* - * 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) + var _this = this; + + //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]; + + var _metadata = { + url: currentMetadata, + format: 'ldt' + }; + + var _config = { + gui: { + zoomTop: zoomTop - this.marginWidth*2, + zoomLeft: zoomLeft, + 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( { - return false; - } - for (var i=0; i fonction loadParameters. */ -mosaic.prototype.loadFromJson = function(path) +Mosaic.prototype.loadFromJson = function(path) { - var _this = this; - var i = 0; - - $.getJSON(path, function(data) - { - $.each(data, function(key, val) - { - $.each(val, function(key_video, val_video) - { - $.getJSON(val_video.metadata, function(meta) - { - if(_this.config['local'] == 'true') - { - _this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://media.iri.centrepompidou.fr/ddc_player/', './player/videos/').replace('mp4:', '').replace('video/', '').replace('ldtplatform/', '').replace('.m4v', '.mp4')); - // console.log(meta.medias[0].url.replace('rtmp://media.iri.centrepompidou.fr/ddc_player/', './player/videos/').replace('mp4:', '').replace('video/', '').replace('ldtplatform/', '').replace('.m4v', '.mp4')); - } - else - { - _this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4')); - // console.log(meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4')); - } - }); - _this.imgs[_this.ids[i]] = val_video.snapshot; - _this.urls[_this.ids[i]] = val_video.metadata; - //Au départ, on commence à 0 ms dans les vidéos. - _this.timeToGoAt[_this.ids[i]] = 0; - // console.log('ids : ' + _this.ids[i]); - i++; - }); - }); - // console.log('rdy'); - _this.loadMosaic(); - }); + var _this = this; + var i = 0; + + //On ouvre le fichier contenant les vidéos et les adresses des métadonnées. + $.getJSON(path, function(data) + { + $.each(data, function(key, val) + { + $.each(val, function(key_video, val_video) + { + //On extrait les métadonnées. + $.getJSON(val_video.metadata, function(meta) + { + //Si on est en chargement local. + if(_this.config.local) + { + //On cherche les vidéos dans les métadonnées. + _this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://media.iri.centrepompidou.fr/ddc_player/', './player/videos/').replace('mp4:', '').replace('video/', '').replace('ldtplatform/', '').replace('.m4v', '.mp4')); + } + //Si on est en chargement en ligne. + else + { + //On met l'adresse des videos en ligne. + _this.affectVideoById(val_video.metadata, meta.medias[0].url.replace('rtmp://', 'http://').replace('/ddc_player/', '/').replace('mp4:', '').replace('.m4v', '.mp4')); + } + }); + + //On affecte les images et métadonnées. + _this.imgs[_this.ids[i]] = val_video.snapshot; + _this.urls[_this.ids[i]] = val_video.metadata; + //Au départ, on commence à 0 ms dans les vidéos. + _this.timeToGoAt[_this.ids[i]] = 0; + i++; + }); + }); + + //On charge la mosaique. + _this.loadMosaic(); + }); } /* - * Affecte une vidéo au tableau des vidéos selon son id + * Affecte une vidéo au tableau des vidéos selon son id. + * Est appelé dans le fichier : + * mosaic > fonction loadFromJson. */ -mosaic.prototype.affectVideoById = function(metadata_id, video) +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; - } - } + for (i = 0 ; i < this.urls.length ; i++) + { + if(this.urls[i] == metadata_id) + { + this.videos[i] = video; + break; + } + } } /* - * Rebind keypress pour body. + * Affiche la date actuelle pour l'affichage de messages dans la console. + * Est appelé dans chaque console.log() où on veut afficher la date à laquelle l'instruction est exécutée. */ -mosaic.prototype.reaffectKeyPress = function() -{ - var _this = this; - - $('body').keypress(function (event) - { - _this.manageControlEvents(event); - }); -} - -mosaic.prototype.date = function() +Mosaic.prototype.date = function() { var date, h, min, s; date = new Date();