|
|
@@ -73,6 +73,12 @@ function JitsiLocalTrack(stream, track, mediaType, videoType, resolution,
|
|
73
|
73
|
// called.
|
|
74
|
74
|
this._realDeviceId = this.deviceId === '' ? undefined : this.deviceId;
|
|
75
|
75
|
|
|
|
76
|
+ /**
|
|
|
77
|
+ * Indicates that we have called RTCUtils.stopMediaStream for the
|
|
|
78
|
+ * MediaStream related to this JitsiTrack object.
|
|
|
79
|
+ */
|
|
|
80
|
+ this.stopStreamInProgress = false;
|
|
|
81
|
+
|
|
76
|
82
|
this._onDeviceListChanged = function (devices) {
|
|
77
|
83
|
self._setRealDeviceIdFromDeviceList(devices);
|
|
78
|
84
|
|
|
|
@@ -101,6 +107,17 @@ function JitsiLocalTrack(stream, track, mediaType, videoType, resolution,
|
|
101
|
107
|
|
|
102
|
108
|
RTCUtils.addListener(RTCEvents.DEVICE_LIST_CHANGED,
|
|
103
|
109
|
this._onDeviceListChanged);
|
|
|
110
|
+
|
|
|
111
|
+ if(this.isVideoTrack() && this.videoType === VideoType.CAMERA) {
|
|
|
112
|
+ this._setHandler("track_mute", () => {
|
|
|
113
|
+ if(this._checkForCameraIssues())
|
|
|
114
|
+ this.eventEmitter.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE);
|
|
|
115
|
+ });
|
|
|
116
|
+ this._setHandler("track_ended", () => {
|
|
|
117
|
+ if(this._checkForCameraIssues())
|
|
|
118
|
+ this.eventEmitter.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE);
|
|
|
119
|
+ });
|
|
|
120
|
+ }
|
|
104
|
121
|
}
|
|
105
|
122
|
|
|
106
|
123
|
JitsiLocalTrack.prototype = Object.create(JitsiTrack.prototype);
|
|
|
@@ -215,7 +232,7 @@ JitsiLocalTrack.prototype._setMute = function (mute) {
|
|
215
|
232
|
this._removeStreamFromConferenceAsMute(() => {
|
|
216
|
233
|
//FIXME: Maybe here we should set the SRC for the containers
|
|
217
|
234
|
// to something
|
|
218
|
|
- RTCUtils.stopMediaStream(this.stream);
|
|
|
235
|
+ this._stopMediaStream();
|
|
219
|
236
|
this._setStream(null);
|
|
220
|
237
|
resolve();
|
|
221
|
238
|
}, (err) => {
|
|
|
@@ -363,7 +380,7 @@ JitsiLocalTrack.prototype.dispose = function () {
|
|
363
|
380
|
}
|
|
364
|
381
|
|
|
365
|
382
|
if (this.stream) {
|
|
366
|
|
- RTCUtils.stopMediaStream(this.stream);
|
|
|
383
|
+ this._stopMediaStream();
|
|
367
|
384
|
this.detach();
|
|
368
|
385
|
}
|
|
369
|
386
|
|
|
|
@@ -468,7 +485,7 @@ JitsiLocalTrack.prototype._setByteSent = function (bytesSent) {
|
|
468
|
485
|
setTimeout(function () {
|
|
469
|
486
|
if(this._bytesSent <= 0){
|
|
470
|
487
|
//we are not receiving anything from the microphone
|
|
471
|
|
- this.eventEmitter.emit(JitsiTrackEvents.TRACK_AUDIO_NOT_WORKING);
|
|
|
488
|
+ this.eventEmitter.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE);
|
|
472
|
489
|
}
|
|
473
|
490
|
}.bind(this), 3000);
|
|
474
|
491
|
this._testByteSent = false;
|
|
|
@@ -516,5 +533,49 @@ JitsiLocalTrack.prototype.getCameraFacingMode = function () {
|
|
516
|
533
|
return undefined;
|
|
517
|
534
|
};
|
|
518
|
535
|
|
|
|
536
|
+/**
|
|
|
537
|
+ * Stops the associated MediaStream.
|
|
|
538
|
+ */
|
|
|
539
|
+JitsiLocalTrack.prototype._stopMediaStream = function () {
|
|
|
540
|
+ this.stopStreamInProgress = true;
|
|
|
541
|
+ RTCUtils.stopMediaStream(this.stream);
|
|
|
542
|
+ this.stopStreamInProgress = false;
|
|
|
543
|
+}
|
|
|
544
|
+
|
|
|
545
|
+/**
|
|
|
546
|
+ * Detects camera issues on ended and mute events from MediaStreamTrack.
|
|
|
547
|
+ * @returns {boolean} true if an issue is detected and false otherwise
|
|
|
548
|
+ */
|
|
|
549
|
+JitsiLocalTrack.prototype._checkForCameraIssues = function () {
|
|
|
550
|
+ if(!this.isVideoTrack() || this.stopStreamInProgress ||
|
|
|
551
|
+ this.videoType === VideoType.DESKTOP)
|
|
|
552
|
+ return false;
|
|
|
553
|
+
|
|
|
554
|
+ return !this._isReceivingData();
|
|
|
555
|
+}
|
|
|
556
|
+
|
|
|
557
|
+/**
|
|
|
558
|
+ * Checks whether the attached MediaStream is reveiving data from source or
|
|
|
559
|
+ * not. If the stream property is null(because of mute or another reason) this
|
|
|
560
|
+ * method will return false.
|
|
|
561
|
+ * NOTE: This method doesn't indicate problem with the streams directly.
|
|
|
562
|
+ * For example in case of video mute the method will return false or if the
|
|
|
563
|
+ * user has disposed the track.
|
|
|
564
|
+ * @returns {boolean} true if the stream is receiving data and false otherwise.
|
|
|
565
|
+ */
|
|
|
566
|
+JitsiLocalTrack.prototype._isReceivingData = function () {
|
|
|
567
|
+ if(!this.stream)
|
|
|
568
|
+ return false;
|
|
|
569
|
+ // In older version of the spec there is no muted property and
|
|
|
570
|
+ // readyState can have value muted. In the latest versions
|
|
|
571
|
+ // readyState can have values "live" and "ended" and there is
|
|
|
572
|
+ // muted boolean property. If the stream is muted that means that
|
|
|
573
|
+ // we aren't receiving any data from the source. We want to notify
|
|
|
574
|
+ // the users for error if the stream is muted or ended on it's
|
|
|
575
|
+ // creation.
|
|
|
576
|
+ return this.stream.getTracks().some(track =>
|
|
|
577
|
+ ((!("readyState" in track) || track.readyState === "live")
|
|
|
578
|
+ && (!("muted" in track) || track.muted === false)));
|
|
|
579
|
+}
|
|
519
|
580
|
|
|
520
|
581
|
module.exports = JitsiLocalTrack;
|