Bläddra i källkod

ref(JitsiTrack): prototype -> class

master
hristoterezov 8 år sedan
förälder
incheckning
0ea6b2a114
3 ändrade filer med 1145 tillägg och 1146 borttagningar
  1. 597
    596
      modules/RTC/JitsiLocalTrack.js
  2. 227
    209
      modules/RTC/JitsiRemoteTrack.js
  3. 321
    341
      modules/RTC/JitsiTrack.js

+ 597
- 596
modules/RTC/JitsiLocalTrack.js
Filskillnaden har hållits tillbaka eftersom den är för stor
Visa fil


+ 227
- 209
modules/RTC/JitsiRemoteTrack.js Visa fil

@@ -13,23 +13,27 @@ let ttfmTrackerVideoAttached = false;
13 13
 
14 14
 /**
15 15
  * Represents a single media track (either audio or video).
16
- * @param {RTC} rtc the RTC service instance.
17
- * @param {JitsiConference} conference the conference to which this track
18
- *        belongs to
19
- * @param {string} ownerEndpointId the endpoint ID of the track owner
20
- * @param {MediaStream} stream WebRTC MediaStream, parent of the track
21
- * @param {MediaStreamTrack} track underlying WebRTC MediaStreamTrack for
22
- *        the new JitsiRemoteTrack
23
- * @param {MediaType} mediaType the type of the media
24
- * @param {VideoType} videoType the type of the video if applicable
25
- * @param {number} ssrc the SSRC number of the Media Stream
26
- * @param {boolean} muted the initial muted state
27
- * @param {boolean} isP2P indicates whether or not this track belongs to a P2P
28
- * session
29
- * @throws {TypeError} if <tt>ssrc</tt> is not a number.
30
- * @constructor
31 16
  */
