Completed
Push — master ( 46959c...a001d3 )
by Jacob
01:35
created

M.tinymce_recordrtc.pad   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
rs 9.6666
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
11
M.tinymce_recordrtc = M.tinymce_recordrtc || {};
12
13
// Initialize some variables.
14
var blobSize = null;
15
var chunks = null;
16
var countdownSeconds = null;
17
var countdownTicker = null;
18
var maxUploadSize = null;
19
20
// Add chunks of audio/video to array when made available.
21
M.tinymce_recordrtc.handle_data_available = function(event) {
22
    // Size of all recorded data so far.
23
    blobSize += event.data.size;
24
25
    // Push recording slice to array.
26
    // If total size of recording so far exceeds max upload limit, stop recording.
27
    // An extra condition exists to avoid displaying alert twice.
28
    if ((blobSize >= maxUploadSize) && (!window.localStorage.getItem('alerted'))) {
29
        window.localStorage.setItem('alerted', 'true');
30
31
        Y.use('node-event-simulate', function() {
32
            startStopBtn.simulate('click');
0 ignored issues
show
Bug introduced by
The variable startStopBtn seems to be never declared. If this is a global, consider adding a /** global: startStopBtn */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
33
        });
34
        M.tinymce_recordrtc.show_alert('nearingmaxsize');
35
    } else if ((blobSize >= maxUploadSize) && (window.localStorage.getItem('alerted') === 'true')) {
36
        window.localStorage.removeItem('alerted');
37
    } else {
38
        chunks.push(event.data);
39
    }
40
};
41
42
// Get everything set up to start recording.
43
M.tinymce_recordrtc.start_recording = function(type, stream) {
44
    // The options for the recording codecs and bitrates.
45
    var options = null;
46
    if (type === 'audio') {
47
        if (window.MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) {
48
            options = {
49
                audioBitsPerSecond: window.params.audiobitrate,
50
                mimeType: 'audio/webm;codecs=opus'
51
            };
52
        } else if (window.MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')) {
53
            options = {
54
                audioBitsPerSecond: window.params.audiobitrate,
55
                mimeType: 'audio/ogg;codecs=opus'
56
            };
57
        }
58
    } else {
59
        if (window.MediaRecorder.isTypeSupported('video/webm;codecs=vp9,opus')) {
60
            options = {
61
                audioBitsPerSecond: window.params.audiobitrate,
62
                videoBitsPerSecond: window.params.videobitrate,
63
                mimeType: 'video/webm;codecs=vp9,opus'
64
            };
65
        } else if (window.MediaRecorder.isTypeSupported('video/webm;codecs=h264,opus')) {
66
            options = {
67
                audioBitsPerSecond: window.params.audiobitrate,
68
                videoBitsPerSecond: window.params.videobitrate,
69
                mimeType: 'video/webm;codecs=h264,opus'
70
            };
71
        } else if (window.MediaRecorder.isTypeSupported('video/webm;codecs=vp8,opus')) {
72
            options = {
73
                audioBitsPerSecond: window.params.audiobitrate,
74
                videoBitsPerSecond: window.params.videobitrate,
75
                mimeType: 'video/webm;codecs=vp8,opus'
76
            };
77
        }
78
    }
79
80
    // If none of the options above are supported, fall back on browser defaults.
81
    mediaRecorder = options ? new window.MediaRecorder(stream, options)
0 ignored issues
show
Bug introduced by
The variable mediaRecorder seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.mediaRecorder.
Loading history...
82
                            : new window.MediaRecorder(stream);
83
84
    // Initialize MediaRecorder events and start recording.
85
    mediaRecorder.ondataavailable = M.tinymce_recordrtc.handle_data_available;
86
    mediaRecorder.start(1000); // Capture in 1s chunks. Must be set to work with Firefox.
87
88
    // Mute audio, distracting while recording.
89
    player.set('muted', true);
0 ignored issues
show
Bug introduced by
The variable player seems to be never declared. If this is a global, consider adding a /** global: player */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
90
91
    // Set recording timer to the time specified in the settings.
92
    countdownSeconds = window.params.timelimit;
93
    countdownSeconds++;
94
    var timerText = M.util.get_string('stoprecording', 'tinymce_recordrtc');
95
    timerText += ' (<span id="minutes"></span>:<span id="seconds"></span>)';
96
    startStopBtn.setHTML(timerText);
0 ignored issues
show
Bug introduced by
The variable startStopBtn seems to be never declared. If this is a global, consider adding a /** global: startStopBtn */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
97
    M.tinymce_recordrtc.set_time();
98
    countdownTicker = window.setInterval(M.tinymce_recordrtc.set_time, 1000);
99
100
    // Make button clickable again, to allow stopping recording.
101
    startStopBtn.set('disabled', false);
102
};
103
104
// Upload recorded audio/video to server.
105
M.tinymce_recordrtc.upload_to_server = function(type, callback) {
106
    var xhr = new window.XMLHttpRequest();
107
108
    // Get src media of audio/video tag.
109
    xhr.open('GET', player.get('src'), true);
0 ignored issues
show
Bug introduced by
The variable player seems to be never declared. If this is a global, consider adding a /** global: player */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
110
    xhr.responseType = 'blob';
111
112
    xhr.onload = function() {
113
        if (xhr.status === 200) { // If src media was successfully retrieved.
114
            // blob is now the media that the audio/video tag's src pointed to.
115
            var blob = this.response;
116
117
            // Generate filename with random ID and file extension.
118
            var fileName = (Math.random() * 1000).toString().replace('.', '');
119
            if (type === 'audio') {
120
                fileName += '-audio.ogg';
121
            } else {
122
                fileName += '-video.webm';
123
            }
124
125
            // Create FormData to send to PHP upload/save script.
126
            var formData = new window.FormData();
127
            formData.append('contextid', window.params.contextid);
128
            formData.append('sesskey', window.params.sesskey);
129
            formData.append(type + '-filename', fileName);
130
            formData.append(type + '-blob', blob);
131
132
            // Pass FormData to PHP script using XHR.
133
            M.tinymce_recordrtc.make_xmlhttprequest('save.php', formData, function(progress, responseText) {
134
                if (progress === 'upload-ended') {
135
                    var initialURL = location.href.replace(location.href.split('/').pop(), '') + 'uploads.php/';
136
                    callback('ended', initialURL + responseText);
137
                } else {
138
                    callback(progress);
139
                }
140
            });
141
        }
142
    };
143
144
    xhr.send();
145
};
146
147
// Handle XHR sending/receiving/status.
148
M.tinymce_recordrtc.make_xmlhttprequest = function(url, data, callback) {
149
    var xhr = new window.XMLHttpRequest();
150
151
    xhr.onreadystatechange = function() {
152
        if ((xhr.readyState === 4) && (xhr.status === 200)) { // When request is finished and successful.
153
            callback('upload-ended', xhr.responseText);
154
        } else if (xhr.status === 404) { // When request returns 404 Not Found.
155
            callback('upload-failed-404');
156
        }
157
    };
158
159
    xhr.upload.onprogress = function(event) {
160
        callback(Math.round(event.loaded / event.total * 100) + "% " + M.util.get_string('uploadprogress', 'tinymce_recordrtc'));
161
    };
162
163
    xhr.upload.onerror = function(error) {
164
        callback('upload-failed', error);
165
    };
166
167
    xhr.upload.onabort = function(error) {
168
        callback('upload-aborted', error);
169
    };
170
171
    // POST FormData to PHP script that handles uploading/saving.
172
    xhr.open('POST', url);
173
    xhr.send(data);
174
};
175
176
// Makes 1min and 2s display as 1:02 on timer instead of 1:2, for example.
177
M.tinymce_recordrtc.pad = function(val) {
178
    var valString = val + "";
179
180
    if (valString.length < 2) {
181
        return "0" + valString;
182
    } else {
183
        return valString;
184
    }
185
};
186
187
// Functionality to make recording timer count down.
188
// Also makes recording stop when time limit is hit.
189
M.tinymce_recordrtc.set_time = function() {
190
    countdownSeconds--;
191
192
    startStopBtn.one('span#seconds').set('textContent', M.tinymce_recordrtc.pad(countdownSeconds % 60));
0 ignored issues
show
Bug introduced by
The variable startStopBtn seems to be never declared. If this is a global, consider adding a /** global: startStopBtn */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
193
    startStopBtn.one('span#minutes').set('textContent', M.tinymce_recordrtc.pad(window.parseInt(countdownSeconds / 60, 10)));
194
195
    if (countdownSeconds === 0) {
196
        Y.use('node-event-simulate', function() {
197
            startStopBtn.simulate('click');
0 ignored issues
show
Bug introduced by
The variable startStopBtn seems to be never declared. If this is a global, consider adding a /** global: startStopBtn */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
198
        });
199
    }
200
};
201