Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

JitsiLocalTrack.js 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. // We want to keep up with postponed events which should have been fired
  165. // on "attach" call, but for local track we not always have the conference
  166. // before attaching. However this may result in duplicated events if they
  167. // have been triggered on "attach" already.
  168. for(var i = 0; i < this.containers.length; i++)
  169. {
  170. this._maybeFireTrackAttached(this.containers[i]);
  171. }
  172. };
  173. /**
  174. * Updates the SSRC associated with the MediaStream in JitsiLocalTrack object.
  175. * @ssrc the new ssrc
  176. */
  177. JitsiLocalTrack.prototype._setSSRC = function (ssrc) {
  178. this.ssrc = ssrc;
  179. }
  180. //FIXME: This dependacy is not necessary. This is quick fix.
  181. /**
  182. * Sets the JitsiConference object associated with the track. This is temp
  183. * solution.
  184. * @param conference the JitsiConference object
  185. */
  186. JitsiLocalTrack.prototype._setConference = function(conference) {
  187. this.conference = conference;
  188. }
  189. /**
  190. * Gets the SSRC of this local track if it's available already or <tt>null</tt>
  191. * otherwise. That's because we don't know the SSRC until local description is
  192. * created.
  193. * @returns {string} or {null}
  194. */
  195. JitsiLocalTrack.prototype.getSSRC = function () {
  196. if (!this.rtc.room.session)
  197. return null;
  198. if (this.isAudioTrack()) {
  199. return this.rtc.room.session.localStreamsSSRC.audio;
  200. } else {
  201. return this.rtc.room.session.localStreamsSSRC.video;
  202. }
  203. };
  204. /**
  205. * Return true;
  206. */
  207. JitsiLocalTrack.prototype.isLocal = function () {
  208. return true;
  209. }
  210. module.exports = JitsiLocalTrack;