Skip to content

Commit

Permalink
Feature/152 pause resume (#191)
Browse files Browse the repository at this point in the history
* save data when navigating forwards/backwards by assigning uniquely suffixed frame IDs upon starting each frame.

* implement pause-unpause mixin and adapt video, calibration, change-detection, and images-audio frames to use
  • Loading branch information
Kim Scott committed Dec 2, 2020
1 parent 26093b2 commit 8cf0b02
Show file tree
Hide file tree
Showing 38 changed files with 1,262 additions and 1,444 deletions.
220 changes: 121 additions & 99 deletions app/components/exp-frame-base/component.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions app/components/exp-frame-base/doc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ parameters

There are also some miscellaneous parameters you can set on any frame:

id [String]
Setting the id explicitly allows you to override the frame ID that will be used in data downloads and video filenames.
This may be useful to identify specific frames within randomizers or frame groups.

displayFullscreenOverride [Boolean | ``false``]
Set to `true` to display this frame in fullscreen mode, even if the frame type
is not always displayed fullscreen. (For instance, you might use this to keep
Expand Down
56 changes: 44 additions & 12 deletions app/components/exp-lookit-calibration/component.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import Ember from 'ember';
import layout from './template';
import ExpFrameBaseComponent from '../exp-frame-base/component';
import FullScreen from '../../mixins/full-screen';
import MediaReload from '../../mixins/media-reload';
import VideoRecord from '../../mixins/video-record';
import PauseUnpause from '../../mixins/pause-unpause';
import ExpandAssets from '../../mixins/expand-assets';
import isColor from '../../utils/is-color';
import { audioAssetOptions, imageAssetOptions, videoAssetOptions } from '../../mixins/expand-assets';
Expand Down Expand Up @@ -106,13 +105,11 @@ let {
* @uses Expand-assets
*/

export default ExpFrameBaseComponent.extend(FullScreen, MediaReload, VideoRecord, ExpandAssets, {
export default ExpFrameBaseComponent.extend(VideoRecord, PauseUnpause, ExpandAssets, {
layout: layout,
type: 'exp-lookit-calibration',

displayFullscreen: true, // force fullscreen for all uses of this component
fullScreenElementId: 'experiment-player',
fsButtonID: 'fsButton',

assetsToExpand: {
'audio': [
Expand Down Expand Up @@ -263,6 +260,7 @@ export default ExpFrameBaseComponent.extend(FullScreen, MediaReload, VideoRecord
// to call next AFTER recording is stopped and we don't want this to have
// already been destroyed at that point.
window.clearInterval(this.get('calTimer'));
this.disablePausing();
var _this = this;
if (this.get('doRecording')) {
this.stopRecorder().then(() => {
Expand Down Expand Up @@ -324,18 +322,23 @@ export default ExpFrameBaseComponent.extend(FullScreen, MediaReload, VideoRecord


_this.set('calTimer', window.setTimeout(function() {
_this.set('retryCalibrationAudio', false);
doCalibrationSegments(calList, thisLoc);
if (!_this.get('_isPaused')) {
_this.set('retryCalibrationAudio', false);
_this.enablePausing(true); // On 2nd+ cal, require FS mode
doCalibrationSegments(calList, thisLoc);
}
}, _this.get('calibrationLength')));

}
};

doCalibrationSegments(this.get('calibrationPositions').slice(), '');
if (!this.get('_isPaused')) {
doCalibrationSegments(this.get('calibrationPositions').slice(), '');
}

},

reloadObserver: Ember.observer('reloadingMedia', function() {
console.log('reloadObserver');
if (!this.get('reloadingMedia')) { // done with most recent reload
if (this.get('retryCalibrationAudio')) {
$('#player-calibration-audio')[0].play();
Expand All @@ -344,12 +347,38 @@ export default ExpFrameBaseComponent.extend(FullScreen, MediaReload, VideoRecord
}),

onRecordingStarted() {
this.startCalibration();
if (!this.get('_isPaused')) {
this.enablePausing(true);
this.startCalibration();
}
},

onSessionRecordingStarted() {
$('#waitForVideo').hide();
this.startCalibration();
if (!this.get('_isPaused')) {
this.enablePausing(true);
this.startCalibration();
}
},

onStudyPause() {
window.clearInterval(this.get('calTimer'));
if ($('#player-calibration-audio').length) {
$('#player-calibration-audio')[0].pause();
}
$('.exp-lookit-calibration').hide();
this.set('retryCalibrationAudio', false);
if (this.get('doRecording')) {
let _this = this;
return this.stopRecorder().finally(() => {
_this.set('stoppedRecording', true);
_this.destroyRecorder();
});
} else {
return new Promise((resolve) => {
resolve();
});
}
},

didInsertElement() {
Expand All @@ -368,7 +397,10 @@ export default ExpFrameBaseComponent.extend(FullScreen, MediaReload, VideoRecord
if (this.get('calibrationImage')) {
$('#calibration-image').addClass(this.get('calibrationImageAnimation'));
}
if (!(this.get('doRecording') || this.get('startSessionRecording'))) {
if (!(this.get('doRecording') && !(this.get('startSessionRecording')))) {
if (this.checkFullscreen()) {
this.enablePausing(); // allow pausing right away if not in process of entering FS, otherwise give a moment
}
this.startCalibration();
}
},
Expand Down
78 changes: 59 additions & 19 deletions app/components/exp-lookit-calibration/doc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,45 @@ Recording

Generally you will want to have webcam video of this frame. You can set doRecording to true to
make a video clip just for this frame. Recording will begin at the same time the first calibration
stimulus is shown. Alternately, you can use session-level recording (set
startSessionRecording to true on this or a previous frame). If either type of recording
is starting on this frame, it waits until recording starts to display the first calibration
segment.
stimulus is shown. Alternately, you can use session-level recording by using an exp-lookit-start-recording sometime
before this one.

Fullscreen display
~~~~~~~~~~~~~~~~~~~

This frame is displayed fullscreen, to match the frames you will likely want to compare
looking behavior on. If the participant leaves fullscreen, that will be
recorded as an event, and a large "return to fullscreen" button will be displayed. Don't
use video coding from any intervals where the participant isn't in fullscreen mode - the
recorded as an event, and a large "return to fullscreen" button will be displayed. By default leaving fullscreen
will pause the study. Don't use video coding from any intervals where the participant isn't in fullscreen mode - the
position of the attention-grabbers won't be as expected.

If the frame before this is not fullscreen, that frame
needs to include a manual "next" button so that there's a user interaction
event to trigger fullscreen mode. (Browsers don't allow us to switch to FS
without a user event.)
If the frame before this is not fullscreen, that frame needs to include a manual "next" button so that there's a user
interaction event to trigger fullscreen mode. (Browsers don't allow us to switch to FS without a user event.)

Pausing
~~~~~~~~~~

This frame supports flexible pausing behavior due to the use of :ref:`pause-unpause`. See that link for more detailed
information about how to adjust pausing behavior.

If the user pauses using the ``pauseKey`` (space bar by default), or leaves fullscreen mode, the study will be paused. You can optionally disable
either form of pausing; see :ref:`pause-unpause`. While paused, audio is paused and stimuli are
not displayed, and instead a ``pauseImage`` or looping ``pauseVideo`` and some ``pausedText`` are displayed. Audio can be played upon pausing and
upon unpausing.

Upon unpausing, either this frame will restart (default) or the study can proceed to a frame of your choice (see the
``frameOffsetAfterPause`` parameter in :ref:`pause-unpause`.

If ``doRecording`` is true and you are recording webcam video during this frame, that recording will stop when the study
is paused. If you are doing session-level recording, you can optionally stop that upon pausing; if you do that, you
will probably want to send families back to an exp-lookit-start-recording frame upon unpausing.

Specifying where files are
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Several of the parameters for this frame can be specified either by providing a list of full URLs and file types, or
by providing just a filename that will be interpreted relative to the ``baseDir``. See the :ref:`expand-assets` mixin that this frame uses.
by providing just a filename that will be interpreted relative to the ``baseDir``. See the :ref:`expand-assets`
mixin that this frame uses.

More general functionality
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -60,6 +75,7 @@ Below is information specific to this particular frame. There may also be availa
and data collected that come from the following more general sources:

- the :ref:`base frame<base frame>` (things all frames do)
- :ref:`pause-unpause`
- :ref:`video-record`
- :ref:`expand-assets`

Expand All @@ -82,6 +98,7 @@ This frame will show an image at center, left, and right, along with chimes each
"webm",
"mp4"
],
"calibrationImage": "peekaboo_remy.jpg",
"calibrationLength": 3000,
"calibrationPositions": [
Expand All @@ -90,7 +107,16 @@ This frame will show an image at center, left, and right, along with chimes each
"right"
],
"calibrationAudio": "chimes",
"calibrationImageAnimation": "spin"
"calibrationImageAnimation": "spin",
"doRecording": true,
"showWaitForUploadMessage": true,
"waitForUploadImage": "peekaboo_remy.jpg",
"pauseVideo": "attentiongrabber",
"pauseAudio": "pause",
"unpauseAudio": "return_after_pause",
"frameOffsetAfterPause": 0
}
This frame will show a small video at center, left, and right, along with chimes each time.
Expand All @@ -108,14 +134,24 @@ This frame will show a small video at center, left, and right, along with chimes
"webm",
"mp4"
],
"calibrationLength": 3000,
"calibrationPositions": [
"center",
"left",
"right"
],
"calibrationAudio": "chimes",
"calibrationVideo": "attentiongrabber"
"calibrationVideo": "attentiongrabber",
"doRecording": true,
"showWaitForUploadMessage": true,
"waitForUploadImage": "peekaboo_remy.jpg",
"pauseVideo": "attentiongrabber",
"pauseAudio": "pause",
"unpauseAudio": "return_after_pause",
"frameOffsetAfterPause": 0
}
Parameters
Expand Down Expand Up @@ -246,14 +282,16 @@ rename ``calibrationAudioSources`` and ``calibrationVideoSources``, and remove t
"calibrationLength": 3000, <-- leave this the same
"calibrationAudio": "chimes", <-- just rename from "calibrationAudioSources"
"calibrationVideo": "attentiongrabber" <-- just rename from "calibrationVideoSources"
"calibrationVideo": "attentiongrabber", <-- just rename from "calibrationVideoSources"
"pauseAudio": "pause", <-- leave these the same
"unpauseAudio": "return_after_pause",
"pauseVideo": "attentiongrabber" <-- just rename from "attnSources"
}
If your old frame defined ``calibrationPositions``, you can leave that the same too. Otherwise this will continue to
use the default of ``['center', 'left', 'right', 'center']``.

The one difference is that you will not yet be able to pause the study during the calibration phase.

.. _update_preferential_to_calibration:

Updating an exp-lookit-preferential-looking frame
Expand Down Expand Up @@ -316,7 +354,9 @@ You can change it to an ``exp-lookit-calibration`` frame just by changing the ``
"calibrationLength": 0, <-- leave this the same
"calibrationAudio": "chimes", <-- leave this the same
"calibrationVideo": "attentiongrabber" <-- leave this the same
}
"calibrationVideo": "attentiongrabber", <-- leave this the same
The one difference is that you will not yet be able to pause the study during the calibration phase.
"pauseAudio": "pause", <-- leave these the same
"unpauseAudio": "return_after_pause",
"pauseVideo": "attentiongrabber" <-- copy this from announcementVideo
}
9 changes: 0 additions & 9 deletions app/components/exp-lookit-calibration/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,3 @@
</audio>

</div>

<!--FULLSCREEN BUTTON-->
{{#unless updatedIsFullscreen}}
<div class="row col-md-6 exp-lookit-video">
<button type="button" class="btn btn-success" id="fsButton" {{ action "showFullscreen"}} {{!-- template-lint-disable no-inline-styles --}}>
please return to fullscreen
</button>
</div>
{{/unless}}

0 comments on commit 8cf0b02

Please sign in to comment.