You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. var RTCBrowserType = require("./RTCBrowserType");
  2. var JitsiTrackEvents = require("../../JitsiTrackEvents");
  3. var EventEmitter = require("events");
  4. /**
  5. * This implements 'onended' callback normally fired by WebRTC after the stream
  6. * is stopped. There is no such behaviour yet in FF, so we have to add it.
  7. * @param jitsiTrack our track object holding the original WebRTC stream object
  8. * to which 'onended' handling will be added.
  9. */
  10. function implementOnEndedHandling(jitsiTrack) {
  11. var stream = jitsiTrack.getOriginalStream();
  12. var originalStop = stream.stop;
  13. stream.stop = function () {
  14. originalStop.apply(stream);
  15. if (jitsiTrack.isActive()) {
  16. stream.onended();
  17. }
  18. };
  19. }
  20. /**
  21. * Adds onended/oninactive handler to a MediaStream.
  22. * @param mediaStream a MediaStream to attach onended/oninactive handler
  23. * @param handler the handler
  24. */
  25. function addMediaStreamInactiveHandler(mediaStream, handler) {
  26. if(RTCBrowserType.isTemasysPluginUsed()) {
  27. // themasys
  28. mediaStream.attachEvent('ended', function () {
  29. handler(mediaStream);
  30. });
  31. }
  32. else {
  33. if(typeof mediaStream.active !== "undefined")
  34. mediaStream.oninactive = handler;
  35. else
  36. mediaStream.onended = handler;
  37. }
  38. }
  39. /**
  40. * Represents a single media track (either audio or video).
  41. * @constructor
  42. * @param rtc the rtc instance
  43. * @param stream the stream
  44. * @param streamInactiveHandler the function that will handle
  45. * onended/oninactive events of the stream.
  46. */
  47. function JitsiTrack(rtc, stream, streamInactiveHandler)
  48. {
  49. /**
  50. * Array with the HTML elements that are displaying the streams.
  51. * @type {Array}
  52. */
  53. this.containers = [];
  54. this.rtc = rtc;
  55. this.stream = stream;
  56. this.eventEmitter = new EventEmitter();
  57. this.audioLevel = -1;
  58. this.type = (this.stream.getVideoTracks().length > 0)?
  59. JitsiTrack.VIDEO : JitsiTrack.AUDIO;
  60. if(this.type == "audio") {
  61. this._getTracks = function () {
  62. return this.stream.getAudioTracks();
  63. }.bind(this);
  64. } else {
  65. this._getTracks = function () {
  66. return this.stream.getVideoTracks();
  67. }.bind(this);
  68. }
  69. if (RTCBrowserType.isFirefox() && this.stream) {
  70. implementOnEndedHandling(this);
  71. }
  72. if(stream)
  73. addMediaStreamInactiveHandler(stream, streamInactiveHandler);
  74. }
  75. /**
  76. * JitsiTrack video type.
  77. * @type {string}
  78. */
  79. JitsiTrack.VIDEO = "video";
  80. /**
  81. * JitsiTrack audio type.
  82. * @type {string}
  83. */
  84. JitsiTrack.AUDIO = "audio";
  85. /**
  86. * Returns the type (audio or video) of this track.
  87. */
  88. JitsiTrack.prototype.getType = function() {
  89. return this.type;
  90. };
  91. /**
  92. * Returns the RTCMediaStream from the browser (?).
  93. */
  94. JitsiTrack.prototype.getOriginalStream = function() {
  95. return this.stream;
  96. }
  97. /**
  98. * Mutes the track.
  99. */
  100. JitsiTrack.prototype.mute = function () {
  101. this._setMute(true);
  102. }
  103. /**
  104. * Unmutes the stream.
  105. */
  106. JitsiTrack.prototype.unmute = function () {
  107. this._setMute(false);
  108. }
  109. /**
  110. * Attaches the MediaStream of this track to an HTML container (?).
  111. * Adds the container to the list of containers that are displaying the track.
  112. * @param container the HTML container
  113. */
  114. JitsiTrack.prototype.attach = function (container) {
  115. if(this.stream)
  116. require("./RTCUtils").attachMediaStream(container, this.stream);
  117. this.containers.push(container);
  118. }
  119. /**
  120. * Removes the track from the passed HTML container.
  121. * @param container the HTML container. If <tt>null</tt> all containers are removed.
  122. */
  123. JitsiTrack.prototype.detach = function (container) {
  124. for(var i = 0; i < this.containers.length; i++)
  125. {
  126. if(this.containers[i].is(container))
  127. {
  128. this.containers.splice(i,1);
  129. }
  130. if(!container)
  131. {
  132. this.containers[i].find(">video").remove();
  133. }
  134. }
  135. if(container)
  136. $(container).find(">video").remove();
  137. }
  138. /**
  139. * Stops sending the media track. And removes it from the HTML.
  140. * NOTE: Works for local tracks only.
  141. */
  142. JitsiTrack.prototype.stop = function () {
  143. }
  144. /**
  145. * Returns true if this is a video track and the source of the video is a
  146. * screen capture as opposed to a camera.
  147. */
  148. JitsiTrack.prototype.isScreenSharing = function(){
  149. }
  150. /**
  151. * Returns id of the track.
  152. * @returns {string} id of the track or null if this is fake track.
  153. */
  154. JitsiTrack.prototype.getId = function () {
  155. var tracks = this.stream.getTracks();
  156. if(!tracks || tracks.length === 0)
  157. return null;
  158. return tracks[0].id;
  159. };
  160. /**
  161. * Checks whether the MediaStream is avtive/not ended.
  162. * When there is no check for active we don't have information and so
  163. * will return that stream is active (in case of FF).
  164. * @returns {boolean} whether MediaStream is active.
  165. */
  166. JitsiTrack.prototype.isActive = function () {
  167. if((typeof this.stream.active !== "undefined"))
  168. return this.stream.active;
  169. else
  170. return true;
  171. };
  172. /**
  173. * Attaches a handler for events(For example - "audio level changed".).
  174. * All possible event are defined in JitsiTrackEvents.
  175. * @param eventId the event ID.
  176. * @param handler handler for the event.
  177. */
  178. JitsiTrack.prototype.on = function (eventId, handler) {
  179. if(this.eventEmitter)
  180. this.eventEmitter.on(eventId, handler);
  181. }
  182. /**
  183. * Removes event listener
  184. * @param eventId the event ID.
  185. * @param [handler] optional, the specific handler to unbind
  186. */
  187. JitsiTrack.prototype.off = function (eventId, handler) {
  188. if(this.eventEmitter)
  189. this.eventEmitter.removeListener(eventId, handler);
  190. }
  191. // Common aliases for event emitter
  192. JitsiTrack.prototype.addEventListener = JitsiTrack.prototype.on;
  193. JitsiTrack.prototype.removeEventListener = JitsiTrack.prototype.off;
  194. /**
  195. * Sets the audio level for the stream
  196. * @param audioLevel the new audio level
  197. */
  198. JitsiTrack.prototype.setAudioLevel = function (audioLevel) {
  199. if(this.audioLevel !== audioLevel) {
  200. this.eventEmitter.emit(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
  201. audioLevel);
  202. this.audioLevel = audioLevel;
  203. }
  204. }
  205. module.exports = JitsiTrack;