mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-462: Merge correct recording playback artifacts during seek().
This commit is contained in:
@@ -228,11 +228,14 @@ Guacamole.Client = function(tunnel) {
|
||||
currentState = state.currentState;
|
||||
currentTimestamp = state.currentTimestamp;
|
||||
|
||||
// Cancel any pending display operations/frames
|
||||
display.cancel();
|
||||
|
||||
// Dispose of all layers
|
||||
for (key in layers) {
|
||||
index = parseInt(key);
|
||||
if (index > 0)
|
||||
display.dispose(layers[key]);
|
||||
layers[key].dispose();
|
||||
}
|
||||
|
||||
layers = {};
|
||||
|
@@ -201,6 +201,22 @@ Guacamole.Display = function() {
|
||||
*/
|
||||
function Frame(callback, tasks) {
|
||||
|
||||
/**
|
||||
* Cancels rendering of this frame and all associated tasks. The
|
||||
* callback provided at construction time, if any, is not invoked.
|
||||
*/
|
||||
this.cancel = function cancel() {
|
||||
|
||||
callback = null;
|
||||
|
||||
tasks.forEach(function cancelTask(task) {
|
||||
task.cancel();
|
||||
});
|
||||
|
||||
tasks = [];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether this frame is ready to be rendered. This function
|
||||
* returns true if and only if ALL underlying tasks are unblocked.
|
||||
@@ -271,6 +287,16 @@ Guacamole.Display = function() {
|
||||
*/
|
||||
this.blocked = blocked;
|
||||
|
||||
/**
|
||||
* Cancels this task such that it will not run. The task handler
|
||||
* provided at construction time, if any, is not invoked. Calling
|
||||
* execute() after calling this function has no effect.
|
||||
*/
|
||||
this.cancel = function cancel() {
|
||||
task.blocked = false;
|
||||
taskHandler = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unblocks this Task, allowing it to run.
|
||||
*/
|
||||
@@ -417,6 +443,27 @@ Guacamole.Display = function() {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancels rendering of all pending frames and associated rendering
|
||||
* operations. The callbacks provided to outstanding past calls to flush(),
|
||||
* if any, are not invoked.
|
||||
*/
|
||||
this.cancel = function cancel() {
|
||||
|
||||
frames.forEach(function cancelFrame(frame) {
|
||||
frame.cancel();
|
||||
});
|
||||
|
||||
frames = [];
|
||||
|
||||
tasks.forEach(function cancelTask(task) {
|
||||
task.cancel();
|
||||
});
|
||||
|
||||
tasks = [];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the hotspot and image of the mouse cursor displayed within the
|
||||
* Guacamole display.
|
||||
|
@@ -577,11 +577,12 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
||||
* @param {function} callback
|
||||
* The callback to invoke once the seek operation has completed.
|
||||
*
|
||||
* @param {number} [delay=0]
|
||||
* The number of milliseconds that the seek operation should be
|
||||
* scheduled to take.
|
||||
* @param {number} [nextRealTimestamp]
|
||||
* The timestamp of the point in time that the given frame should be
|
||||
* displayed, as would be returned by new Date().getTime(). If omitted,
|
||||
* the frame will be displayed as soon as possible.
|
||||
*/
|
||||
var seekToFrame = function seekToFrame(index, callback, delay) {
|
||||
var seekToFrame = function seekToFrame(index, callback, nextRealTimestamp) {
|
||||
|
||||
// Abort any in-progress seek
|
||||
abortSeek();
|
||||
@@ -591,29 +592,7 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
||||
aborted : false
|
||||
};
|
||||
|
||||
var startIndex;
|
||||
|
||||
// Back up until startIndex represents current state
|
||||
for (startIndex = index; startIndex >= 0; startIndex--) {
|
||||
|
||||
var frame = frames[startIndex];
|
||||
|
||||
// If we've reached the current frame, startIndex represents
|
||||
// current state by definition
|
||||
if (startIndex === currentFrame)
|
||||
break;
|
||||
|
||||
// If frame has associated absolute state, make that frame the
|
||||
// current state
|
||||
if (frame.clientState) {
|
||||
frame.clientState.text().then(function textReady(text) {
|
||||
playbackClient.importState(JSON.parse(text));
|
||||
currentFrame = index;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
var startIndex = index;
|
||||
|
||||
// Replay any applicable incremental frames
|
||||
var continueReplay = function continueReplay() {
|
||||
@@ -629,7 +608,7 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
||||
return;
|
||||
|
||||
// If frames remain, replay the next frame
|
||||
if (!thisSeek.aborted && currentFrame < index)
|
||||
if (currentFrame < index)
|
||||
replayFrame(currentFrame + 1, continueReplay);
|
||||
|
||||
// Otherwise, the seek operation is completed
|
||||
@@ -640,10 +619,38 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
||||
|
||||
// Continue replay after requested delay has elapsed, or
|
||||
// immediately if no delay was requested
|
||||
if (delay)
|
||||
window.setTimeout(continueReplay, delay);
|
||||
else
|
||||
continueReplay();
|
||||
var continueAfterRequiredDelay = function continueAfterRequiredDelay() {
|
||||
var delay = nextRealTimestamp ? Math.max(nextRealTimestamp - new Date().getTime(), 0) : 0;
|
||||
if (delay)
|
||||
window.setTimeout(continueReplay, delay);
|
||||
else
|
||||
continueReplay();
|
||||
};
|
||||
|
||||
// Back up until startIndex represents current state
|
||||
for (; startIndex >= 0; startIndex--) {
|
||||
|
||||
var frame = frames[startIndex];
|
||||
|
||||
// If we've reached the current frame, startIndex represents
|
||||
// current state by definition
|
||||
if (startIndex === currentFrame)
|
||||
break;
|
||||
|
||||
// If frame has associated absolute state, make that frame the
|
||||
// current state
|
||||
if (frame.clientState) {
|
||||
frame.clientState.text().then(function textReady(text) {
|
||||
playbackClient.importState(JSON.parse(text));
|
||||
currentFrame = startIndex;
|
||||
continueAfterRequiredDelay();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
continueAfterRequiredDelay();
|
||||
|
||||
};
|
||||
|
||||
@@ -679,14 +686,10 @@ Guacamole.SessionRecording = function SessionRecording(source) {
|
||||
// frame begins
|
||||
var nextRealTimestamp = next.timestamp - startVideoTimestamp + startRealTimestamp;
|
||||
|
||||
// Calculate the relative delay between the current time and
|
||||
// the next frame start
|
||||
var delay = Math.max(nextRealTimestamp - new Date().getTime(), 0);
|
||||
|
||||
// Advance to next frame after enough time has elapsed
|
||||
seekToFrame(currentFrame + 1, function frameDelayElapsed() {
|
||||
continuePlayback();
|
||||
}, delay);
|
||||
}, nextRealTimestamp);
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user