Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recording controller #10

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions src/audio/audio_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Translates user input into actions that modify the audio model
// Responsible for drawing the audio timeline and displaying updates
"use strict";
var AudioController = function(audio_model) {
var AudioController = function(audio_model, timeController, globalState) {

///////////////////////////////////////////////////////////////////////////////
// Member vars
Expand Down Expand Up @@ -170,7 +170,7 @@ var AudioController = function(audio_model) {
this.startRecording = function(currentTime) {

// This method can only be called if the time controller is recording and a recording is not currently in progress
if ( !lectureController.isRecording() || isAudioRecording ) {
if ( !globalState.isRecording() || isAudioRecording ) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Consider making more sensible classes to pass around

console.error("Cannot begin recording");
return;
};
Expand All @@ -189,12 +189,12 @@ var AudioController = function(audio_model) {
// End the recording (only applies if there is an ongoing recording)
// Callback method registered to the time controller
this.stopRecording = function(currentTime) {
var beginTime = lectureController.getTimeController().getBeginTime();
var beginTime = timeController.getBeginTime();
var endTime = currentTime;
console.log("End audio recording (" + beginTime + ", " + endTime + ")");

// This method can only be called if the time controller is not recording and a recording is currently in progress
if ( lectureController.isRecording() || !isAudioRecording ) {
if ( globalState.isRecording() || !isAudioRecording ) {
console.error("Cannot end recording");
return;
};
Expand Down Expand Up @@ -228,7 +228,7 @@ var AudioController = function(audio_model) {
console.log("AudioController: Start playback");

// This method can only be called if the time controller is playing and a recording is not currently in progress
if ( !lectureController.isPlaying() || isAudioRecording ) {
if ( !globalState.isPlaying() || isAudioRecording ) {
console.error("Cannot begin playback");
return;
};
Expand All @@ -248,7 +248,7 @@ var AudioController = function(audio_model) {
console.log("AudioController: Stop playback");

// This method can only be called if the time controller is not playing and a recording is not currently in progress
if ( lectureController.isPlaying() || isAudioRecording ) {
if ( globalState.isPlaying() || isAudioRecording ) {
console.error("Cannot end playback");
return;
};
Expand Down Expand Up @@ -366,17 +366,17 @@ var AudioController = function(audio_model) {
// Calculate the length of the timeline in seconds.
// This should be twice as long as the lecture length, or at least 100 seconds.
// During a recording, the time controller cursor also counts as length.
var lecture_length = lectureController.getLectureModel().getLectureDuration();
var lecture_length = globalState.getLectureDuration();

if (lectureController.isRecording()) {
lecture_length = Math.max(lectureController.getTimeController().getTime(), lecture_length);
if (globalState.isRecording()) {
lecture_length = Math.max(timeController.getTime(), lecture_length);
}
var old_timeline_length = timelineLengthSeconds;
timelineLengthSeconds = Math.max(2*lecture_length/1000, minumum_timeline_seconds);

// During a recording, if the new timeline length is less than the old timeline length,
// then the old value of the timeline is used.
if (lectureController.isRecording() && timelineLengthSeconds < old_timeline_length) {
if (globalState.isRecording() && timelineLengthSeconds < old_timeline_length) {
timelineLengthSeconds = old_timeline_length;
};

Expand Down Expand Up @@ -481,7 +481,7 @@ var AudioController = function(audio_model) {
drag: function() {
// Update the time controller during dragging
var newTrackTime = self.pixelsToMilliseconds($('#'+playheadID).position().left);
lectureController.getTimeController().updateTime(newTrackTime);
timeController.updateTime(newTrackTime);
}
});

Expand Down Expand Up @@ -682,7 +682,7 @@ var AudioController = function(audio_model) {
var tracksContainer = $('#'+tracksContainerID);

// Clicking to update time is not allowed during a timing
if (lectureController.getTimeController().isTiming()) {
if (timeController.isTiming()) {
return;
}

Expand All @@ -707,7 +707,7 @@ var AudioController = function(audio_model) {

// Use the position to calculate and update the time that is represented by the click
var time = self.pixelsToMilliseconds(x);
lectureController.getTimeController().updateTime(time);
timeController.updateTime(time);
};


Expand Down Expand Up @@ -782,7 +782,7 @@ var AudioController = function(audio_model) {
);

// Register callbacks with the time controller
lectureController.getTimeController().addUpdateTimeCallback(updatePlayheadTime);
timeController.addUpdateTimeCallback(updatePlayheadTime);

// Mousedown listener for audio timeline
$('#'+timelineID).click(timelineClicked);
Expand Down
3 changes: 3 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<!--The entry point for the application is in lecture_controller.js-->
<script type="text/javascript" src="compatibility.js"></script>

<script type="text/javascript" src="time/TimeManager.js"></script>
<script type="text/javascript" src="recording/recording_controller.js"></script>

<script type="text/javascript" src="lecture_controller.js"></script>
<script type="text/javascript" src="lecture_model.js"></script>
<script type="text/javascript" src="time_controller.js"></script>
Expand Down
142 changes: 41 additions & 101 deletions src/lecture_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ var LectureController = function() {
var visualsController = null;
var audioController = null;
var retimerController = null;
var recordingController = null;
var toolsController = null;

// State for pen parameters
this.pressure = false;
Expand Down Expand Up @@ -56,6 +58,18 @@ var LectureController = function() {
// The lecture controller can be initialized from scratch or from a saved file.
///////////////////////////////////////////////////////////////////////////////

var globalState = {
isRecording: function() {
return recordingController ? recordingController.isRecording() : false;
},
getLectureDuration: function() {
return lectureModel ? lectureModel.getLectureDuration() : 0;
},
isPlaying: function() {
return timeController ? (timeController.isTiming() && playbackEndTime >= 0 && playbackEndTimeout) : false;
}
};

this.init = function() {

// Create the time controller, which is responsible for handling the current lecture time (also known as audio time)
Expand All @@ -70,9 +84,11 @@ var LectureController = function() {
// Initialize the controllers with their respective models.
// These controllers might register for time controller or undo manager callbacks, so they should be initialized
// after initializing the time controller and undo manager.
visualsController = new VisualsController(lectureModel.getVisualsModel(), lectureModel.getRetimerModel());
audioController = new AudioController(lectureModel.getAudioModel());
retimerController = new RetimerController(lectureModel.getRetimerModel(), visualsController, audioController);
visualsController = new VisualsController(lectureModel.getVisualsModel(), lectureModel.getRetimerModel(), timeController);
audioController = new AudioController(lectureModel.getAudioModel(), timeController, globalState);
retimerController = new RetimerController(lectureModel.getRetimerModel(), visualsController, audioController, timeController, globalState);
toolsController = new ToolsController(visualsController, globalState);
recordingController = new RecordingController(visualsController, audioController, retimerController, toolsController, timeController, undoManager);

// Setup input
loadInputHandlers();
Expand Down Expand Up @@ -314,80 +330,18 @@ var LectureController = function() {
// methods in the visuals/retimer/audio controllers to signal the event.
///////////////////////////////////////////////////////////////////////////////

// Returns true if a recording is in progress
this.isRecording = function() {
return (timeController.isTiming() && !self.isPlaying());
// Start recording; return true if it succeeds
var startRecording = function() {
return recordingController.startRecording(
self.recordingTypeIsVisuals(),
self.recordingTypeIsAudio(),
updateButtons
);
};

// Returns true if a playback is in progress
this.isPlaying = function() {
return (timeController.isTiming() && playbackEndTime >= 0 && playbackEndTimeout);
};

// Start recording and notify other controllers
// Returns true if it succeeds
this.startRecording = function() {

// Start the timing and exit if it fails
if (!timeController.startTiming()) {
return false;
};

// Start the undo hierarchy so that an undo after recording ends will undo the entire recording
undoManager.beginGrouping();

var beginTime = timeController.getBeginTime();

// On undo, revert to the begin time
undoManager.registerUndoAction(self, changeTime, [beginTime]);

// Notify controllers depending on the recording types
if (self.recordingTypeIsVisuals()) { // visuals
visualsController.startRecording(beginTime);
};
if (self.recordingTypeIsAudio()) { // audio
audioController.startRecording(beginTime);
};
retimerController.beginRecording(beginTime);

// Update the UI buttons
updateButtons();

return true;
};

// Stop recording and notify other controllers
// Returns true if it succeeds
this.stopRecording = function() {

// Only stop if we are currently recording
if (!self.isRecording()) {
return false;
};

// Stop the timing and exit if it fails
if (!timeController.stopTiming()) {
return false;
};

var endTime = timeController.getEndTime();

// Notify controllers depending on the recording types
if (self.recordingTypeIsVisuals()) { // visuals
visualsController.stopRecording(endTime);
};
if (self.recordingTypeIsAudio()) { // audio
audioController.stopRecording(endTime);
};
retimerController.endRecording(endTime);

// End the undo hierarchy so that an undo will undo the entire recording
undoManager.endGrouping();

// Update the UI buttons
updateButtons();

return true;
// Stop recording; return true if it succeeds
var stopRecording = function() {
return recordingController.stopRecording(updateButtons);
};

// Start playback and and notify other controllers
Expand All @@ -413,12 +367,12 @@ var LectureController = function() {
console.log('playback begin time: ' + beginTime);
console.log('playback end time: ' + playbackEndTime);

// Set the timeout to stop the recording
// Set the timeout to stop playback
playbackEndTimeout = setTimeout(self.stopPlayback, playbackEndTime - beginTime);

// Notify controllers
visualsController.startPlayback(beginTime);
audioController.startPlayback(beginTime);
toolsController.startPlayback();

// Update the UI buttons
updateButtons();
Expand All @@ -431,7 +385,7 @@ var LectureController = function() {
this.stopPlayback = function() {

// Only stop if we are currently playing
if (!self.isPlaying()) {
if (!globalState.isPlaying()) {
return false;
};

Expand All @@ -448,8 +402,8 @@ var LectureController = function() {
var endTime = timeController.getEndTime();

// Notify controllers
visualsController.stopPlayback(endTime);
audioController.stopPlayback(endTime);
toolsController.stopPlayback();

// Update the UI buttons
updateButtons();
Expand Down Expand Up @@ -491,18 +445,6 @@ var LectureController = function() {
draw();
};

// When undoing or redoing a recording, the time should also revert back to
// the previous time. This function helps achieve that by wrapping around
// a call to the time controller and the undo manager.
var changeTime = function(time) {

// Create an undo call to revert to the previous time
undoManager.registerUndoAction(self, changeTime, [timeController.getTime()]);

// Update the time
timeController.updateTime(time);
};

///////////////////////////////////////////////////////////////////////////////
// Input Handlers and Tools
//
Expand All @@ -529,10 +471,10 @@ var LectureController = function() {
};

// Start recording button handler
$('#'+startRecordButtonID).click(self.startRecording);
$('#'+startRecordButtonID).click(startRecording);

// Stop recording button handler
$('#'+stopRecordButtonID).click(self.stopRecording);
$('#'+stopRecordButtonID).click(stopRecording);

// Start playback button handler
$('#'+startPlaybackButtonID).click(self.startPlayback);
Expand Down Expand Up @@ -572,23 +514,23 @@ var LectureController = function() {
var updateButtons = function() {

// Hide/unhide the record start/stop buttons
if (self.isRecording()) {
if (recordingController.isRecording()) {
$('#'+startRecordButtonID).addClass(hiddenClass);
$('#'+stopRecordButtonID).removeClass(hiddenClass);
} else {
$('#'+startRecordButtonID).removeClass(hiddenClass);
$('#'+stopRecordButtonID).addClass(hiddenClass);
};
if (self.isPlaying()) {

// Hide/unhide the playback start/stop buttons
if (globalState.isPlaying()) {
$('#'+startPlaybackButtonID).addClass(hiddenClass);
$('#'+stopPlaybackButtonID).removeClass(hiddenClass);
} else {
$('#'+startPlaybackButtonID).removeClass(hiddenClass);
$('#'+stopPlaybackButtonID).addClass(hiddenClass);
};

// Hide/unhide the playback start/stop buttons

// Enable or disable the undo/redo buttons
if (undoManager.canUndo()) {
$('#'+undoButtonID).removeClass(hiddenClass);
Expand Down Expand Up @@ -671,8 +613,7 @@ var LectureController = function() {
// Main: The single entry point for the entire application
///////////////////////////////////////////////////////////////////////////////

// Define the global lecture controller and undo manager objects
var lectureController;
// Define the global and undo manager objects
var undoManager;

// Objects and controllers should only be created after the document is ready
Expand All @@ -682,6 +623,5 @@ $(document).ready(function() {
undoManager = new UndoManager();

// Create and initialize the lecture controller
lectureController = new LectureController();
lectureController.init();
new LectureController().init();
});
5 changes: 5 additions & 0 deletions src/lecture_model.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ var LectureModel = function() {
var retimerModel = null;

var init = function() {
TimeManager.getVisualInstance().clear();
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Move this to LectureController

TimeManager.getAudioInstance().clear();

visualsModel = new VisualsModel(800, 500);
audioModel = new AudioModel();
Expand All @@ -29,6 +31,9 @@ var LectureModel = function() {

// Loading the model from JSON
this.loadFromJSON = function(json_object) {
TimeManager.getVisualInstance().clear();
TimeManager.getAudioInstance().clear();

visualsModel = VisualsModel.loadFromJSON(json_object['visuals_model']);
audioModel = AudioModel.loadFromJSON(json_object['audio_model']);
retimerModel = RetimerModel.loadFromJSON(json_object['retimer_model']);
Expand Down
Loading