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

tinymce/js/premiumaudiomodule.js   B

Complexity

Total Complexity 36
Complexity/F 1.71

Size

Lines of Code 220
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 220
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_audio 0 31 1
A M.tinymce_recordrtc.capture_audio 0 21 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('audio#player');
29
    playerDOM = document.querySelector('audio#player');
30
    startStopBtn = Y.one('button#start-stop');
31
    uploadBtn = Y.one('button#upload');
32
    recType = 'audio';
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 audio player and upload button are not shown.
52
            player.ancestor().ancestor().addClass('hide');
53
            uploadBtn.ancestor().ancestor().addClass('hide');
54
55
            // Change look of recording button.
56
            if (!recordrtc.oldermoodle) {
57
                startStopBtn.replaceClass('btn-outline-danger', 'btn-danger');
58
            }
59
60
            // Initialize common configurations.
61
            var commonConfig = {
62
                // When the stream is captured from the microphone/webcam.
63
                onMediaCaptured: function(stream) {
64
                    // Make audio stream available at a higher level by making it a property of startStopBtn.
65
                    startStopBtn.stream = stream;
66
67
                    M.tinymce_recordrtc.start_recording(recType, startStopBtn.stream);
68
                },
69
70
                // Revert button to "Record Again" when recording is stopped.
71
                onMediaStopped: function(btnLabel) {
72
                    startStopBtn.set('textContent', btnLabel);
73
                    startStopBtn.set('disabled', false);
74
                    if (!recordrtc.oldermoodle) {
75
                        startStopBtn.replaceClass('btn-danger', 'btn-outline-danger');
76
                    }
77
                },
78
79
                // Handle recording errors.
80
                onMediaCapturingFailed: function(error) {
81
                    var btnLabel = M.util.get_string('recordingfailed', 'tinymce_recordrtc');
82
83
                    // Handle getUserMedia-thrown errors.
84
                    switch (error.name) {
85
                        case 'AbortError':
86
                            Y.use('moodle-core-notification-alert', function() {
87
                                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...
88
                                    title: M.util.get_string('gumabort_title', 'tinymce_recordrtc'),
89
                                    message: M.util.get_string('gumabort', 'tinymce_recordrtc')
90
                                });
91
                            });
92
93
                            // Proceed to treat as a stopped recording.
94
                            commonConfig.onMediaStopped(btnLabel);
95
                            break;
96
                        case 'NotAllowedError':
97
                            Y.use('moodle-core-notification-alert', function() {
98
                                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...
99
                                    title: M.util.get_string('gumnotallowed_title', 'tinymce_recordrtc'),
100
                                    message: M.util.get_string('gumnotallowed', 'tinymce_recordrtc')
101
                                });
102
                            });
103
104
                            // Proceed to treat as a stopped recording.
105
                            commonConfig.onMediaStopped(btnLabel);
106
                            break;
107
                        case 'NotFoundError':
108
                            Y.use('moodle-core-notification-alert', function() {
109
                                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...
110
                                    title: M.util.get_string('gumnotfound_title', 'tinymce_recordrtc'),
111
                                    message: M.util.get_string('gumnotfound', 'tinymce_recordrtc')
112
                                });
113
                            });
114
115
                            // Proceed to treat as a stopped recording.
116
                            commonConfig.onMediaStopped(btnLabel);
117
                            break;
118
                        case 'NotReadableError':
119
                            Y.use('moodle-core-notification-alert', function() {
120
                                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...
121
                                    title: M.util.get_string('gumnotreadable_title', 'tinymce_recordrtc'),
122
                                    message: M.util.get_string('gumnotreadable', 'tinymce_recordrtc')
123
                                });
124
                            });
125
126
                            // Proceed to treat as a stopped recording.
127
                            commonConfig.onMediaStopped(btnLabel);
128
                            break;
129
                        case 'OverConstrainedError':
