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

tinymce/js/premiumcommonmodule.js   B

Complexity

Total Complexity 37
Complexity/F 1.76

Size

Lines of Code 225
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 352
dl 0
loc 225
rs 8.6
wmc 37
mnd 4
bc 38
fnc 21
bpm 1.8095
cpm 1.7619
noi 2

11 Functions

Rating   Name   Duplication   Size   Complexity  
A premiumcommonmodule.js ➔ d 0 3 1
A M.tinymce_recordrtc.check_secure 0 8 2
A M.tinymce_recordrtc.check_browser 0 7 2
B 0 21 5
A M.tinymce_recordrtc.create_annotation 0 12 2
A M.tinymce_recordrtc.handle_data_available 0 3 1
A M.tinymce_recordrtc.handle_stop 0 12 1
C M.tinymce_recordrtc.start_recording 0 70 9
B M.tinymce_recordrtc.init_connection 0 42 1
A M.tinymce_recordrtc.capture_user_media 0 3 1
A M.tinymce_recordrtc.insert_annotation 0 12 2
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: recordrtc */
11
/** global: tinyMCEPopup */
12
13
M.tinymce_recordrtc = M.tinymce_recordrtc || {};
14
15
// Extract plugin settings to params hash.
16
(function() {
17
    var params = {};
18
    var r = /([^&=]+)=?([^&]*)/g;
19
20
    var d = function(s) {
21
        return window.decodeURIComponent(s.replace(/\+/g, ' '));
22
    };
23
24
    var search = window.location.search;
25
    var match = r.exec(search.substring(1));
26
    while (match) {
27
        params[d(match[1])] = d(match[2]);
28
29
        if (d(match[2]) === 'true' || d(match[2]) === 'false') {
30
            params[d(match[1])] = d(match[2]) === 'true' ? true : false;
31
        }
32
        match = r.exec(search.substring(1));
33
    }
34
35
    window.params = params;
36
})();
37
38
// Initialize some variables.
39
var alertWarning = null;
40
var alertDanger = null;
41
var mediaRecorder = null;
42
var player = null;
43
var playerDOM = null;
44
var recType = null;
45
var startStopBtn = null;
46
var uploadBtn = null;
47
var socket = null;
48
49
// Notify and redirect user if plugin is used from insecure location.
50
M.tinymce_recordrtc.check_secure = function() {
51
    var isSecureOrigin = (window.location.protocol === 'https:') ||
52
                         (window.location.host.indexOf('localhost') !== -1);
53
54
    if (!isSecureOrigin) {
55
        alertDanger.ancestor().ancestor().removeClass('hide');
56
    }
57
};
58
59
// Display "consider switching browsers" message if not using:
60
// - Firefox 29+;
61
// - Chrome 49+;
62
// - Opera 36+.
63
M.tinymce_recordrtc.check_browser = function() {
64
    if (!((window.bowser.firefox && window.bowser.version >= 29) ||
65
          (window.bowser.chrome && window.bowser.version >= 49) ||
66
          (window.bowser.opera && window.bowser.version >= 36))) {
67
        alertWarning.ancestor().ancestor().removeClass('hide');
68
    }
69
};
70
71
// Attempt to connect to the premium server via Socket.io.
72
M.tinymce_recordrtc.init_connection = function() {
73
    socket.connect();
74
75
    socket.on('connect', function() {
76
        // Send key and secret from Moodle settings
77
        socket.emit('authentication', {
78
            key: window.params.apikey,
79
            secret: window.params.apisecret
80
        });
81
82
        socket.on('authenticated', function() {
83
            // Continue as normal.
84
        });
85
86
        socket.on('unauthorized', function(err) {
0 ignored issues
show
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
87
            Y.use('moodle-core-notification-alert', function() {
88
                var dialogue = new M.core.alert({
89
                    title: M.util.get_string('notpremium_title', 'tinymce_recordrtc'),
90
                    message: M.util.get_string('notpremium', 'tinymce_recordrtc')
91
                });
92
93
                dialogue.after('complete', function() {
94
                    tinyMCEPopup.close();
95
                });
96
            });
97
        });
98
    });
99
100
    socket.on('connect_error', function() {
101
        socket.disconnect();
102
        Y.use('moodle-core-notification-alert', function() {
103
            var dialogue = new M.core.alert({
104
                title: M.util.get_string('servernotfound_title', 'tinymce_recordrtc'),
105
                message: M.util.get_string('servernotfound', 'tinymce_recordrtc')
106
            });
107
108
            dialogue.after('complete', function() {
109
                tinyMCEPopup.close();
110
            });
111
        });
112
    });
113
};
114
115
// Capture webcam/microphone stream.
116
M.tinymce_recordrtc.capture_user_media = function(mediaConstraints, successCallback, errorCallback) {
117
    window.navigator.mediaDevices.getUserMedia(mediaConstraints).then(successCallback).catch(errorCallback);
118
};
119
120
// Push chunks of audio/video to server when made available.
121
M.tinymce_recordrtc.handle_data_available = function(event) {
122
    socket.emit('data available', event.data);
123
};
124
125
// Stop recording and handle end.
126
M.tinymce_recordrtc.handle_stop = function(event) {
0 ignored issues
show
Unused Code introduced by
The parameter event is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
127
    startStopBtn.set('textContent', 'Start Recording');
128
129
    socket.emit('recording stopped');
130
131
    socket.on('save finished', function(path) {
132
        player.set('src', path);
133
        player.set('controls', true);
134
        player.set('muted', false);
135
        player.ancestor().ancestor().removeClass('hide'); // AUDIO ONLY
136
    });
137
};
138
139
// Get everything set up to start recording.
140
M.tinymce_recordrtc.start_recording = function(type, stream) {
141
    // Generate filename with random ID and file extension.
142
    var fileName = (Math.random() * 1000).toString().replace('.', '');
143
    if (type === 'audio') {
144
        fileName += '-audio.ogg';
145
    } else {
146
        fileName += '-video.webm';
147
    }
148
149
    var data = {
150
        contextid: window.params.contextid,
151
        type: recType,
152
        itemid: window.params.sesskey, // Use session key as item ID.
153
        filename: fileName
154
    };
155
    socket.emit('recording started', data);
156
157
    // The options for the recording codecs and bitrates.
158
    var options = null;
159
    if (type === 'audio') {
160
        if (window.MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) {
161
            options = {
162
                audioBitsPerSecond: window.params.audiobitrate,
163
                mimeType: 'audio/webm;codecs=opus'
164
            };
165
        } else if (window.MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')) {
166
            options = {
167
                audioBitsPerSecond: window.params.audiobitrate,
168
                mimeType: 'audio/ogg;codecs=opus'
169
            };
170
        }
171
    } else {
172
        if (window.MediaRecorder.isTypeSupported('video/webm;codecs=vp9,opus')) {
173
            options = {
174
                audioBitsPerSecond: window.params.audiobitrate,
175
                videoBitsPerSecond: window.params.videobitrate,
176
                mimeType: 'video/webm;codecs=vp9,opus'
177
            };
178
        } else if (window.MediaRecorder.isTypeSupported('video/webm;codecs=h264,opus')) {
179
            options = {
180
                audioBitsPerSecond: window.params.audiobitrate,
181
                videoBitsPerSecond: window.params.videobitrate,
182
                mimeType: 'video/webm;codecs=h264,opus'
183
            };
184
        } else if (window.MediaRecorder.isTypeSupported('video/webm;codecs=vp8,opus')) {
185
            options = {
186
                audioBitsPerSecond: window.params.audiobitrate,
187
                videoBitsPerSecond: window.params.videobitrate,
188
                mimeType: 'video/webm;codecs=vp8,opus'
189
            };
190
        }
191
    }
192
193
    // If none of the options above are supported, fall back on browser defaults.
194
    mediaRecorder = options ? new window.MediaRecorder(stream, options)
195
                            : new window.MediaRecorder(stream);
196
197
    socket.on('recording started', function() {
198
        // Make button clickable again, to allow stopping recording.
199
        startStopBtn.set('textContent', M.util.get_string('stoprecording', 'tinymce_recordrtc'));
200
        startStopBtn.set('disabled', false);
201
202
        // Mute audio, distracting while recording.
203
        player.set('muted', true);
204
205
        mediaRecorder.ondataavailable = M.tinymce_recordrtc.handle_data_available;
206
        mediaRecorder.onstop = M.tinymce_recordrtc.handle_stop;
207
        mediaRecorder.start(1500); // Capture in 1.5s chunks.
208
    });
209
};
210
211
// Generates link to recorded annotation to be inserted.
212
M.tinymce_recordrtc.create_annotation = function(type, recording_url) {
213
    var linkText = window.prompt(M.util.get_string('annotationprompt', 'tinymce_recordrtc'),
214
                                 M.util.get_string('annotation:' + type, 'tinymce_recordrtc'));
215
216
    // Return HTML for annotation link, if user did not press "Cancel".
217
    if (!linkText) {
218
        return undefined;
219
    } else {
220
        var annotation = '<div><a target="_blank" href="' + recording_url + '">' + linkText + '</a></div>';
221
        return annotation;
222
    }
223
};
224
225
// Inserts link to annotation in editor text area.
226
M.tinymce_recordrtc.insert_annotation = function(type, recording_url) {
227
    var annotation = M.tinymce_recordrtc.create_annotation(type, recording_url);
228
229
    // Insert annotation link.
230
    // If user pressed "Cancel", just go back to main recording screen.
231
    if (!annotation) {
232
        uploadBtn.set('textContent', M.util.get_string('attachrecording', 'tinymce_recordrtc'));
233
    } else {
234
        tinyMCEPopup.editor.execCommand('mceInsertContent', false, annotation);
235
        tinyMCEPopup.close();
236
    }
237
};
238