Skip to content

Commit

Permalink
Encapsulation on ProjectData (break tabNavigation.js)
Browse files Browse the repository at this point in the history
* AnalysisCollection is now a dictionary: Every Analysis is identified by its own name, not by index
* ProjectData encapsulation: Management for Analysis and Cue objects inside ProjectData
* WARNING: tabNavigation.js is broken because of changes in AnalysisCollection
* TODO: Implement Angular Events
  • Loading branch information
Roboe committed Aug 13, 2015
1 parent 5a5ef66 commit df34a97
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 89 deletions.
15 changes: 7 additions & 8 deletions pages/editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<!-- Analysis / webVTT tab-navigation selector -->
<!-- start scope tab-nav -->
<tab-navigation items="project.project.analysisCollection" deletable="true">

<div class="row">

<!-- videoPLayer -->
Expand All @@ -12,19 +12,18 @@

<!-- automatic analysis selected -->
<div class="col-lg-6">

<video-controller></video-controller>
<!-- start sub-scope tab-nav -->
<tab-navigation items="[{name:'Visualization'},
{name:'Metadata Editor'}]"
<tab-navigation items="['Visualization', 'Metadata Editor']"
ng-show="$parent.activeTab < 3">
<!-- option 0: visualization -->
<section class="panel" id="frame-viz-panel"
<section class="panel" id="frame-viz-panel"
ng-show="$parent.activeTab == 0">
<frame-viz></frame-viz>
</section>
<!-- option 1: metadata Editor -->
<section class="panel" id="frame-viz-panel"
<section class="panel" id="frame-viz-panel"
ng-show="$parent.activeTab == 1">
<metadata-editor analysis="project.project.analysis">
</metadata-editor>
Expand Down Expand Up @@ -53,8 +52,8 @@

<!-- timeline -->
<timeline-viz class="row"></timeline-viz>
</tab-navigation>

</tab-navigation>
<!-- end scope tab-nav -->

</div> <!-- end scope project -->
6 changes: 3 additions & 3 deletions scripts/common/tabNavigation.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<div class="tab container-fluid">
<div class="row">
<ul class="nav nav-pills">
<li ng-class="{ active:isSelected($index)}" ng-repeat="item in items">
<a href class="tag-button" ng-click="selectTab($index)">{{ item.name }}</a>
<li ng-class="{ active:isSelected($index)}" ng-repeat="(key, item) in items">
<a href class="tag-button" ng-click="selectTab($index)">{{ key }}</a>
<a href class="delete-button" ng-if="isSelected($index) && $parent.isDeletable && $index>2" ng-click="remove($index)"></a>
</li> <!-- end scope item -->

Expand All @@ -15,4 +15,4 @@
<!-- tab-panel placeholder -->
<div ng-transclude></div>

</div> <!-- end container -->
</div> <!-- end container -->
16 changes: 7 additions & 9 deletions scripts/common/tabNavigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@

scope.activeTab = 0;

scope.analysis = {};
var currentAnalysisName = '';

scope.selectTab = function(setTab) {
scope.activeTab = setTab;
ProjectData.currentAnalysisIndex = setTab;
};

scope.isSelected = function(checkTab) {
Expand All @@ -32,24 +31,23 @@
var r = confirm('Delete analysis???');
if (r === true) {
ProjectData.analysisCollection.splice(scope.activeTab, 1);
scope.activeTab = ProjectData.analysisCollection.length - 1;
scope.activeTab = Object.keys(ProjectData.analysisCollection).length - 1;
}
};

