diff --git a/.changeset/cool-creatures-crawl.md b/.changeset/cool-creatures-crawl.md new file mode 100644 index 00000000..21d12de1 --- /dev/null +++ b/.changeset/cool-creatures-crawl.md @@ -0,0 +1,5 @@ +--- +"@jspsych/plugin-html-audio-response": patch +--- + +added error handling if a microphone is not detected on trial start \ No newline at end of file diff --git a/.changeset/fluffy-books-act.md b/.changeset/fluffy-books-act.md new file mode 100644 index 00000000..38a4bfbc --- /dev/null +++ b/.changeset/fluffy-books-act.md @@ -0,0 +1,5 @@ +--- +"@jspsych/plugin-html-video-response": patch +--- + +added error handling if a camera is not detected on trial start diff --git a/.changeset/hungry-elephants-jam.md b/.changeset/hungry-elephants-jam.md new file mode 100644 index 00000000..85a40ceb --- /dev/null +++ b/.changeset/hungry-elephants-jam.md @@ -0,0 +1,5 @@ +--- +"@jspsych/plugin-initialize-microphone": minor +--- + +added custom rejection message upon microphone permission denial diff --git a/.changeset/poor-cherries-pay.md b/.changeset/poor-cherries-pay.md new file mode 100644 index 00000000..65ee91ef --- /dev/null +++ b/.changeset/poor-cherries-pay.md @@ -0,0 +1,5 @@ +--- +"@jspsych/plugin-initialize-camera": minor +--- + +added custom rejection message upon camera permission denial diff --git a/docs/plugins/initialize-camera.md b/docs/plugins/initialize-camera.md index 69ce273d..612c09c2 100644 --- a/docs/plugins/initialize-camera.md +++ b/docs/plugins/initialize-camera.md @@ -23,6 +23,7 @@ include_audio | bool | false | Set to `true` to include an audio track in the re width | int | null | Request a specific width for the recording. This is not a guarantee that this width will be used, as it depends on the capabilities of the participant's device. Learn more about `MediaRecorder` constraints [here](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints#requesting_a_specific_value_for_a_setting). height | int | null | Request a specific height for the recording. This is not a guarantee that this height will be used, as it depends on the capabilities of the participant's device. Learn more about `MediaRecorder` constraints [here](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints#requesting_a_specific_value_for_a_setting). mime_type | string | null | Set this to use a specific [MIME type](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/mimeType) for the recording. Set the entire type, e.g., `'video/mp4; codecs="avc1.424028, mp4a.40.2"'`. +rejection_message | html string | `

You must allow access to a camera in order to participate in the experiment.

` | The message to display if the user rejects access to the camera. ## Data Generated diff --git a/docs/plugins/initialize-microphone.md b/docs/plugins/initialize-microphone.md index 6cd185f4..5f000962 100644 --- a/docs/plugins/initialize-microphone.md +++ b/docs/plugins/initialize-microphone.md @@ -19,6 +19,7 @@ Parameter | Type | Default Value | Description ----------|------|---------------|------------ device_select_message | html string | `

Please select the microphone you would like to use.

` | The message to display when the user is presented with a dropdown list of available devices. button_label | string | 'Use this microphone.' | The label for the select button. +rejection_message | html string | `

You must allow access to a microphone in order to participate in the experiment.

` | The message to display if the user rejects access to the microphone. ## Data Generated diff --git a/examples/jspsych-initialize-camera.html b/examples/jspsych-initialize-camera.html index face9569..86b7b883 100644 --- a/examples/jspsych-initialize-camera.html +++ b/examples/jspsych-initialize-camera.html @@ -1,20 +1,28 @@ - - - - - - - + + + + + + - \ No newline at end of file + jsPsych.run([init_camera, vr]); + + diff --git a/packages/plugin-html-audio-response/src/index.ts b/packages/plugin-html-audio-response/src/index.ts index 5071985e..e8821f1a 100644 --- a/packages/plugin-html-audio-response/src/index.ts +++ b/packages/plugin-html-audio-response/src/index.ts @@ -122,11 +122,15 @@ class HtmlAudioResponsePlugin implements JsPsychPlugin { private data_available_handler; private recorded_data_chunks = []; - constructor(private jsPsych: JsPsych) {} + constructor(private jsPsych: JsPsych) { } trial(display_element: HTMLElement, trial: TrialType) { this.recorder = this.jsPsych.pluginAPI.getMicrophoneRecorder(); + if (this.recorder === null) { + throw new Error('Error in html-audio-response plugin. A microphone has not been found, have you ran the initialize-microphone plugin?'); + } + this.setupRecordingEvents(display_element, trial); this.startRecording(); diff --git a/packages/plugin-html-video-response/src/index.ts b/packages/plugin-html-video-response/src/index.ts index 5764eaad..8da2f75d 100644 --- a/packages/plugin-html-video-response/src/index.ts +++ b/packages/plugin-html-video-response/src/index.ts @@ -131,11 +131,15 @@ class HtmlVideoResponsePlugin implements JsPsychPlugin { private data_available_handler; private recorded_data_chunks = []; - constructor(private jsPsych: JsPsych) {} + constructor(private jsPsych: JsPsych) { } trial(display_element: HTMLElement, trial: TrialType) { this.recorder = this.jsPsych.pluginAPI.getCameraRecorder(); + if (this.recorder === null) { + throw new Error("Error in html-video-response plugin. A camera has not been found, have you ran the initialize-camera plugin?"); + } + this.setupRecordingEvents(display_element, trial); this.startRecording(); diff --git a/packages/plugin-initialize-camera/src/index.ts b/packages/plugin-initialize-camera/src/index.ts index 18a4354c..ddea3bdb 100644 --- a/packages/plugin-initialize-camera/src/index.ts +++ b/packages/plugin-initialize-camera/src/index.ts @@ -41,6 +41,11 @@ const info = { type: ParameterType.STRING, default: null, }, + /** The message to display when permission to access the camera is rejected. */ + rejection_message: { + type: ParameterType.HTML_STRING, + default: `

You must allow access to a camera in order to participate in the experiment.

`, + }, }, data: { /** The [device ID](https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/deviceId) of the selected camera. */ @@ -74,7 +79,7 @@ type Info = typeof info; class InitializeCameraPlugin implements JsPsychPlugin { static info = info; - constructor(private jsPsych: JsPsych) {} + constructor(private jsPsych: JsPsych) { } trial(display_element: HTMLElement, trial: TrialType) { this.run_trial(display_element, trial).then((id) => { @@ -85,7 +90,12 @@ class InitializeCameraPlugin implements JsPsychPlugin { } private async run_trial(display_element: HTMLElement, trial: TrialType) { - await this.askForPermission(trial); + try { + await this.askForPermission(trial); + } catch (e) { + this.rejectPermission(trial); + return null; + } this.showCameraSelection(display_element, trial); @@ -171,6 +181,12 @@ class InitializeCameraPlugin implements JsPsychPlugin { }); }); } + + private rejectPermission(trial: TrialType) { + this.jsPsych.getDisplayElement().innerHTML = ""; + + this.jsPsych.abortExperiment(trial.rejection_message, {}); + } } export default InitializeCameraPlugin; diff --git a/packages/plugin-initialize-microphone/src/index.ts b/packages/plugin-initialize-microphone/src/index.ts index c0eb4ba9..2c546b5b 100644 --- a/packages/plugin-initialize-microphone/src/index.ts +++ b/packages/plugin-initialize-microphone/src/index.ts @@ -16,6 +16,11 @@ const info = { type: ParameterType.STRING, default: "Use this microphone", }, + /** The message to display when permission to access the microphone is rejected. */ + rejection_message: { + type: ParameterType.HTML_STRING, + default: `

You must allow access to a microphone in order to participate in the experiment.

`, + }, }, data: { /** The [device ID](https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/deviceId) of the selected microphone. */ @@ -60,7 +65,12 @@ class InitializeMicrophonePlugin implements JsPsychPlugin { } private async run_trial(display_element: HTMLElement, trial: TrialType) { - await this.askForPermission(); + try { + await this.askForPermission(); + } catch(e) { + this.rejectPermission(trial); + return null; + } this.showMicrophoneSelection(display_element, trial); @@ -126,6 +136,12 @@ class InitializeMicrophonePlugin implements JsPsychPlugin { }); }); } + + private rejectPermission(trial: TrialType) { + this.jsPsych.getDisplayElement().innerHTML = ""; + + this.jsPsych.abortExperiment(trial.rejection_message, {}); + } } export default InitializeMicrophonePlugin;