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.

JitsiTrack.js 6.6KB

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