scope.addAnalysis = function() {
scope.analysis.name = prompt('Please enter analysis name', 'Metadata');
currentAnalysisName = prompt('Please enter analysis name', 'Metadata');
if (name != null) {

keys = [];
for (var key in ProjectData.analysisCollection) {
keys.push(ProjectData.analysisCollection[key].name);
}

if (!keys.indexOf(scope.analysis.name) !== -1) {
var analysis = ProjectData.createAnalysis(scope.analysis.name);
scope.activeTab = ProjectData.analysisCollection.indexOf(analysis);
ProjectData.currentAnalysisIndex = scope.activeTab;
scope.analysis = {};
if (!keys.indexOf(currentAnalysisName) !== -1) {
ProjectData.createAnalysis(currentAnalysisName);
scope.activeTab = currentAnalysisName;
ProjectData.currentAnalysisName = scope.activeTab;
}
}
};
Expand Down
91 changes: 40 additions & 51 deletions scripts/services/analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,16 @@ angular.module('filmViz')
function seekedListener(event) {
var cueStartTime = video.currentTime;

// function loopInAnalysis
console.log('seeked: analyzing frame');
context.drawImage(video, 0, 0, canvas.width, canvas.height);
currentImgSrc = canvas.toDataURL('image/jpg');

// Generate color analysis
// Run color analysis
var colorFramePromise = Promise.resolve(Color.capturePalette(currentImgSrc, 16));

// Generate audio analysis
// Run audio analysis
var audioFramePromise = Promise.resolve(1);

// Generate motion analysis
// Run motion analysis
var motionFramePromise = new Promise(function(resolve, reject) {
if (!previousImgSrc) {
resolve(0);
Expand All @@ -52,81 +50,72 @@ angular.module('filmViz')
}
});

colorFramePromise = colorFramePromise.then(function(value) {
return new ProjectData.Cue(value, cueStartTime);
colorFramePromise = colorFramePromise.then(function(result) {
return {
content: result,
startTime: cueStartTime,
};
});

audioFramePromise = audioFramePromise.then(function(value) {
return new ProjectData.Cue(value, cueStartTime);
audioFramePromise = audioFramePromise.then(function(result) {
return {
content: result,
startTime: cueStartTime,
};
});

motionFramePromise = motionFramePromise.then(function(value) {
return new ProjectData.Cue(value, cueStartTime);
motionFramePromise = motionFramePromise.then(function(result) {
return {
content: result,
startTime: cueStartTime,
};
});

// create cueObjects and store in each analysis
colorTrackPromises.push(colorFramePromise);
audioTrackPromises.push(audioFramePromise);
motionTrackPromises.push(motionFramePromise);

if (video.currentTime < video.duration - interval) {
video.currentTime += interval;
previousImgSrc = currentImgSrc;
} else {
// analysis finished

} else { // Analysis finished
video.pause();
video.removeEventListener('seeked', seekedListener, false);

Promise.all(colorTrackPromises).then(function(cues) {
var colorAnalysis = ProjectData.createAnalysis('color');

cues.forEach(function(cue) {
colorAnalysis.data.push(cue);
});

colorAnalysis.isDone = true;

var colorTrack = video.addTextTrack('metadata', 'color');
_this.addCuesToVideoTrack(colorTrack, colorAnalysis.data, video);
Promise.all(colorTrackPromises).then(function(resultObjs) {
var analysisName = 'color';
ProjectData.createAnalysis(analysisName);

colorTrack.addEventListener('cuechange', function() {
showFrameColorViz();
resultObjs.forEach(function(resultObj) {
ProjectData.addCueToAnalysis(analysisName, resultObj.content, resultObj.startTime);
});

showTimelineColorViz(colorAnalysis.data);
ProjectData.addTrackToVideo(analysisName, video, showFrameColorViz);
ProjectData.setAnalysisAsDone(analysisName, showTimelineColorViz);
});

Promise.all(audioTrackPromises).then(function(cues) {
var audioAnalysis = ProjectData.createAnalysis('audio');
Promise.all(audioTrackPromises).then(function(resultObjs) {
var analysisName = 'audio';
ProjectData.createAnalysis(analysisName);

cues.forEach(function(cue) {
audioAnalysis.data.push(cue);
resultObjs.forEach(function(resultObj) {
ProjectData.addCueToAnalysis(analysisName, resultObj.content, resultObj.startTime);
});

audioAnalysis.isDone = true;

var audioTrack = video.addTextTrack('metadata', 'audio');
_this.addCuesToVideoTrack(audioTrack, audioAnalysis.data, video);
ProjectData.addTrackToVideo(analysisName, video, console.log.bind(console));
ProjectData.setAnalysisAsDone(analysisName, console.log.bind(console));
});

Promise.all(motionTrackPromises).then(function(cues) {
var motionAnalysis = ProjectData.createAnalysis('motion');

cues.forEach(function(cue) {
motionAnalysis.data.push(cue);
});

motionAnalysis.isDone = true;

var motionTrack = video.addTextTrack('metadata', 'motion');
_this.addCuesToVideoTrack(motionTrack, motionAnalysis.data, video);
Promise.all(motionTrackPromises).then(function(resultObjs) {
var analysisName = 'motion';
ProjectData.createAnalysis(analysisName);

motionTrack.addEventListener('cuechange', function() {
showFrameMotionViz();
resultObjs.forEach(function(resultObj) {
ProjectData.addCueToAnalysis(analysisName, resultObj.content, resultObj.startTime);
});

showTimelineMotionViz(motionAnalysis.data);
ProjectData.addTrackToVideo(analysisName, video, showFrameMotionViz);
ProjectData.setAnalysisAsDone(analysisName, showTimelineMotionViz);
});
}
};
Expand Down
62 changes: 44 additions & 18 deletions scripts/services/projectData.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,75 @@ angular.module('filmViz')
this.project = ProjectData;
},])
.service('ProjectData', ['Timecode', 'JSZipLib', function(Timecode, JSZipLib) {
this.name = '' || 'project';
this.videoSrc = '';
this.analysisCollection = {};
this.currentAnalysisName = 0;

/**
* Analysis object
* @param [string] name Name of the analysis
* @param [boolean] isDone Flag to check if the analysis is completed
* @param [array] data The data of the analysis (array of cue objects)
* @param [array] data Raw data of the analysis (array of Cue objects)
*/
var Analysis = function(name, data) {
this.name = name;
var Analysis = function(data) {
this.isDone = false;
this.data = data || [];
};

this.createAnalysis = function(analysisName, analysisData) {
var newAnalysis = new Analysis(analysisData);
this.analysisCollection[analysisName] = newAnalysis;
return newAnalysis;
};

this.addCueToAnalysis = function(analysisName, content, startTime, endTime) {
var newCue = new Cue(content, startTime, endTime);
this.analysisCollection[analysisName].data.push(newCue);
};

this.setAnalysisAsDone = function(analysisName, onComplete) {
// TODO: Use Angular Event
currentAnalysis = this.analysisCollection[analysisName];
currentAnalysis.isDone = true;
if (onComplete) {
onComplete(currentAnalysis.data);
}
};

/**
* Cue object (like in html track cues)
* @param [array || string || number] content Information stored in the cue
* @param [number] startTime Start time of cue in seconds with 3 decimal places
* @param [number] endTime End time of cue in seconds with 3 decimal places
*/
this.Cue = function(content, startTime, endTime) {
var Cue = function(content, startTime, endTime) {
this.content = content;
this.startTime = startTime;
this.endTime = endTime || null;
};

this.name = '' || 'project';
this.videoSrc = '';
this.analysisCollection = [];
this.currentAnalysisIndex = 0;
this.addTrackToVideo = function(analysisName, videoElt, onCuechange) {
var track = videoElt.addTextTrack('metadata', analysisName);

this.createAnalysis = function(name) {
var newAnalysis = new Analysis(name);
this.analysisCollection.push(newAnalysis);
return newAnalysis;
this.analysisCollection[analysisName].data
.forEach(function(cueObj, index, arr) {
var startTime = cueObj.startTime;
var endTime = (index === arr.length - 1) ? videoElt.duration : arr[index + 1].startTime;
track.addCue(new VTTCue(startTime, endTime, angular.toJson(cueObj.content)));
});

// TODO: Use Angular Event
track.addEventListener('cuechange', onCuechange);
};

this.createVtt = function(analysisIndex, isBlob) {
this.createVtt = function(analysisName, isBlob) {
var _this = this;
var text = '';

// Select analysis to write
analysisIndex = analysisIndex || project.currentAnalysisIndex;
var analysis = project.analysisCollection[analysisIndex];
analysisName = analysisName || project.currentAnalysisName;
var analysis = project.analysisCollection[analysisName];

function newLine(string) {
text += (string) ? string + '\n' : '\n';
Expand Down Expand Up @@ -92,7 +118,7 @@ angular.module('filmViz')
name: _this.name,
videoSrc: _this.videoSrc,
analysisCollection: _this.analysisCollection,
currentAnalysisIndex: _this.currentAnalysisIndex,
currentAnalysisName: _this.currentAnalysisName,
}));

return zip.generate({
Expand Down Expand Up @@ -154,10 +180,10 @@ angular.module('filmViz')
reader.readAsArrayBuffer(zipBlob);
};

this.sortData = function(analysisIndex) {
this.sortData = function(analysisName) {
};

this.calculateEndTime = function(analysisIndex) {
this.calculateEndTime = function(analysisName) {
// TODO
};
},]);

1 comment on commit df34a97

@Roboe
Copy link
Member Author

@Roboe Roboe commented on df34a97 Aug 13, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix #62

Please sign in to comment.