32
-export default function JitsiRemoteTrack(
17
+export default class JitsiRemoteTrack extends JitsiTrack {
18
+    /**
19
+     * Creates new JitsiRemoteTrack instance.
20
+     * @param {RTC} rtc the RTC service instance.
21
+     * @param {JitsiConference} conference the conference to which this track
22
+     *        belongs to
23
+     * @param {string} ownerEndpointId the endpoint ID of the track owner
24
+     * @param {MediaStream} stream WebRTC MediaStream, parent of the track
25
+     * @param {MediaStreamTrack} track underlying WebRTC MediaStreamTrack for
26
+     *        the new JitsiRemoteTrack
27
+     * @param {MediaType} mediaType the type of the media
28
+     * @param {VideoType} videoType the type of the video if applicable
29
+     * @param {number} ssrc the SSRC number of the Media Stream
30
+     * @param {boolean} muted the initial muted state
31
+     * @param {boolean} isP2P indicates whether or not this track belongs to a
32
+     * P2P session
33
+     * @throws {TypeError} if <tt>ssrc</tt> is not a number.
34
+     * @constructor
35
+     */
36
+    constructor(
33 37
         rtc,
34 38
         conference,
35 39
         ownerEndpointId,
@@ -40,222 +44,236 @@ export default function JitsiRemoteTrack(
40 44
         ssrc,
41 45
         muted,
42 46
         isP2P) {
43
-    JitsiTrack.call(
44
-        this,
45
-        conference,
46
-        stream,
47
-        track,
48
-        () => {
49
-            // Nothing to do if the track is inactive.
50
-        },
51
-        mediaType,
52
-        videoType);
53
-    this.rtc = rtc;
54
-
55
-    // Prevent from mixing up type of SSRC which should be a number
56
-    if (typeof ssrc !== 'number') {
57
-        throw new TypeError(`SSRC ${ssrc} is not a number`);
58
-    }
59
-    this.ssrc = ssrc;
60
-    this.ownerEndpointId = ownerEndpointId;
61
-    this.muted = muted;
62
-    this.isP2P = isP2P;
63
-
64
-    // we want to mark whether the track has been ever muted
65
-    // to detect ttfm events for startmuted conferences, as it can significantly
66
-    // increase ttfm values
67
-    this.hasBeenMuted = muted;
68
-
69
-    // Bind 'onmute' and 'onunmute' event handlers
70
-    if (this.rtc && this.track) {
71
-        this._bindMuteHandlers();
47
+        super(
48
+            conference,
49
+            stream,
50
+            track,
51
+            () => {
52
+                // Nothing to do if the track is inactive.
53
+            },
54
+            mediaType,
55
+            videoType);
56
+        this.rtc = rtc;
57
+
58
+        // Prevent from mixing up type of SSRC which should be a number
59
+        if (typeof ssrc !== 'number') {
60
+            throw new TypeError(`SSRC ${ssrc} is not a number`);
61
+        }
62
+        this.ssrc = ssrc;
63
+        this.ownerEndpointId = ownerEndpointId;
64
+        this.muted = muted;
65
+        this.isP2P = isP2P;
66
+
67
+        // we want to mark whether the track has been ever muted
68
+        // to detect ttfm events for startmuted conferences, as it can
69
+        // significantly increase ttfm values
70
+        this.hasBeenMuted = muted;
71
+
72
+        // Bind 'onmute' and 'onunmute' event handlers
73
+        if (this.rtc && this.track) {
74
+            this._bindMuteHandlers();
75
+        }
72 76
     }
73
-}
74 77
 
75
-/* eslint-enable max-params */
76
-
77
-JitsiRemoteTrack.prototype = Object.create(JitsiTrack.prototype);
78
-JitsiRemoteTrack.prototype.constructor = JitsiRemoteTrack;
79
-
80
-JitsiRemoteTrack.prototype._bindMuteHandlers = function() {
81
-    // Use feature detection for finding what event handling function is
82
-    // supported. On Internet Explorer, which uses uses temasys/firebreath, the
83
-    // track will have attachEvent instead of addEventListener.
84
-    //
85
-    // FIXME it would be better to use recently added '_setHandler' method, but
86
-    // 1. It does not allow to set more than one handler to the event
87
-    // 2. It does mix MediaStream('inactive') with MediaStreamTrack events
88
-    // 3. Allowing to bind more than one event handler requires too much
89
-    //    refactoring around camera issues detection.
90
-    if (this.track.addEventListener) {
91
-        this.track.addEventListener('mute', () => this._onTrackMute());
92
-        this.track.addEventListener('unmute', () => this._onTrackUnmute());
93
-    } else if (this.track.attachEvent) {
94
-        // FIXME Internet Explorer is not emitting out mute/unmute events.
95
-        this.track.attachEvent('onmute', () => this._onTrackMute());
96
-        this.track.attachEvent('onunmute', () => this._onTrackUnmute());
78
+    /* eslint-enable max-params */
79
+    /**
80
+     * Attaches the track muted handlers.
81
+     *
82
+     * @returns {void}
83
+     */
84
+    _bindMuteHandlers() {
85
+        // Use feature detection for finding what event handling function is
86
+        // supported. On Internet Explorer, which uses uses temasys/firebreath,
87
+        // the track will have attachEvent instead of addEventListener.
88
+        //
89
+        // FIXME it would be better to use recently added '_setHandler' method,
90
+        // but:
91
+        // 1. It does not allow to set more than one handler to the event
92
+        // 2. It does mix MediaStream('inactive') with MediaStreamTrack events
93
+        // 3. Allowing to bind more than one event handler requires too much
94
+        //    refactoring around camera issues detection.
95
+        if (this.track.addEventListener) {
96
+            this.track.addEventListener('mute', () => this._onTrackMute());
97
+            this.track.addEventListener('unmute', () => this._onTrackUnmute());
98
+        } else if (this.track.attachEvent) {
99
+            // FIXME Internet Explorer is not emitting out mute/unmute events.
100
+            this.track.attachEvent('onmute', () => this._onTrackMute());
101
+            this.track.attachEvent('onunmute', () => this._onTrackUnmute());
102
+        }
97 103
     }
98
-};
99
-
100
-/**
101
- * Callback invoked when the track is muted. Emits an event notifying listeners
102
- * of the mute event.
103
- *
104
- * @private
105
- * @returns {void}
106
- */
107
-JitsiRemoteTrack.prototype._onTrackMute = function() {
108
-    logger.debug(
109
-        `"onmute" event(${Date.now()}): `,
110
-        this.getParticipantId(), this.getType(), this.getSSRC());
111
-
112
-    this.rtc.eventEmitter.emit(RTCEvents.REMOTE_TRACK_MUTE, this);
113
-};
114 104
 
115
-/**
116
- * Callback invoked when the track is unmuted. Emits an event notifying
117
- * listeners of the mute event.
118
- *
119
- * @private
120
- * @returns {void}
121
- */
122
-JitsiRemoteTrack.prototype._onTrackUnmute = function() {
123
-    logger.debug(
124
-        `"onunmute" event(${Date.now()}): `,
125
-        this.getParticipantId(), this.getType(), this.getSSRC());
126
-
127
-    this.rtc.eventEmitter.emit(RTCEvents.REMOTE_TRACK_UNMUTE, this);
128
-};
129
-
130
-/**
131
- * Sets current muted status and fires an events for the change.
132
- * @param value the muted status.
133
- */
134
-JitsiRemoteTrack.prototype.setMute = function(value) {
135
-    if (this.muted === value) {
136
-        return;
105
+    /**
106
+     * Callback invoked when the track is muted. Emits an event notifying
107
+     * listeners of the mute event.
108
+     *
109
+     * @private
110
+     * @returns {void}
111
+     */
112
+    _onTrackMute() {
113
+        logger.debug(
114
+            `"onmute" event(${Date.now()}): `,
115
+            this.getParticipantId(), this.getType(), this.getSSRC());
116
+
117
+        this.rtc.eventEmitter.emit(RTCEvents.REMOTE_TRACK_MUTE, this);
137 118
     }
138 119
 
139
-    if (value) {
140
-        this.hasBeenMuted = true;
120
+    /**
121
+     * Callback invoked when the track is unmuted. Emits an event notifying
122
+     * listeners of the mute event.
123
+     *
124
+     * @private
125
+     * @returns {void}
126
+     */
127
+    _onTrackUnmute() {
128
+        logger.debug(
129
+            `"onunmute" event(${Date.now()}): `,
130
+            this.getParticipantId(), this.getType(), this.getSSRC());
131
+
132
+        this.rtc.eventEmitter.emit(RTCEvents.REMOTE_TRACK_UNMUTE, this);
141 133
     }
142 134
 
143
-    // we can have a fake video stream
144
-    if (this.stream) {
145
-        this.stream.muted = value;
135
+    /**
136
+     * Sets current muted status and fires an events for the change.
137
+     * @param value the muted status.
138
+     */
139
+    setMute(value) {
140
+        if (this.muted === value) {
141
+            return;
142
+        }
143
+
144
+        if (value) {
145
+            this.hasBeenMuted = true;
146
+        }
147
+
148
+        // we can have a fake video stream
149
+        if (this.stream) {
150
+            this.stream.muted = value;
151
+        }
152
+
153
+        this.muted = value;
154
+        this.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED, this);
146 155
     }
147 156
 
148
-    this.muted = value;
149
-    this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED, this);
150
-};
151
-
152
-/**
153
- * Returns the current muted status of the track.
154
- * @returns {boolean|*|JitsiRemoteTrack.muted} <tt>true</tt> if the track is
155
- * muted and <tt>false</tt> otherwise.
156
- */
157
-JitsiRemoteTrack.prototype.isMuted = function() {
158
-    return this.muted;
159
-};
160
-
161
-/**
162
- * Returns the participant id which owns the track.
163
- * @returns {string} the id of the participants. It corresponds to the Colibri
164
- * endpoint id/MUC nickname in case of Jitsi-meet.
165
- */
166
-JitsiRemoteTrack.prototype.getParticipantId = function() {
167
-    return this.ownerEndpointId;
168
-};
157
+    /**
158
+     * Returns the current muted status of the track.
159
+     * @returns {boolean|*|JitsiRemoteTrack.muted} <tt>true</tt> if the track is
160
+     * muted and <tt>false</tt> otherwise.
161
+     */
162
+    isMuted() {
163
+        return this.muted;
164
+    }
169 165
 
170
-/**
171
- * Return false;
172
- */
173
-JitsiRemoteTrack.prototype.isLocal = function() {
174
-    return false;
175
-};
166
+    /**
167
+     * Returns the participant id which owns the track.
168
+     *
169
+     * @returns {string} the id of the participants. It corresponds to the
170
+     * Colibri endpoint id/MUC nickname in case of Jitsi-meet.
171
+     */
172
+    getParticipantId() {
173
+        return this.ownerEndpointId;
174
+    }
176 175
 
177
-/**
178
- * Returns the synchronization source identifier (SSRC) of this remote track.
179
- * @returns {number} the SSRC of this remote track
180
- */
181
-JitsiRemoteTrack.prototype.getSSRC = function() {
182
-    return this.ssrc;
183
-};
176
+    /**
177
+     * Return false;
178
+     */
179
+    isLocal() {
180
+        return false;
181
+    }
184 182
 
185
-/**
186
- * Changes the video type of the track
187
- * @param type the new video type("camera", "desktop")
188
- */
189
-JitsiRemoteTrack.prototype._setVideoType = function(type) {
190
-    if (this.videoType === type) {
191
-        return;
183
+    /**
184
+     * Returns the synchronization source identifier (SSRC) of this remote
185
+     * track.
186
+     *
187
+     * @returns {number} the SSRC of this remote track.
188
+     */
189
+    getSSRC() {
190
+        return this.ssrc;
192 191
     }
193
-    this.videoType = type;
194
-    this.eventEmitter.emit(JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED, type);
195
-};
196 192
 
197
-JitsiRemoteTrack.prototype._playCallback = function() {
198
-    const type = this.isVideoTrack() ? 'video' : 'audio';
193
+    /**
194
+     * Changes the video type of the track.
195
+     *
196
+     * @param {string} type - The new video type("camera", "desktop").
197
+     */
198
+    _setVideoType(type) {
199
+        if (this.videoType === type) {
200
+            return;
201
+        }
202
+        this.videoType = type;
203
+        this.emit(JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED, type);
204
+    }
199 205
 
200
-    const now = window.performance.now();
206
+    /**
207
+     * Handles track play events.
208
+     */
209
+    _playCallback() {
210
+        const type = this.isVideoTrack() ? 'video' : 'audio';
201 211
 
202
-    console.log(`(TIME) Render ${type}:\t`, now);
203
-    this.conference.getConnectionTimes()[`${type}.render`] = now;
212
+        const now = window.performance.now();
204 213
 
205
-    const ttfm = now
206
-        - (this.conference.getConnectionTimes()['session.initiate']
207
-        - this.conference.getConnectionTimes()['muc.joined'])
208
-        - (window.connectionTimes['obtainPermissions.end']
209
-        - window.connectionTimes['obtainPermissions.start']);
214
+        console.log(`(TIME) Render ${type}:\t`, now);
215
+        this.conference.getConnectionTimes()[`${type}.render`] = now;
210 216
 
211
-    this.conference.getConnectionTimes()[`${type}.ttfm`] = ttfm;
212
-    console.log(`(TIME) TTFM ${type}:\t`, ttfm);
213
-    let eventName = `${type}.ttfm`;
217
+        const ttfm = now
218
+            - (this.conference.getConnectionTimes()['session.initiate']
219
+            - this.conference.getConnectionTimes()['muc.joined'])
220
+            - (window.connectionTimes['obtainPermissions.end']
221
+            - window.connectionTimes['obtainPermissions.start']);
214 222
 
215
-    if (this.hasBeenMuted) {
216
-        eventName += '.muted';
217
-    }
218
-    Statistics.analytics.sendEvent(eventName, { value: ttfm });
219
-};
223
+        this.conference.getConnectionTimes()[`${type}.ttfm`] = ttfm;
224
+        console.log(`(TIME) TTFM ${type}:\t`, ttfm);
225
+        let eventName = `${type}.ttfm`;
220 226
 
221
-/**
222
- * Attach time to first media tracker only if there is conference and only
223
- * for the first element.
224
- * @param container the HTML container which can be 'video' or 'audio' element.
225
- *        It can also be 'object' element if Temasys plugin is in use and this
226
- *        method has been called previously on video or audio HTML element.
227
- * @private
228
- */
229
-JitsiRemoteTrack.prototype._attachTTFMTracker = function(container) {
230
-    if ((ttfmTrackerAudioAttached && this.isAudioTrack())
231
-        || (ttfmTrackerVideoAttached && this.isVideoTrack())) {
232
-        return;
227
+        if (this.hasBeenMuted) {
228
+            eventName += '.muted';
229
+        }
230
+        Statistics.analytics.sendEvent(eventName, { value: ttfm });
233 231
     }
234 232
 
235
-    if (this.isAudioTrack()) {
236
-        ttfmTrackerAudioAttached = true;
237
-    }
238
-    if (this.isVideoTrack()) {
239
-        ttfmTrackerVideoAttached = true;
233
+    /**
234
+     * Attach time to first media tracker only if there is conference and only
235
+     * for the first element.
236
+     * @param container the HTML container which can be 'video' or 'audio'
237
+     * element. It can also be 'object' element if Temasys plugin is in use and
238
+     * this method has been called previously on video or audio HTML element.
239
+     * @private
240
+     */
241
+    _attachTTFMTracker(container) {
242
+        if ((ttfmTrackerAudioAttached && this.isAudioTrack())
243
+            || (ttfmTrackerVideoAttached && this.isVideoTrack())) {
244
+            return;
245
+        }
246
+
247
+        if (this.isAudioTrack()) {
248
+            ttfmTrackerAudioAttached = true;
249
+        }
250
+        if (this.isVideoTrack()) {
251
+            ttfmTrackerVideoAttached = true;
252
+        }
253
+
254
+        if (RTCBrowserType.isTemasysPluginUsed()) {
255
+            // XXX Don't require Temasys unless it's to be used because it
256
+            // doesn't run on React Native, for example.
257
+            const AdapterJS = require('./adapter.screenshare');
258
+
259
+            // FIXME: this is not working for IE11
260
+            AdapterJS.addEvent(
261
+                container,
262
+                'play',
263
+                this._playCallback.bind(this));
264
+        } else {
265
+            container.addEventListener(
266
+                'canplay',
267
+                this._playCallback.bind(this));
268
+        }
240 269
     }
241 270
 
242
-    if (RTCBrowserType.isTemasysPluginUsed()) {
243
-        // XXX Don't require Temasys unless it's to be used because it doesn't
244
-        // run on React Native, for example.
245
-        const AdapterJS = require('./adapter.screenshare');
246
-
247
-        // FIXME: this is not working for IE11
248
-        AdapterJS.addEvent(container, 'play', this._playCallback.bind(this));
249
-    } else {
250
-        container.addEventListener('canplay', this._playCallback.bind(this));
271
+    /**
272
+     * Creates a text representation of this remote track instance.
273
+     * @return {string}
274
+     */
275
+    toString() {
276
+        return `RemoteTrack[${this.ownerEndpointId}, ${this.getType()
277
+                }, p2p: ${this.isP2P}]`;
251 278
     }
252
-};
253
-
254
-/**
255
- * Creates a text representation of this remote track instance.
256
- * @return {string}
257
- */
258
-JitsiRemoteTrack.prototype.toString = function() {
259
-    return `RemoteTrack[${this.ownerEndpointId}, ${this.getType()
260
-            }, p2p: ${this.isP2P}]`;
261
-};
279
+}

+ 321
- 341
modules/RTC/JitsiTrack.js Visa fil

@@ -54,400 +54,380 @@ function addMediaStreamInactiveHandler(mediaStream, handler) {
54 54
     }
55 55
 }
56 56
 
57
-/* eslint-disable max-params */
58
-
59 57
 /**
60 58
  * Represents a single media track (either audio or video).
61
- * @constructor
62
- * @param rtc the rtc instance
63
- * @param stream the WebRTC MediaStream instance
64
- * @param track the WebRTC MediaStreamTrack instance, must be part of
65
- * the given <tt>stream</tt>.
66
- * @param streamInactiveHandler the function that will handle
67
- *        onended/oninactive events of the stream.
68
- * @param trackMediaType the media type of the JitsiTrack
69
- * @param videoType the VideoType for this track if any
70 59
  */
71
-export default function JitsiTrack(
72
-    conference,
73
-    stream,
74
-    track,
75
-    streamInactiveHandler,
76
-    trackMediaType,
77
-    videoType) {
60
+export default class JitsiTrack extends EventEmitter {
61
+    /* eslint-disable max-params */
78 62
     /**
79
-     * Array with the HTML elements that are displaying the streams.
80
-     * @type {Array}
63
+     * Represents a single media track (either audio or video).
64
+     * @constructor
65
+     * @param rtc the rtc instance
66
+     * @param stream the WebRTC MediaStream instance
67
+     * @param track the WebRTC MediaStreamTrack instance, must be part of
68
+     * the given <tt>stream</tt>.
69
+     * @param streamInactiveHandler the function that will handle
70
+     *        onended/oninactive events of the stream.
71
+     * @param trackMediaType the media type of the JitsiTrack
72
+     * @param videoType the VideoType for this track if any
81 73
      */
82
-    this.containers = [];
83
-    this.conference = conference;
84
-    this.stream = stream;
85
-    this.eventEmitter = new EventEmitter();
86
-    this.audioLevel = -1;
87
-    this.type = trackMediaType;
88
-    this.track = track;
89
-    this.videoType = videoType;
90
-    this.handlers = {};
74
+    constructor(
75
+        conference,
76
+        stream,
77
+        track,
78
+        streamInactiveHandler,
79
+        trackMediaType,
80
+        videoType) {
81
+        super();
82
+
83
+        // aliases for addListener/removeListener
84
+        this.addEventListener = this.addListener;
85
+        this.removeEventListener = this.off = this.removeListener;
86
+
87
+        /**
88
+         * Array with the HTML elements that are displaying the streams.
89
+         * @type {Array}
90
+         */
91
+        this.containers = [];
92
+        this.conference = conference;
93
+        this.stream = stream;
94
+        this.audioLevel = -1;
95
+        this.type = trackMediaType;
96
+        this.track = track;
97
+        this.videoType = videoType;
98
+        this.handlers = {};
99
+
100
+        /**
101
+         * Indicates whether this JitsiTrack has been disposed. If true, this
102
+         * JitsiTrack is to be considered unusable and operations involving it
103
+         * are to fail (e.g. {@link JitsiConference#addTrack(JitsiTrack)},
104
+         * {@link JitsiConference#removeTrack(JitsiTrack)}).
105
+         * @type {boolean}
106
+         */
107
+        this.disposed = false;
108
+        this._setHandler('inactive', streamInactiveHandler);
109
+    }
110
+
111
+    /* eslint-enable max-params */
91 112
 
92 113
     /**
93
-     * Indicates whether this JitsiTrack has been disposed. If true, this
94
-     * JitsiTrack is to be considered unusable and operations involving it are
95
-     * to fail (e.g. {@link JitsiConference#addTrack(JitsiTrack)},
96
-     * {@link JitsiConference#removeTrack(JitsiTrack)}).
97
-     * @type {boolean}
114
+     * Sets handler to the WebRTC MediaStream or MediaStreamTrack object
115
+     * depending on the passed type.
116
+     * @param {string} type the type of the handler that is going to be set
117
+     * @param {Function} handler the handler.
98 118
      */
99
-    this.disposed = false;
100
-    this._setHandler('inactive', streamInactiveHandler);
101
-}
102
-
103
-/* eslint-enable max-params */
119
+    _setHandler(type, handler) {
120
+        this.handlers[type] = handler;
121
+        if (!this.stream) {
122
+            return;
123
+        }
104 124
 
105
-/**
106
- * Sets handler to the WebRTC MediaStream or MediaStreamTrack object depending
107
- * on the passed type.
108
- * @param {string} type the type of the handler that is going to be set
109
- * @param {Function} handler the handler.
110
- */
111
-JitsiTrack.prototype._setHandler = function(type, handler) {
112
-    this.handlers[type] = handler;
113
-    if (!this.stream) {
114
-        return;
125
+        if (type === 'inactive') {
126
+            if (RTCBrowserType.isFirefox()) {
127
+                implementOnEndedHandling(this);
128
+            }
129
+            addMediaStreamInactiveHandler(this.stream, handler);
130
+        } else if (trackHandler2Prop.hasOwnProperty(type)) {
131
+            this.stream.getVideoTracks().forEach(track => {
132
+                track[trackHandler2Prop[type]] = handler;
133
+            }, this);
134
+        }
115 135
     }
116 136
 
117
-    if (type === 'inactive') {
118
-        if (RTCBrowserType.isFirefox()) {
119
-            implementOnEndedHandling(this);
120
-        }
121
-        addMediaStreamInactiveHandler(this.stream, handler);
122
-    } else if (trackHandler2Prop.hasOwnProperty(type)) {
123
-        this.stream.getVideoTracks().forEach(track => {
124
-            track[trackHandler2Prop[type]] = handler;
137
+    /**
138
+     * Sets the stream property of JitsiTrack object and sets all stored
139
+     * handlers to it.
140
+     * @param {MediaStream} stream the new stream.
141
+     */
142
+    _setStream(stream) {
143
+        this.stream = stream;
144
+        Object.keys(this.handlers).forEach(type => {
145
+            typeof this.handlers[type] === 'function'
146
+                && this._setHandler(type, this.handlers[type]);
125 147
         }, this);
126 148
     }
127
-};
128
-
129
-/**
130
- * Sets the stream property of JitsiTrack object and sets all stored handlers
131
- * to it.
132
- * @param {MediaStream} stream the new stream.
133
- */
134
-JitsiTrack.prototype._setStream = function(stream) {
135
-    this.stream = stream;
136
-    Object.keys(this.handlers).forEach(function(type) {
137
-        typeof this.handlers[type] === 'function'
138
-            && this._setHandler(type, this.handlers[type]);
139
-    }, this);
140
-};
141
-
142
-/**
143
- * Returns the type (audio or video) of this track.
144
- */
145
-JitsiTrack.prototype.getType = function() {
146
-    return this.type;
147
-};
148
-
149
-/**
150
- * Check if this is an audio track.
151
- */
152
-JitsiTrack.prototype.isAudioTrack = function() {
153
-    return this.getType() === MediaType.AUDIO;
154
-};
155
-
156
-/**
157
- * Checks whether the underlying WebRTC <tt>MediaStreamTrack</tt> is muted
158
- * according to it's 'muted' field status.
159
- * @return {boolean} <tt>true</tt> if the underlying <tt>MediaStreamTrack</tt>
160
- * is muted or <tt>false</tt> otherwise.
161
- */
162
-JitsiTrack.prototype.isWebRTCTrackMuted = function() {
163
-    return this.track && this.track.muted;
164
-};
165
-
166
-/**
167
- * Check if this is a video track.
168
- */
169
-JitsiTrack.prototype.isVideoTrack = function() {
170
-    return this.getType() === MediaType.VIDEO;
171
-};
172
-
173
-/**
174
- * Checks whether this is a local track.
175
- * @abstract
176
- * @return {boolean} 'true' if it's a local track or 'false' otherwise.
177
- */
178
-JitsiTrack.prototype.isLocal = function() {
179
-    throw new Error('Not implemented by subclass');
180
-};
181
-
182
-/**
183
- * Returns the WebRTC MediaStream instance.
184
- */
185
-JitsiTrack.prototype.getOriginalStream = function() {
186
-    return this.stream;
187
-};
188 149
 
189
-/**
190
- * Returns the ID of the underlying WebRTC Media Stream(if any)
191
- * @returns {String|null}
192
- */
193
-JitsiTrack.prototype.getStreamId = function() {
194
-    return this.stream ? this.stream.id : null;
195
-};
196
-
197
-/**
198
- * Return the underlying WebRTC MediaStreamTrack
199
- * @returns {MediaStreamTrack}
200
- */
201
-JitsiTrack.prototype.getTrack = function() {
202
-    return this.track;
203
-};
204
-
205
-/**
206
- * Returns the ID of the underlying WebRTC MediaStreamTrack(if any)
207
- * @returns {String|null}
208
- */
209
-JitsiTrack.prototype.getTrackId = function() {
210
-    return this.track ? this.track.id : null;
211
-};
150
+    /**
151
+     * Returns the type (audio or video) of this track.
152
+     */
153
+    getType() {
154
+        return this.type;
155
+    }
212 156
 
213
-/**
214
- * Return meaningful usage label for this track depending on it's media and
215
- * eventual video type.
216
- * @returns {string}
217
- */
218
-JitsiTrack.prototype.getUsageLabel = function() {
219
-    if (this.isAudioTrack()) {
220
-        return 'mic';
157
+    /**
158
+     * Check if this is an audio track.
159
+     */
160
+    isAudioTrack() {
161
+        return this.getType() === MediaType.AUDIO;
221 162
     }
222 163
 
223
-    return this.videoType ? this.videoType : 'default';
164
+    /**
165
+     * Checks whether the underlying WebRTC <tt>MediaStreamTrack</tt> is muted
166
+     * according to it's 'muted' field status.
167
+     * @return {boolean} <tt>true</tt> if the underlying
168
+     * <tt>MediaStreamTrack</tt> is muted or <tt>false</tt> otherwise.
169
+     */
170
+    isWebRTCTrackMuted() {
171
+        return this.track && this.track.muted;
172
+    }
224 173
 
225
-};
174
+    /**
175
+     * Check if this is a video track.
176
+     */
177
+    isVideoTrack() {
178
+        return this.getType() === MediaType.VIDEO;
179
+    }
226 180
 
227
-/**
228
- * Eventually will trigger RTCEvents.TRACK_ATTACHED event.
229
- * @param container the video/audio container to which this stream is attached
230
- *        and for which event will be fired.
231
- * @private
232
- */
233
-JitsiTrack.prototype._maybeFireTrackAttached = function(container) {
234
-    if (this.conference && container) {
235
-        this.conference._onTrackAttach(this, container);
181
+    /**
182
+     * Checks whether this is a local track.
183
+     * @abstract
184
+     * @return {boolean} 'true' if it's a local track or 'false' otherwise.
185
+     */
186
+    isLocal() {
187
+        throw new Error('Not implemented by subclass');
236 188
     }
237
-};
238 189
 
239
-/**
240
- * Attaches the MediaStream of this track to an HTML container.
241
- * Adds the container to the list of containers that are displaying the track.
242
- * Note that Temasys plugin will replace original audio/video element with
243
- * 'object' when stream is being attached to the container for the first time.
244
- *
245
- * * NOTE * if given container element is not visible when the stream is being
246
- * attached it will be shown back given that Temasys plugin is currently in use.
247
- *
248
- * @param container the HTML container which can be 'video' or 'audio' element.
249
- *        It can also be 'object' element if Temasys plugin is in use and this
250
- *        method has been called previously on video or audio HTML element.
251
- *
252
- * @returns potentially new instance of container if it was replaced by the
253
- *          library. That's the case when Temasys plugin is in use.
254
- */
255
-JitsiTrack.prototype.attach = function(container) {
256
-    let c = container;
190
+    /**
191
+     * Returns the WebRTC MediaStream instance.
192
+     */
193
+    getOriginalStream() {
194
+        return this.stream;
195
+    }
257 196
 
258
-    if (this.stream) {
259
-        c = RTCUtils.attachMediaStream(container, this.stream);
197
+    /**
198
+     * Returns the ID of the underlying WebRTC Media Stream(if any)
199
+     * @returns {String|null}
200
+     */
201
+    getStreamId() {
202
+        return this.stream ? this.stream.id : null;
260 203
     }
261
-    this.containers.push(c);
262
-    this._maybeFireTrackAttached(c);
263
-    this._attachTTFMTracker(c);
264 204
 
265
-    return c;
266
-};
205
+    /**
206
+     * Return the underlying WebRTC MediaStreamTrack
207
+     * @returns {MediaStreamTrack}
208
+     */
209
+    getTrack() {
210
+        return this.track;
211
+    }
267 212
 
268
-/**
269
- * Removes this JitsiTrack from the passed HTML container.
270
- *
271
- * @param container the HTML container to detach from this JitsiTrack. If
272
- * <tt>null</tt> or <tt>undefined</tt>, all containers are removed. A container
273
- * can be a 'video', 'audio' or 'object' HTML element instance to which this
274
- * JitsiTrack is currently attached.
275
- */
276
-JitsiTrack.prototype.detach = function(container) {
277
-    for (let cs = this.containers, i = cs.length - 1; i >= 0; --i) {
278
-        const c = cs[i];
213
+    /**
214
+     * Returns the ID of the underlying WebRTC MediaStreamTrack(if any)
215
+     * @returns {String|null}
216
+     */
217
+    getTrackId() {
218
+        return this.track ? this.track.id : null;
219
+    }
279 220
 
280
-        if (!container) {
281
-            RTCUtils.attachMediaStream(c, null);
282
-        }
283
-        if (!container || c === container) {
284
-            cs.splice(i, 1);
221
+    /**
222
+     * Return meaningful usage label for this track depending on it's media and
223
+     * eventual video type.
224
+     * @returns {string}
225
+     */
226
+    getUsageLabel() {
227
+        if (this.isAudioTrack()) {
228
+            return 'mic';
285 229
         }
230
+
231
+        return this.videoType ? this.videoType : 'default';
286 232
     }
287 233
 
288
-    if (container) {
289
-        RTCUtils.attachMediaStream(container, null);
234
+    /**
235
+     * Eventually will trigger RTCEvents.TRACK_ATTACHED event.
236
+     * @param container the video/audio container to which this stream is
237
+     *        attached and for which event will be fired.
238
+     * @private
239
+     */
240
+    _maybeFireTrackAttached(container) {
241
+        if (this.conference && container) {
242
+            this.conference._onTrackAttach(this, container);
243
+        }
290 244
     }
291
-};
292 245
 
293
-/**
294
- * Attach time to first media tracker only if there is conference and only
295
- * for the first element.
296
- * @param container the HTML container which can be 'video' or 'audio' element.
297
- *        It can also be 'object' element if Temasys plugin is in use and this
298
- *        method has been called previously on video or audio HTML element.
299
- * @private
300
- */
301
-// eslint-disable-next-line no-unused-vars
302
-JitsiTrack.prototype._attachTTFMTracker = function(container) {
303
-    // Should be defined by the classes that are extending JitsiTrack
304
-};
246
+    /**
247
+     * Attaches the MediaStream of this track to an HTML container.
248
+     * Adds the container to the list of containers that are displaying the
249
+     * track. Note that Temasys plugin will replace original audio/video element
250
+     * with 'object' when stream is being attached to the container for the
251
+     * first time.
252
+     * * NOTE * if given container element is not visible when the stream is
253
+     * being attached it will be shown back given that Temasys plugin is
254
+     * currently in use.
255
+     *
256
+     * @param container the HTML container which can be 'video' or 'audio'
257
+     * element. It can also be 'object' element if Temasys plugin is in use and
258
+     * this method has been called previously on video or audio HTML element.
259
+     *
260
+     * @returns potentially new instance of container if it was replaced by the
261
+     *          library. That's the case when Temasys plugin is in use.
262
+     */
263
+    attach(container) {
264
+        let c = container;
305 265
 
306
-/**
307
- * Removes attached event listeners.
308
- *
309
- * @returns {Promise}
310
- */
311
-JitsiTrack.prototype.dispose = function() {
312
-    this.eventEmitter.removeAllListeners();
266
+        if (this.stream) {
267
+            c = RTCUtils.attachMediaStream(container, this.stream);
268
+        }
269
+        this.containers.push(c);
270
+        this._maybeFireTrackAttached(c);
271
+        this._attachTTFMTracker(c);
313 272
 
314
-    this.disposed = true;
273
+        return c;
274
+    }
315 275
 
316
-    return Promise.resolve();
317
-};
276
+    /**
277
+     * Removes this JitsiTrack from the passed HTML container.
278
+     *
279
+     * @param container the HTML container to detach from this JitsiTrack. If
280
+     * <tt>null</tt> or <tt>undefined</tt>, all containers are removed. A
281
+     * container can be a 'video', 'audio' or 'object' HTML element instance to
282
+     * which this JitsiTrack is currently attached.
283
+     */
284
+    detach(container) {
285
+        for (let cs = this.containers, i = cs.length - 1; i >= 0; --i) {
286
+            const c = cs[i];
287
+
288
+            if (!container) {
289
+                RTCUtils.attachMediaStream(c, null);
290
+            }
291
+            if (!container || c === container) {
292
+                cs.splice(i, 1);
293
+            }
294
+        }
318 295
 
319
-/**
320
- * Returns true if this is a video track and the source of the video is a
321
- * screen capture as opposed to a camera.
322
- */
323
-JitsiTrack.prototype.isScreenSharing = function() {
324
-    // FIXME: Should be fixed or removed.
325
-};
296
+        if (container) {
297
+            RTCUtils.attachMediaStream(container, null);
298
+        }
299
+    }
326 300
 
327
-/**
328
- * Returns id of the track.
329
- * @returns {string|null} id of the track or null if this is fake track.
330
- */
331
-JitsiTrack.prototype.getId = function() {
332
-    if (this.stream) {
333
-        return RTCUtils.getStreamID(this.stream);
301
+    /**
302
+     * Attach time to first media tracker only if there is conference and only
303
+     * for the first element.
304
+     *
305
+     * @param {HTMLElement} container the HTML container which can be 'video' or
306
+     * 'audio' element. It can also be 'object' element if Temasys plugin is in
307
+     * use and this method has been called previously on video or audio HTML
308
+     * element.
309
+     * @private
310
+     */
311
+    _attachTTFMTracker(container) { // eslint-disable-line no-unused-vars
312
+        // Should be defined by the classes that are extending JitsiTrack
334 313
     }
335 314
 
336
-    return null;
315
+    /**
316
+     * Removes attached event listeners.
317
+     *
318
+     * @returns {Promise}
319
+     */
320
+    dispose() {
321
+        this.removeAllListeners();
337 322
 
338
-};
323
+        this.disposed = true;
339 324
 
340
-/**
341
- * Checks whether the MediaStream is active/not ended.
342
- * When there is no check for active we don't have information and so
343
- * will return that stream is active (in case of FF).
344
- * @returns {boolean} whether MediaStream is active.
345
- */
346
-JitsiTrack.prototype.isActive = function() {
347
-    if (typeof this.stream.active !== 'undefined') {
348
-        return this.stream.active;
325
+        return Promise.resolve();
349 326
     }
350 327
 
351
-    return true;
328
+    /**
329
+     * Returns true if this is a video track and the source of the video is a
330
+     * screen capture as opposed to a camera.
331
+     */
332
+    isScreenSharing() {
333
+        // FIXME: Should be fixed or removed.
334
+    }
352 335
 
353
-};
336
+    /**
337
+     * Returns id of the track.
338
+     * @returns {string|null} id of the track or null if this is fake track.
339
+     */
340
+    getId() {
341
+        if (this.stream) {
342
+            return RTCUtils.getStreamID(this.stream);
343
+        }
354 344
 
355
-/**
356
- * Attaches a handler for events(For example - "audio level changed".).
357
- * All possible event are defined in JitsiTrackEvents.
358
- * @param eventId the event ID.
359
- * @param handler handler for the event.
360
- */
361
-JitsiTrack.prototype.on = function(eventId, handler) {
362
-    if (this.eventEmitter) {
363
-        this.eventEmitter.on(eventId, handler);
345
+        return null;
364 346
     }
365
-};
366 347
 
367
-/**
368
- * Removes event listener
369
- * @param eventId the event ID.
370
- * @param [handler] optional, the specific handler to unbind
371
- */
372
-JitsiTrack.prototype.off = function(eventId, handler) {
373
-    if (this.eventEmitter) {
374
-        this.eventEmitter.removeListener(eventId, handler);
375
-    }
376
-};
348
+    /**
349
+     * Checks whether the MediaStream is active/not ended.
350
+     * When there is no check for active we don't have information and so
351
+     * will return that stream is active (in case of FF).
352
+     * @returns {boolean} whether MediaStream is active.
353
+     */
354
+    isActive() {
355
+        if (typeof this.stream.active !== 'undefined') {
356
+            return this.stream.active;
357
+        }
377 358
 
378
-// Common aliases for event emitter
379
-JitsiTrack.prototype.addEventListener = JitsiTrack.prototype.on;
380
-JitsiTrack.prototype.removeEventListener = JitsiTrack.prototype.off;
359
+        return true;
360
+    }
381 361
 
382
-/**
383
- * Sets the audio level for the stream
384
- * @param {number} audioLevel value between 0 and 1
385
- * @param {TraceablePeerConnection} [tpc] the peerconnection instance which
386
- * is source for the audio level. It can be <tt>undefined</tt> for
387
- * a local track if the audio level was measured outside of the peerconnection
388
- * (see /modules/statistics/LocalStatsCollector.js).
389
- */
390
-JitsiTrack.prototype.setAudioLevel = function(audioLevel, tpc) {
391
-    if (this.audioLevel !== audioLevel) {
392
-        this.audioLevel = audioLevel;
393
-        this.eventEmitter.emit(
394
-            JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
395
-            audioLevel,
396
-            tpc);
362
+    /**
363
+     * Sets the audio level for the stream
364
+     * @param {number} audioLevel value between 0 and 1
365
+     * @param {TraceablePeerConnection} [tpc] the peerconnection instance which
366
+     * is source for the audio level. It can be <tt>undefined</tt> for
367
+     * a local track if the audio level was measured outside of the
368
+     * peerconnection (see /modules/statistics/LocalStatsCollector.js).
369
+     */
370
+    setAudioLevel(audioLevel, tpc) {
371
+        if (this.audioLevel !== audioLevel) {
372
+            this.audioLevel = audioLevel;
373
+            this.emit(
374
+                JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
375
+                audioLevel,
376
+                tpc);
377
+        }
397 378
     }
398
-};
399 379
 
400
-/**
401
- * Returns the msid of the stream attached to the JitsiTrack object or null if
402
- * no stream is attached.
403
- */
404
-JitsiTrack.prototype.getMSID = function() {
405
-    const streamId = this.getStreamId();
406
-    const trackId = this.getTrackId();
380
+    /**
381
+     * Returns the msid of the stream attached to the JitsiTrack object or null
382
+     * if no stream is attached.
383
+     */
384
+    getMSID() {
385
+        const streamId = this.getStreamId();
386
+        const trackId = this.getTrackId();
407 387
 
408 388
 
409
-    return streamId && trackId ? `${streamId} ${trackId}` : null;
410
-};
389
+        return streamId && trackId ? `${streamId} ${trackId}` : null;
390
+    }
411 391
 
412
-/**
413
- * Sets new audio output device for track's DOM elements. Video tracks are
414
- * ignored.
415
- * @param {string} audioOutputDeviceId - id of 'audiooutput' device from
416
- *      navigator.mediaDevices.enumerateDevices(), '' for default device
417
- * @emits JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED
418
- * @returns {Promise}
419
- */
420
-JitsiTrack.prototype.setAudioOutput = function(audioOutputDeviceId) {
421
-    const self = this;
392
+    /**
393
+     * Sets new audio output device for track's DOM elements. Video tracks are
394
+     * ignored.
395
+     * @param {string} audioOutputDeviceId - id of 'audiooutput' device from
396
+     *      navigator.mediaDevices.enumerateDevices(), '' for default device
397
+     * @emits JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED
398
+     * @returns {Promise}
399
+     */
400
+    setAudioOutput(audioOutputDeviceId) {
401
+        if (!RTCUtils.isDeviceChangeAvailable('output')) {
402
+            return Promise.reject(
403
+                new Error('Audio output device change is not supported'));
404
+        }
422 405
 
423
-    if (!RTCUtils.isDeviceChangeAvailable('output')) {
424
-        return Promise.reject(
425
-            new Error('Audio output device change is not supported'));
426
-    }
406
+        // All audio communication is done through audio tracks, so ignore
407
+        // changing audio output for video tracks at all.
408
+        if (this.isVideoTrack()) {
409
+            return Promise.resolve();
410
+        }
427 411
 
428
-    // All audio communication is done through audio tracks, so ignore changing
429
-    // audio output for video tracks at all.
430
-    if (this.isVideoTrack()) {
431
-        return Promise.resolve();
412
+        return (
413
+            Promise.all(
414
+                    this.containers.map(
415
+                        element =>
416
+                            element.setSinkId(audioOutputDeviceId)
417
+                                .catch(error => {
418
+                                    logger.warn(
419
+                                        'Failed to change audio output device'
420
+                                            + ' on element. Default or'
421
+                                            + ' previously set audio output'
422
+                                            + ' device will be used.',
423
+                                        element,
424
+                                        error);
425
+                                    throw error;
426
+                                })))
427
+                .then(() => {
428
+                    this.emit(
429
+                        JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED,
430
+                        audioOutputDeviceId);
431
+                }));
432 432
     }
433
-
434
-    return (
435
-        Promise.all(
436
-                this.containers.map(
437
-                    element =>
438
-                        element.setSinkId(audioOutputDeviceId)
439
-                            .catch(error => {
440
-                                logger.warn(
441
-                                    'Failed to change audio output device on'
442
-                                        + ' element. Default or previously set'
443
-                                        + ' audio output device will be used.',
444
-                                    element,
445
-                                    error);
446
-                                throw error;
447
-                            })))
448
-            .then(() => {
449
-                self.eventEmitter.emit(
450
-                    JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED,
451
-                    audioOutputDeviceId);
452
-            }));
453
-};
433
+}

Laddar…
Avbryt
Spara