130
                            Y.use('moodle-core-notification-alert', function() {
131
                                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...
132
                                    title: M.util.get_string('gumoverconstrained_title', 'tinymce_recordrtc'),
133
                                    message: M.util.get_string('gumoverconstrained', 'tinymce_recordrtc')
134
                                });
135
                            });
136
137
                            // Proceed to treat as a stopped recording.
138
                            commonConfig.onMediaStopped(btnLabel);
139
                            break;
140
                        case 'SecurityError':
141
                            Y.use('moodle-core-notification-alert', function() {
142
                                var dialogue = new M.core.alert({
143
                                    title: M.util.get_string('gumsecurity_title', 'tinymce_recordrtc'),
144
                                    message: M.util.get_string('gumsecurity', 'tinymce_recordrtc')
145
                                });
146
147
                                dialogue.after('complete', function() {
148
                                    tinyMCEPopup.close();
149
                                });
150
                            });
151
152
                            break;
153
                        case 'TypeError':
154
                            Y.use('moodle-core-notification-alert', function() {
155
                                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...
156
                                    title: M.util.get_string('gumtype_title', 'tinymce_recordrtc'),
157
                                    message: M.util.get_string('gumtype', 'tinymce_recordrtc')
158
                                });
159
                            });
160
161
                            // Proceed to treat as a stopped recording.
162
                            commonConfig.onMediaStopped(btnLabel);
163
                            break;
164
                        default:
165
                            break;
166
                    }
167
                }
168
            };
169
170
            // Capture audio stream from microphone.
171
            M.tinymce_recordrtc.capture_audio(commonConfig);
172
        } else { // If button is displaying "Stop Recording".
173
            // Disable "Record Again" button for 1s to allow background processing (closing streams).
174
            window.setTimeout(function() {
175
                startStopBtn.set('disabled', false);
176
            }, 1000);
177
178
            // Stop recording.
179
            M.tinymce_recordrtc.stop_recording_audio(startStopBtn.stream);
180
181
            // Change button to offer to record again.
182
            startStopBtn.set('textContent', M.util.get_string('recordagain', 'tinymce_recordrtc'));
183
            if (!recordrtc.oldermoodle) {
184
                startStopBtn.replaceClass('btn-danger', 'btn-outline-danger');
185
            }
186
        }
187
    });
188
};
189
190
// Setup to get audio stream from microphone.
191
M.tinymce_recordrtc.capture_audio = function(config) {
192
    M.tinymce_recordrtc.capture_user_media(
193
        // Media constraints.
194
        {
195
            audio: true
196
        },
197
198
        // Success callback.
199
        function(audioStream) {
200
            // Set audio player source to microphone stream.
201
            playerDOM.srcObject = audioStream;
202
203
            config.onMediaCaptured(audioStream);
204
        },
205
206
        // Error callback.
207
        function(error) {
208
            config.onMediaCapturingFailed(error);
209
        }
210
    );
211
};
212
213
M.tinymce_recordrtc.stop_recording_audio = function(stream) {
214
    // Stop recording microphone stream.
215
    mediaRecorder.stop();
216
217
    // Stop each individual MediaTrack.
218
    stream.getTracks().forEach(function(track) {
219
        track.stop();
220
    });
221
222
    // Show upload button.
223
    uploadBtn.ancestor().ancestor().removeClass('hide');
224
    uploadBtn.set('textContent', M.util.get_string('attachrecording', 'tinymce_recordrtc'));
225
    uploadBtn.set('disabled', false);
226
227
    // Handle when upload button is clicked.
228
    uploadBtn.on('click', function() {
229
        // Trigger error if no recording has been made.
230
        if (!player.get('src')) {
231
            Y.use('moodle-core-notification-alert', function() {
232
                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...
233
                    title: M.util.get_string('norecordingfound_title', 'tinymce_recordrtc'),
234
                    message: M.util.get_string('norecordingfound', 'tinymce_recordrtc')
235
                });
236
            });
237
        } else {
238
            uploadBtn.set('disabled', true);
239
240
            M.tinymce_recordrtc.insert_annotation(recType, player.get('src'));
241
        }
242
    });
243
};
244