Completed
Push — master ( 34c416...93164a )
by Jacob
02:03
created

tinymce/js/premiumvideomodule.js   B

Complexity

Total Complexity 36
Complexity/F 1.71

Size

Lines of Code 228
Function Count 21

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 0
c 1
b 0
f 0
nc 3
dl 0
loc 228
rs 8.8
wmc 36
mnd 2
bc 28
fnc 21
bpm 1.3333
cpm 1.7142
noi 7

2 Functions

Rating   Name   Duplication   Size   Complexity  
B M.tinymce_recordrtc.stop_recording_video 0 31 1
B M.tinymce_recordrtc.capture_audio_video 0 26 1
1
// TinyMCE recordrtc library functions.
2
// @package    tinymce_recordrtc.
3
// @author     Jesus Federico  (jesus [at] blindsidenetworks [dt] com).
4
// @copyright  2016 to present, Blindside Networks Inc.
5
// @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
6
7
// Scrutinizer CI directives.
8
/** global: M */
9
/** global: Y */
10
/** global: tinyMCEPopup */
11
/** global: recordrtc */
12
/** global: alertWarning */
13
/** global: alertDanger */
14
/** global: maxUploadSize */
15
/** global: mediaRecorder */
16
/** global: player */
17
/** global: playerDOM */
18
/** global: recType */
19
/** global: startStopBtn */
20
/** global: uploadBtn */
21
/** global: socket */
22
23
// This function is initialized from PHP.
24
M.tinymce_recordrtc.view_init = function() {
25
    // Assignment of global variables.
26
    alertWarning = Y.one('div#alert-warning');
27
    alertDanger = Y.one('div#alert-danger');
28
    player = Y.one('video#player');
29
    playerDOM = document.querySelector('video#player');
30
    startStopBtn = Y.one('button#start-stop');
31
    uploadBtn = Y.one('button#upload');
32
    recType = 'video';
33
    socket = window.io(window.params.serverurl);
34
35
    // Show alert and redirect user if connection is not secure.
36
    M.tinymce_recordrtc.check_secure();
37
    // Show alert if using non-ideal browser.
38
    M.tinymce_recordrtc.check_browser();
39
40
    // Connect to premium recording server.
41
    M.tinymce_recordrtc.init_connection();
42
43
    // Run when user clicks on "record" button.
44
    startStopBtn.on('click', function() {
45
        startStopBtn.set('disabled', true);
46
47
        // If button is displaying "Start Recording" or "Record Again".
48
        if ((startStopBtn.get('textContent') === M.util.get_string('startrecording', 'tinymce_recordrtc')) ||
49
            (startStopBtn.get('textContent') === M.util.get_string('recordagain', 'tinymce_recordrtc')) ||
50
            (startStopBtn.get('textContent') === M.util.get_string('recordingfailed', 'tinymce_recordrtc'))) {
51
            // Make sure the upload button is not shown.
52
            uploadBtn.ancestor().ancestor().addClass('hide');
53
54
            // Change look of recording button.
55
            if (!recordrtc.oldermoodle) {
56
                startStopBtn.replaceClass('btn-outline-danger', 'btn-danger');
57
            }
58
59
            // Initialize common configurations.
60
            var commonConfig = {
61
                // When the stream is captured from the microphone/webcam.
62
                onMediaCaptured: function(stream) {
63
                    // Make video stream available at a higher level by making it a property of startStopBtn.
64
                    startStopBtn.stream = stream;
65
66
                    M.tinymce_recordrtc.start_recording(recType, startStopBtn.stream);
67
                },
68
69
                // Revert button to "Record Again" when recording is stopped.
70
                onMediaStopped: function(btnLabel) {
71
                    startStopBtn.set('textContent', btnLabel);
72
                    startStopBtn.set('disabled', false);
73
                    if (!recordrtc.oldermoodle) {
74
                        startStopBtn.replaceClass('btn-danger', 'btn-outline-danger');
75
                    }
76
                },
77
78
                // Handle recording errors.
79
                onMediaCapturingFailed: function(error) {
80
                    var btnLabel = M.util.get_string('recordingfailed', 'tinymce_recordrtc');
81
82
                    // Handle getUserMedia-thrown errors.
83
                    switch (error.name) {
84
                        case 'AbortError':
85
                            Y.use('moodle-core-notification-alert', function() {
86
                                var dialogue = new M.core.alert({
0 ignored issues
show
Unused Code introduced by
The variable dialogue seems to be never used. Consider removing it.
Loading history...
87
                                    title: M.util.get_string('gumabort_title', 'tinymce_recordrtc'),
88
                                    message: M.util.get_string('gumabort', 'tinymce_recordrtc')
89
                                });
90
                            });
91
92
                            // Proceed to treat as a stopped recording.
93
                            commonConfig.onMediaStopped(btnLabel);
94
                            break;
95
                        case 'NotAllowedError':
96
                            Y.use('moodle-core-notification-alert', function() {
97
                                var dialogue = new M.core.alert({
0 ignored issues
show
Unused Code introduced by
The variable dialogue seems to be never used. Consider removing it.
Loading history...
98
                                    title: M.util.get_string('gumnotallowed_title', 'tinymce_recordrtc'),
99
                                    message: M.util.get_string('gumnotallowed', 'tinymce_recordrtc')
100
                                });
101
                            });
102
103
                            // Proceed to treat as a stopped recording.
104
                            commonConfig.onMediaStopped(btnLabel);
105
                            break;
106
                        case 'NotFoundError':
107
                            Y.use('moodle-core-notification-alert', function() {
108
                                var dialogue = new M.core.alert({
0 ignored issues
show
Unused Code introduced by
The variable dialogue seems to be never used. Consider removing it.
Loading history...
109
                                    title: M.util.get_string('gumnotfound_title', 'tinymce_recordrtc'),
110
                                    message: M.util.get_string('gumnotfound', 'tinymce_recordrtc')
111
                                });
112
                            });
113
114
                            // Proceed to treat as a stopped recording.
115
                            commonConfig.onMediaStopped(btnLabel);
116
                            break;
117
                        case 'NotReadableError':
118
                            Y.use('moodle-core-notification-alert', function() {
119
                                var dialogue = new M.core.alert({
0 ignored issues
show
Unused Code introduced by
The variable dialogue seems to be never used. Consider removing it.
Loading history...
120
                                    title: M.util.get_string('gumnotreadable_title', 'tinymce_recordrtc'),
121
                                    message: M.util.get_string('gumnotreadable', 'tinymce_recordrtc')
122
                                });
123
                            });
124
125
                            // Proceed to treat as a stopped recording.
126
                            commonConfig.onMediaStopped(btnLabel);
127
                            break;
128
                        case 'OverConstrainedError':
129
                            Y.use('moodle-core-notification-alert', function() {
130
                                var dialogue = new M.core.alert({
0 ignored issues
show
Unused Code introduced by
The variable dialogue seems to be never used. Consider removing it.
Loading history...
131
                                    title: M.util.get_string('gumoverconstrained_title', 'tinymce_recordrtc'),
132
                                    message: M.util.get_string('gumoverconstrained', 'tinymce_recordrtc')
133
                                });
134
                            });
135
136
                            // Proceed to treat as a stopped recording.
137
                            commonConfig.onMediaStopped(btnLabel);
138
                            break;
139
                        case 'SecurityError':
140
                            Y.use('moodle-core-notification-alert', function() {
141
                                var dialogue = new M.core.alert({
142
                                    title: M.util.get_string('gumsecurity_title', 'tinymce_recordrtc'),
143
                                    message: M.util.get_string('gumsecurity', 'tinymce_recordrtc')
144
                                });
145
146
                                dialogue.after('complete', function() {
147
                                    tinyMCEPopup.close();
148
                                });
149
                            });
150
151
                            break;
152
                        case 'TypeError':
153
                            Y.use('moodle-core-notification-alert', function() {
154
                                var dialogue = new M.core.alert({
0 ignored issues
show
Unused Code introduced by
The variable dialogue seems to be never used. Consider removing it.
Loading history...
155
                                    title: M.util.get_string('gumtype_title', 'tinymce_recordrtc'),
156
                                    message: M.util.get_string('gumtype', 'tinymce_recordrtc')
157
                                });
158
                            });
159
160
                            // Proceed to treat as a stopped recording.
161
                            commonConfig.onMediaStopped(btnLabel);
162
                            break;
163
                        default:
164
                            break;
165
                    }
166
                }
167
            };
168
169
            // Show video tag without controls to view webcam stream.
170
            player.ancestor().ancestor().removeClass('hide');
171
            player.set('controls', false);
172
173
            // Capture audio+video stream from webcam/microphone.
174
            M.tinymce_recordrtc.capture_audio_video(commonConfig);
175
        } else { // If button is displaying "Stop Recording".
176
            // Disable "Record Again" button for 1s to allow background processing (closing streams).
177
            window.setTimeout(function() {
178
                startStopBtn.set('disabled', false);
179
            }, 1000);
180
181
            // Stop recording.
182
            M.tinymce_recordrtc.stop_recording_video(startStopBtn.stream);
183
184
            // Change button to offer to record again.
185
            startStopBtn.set('textContent', M.util.get_string('recordagain', 'tinymce_recordrtc'));
186
            if (!recordrtc.oldermoodle) {
187
                startStopBtn.replaceClass('btn-danger', 'btn-outline-danger');
188
            }
189
        }
190
    });
191
};
192
193
// Setup to get audio+video stream from microphone/webcam.
194
M.tinymce_recordrtc.capture_audio_video = function(config) {
195
    M.tinymce_recordrtc.capture_user_media(
196
        // Media constraints.
197
        {
198
            audio: true,
199
            video: {
200
                width: {ideal: 640},
201
                height: {ideal: 480}
202
            }
203
        },
204
205
        // Success callback.
206
        function(audioVideoStream) {
207
            // Set video player source to microphone+webcam stream, and play it back as it's recording.
208
            playerDOM.srcObject = audioVideoStream;
209
            playerDOM.play();
210
211
            config.onMediaCaptured(audioVideoStream);
212
        },
213
214
        // Error callback.
215
        function(error) {
216
            config.onMediaCapturingFailed(error);
217
        }
218
    );
219
};
220
221
M.tinymce_recordrtc.stop_recording_video = function(stream) {
222
    // Stop recording microphone stream.
223
    mediaRecorder.stop();
224
225
    // Stop each individual MediaTrack.
226
    stream.getTracks().forEach(function(track) {
227
        track.stop();
228
    });
229
230
    // Show upload button.
231
    uploadBtn.ancestor().ancestor().removeClass('hide');
232
    uploadBtn.set('textContent', M.util.get_string('attachrecording', 'tinymce_recordrtc'));
233
    uploadBtn.set('disabled', false);
234
235
    // Handle when upload button is clicked.
236
    uploadBtn.on('click', function() {
237
        // Trigger error if no recording has been made.
238
        if (!player.get('src')) {
239
            Y.use('moodle-core-notification-alert', function() {
240
                var dialogue = new M.core.alert({
0 ignored issues
show
Unused Code introduced by
The variable dialogue seems to be never used. Consider removing it.
Loading history...
241
                    title: M.util.get_string('norecordingfound_title', 'tinymce_recordrtc'),
242
                    message: M.util.get_string('norecordingfound', 'tinymce_recordrtc')
243
                });
244
            });
245
        } else {
246
            uploadBtn.set('disabled', true);
247
248
            M.tinymce_recordrtc.insert_annotation(recType, player.get('src'));
249
        }
250
    });
251
};
252