Completed
Push — master ( 1c4a3d...6855e2 )
by Jacob
01:41
created

M.tinymce_recordrtc.captureAudio   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 21
rs 9.3142

2 Functions

Rating   Name   Duplication   Size   Complexity  
A 0 6 1
A 0 3 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
/** global: M */
8
/** global: bowser */
9
/** global: player */
10
/** global: startStopBtn */
11
/** global: uploadBtn */
12
/** global: countdownSeconds */
13
/** global: countdownTicker */
14
/** global: mediaRecorder */
15
/** global: chunks */
16
17
/**
18
 * This function is initialized from PHP
19
 *
20
 * @param {Object}
21
 *            Y YUI instance
22
 */
23
M.tinymce_recordrtc.view_init = function() {
24
    // Assignment of global variables.
25
    player = document.querySelector('audio#player');
26
    startStopBtn = document.querySelector('button#start-stop');
27
    uploadBtn = document.querySelector('button#upload');
28
29
    // Show alert if using non-ideal browser.
30
    M.tinymce_recordrtc.check_browser();
31
32
    // Run when user clicks on "record" button.
33
    startStopBtn.onclick = function() {
34
        var btn = this;
35
        btn.disabled = true;
36
37
        // If button is displaying "Start Recording" or "Record Again".
38
        if ((btn.textContent === M.util.get_string('startrecording', 'tinymce_recordrtc')) ||
39
            (btn.textContent === M.util.get_string('recordagain', 'tinymce_recordrtc')) ||
40
            (btn.textContent === M.util.get_string('recordingfailed', 'tinymce_recordrtc'))) {
41
            // Hide alert-danger if it is shown.
42
            var alert = document.querySelector('div[id=alert-danger]');
43
            alert.parentElement.parentElement.classList.add('hide');
44
45
            // Make sure the audio player and upload button are not shown.
46
            player.parentElement.parentElement.classList.add('hide');
47
            uploadBtn.parentElement.parentElement.classList.add('hide');
48
49
            // Change look of recording button.
50
            startStopBtn.classList.remove('btn-outline-danger');
51
            startStopBtn.classList.add('btn-danger');
52
53
            // Empty the array containing the previously recorded chunks.
54
            chunks = [];
55
56
            // Initialize common configurations.
57
            var commonConfig = {
58
                // When the stream is captured from the microphone/webcam.
59
                onMediaCaptured: function(stream) {
60
                    // Make audio stream available at a higher level by making it a property of btn.
61
                    btn.stream = stream;
62
63
                    if (btn.mediaCapturedCallback) {
64
                        btn.mediaCapturedCallback();
65
                    }
66
                },
67
68
                // Revert button to "Record Again" when recording is stopped.
69
                onMediaStopped: function(btnLabel) {
70
                    btn.textContent = btnLabel;
71
                },
72
73
                // Handle recording errors.
74
                onMediaCapturingFailed: function(error) {
75
                    var btnLabel = null;
76
77
                    // If Firefox and Permission Denied error.
78
                    if ((error.name === 'PermissionDeniedError') && bowser.firefox) {
79
                        InstallTrigger.install({
80
                            'Foo': {
81
                                // Link: https://addons.mozilla.org/firefox/downloads/latest/655146/addon-655146...
82
                                // ...-latest.xpi?src=dp-btn-primary.
83
                                URL: 'https://addons.mozilla.org/en-US/firefox/addon/enable-screen-capturing/',
84
                                toString: function() {
85
                                    return this.URL;
86
                                }
87
                            }
88
                        });
89
90
                        btnLabel = M.util.get_string('startrecording', 'tinymce_recordrtc');
91
                    } else if ((error.name === 'DevicesNotFoundError') ||
92
                               (error.name === 'NotFoundError')) { // If Device Not Found error.
93
                        var alert = document.querySelector('div[id=alert-danger]');
94
                        alert.parentElement.parentElement.classList.remove('hide');
95
                        alert.textContent = M.util.get_string('inputdevicealert_title', 'tinymce_recordrtc') + ' ' + M.util.get_string('inputdevicealert', 'tinymce_recordrtc');
96
97
                        btnLabel = M.util.get_string('recordingfailed', 'tinymce_recordrtc');
98
                    }
99
100
                    // Proceed to treat as a stopped recording.
101
                    commonConfig.onMediaStopped(btnLabel);
102
                }
103
            };
104
105
            // Capture audio stream from microphone.
106
            M.tinymce_recordrtc.captureAudio(commonConfig);
107
108
            // When audio stream is successfully captured, start recording.
109
            btn.mediaCapturedCallback = function() {
110
                M.tinymce_recordrtc.startRecording(btn.stream);
111
            };
112
        } else { // If button is displaying "Stop Recording".
113
            // First of all clears the countdownTicker.
114
            clearInterval(countdownTicker);
115
116
            // Disable "Record Again" button for 1s to allow background processing (closing streams).
117
            setTimeout(function() {
118
                btn.disabled = false;
119
            }, 1000);
120
121
            // Stop recording.
122
            M.tinymce_recordrtc.stopRecording(btn.stream);
123
124
            // Change button to offer to record again.
125
            btn.textContent = M.util.get_string('recordagain', 'tinymce_recordrtc');
126
            startStopBtn.classList.remove('btn-danger');
127
            startStopBtn.classList.add('btn-outline-danger');
128
        }
129
    };
130
};
131
132
// Setup to get audio stream from microphone.
133
M.tinymce_recordrtc.captureAudio = function(config) {
134
    M.tinymce_recordrtc.captureUserMedia(
135
        // Media constraints.
136
        {
137
            audio: true
138
        },
139
140
        // Success callback.
141
        function(audioStream) {
142
            // Set audio player source to microphone stream.
143
            player.srcObject = audioStream;
144
145
            config.onMediaCaptured(audioStream);
146
        },
147
148
        // Error callback.
149
        function(error) {
150
            config.onMediaCapturingFailed(error);
151
        }
152
    );
153
};
154
155
M.tinymce_recordrtc.stopRecording = function(stream) {
156
    // Stop recording microphone stream.
157
    mediaRecorder.stop();
158
159
    // Stop each individual MediaTrack.
160
    stream.getTracks().forEach(function(track) {
161
        track.stop();
162
    });
163
164
    // Set source of audio player.
165
    var blob = new Blob(chunks, {
166
        type: 'audio/ogg;codecs=opus'
167
    });
168
    player.src = URL.createObjectURL(blob);
169
170
    // Show audio player with controls enabled, and unmute.
171
    player.muted = false;
172
    player.controls = true;
173
    player.parentElement.parentElement.classList.remove('hide');
174
175
    // Show upload button.
176
    uploadBtn.parentElement.parentElement.classList.remove('hide');
177
    uploadBtn.textContent = M.util.get_string('attachrecording', 'tinymce_recordrtc');
178
    uploadBtn.disabled = false;
179
180
    // Handle when upload button is clicked.
181
    uploadBtn.onclick = function() {
182
        // Trigger error if no recording has been made.
183
        if (!player.src || chunks === []) {
184
            return alert(M.util.get_string('norecordingfound', 'tinymce_recordrtc'));
185
        }
186
187
        var btn = uploadBtn;
188
        btn.disabled = true;
189
190
        // Upload recording to server.
191
        M.tinymce_recordrtc.uploadToServer('audio', function(progress, fileURL) {
192
            if (progress === 'ended') { // Insert annotation in text.
193
                btn.disabled = false;
194
                M.tinymce_recordrtc.insert_annotation(fileURL);
195
            } else if (progress === 'upload-failed') { // Show error message in upload button.
196
                btn.disabled = false;
197
                btn.textContent = M.util.get_string('uploadfailed', 'tinymce_recordrtc');
198
            } else {
199
                btn.textContent = progress;
200
            }
201
        });
202
    };
203
};
204