您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

JitsiLocalTrack.js 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /* global Promise */
  2. var JitsiTrack = require("./JitsiTrack");
  3. var RTCBrowserType = require("./RTCBrowserType");
  4. var JitsiTrackEvents = require('../../JitsiTrackEvents');
  5. var RTCUtils = require("./RTCUtils");
  6. /**
  7. * Represents a single media track (either audio or video).
  8. * @constructor
  9. */
  10. function JitsiLocalTrack(stream, videoType,
  11. resolution, deviceId)
  12. {
  13. this.videoType = videoType;
  14. this.dontFireRemoveEvent = false;
  15. this.resolution = resolution;
  16. this.deviceId = deviceId;
  17. this.startMuted = false;
  18. this.ssrc = null;
  19. //FIXME: This dependacy is not necessary.
  20. this.conference = null;
  21. JitsiTrack.call(this, null, stream,
  22. function () {
  23. if(!this.dontFireRemoveEvent)
  24. this.eventEmitter.emit(
  25. JitsiTrackEvents.TRACK_STOPPED);
  26. this.dontFireRemoveEvent = false;
  27. }.bind(this));
  28. }
  29. JitsiLocalTrack.prototype = Object.create(JitsiTrack.prototype);
  30. JitsiLocalTrack.prototype.constructor = JitsiLocalTrack;
  31. /**
  32. * Mutes / unmutes the track.
  33. * @param mute {boolean} if true the track will be muted. Otherwise the track will be unmuted.
  34. */
  35. JitsiLocalTrack.prototype._setMute = function (mute) {
  36. if (this.isMuted() === mute) {
  37. return;
  38. }
  39. if(!this.rtc) {
  40. this.startMuted = mute;
  41. return;
  42. }
  43. var isAudio = this.type === JitsiTrack.AUDIO;
  44. this.dontFireRemoveEvent = false;
  45. if ((window.location.protocol != "https:") ||
  46. (isAudio) || this.videoType === "desktop" ||
  47. // FIXME FF does not support 'removeStream' method used to mute
  48. RTCBrowserType.isFirefox()) {
  49. var tracks = this._getTracks();
  50. for (var idx = 0; idx < tracks.length; idx++) {
  51. tracks[idx].enabled = !mute;
  52. }
  53. if(isAudio)
  54. this.rtc.room.setAudioMute(mute);
  55. else
  56. this.rtc.room.setVideoMute(mute);
  57. this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
  58. } else {
  59. if (mute) {
  60. this.dontFireRemoveEvent = true;
  61. this.rtc.room.removeStream(this.stream, function () {},
  62. {mtype: this.type, type: "mute", ssrc: this.ssrc});
  63. RTCUtils.stopMediaStream(this.stream);
  64. if(isAudio)
  65. this.rtc.room.setAudioMute(mute);
  66. else
  67. this.rtc.room.setVideoMute(mute);
  68. this.stream = null;
  69. this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
  70. //FIXME: Maybe here we should set the SRC for the containers to something
  71. } else {
  72. var self = this;
  73. var streamOptions = {
  74. devices: (isAudio ? ["audio"] : ["video"]),
  75. resolution: self.resolution
  76. };
  77. if (isAudio) {
  78. streamOptions['micDeviceId'] = self.deviceId;
  79. } else if(self.videoType === 'camera') {
  80. streamOptions['cameraDeviceId'] = self.deviceId;
  81. }
  82. RTCUtils.obtainAudioAndVideoPermissions(streamOptions)
  83. .then(function (streams) {
  84. var stream = null;
  85. for(var i = 0; i < streams.length; i++) {
  86. stream = streams[i];
  87. if(stream.type === self.type) {
  88. self.stream = stream.stream;
  89. self.videoType = stream.videoType;
  90. break;
  91. }
  92. }
  93. if(!stream)
  94. return;
  95. for(var i = 0; i < self.containers.length; i++)
  96. {
  97. self.containers[i]
  98. = RTCUtils.attachMediaStream(
  99. self.containers[i], self.stream);
  100. }
  101. self.rtc.room.addStream(self.stream,
  102. function () {
  103. if(isAudio)
  104. self.rtc.room.setAudioMute(mute);
  105. else
  106. self.rtc.room.setVideoMute(mute);
  107. self.eventEmitter.emit(
  108. JitsiTrackEvents.TRACK_MUTE_CHANGED);
  109. }, {
  110. mtype: self.type,
  111. type: "unmute",
  112. ssrc: self.ssrc,
  113. msid: self.getMSID()});
  114. });
  115. }
  116. }
  117. }
  118. /**
  119. * Stops sending the media track. And removes it from the HTML.
  120. * NOTE: Works for local tracks only.
  121. * @returns {Promise}
  122. */
  123. JitsiLocalTrack.prototype.stop = function () {
  124. var promise = Promise.resolve();
  125. if (this.conference){
  126. promise = this.conference.removeTrack(this);
  127. }
  128. if (this.stream) {
  129. RTCUtils.stopMediaStream(this.stream);
  130. this.detach();
  131. }
  132. return promise;
  133. };
  134. /**
  135. * Returns <tt>true</tt> - if the stream is muted
  136. * and <tt>false</tt> otherwise.
  137. * @returns {boolean} <tt>true</tt> - if the stream is muted
  138. * and <tt>false</tt> otherwise.
  139. */
  140. JitsiLocalTrack.prototype.isMuted = function () {
  141. if (!this.stream)
  142. return true;
  143. var tracks = [];
  144. var isAudio = this.type === JitsiTrack.AUDIO;
  145. if (isAudio) {
  146. tracks = this.stream.getAudioTracks();
  147. } else {
  148. if (!this.isActive())
  149. return true;
  150. tracks = this.stream.getVideoTracks();
  151. }
  152. for (var idx = 0; idx < tracks.length; idx++) {
  153. if(tracks[idx].enabled)
  154. return false;
  155. }
  156. return true;
  157. };
  158. /**
  159. * Private method. Updates rtc property of the track.
  160. * @param rtc the rtc instance.
  161. */
  162. JitsiLocalTrack.prototype._setRTC = function (rtc) {
  163. this.rtc = rtc;
  164. };
  165. /**
  166. * Updates the SSRC associated with the MediaStream in JitsiLocalTrack object.
  167. * @ssrc the new ssrc
  168. */
  169. JitsiLocalTrack.prototype._setSSRC = function (ssrc) {
  170. this.ssrc = ssrc;
  171. }
  172. //FIXME: This dependacy is not necessary. This is quick fix.
  173. /**
  174. * Sets the JitsiConference object associated with the track. This is temp
  175. * solution.
  176. * @param conference the JitsiConference object
  177. */
  178. JitsiLocalTrack.prototype._setConference = function(conference) {
  179. this.conference = conference;
  180. }
  181. /**
  182. * Gets the SSRC of this local track if it's available already or <tt>null</tt>
  183. * otherwise. That's because we don't know the SSRC until local description is
  184. * created.
  185. * @returns {string} or {null}
  186. */
  187. JitsiLocalTrack.prototype.getSSRC = function () {
  188. if (!this.rtc.room.session)
  189. return null;
  190. if (this.isAudioTrack()) {
  191. return this.rtc.room.session.localStreamsSSRC.audio;
  192. } else {
  193. return this.rtc.room.session.localStreamsSSRC.video;
  194. }
  195. };
  196. /**
  197. * Return true;
  198. */
  199. JitsiLocalTrack.prototype.isLocal = function () {
  200. return true;
  201. }
  202. module.exports = JitsiLocalTrack;