diff -r 7c394ea40f28 -r b2d068afdbd8 integration/js/editor.js --- a/integration/js/editor.js Mon Oct 29 18:11:09 2012 +0100 +++ b/integration/js/editor.js Tue Oct 30 18:44:45 2012 +0100 @@ -1,28 +1,31 @@ -IriSP.Hashcut = function() { +IriSP.Hashcut = function(options) { /* Load Media List */ var directory = new IriSP.Model.Directory(), project = directory.remoteSource({ - url: "data/bpidata.json", + url: options.url, serializer: IriSP.serializers.medialist }), mashup = new IriSP.Model.Mashup(false, project), - mediatemplate = '
  • {{title}}' - + '{{title}}{{description}}' - + 'Durée : {{duration}}
  • ', - segmenttemplate = '
  • {{media_title}}' - + '{{media_title}}' - + '{{title}}{{begin}} - {{end}} ({{duration}})' - + '
  • '; + mediatemplate = _.template('
  • <%= title %>' + + '<%= title %><%= description %>' + + 'Durée : <%= duration.toString() %>
  • '), + segmenttemplate = _.template('
  • ' + + '<%= annotation.getMedia().title %>' + + '<%= annotation.getMedia().title %>' + + '<%= annotation.title %><%= annotation.begin.toString() %> - <%= annotation.end.toString() %> (<%= annotation.getDuration().toString() %>)' + + '
  • '), + viztemplate = _.template('
    '), + intervaltemplate = _.template('<%= time.toString() %>'); /* Fill left column with Media List */ project.onLoad(function() { var html = ''; project.getMedias().forEach(function(_m) { - html += Mustache.to_html(mediatemplate, _m); + html += mediatemplate(_m); }); $(".col-left .list-video").html(html); }); @@ -55,15 +58,58 @@ /* Fill right column when mashup is updated */ - function fillRightColumn() { - var html = ''; - mashup.segments.forEach(function(_s) { - html += Mustache.to_html(segmenttemplate, _s); - }); - $(".col-right .list-video").html(html); + function setPointerToCurrentAnnotation() { + if (mashupCurrentAnnotation) { + var p = (mashupCurrentAnnotation.begin + mashupCurrentAnnotation.end) / (2 * mashup.duration); + $(".mashup-description .pointer").css("left", (100 * p) + "%"); + } } - mashup.on("add-segments",fillRightColumn); + function updateMashupUI() { + var listhtml = '', vizhtml = '', t = 0, k = mashup.duration ? (100 / mashup.duration) : 0; + mashup.segments.forEach(function(_s) { + listhtml += segmenttemplate(_s); + var vizdata = { + left: k * t, + width: k * _s.duration, + color: _s.getMedia().color + } + vizhtml += viztemplate(vizdata); + t += _s.duration.milliseconds; + }); + + var intervals = [ 1000, 2000, 5000, 10000, 30000, 60000, 120000, 300000, 600000, 900000, 1800000, 3600000, 7200000 ]; + + function createIntervals(maxn) { + for (var i = 0; i < intervals.length; i++) { + if (mashup.duration / intervals[i] <= maxn) { + var html = ''; + for (var j = intervals[i]; j < mashup.duration; j += intervals[i]) { + html += intervaltemplate({ left: k * j, time: new IriSP.Model.Time(j) }); + } + return html; + } + } + return ""; + } + + $(".col-right .list-video").html(listhtml).find(".item-video:last-child .bottom, .item-video:first-child .top").addClass("disable"); + $(".mashup-total-duration").text(mashup.duration.toString()); + $(".frise-segments").html(vizhtml); + $(".col-right .frise-indications").html(createIntervals(4)); + $(".bloc-pvw .frise-indications").html(createIntervals(8)); + highlightCurrentSegment(); + if (currentMedia === mashup) { + $(".Ldt-Ctrl-Time-Total").text(currentMedia.duration.toString()); + if (mashupTimecode > mashup.duration) { + mashup.setCurrentTime(mashup.duration); + } + changeCurrentAnnotation(); + setPointerToCurrentAnnotation(); + } + } + + mashup.on("change",updateMashupUI); /* Slider */ @@ -229,13 +275,13 @@ }); $(".Ldt-Ctrl-SetIn").click(function() { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.currentSegment.setBegin(currentMedia.getCurrentTime()); + if (currentMedia && currentSegment) { + currentSegment.setBegin(currentMedia.getCurrentTime()); } }); $(".Ldt-Ctrl-SetOut").click(function() { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.currentSegment.setEnd(currentMedia.getCurrentTime()); + if (currentMedia && currentSegment) { + currentSegment.setEnd(currentMedia.getCurrentTime()); } }); @@ -257,12 +303,12 @@ } }, slide: function(event, ui) { - if (currentMedia && currentMedia.currentSegment) { + if (currentMedia && currentSegment) { var t = currentMedia.duration * ui.value / slidersRange; if (ui.value === ui.values[0]) { - currentMedia.currentSegment.setBegin(t); + currentSegment.setBegin(t); } else { - currentMedia.currentSegment.setEnd(t); + currentSegment.setEnd(t); } } } @@ -271,15 +317,15 @@ sliceSlider.find(".ui-slider-handle:first") .addClass("Ldt-Slice-left-handle") .click(function() { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.setCurrentTime(currentMedia.currentSegment.begin); + if (currentMedia && currentSegment) { + currentMedia.setCurrentTime(currentSegment.begin); } }); sliceSlider.find(".ui-slider-handle:last") .addClass("Ldt-Slice-right-handle") .click(function() { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.setCurrentTime(currentMedia.currentSegment.end); + if (currentMedia && currentSegment) { + currentMedia.setCurrentTime(currentSegment.end); } }); @@ -304,71 +350,155 @@ timeSlider.slider("value",slidersRange * _time / currentMedia.duration); } + /* Mashup Player */ + + var mashupCurrentMedia = null, + mashupCurrentAnnotation = null, + mashupSegmentBegin, + mashupSegmentEnd, + mashupTimecode = 0, + mashupSeeking = false, + mashupSeekdiv, + mashupTimedelta; + + function changeCurrentAnnotation() { + if (mashupTimecode >= mashup.duration) { + if (!mashup.paused) { + mashup.paused = true; + mashup.trigger("pause"); + } + mashupTimecode = 0; + } + var _annotation = mashup.getAnnotationAtTime( mashupTimecode ); + if (typeof _annotation === "undefined") { + if (mashupCurrentMedia) { + mashupCurrentMedia.pause(); + if (!mashup.paused) { + mashup.paused = true; + mashup.trigger("pause"); + } + } + return; + } + mashupCurrentAnnotation = _annotation; + mashupSegmentBegin = mashupCurrentAnnotation.annotation.begin.milliseconds; + mashupSegmentEnd = mashupCurrentAnnotation.annotation.end.milliseconds; + mashupTimedelta = mashupSegmentBegin - mashupCurrentAnnotation.begin.milliseconds; + mashupCurrentMedia = mashupCurrentAnnotation.getMedia(); + + project.getMedias().forEach(function(_media) { + if (_media !== mashupCurrentMedia) { + _media.hide(); + _media.pause(); + } else { + _media.show(); + } + }); + + mashupCurrentMedia.setCurrentTime( mashupTimecode + mashupTimedelta); + mashupCurrentMedia.seeking = true; + + if (!mashup.paused) { + mashupCurrentMedia.play(); + mashupSeeking = true; +//TODO: _seekdiv.show(); + } + mashup.trigger("timeupdate", new IriSP.Model.Time(mashupTimecode)); + + } + /* Set current Media */ - var currentMedia; + var currentMedia, currentSegment; function updateSliderAndTangles() { - if (currentMedia && currentMedia.currentSegment) { - var start = currentMedia.currentSegment.begin, - end = currentMedia.currentSegment.end, - dur = currentMedia.currentSegment.getDuration(), - f = slidersRange / currentMedia.duration; + if (currentMedia && currentSegment) { + var start = currentSegment.begin, + end = currentSegment.end, + dur = currentSegment.getDuration(), + f = slidersRange / currentMedia.duration, + tangleStart = $(".tangle-start"), + tangleEnd = $(".tangle-end"), + tangleDuration = $(".tangle-duration"); sliceSlider.slider( "values", [ f * start, f * end ] ); - $(".tangle-start").text(start.toString()).attr("data-milliseconds",start.milliseconds); - $(".tangle-end").text(end.toString()).attr("data-milliseconds",end.milliseconds); - $(".tangle-duration").text(dur.toString()).attr("data-milliseconds",dur.milliseconds); + tangleStart.text(start.toString(tangleStart.hasClass("active"))).attr("data-milliseconds",start.milliseconds); + tangleEnd.text(end.toString(tangleEnd.hasClass("active"))).attr("data-milliseconds",end.milliseconds); + tangleDuration.text(dur.toString(tangleDuration.hasClass("active"))).attr("data-milliseconds",dur.milliseconds); $(".segment-info .pointer").css("left",(parseFloat($(".Ldt-Slice-left-handle").css("left")) + parseFloat($(".Ldt-Slice-right-handle").css("left")))/2) } } - function setMedia(mediaid) { + var addMode; + + function setMedia(media) { $(".col-left .item-video").removeClass("active"); $(".tutorial").hide(); - $("video").hide(); if (currentMedia) { currentMedia.pause(); } - currentMedia = project.getElement(mediaid); + currentMedia = media; if (currentMedia.elementType == "media") { - $(".col-left .item-video[data-media-id='" + mediaid + "']").addClass("active"); + $("video").hide(); + $(".col-left .item-video[data-media-id='" + currentMedia.id + "']").addClass("active"); showSegmentation(); - var currentvideo = $('#video_' + mediaid); + var currentvideo = $('#video_' + currentMedia.id); if (!currentvideo.length) { addMediaPlayer(currentMedia); - currentvideo = $('#video_' + mediaid); } $(".tab-media-title").text(currentMedia.title); - if (!currentMedia.currentSegment) { - currentMedia.currentSegment = new IriSP.Model.Annotation(false, project); - currentMedia.currentSegment.setMedia(currentMedia.id); - currentMedia.currentSegment.setBegin(0); - currentMedia.currentSegment.setEnd(currentMedia.duration); - currentMedia.currentSegment.thumbnail = currentMedia.thumbnail; - currentMedia.currentSegment.title = "Segment sans titre"; - currentMedia.currentSegment.description = "Extrait de « " + currentMedia.title + " »"; - currentMedia.currentSegment.on("change-begin", function() { - if (currentMedia && currentMedia.currentSegment === this) { + + addMode = !(currentSegment && mashup.hasAnnotation(currentSegment)); + + if (!currentSegment) { + currentSegment = new IriSP.Model.Annotation(false, project); + currentSegment.setMedia(currentMedia.id); + currentSegment.setBegin(0); + currentSegment.setEnd(currentMedia.duration); + currentSegment.title = "Segment sans titre"; + currentSegment.description = "Extrait de « " + currentMedia.title + " »"; + currentSegment.on("change-begin", function() { + if (currentMedia && currentSegment === this) { currentMedia.setCurrentTime(this.begin); updateSliderAndTangles(); } }); - currentMedia.currentSegment.on("change-end", function() { - if (currentMedia && currentMedia.currentSegment === this) { + currentSegment.on("change-end", function() { + if (currentMedia && currentSegment === this) { currentMedia.setCurrentTime(this.end); updateSliderAndTangles(); } }); + currentSegment.on("enter", function() { + if (currentMedia === mashup) { + $(".annotation-title").text(this.title); + $(".annotation-begin").text(this.begin.toString()); + $(".annotation-end").text(this.end.toString()); + $(".annotation-media-title").text(this.getMedia().title); + $(".annotation-description").text(this.description); + setPointerToCurrentAnnotation(); + } + }) } + if (currentMedia.loaded) { + currentMedia.setCurrentTime(currentSegment.begin); + } + $(".add-segment").val(addMode ? "Ajouter au Hashcut" : "Sauvegarder"); + $(".create-or-edit").text(addMode ? "Créer un nouveau segment" : "Modifier le segment"); updateSliderAndTangles(); + media.show(); + $("#segment-title").val(currentSegment.title); + $("#segment-description").val(currentSegment.description); + $("#segment-tags").val(""); } - currentvideo.show(); + if (currentMedia.elementType === "mashup") { + showPreview(); + mashup.checkLoaded(); + } $(".Ldt-Ctrl-Time-Total").text(currentMedia.duration.toString()); - $("#segment-title").val(currentMedia.currentSegment.title); - $("#segment-description").text(currentMedia.currentSegment.description); // TODO: Do something with the tags ! onCurrentMediaTimeupdate(currentMedia.getCurrentTime()); onCurrentMediaPause(); + highlightCurrentSegment(); } function addMediaPlayer(media) { @@ -401,31 +531,48 @@ }); videoEl.append(mp4_src).append(webm_src); $(".video").append(videoEl); - + + media.show = function() { + videoEl.show(); + } + media.hide = function() { + videoEl.hide(); + } + var popcorn = Popcorn("#" + videoid); // Binding functions to Popcorn media.on("setcurrenttime", function(_milliseconds) { - popcorn.currentTime(_milliseconds / 1000); + if (media.loaded) { + popcorn.currentTime(_milliseconds / 1000); + } }); media.on("setvolume", function(_vol) { - popcorn.volume(_vol); media.volume = _vol; + if (media.loaded) { + popcorn.volume(_vol); + } }); media.on("setmuted", function(_muted) { - popcorn.muted(_muted); media.muted = _muted; + if (media.loaded) { + popcorn.muted(_muted); + } }); media.on("setplay", function() { - popcorn.play(); + if (media.loaded) { + popcorn.play(); + } }); media.on("setpause", function() { - popcorn.pause(); + if (media.loaded) { + popcorn.pause(); + } }); // Binding Popcorn events to media @@ -437,6 +584,7 @@ popcorn.on("loadedmetadata", function() { getVolume(); + media.loaded = true; media.trigger("loadedmetadata"); media.trigger("volumechange"); }) @@ -462,55 +610,162 @@ media.trigger("seeked"); }); - // Binding UI Events to Media + // Binding UI Events and Mashup Playing to Media + + media.on("loadedmetadata", function() { + mashup.checkLoaded(); + }); media.on("play", function() { if (media === currentMedia) { onCurrentMediaPlay(); } + if (mashup === currentMedia && media === mashupCurrentMedia) { + mashup.trigger("play"); + } }); media.on("pause", function() { if (media === currentMedia) { onCurrentMediaPause(); } + if (mashup === currentMedia && media === mashupCurrentMedia) { + mashup.trigger("pause"); + } }); media.on("timeupdate", function(_time) { if (media === currentMedia) { onCurrentMediaTimeupdate(_time); } + if (mashup === currentMedia && !mashup.paused && media === mashupCurrentMedia && !media.seeking) { + if ( _time < mashupSegmentEnd ) { + if ( _time >= mashupSegmentBegin ) { + mashupTimecode = _time - mashupTimedelta; + } else { + mashupTimecode = mashupSegmentBegin - mashupTimedelta; + media.setCurrentTime(mashupSegmentBegin); + } + } else { + mashupTimecode = mashupSegmentEnd - mashupTimedelta; + media.pause(); + changeCurrentAnnotation(); + } + mashup.trigger("timeupdate", new IriSP.Model.Time(mashupTimecode)); + } + }); + + media.on("seeked", function() { + media.seeking = false; + if (mashup === currentMedia && media === mashupCurrentMedia && mashupSeeking) { + mashupSeeking = false; +//TODO: _seekdiv.hide(); + } }); media.on("volumechange", function() { if (media === currentMedia) { ctrlVolumeUpdater(); } + mashup.muted = media.muted; + mashup.volume = media.volume; + mashup.trigger("volumechange"); }) } + + // Mashup Events + mashup.on("setcurrenttime", function(_milliseconds) { + mashupTimecode = _milliseconds; + changeCurrentAnnotation(); + }); + + mashup.on("setvolume", function(_vol) { + mashup.getMedias().forEach(function(_media) { + _media.setVolume(_vol); + }); + mashup.volume = _vol; + }); + + mashup.on("setmuted", function(_muted) { + mashup.getMedias().forEach(function(_media) { + _media.setMuted(_muted); + }); + mashup.muted = _muted; + }); + + mashup.on("setplay", function() { + mashup.paused = false; + changeCurrentAnnotation(); + }); + + mashup.on("setpause", function() { + mashup.paused = true; + if (mashupCurrentMedia) { + mashupCurrentMedia.pause(); + } + }); + + mashup.on("loadedmetadata", function() { + if (mashup === currentMedia) { + changeCurrentAnnotation(); + } + }); + + /* Mashup Events to UI */ + + mashup.on("play", function() { + if (mashup === currentMedia) { + onCurrentMediaPlay(); + } + }); + + mashup.on("pause", function() { + if (mashup === currentMedia) { + onCurrentMediaPause(); + } + }); + + mashup.on("timeupdate", function(_time) { + if (mashup === currentMedia) { + $(".frise-position").css("left",(100*_time/mashup.duration)+"%"); + onCurrentMediaTimeupdate(_time); + } + }); + /* Segment Form interaction */ $("#segment-title").on("keyup change input paste", function() { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.currentSegment.title = $(this).val(); + if (currentMedia && currentSegment) { + currentSegment.title = $(this).val(); + updateMashupUI(); } }); $("#segment-description").on("keyup change input paste", function() { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.currentSegment.title = $(this).val(); + if (currentMedia && currentSegment) { + currentSegment.description = $(this).val(); } }); $("#segment-form").submit(function() { - mashup.addSegment(currentMedia.currentSegment); - currentMedia.currentSegment = undefined; + if (addMode) { + mashup.addAnnotation(currentSegment); + } else { + updateMashupUI(); + } + var segment = mashup.getAnnotation(currentSegment); + currentSegment = undefined; + setMedia(mashup); + if (segment) { + mashup.setCurrentTime(segment.begin); + } }) /* Click on media items */ $(".col-left").on("click", ".item-video", function() { - setMedia($(this).attr("data-media-id")); + currentSegment = undefined; + setMedia(project.getElement($(this).attr("data-media-id"))); }); /* Click on Tabs */ @@ -524,30 +779,67 @@ return false; } - $(".tab-pvw").click(showPreview); - - function disableMoveItemVideo() { - $(".organize-segments .top, .organize-segments .bottom").removeClass("disable"); - $(".organize-segments .item-video:last-child .bottom, .organize-segments .item-video:first-child .top").addClass("disable"); - } - disableMoveItemVideo(); - - $(".organize-segments").sortable({ - stop : function(){ - disableMoveItemVideo(); + $(".tab-pvw").click(function() { + if (mashup.segments.length) { + setMedia(mashup); } }); - $(".organize-segments .top").click(function(e){ + /* Click on segments */ + + function reorganizeMashup() { + var ids = $(".organize-segments .item-video").map(function(){return $(this).attr("data-segment-id")}); + mashup.setAnnotationsById(ids); + } + + function highlightCurrentSegment() { + $(".organize-segments .item-video").removeClass("active"); + if (currentMedia && currentSegment) { + $(".item-video[data-segment-id='" + currentSegment.id + "']").addClass("active"); + } + } + + $(".organize-segments").sortable({ + stop : reorganizeMashup + }); + + $(".organize-segments").on("click", ".item-video", function(e) { + var el = $(this), + segment = mashup.getAnnotationById(el.attr("data-segment-id")); + setMedia(mashup); + if (segment) { + mashup.setCurrentTime(segment.begin); + } + return false; + }); + + $(".organize-segments").on("click", ".edit", function(e) { + var currentItem = $(this).parents(".item-video"), + media = project.getElement(currentItem.attr("data-media-id")), + segment = project.getElement(currentItem.attr("data-segment-id")); + currentSegment = segment; + setMedia(media); + return false; + }); + + $(".organize-segments").on("click", ".top", function(e){ var currentItem = $(this).parents(".item-video"); currentItem.insertBefore(currentItem.prev()); - disableMoveItemVideo(); + reorganizeMashup(); + return false; }); - $(".organize-segments .bottom").click(function(e){ + $(".organize-segments").on("click", ".bottom", function(e){ var currentItem = $(this).parents(".item-video"); currentItem.insertAfter(currentItem.next()); - disableMoveItemVideo(); + reorganizeMashup(); + return false; + }); + + $(".organize-segments").on("click", ".delete", function(e){ + var id = $(this).parents(".item-video").attr("data-segment-id"); + mashup.removeAnnotationById(id); + return false; }); /* Tangles */ @@ -577,6 +869,7 @@ }) .mouseup(function() { if (activeTangle) { + activeTangle.text(activeTangle.text().replace(/\.\d+$/,'')); $(".time-tangle").removeClass("active deactivate"); activeTangle = undefined; } @@ -584,33 +877,36 @@ $(".tangle-start") .mouseup(function(evt) { - if (!tangleHasMoved && currentMedia && currentMedia.currentSegment) { - currentMedia.setCurrentTime(currentMedia.currentSegment.begin); + if (!tangleHasMoved && currentMedia && currentSegment) { + currentMedia.setCurrentTime(currentSegment.begin); } }) .on("valuechange", function(evt, val) { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.currentSegment.setBegin(val); + if (currentMedia && currentSegment) { + currentSegment.setBegin(val); } }); $(".tangle-end") .mouseup(function(evt) { - if (!tangleHasMoved && currentMedia && currentMedia.currentSegment) { - currentMedia.setCurrentTime(currentMedia.currentSegment.end); + if (!tangleHasMoved && currentMedia && currentSegment) { + currentMedia.setCurrentTime(currentSegment.end); } }) .on("valuechange", function(evt, val) { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.currentSegment.setEnd(val); + if (currentMedia && currentSegment) { + currentSegment.setEnd(val); } }); $(".tangle-duration").on("valuechange", function(evt, val) { - if (currentMedia && currentMedia.currentSegment) { - currentMedia.currentSegment.setDuration(val); + if (currentMedia && currentSegment) { + currentSegment.setDuration(val); } }); + + $(".mashup-description .edit").click(function() { + if (mashupCurrentAnnotation) { + currentSegment = mashupCurrentAnnotation.annotation; + setMedia(mashupCurrentAnnotation.getMedia()); + } + }) } - -$(function() { - var hashcut = new IriSP.Hashcut(); -});