選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

strophe.jingle.sessionbase.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /**
  2. * Base class for ColibriFocus and JingleSession.
  3. * @param connection Strophe connection object
  4. * @param sid my session identifier(resource)
  5. * @constructor
  6. */
  7. function SessionBase(connection, sid){
  8. this.connection = connection;
  9. this.sid = sid;
  10. this.peerconnection
  11. = new TraceablePeerConnection(
  12. connection.jingle.ice_config,
  13. connection.jingle.pc_constraints);
  14. }
  15. SessionBase.prototype.modifySources = function (successCallback) {
  16. var self = this;
  17. this.peerconnection.modifySources(function(){
  18. $(document).trigger('setLocalDescription.jingle', [self.sid]);
  19. if(successCallback) {
  20. successCallback();
  21. }
  22. });
  23. };
  24. SessionBase.prototype.addSource = function (elem, fromJid) {
  25. this.peerconnection.addSource(elem);
  26. this.modifySources();
  27. };
  28. SessionBase.prototype.removeSource = function (elem, fromJid) {
  29. this.peerconnection.removeSource(elem);
  30. this.modifySources();
  31. };
  32. /**
  33. * Switches video streams.
  34. * @param new_stream new stream that will be used as video of this session.
  35. * @param oldStream old video stream of this session.
  36. * @param success_callback callback executed after successful stream switch.
  37. */
  38. SessionBase.prototype.switchStreams = function (new_stream, oldStream, success_callback) {
  39. var self = this;
  40. // Remember SDP to figure out added/removed SSRCs
  41. var oldSdp = new SDP(self.peerconnection.localDescription.sdp);
  42. self.peerconnection.removeStream(oldStream);
  43. self.connection.jingle.localVideo = new_stream;
  44. self.peerconnection.addStream(self.connection.jingle.localVideo);
  45. self.connection.jingle.localStreams = [];
  46. self.connection.jingle.localStreams.push(self.connection.jingle.localAudio);
  47. self.connection.jingle.localStreams.push(self.connection.jingle.localVideo);
  48. self.peerconnection.switchstreams = true;
  49. self.modifySources(function() {
  50. console.log('modify sources done');
  51. var newSdp = new SDP(self.peerconnection.localDescription.sdp);
  52. console.log("SDPs", oldSdp, newSdp);
  53. self.notifyMySSRCUpdate(oldSdp, newSdp);
  54. success_callback();
  55. });
  56. };
  57. /**
  58. * Figures out added/removed ssrcs and send update IQs.
  59. * @param old_sdp SDP object for old description.
  60. * @param new_sdp SDP object for new description.
  61. */
  62. SessionBase.prototype.notifyMySSRCUpdate = function (old_sdp, new_sdp) {
  63. var old_media = old_sdp.getMediaSsrcMap();
  64. var new_media = new_sdp.getMediaSsrcMap();
  65. //console.log("old/new medias: ", old_media, new_media);
  66. var toAdd = old_sdp.getNewMedia(new_sdp);
  67. var toRemove = new_sdp.getNewMedia(old_sdp);
  68. //console.log("to add", toAdd);
  69. //console.log("to remove", toRemove);
  70. if(Object.keys(toRemove).length > 0){
  71. this.sendSSRCUpdate(toRemove, null, false);
  72. }
  73. if(Object.keys(toAdd).length > 0){
  74. this.sendSSRCUpdate(toAdd, null, true);
  75. }
  76. };
  77. /**
  78. * Empty method that does nothing by default. It should send SSRC update IQs to session participants.
  79. * @param sdpMediaSsrcs array of
  80. * @param fromJid
  81. * @param isAdd
  82. */
  83. SessionBase.prototype.sendSSRCUpdate = function(sdpMediaSsrcs, fromJid, isAdd) {
  84. //FIXME: put default implementation here(maybe from JingleSession?)
  85. }
  86. /**
  87. * Sends SSRC update IQ.
  88. * @param sdpMediaSsrcs SSRCs map obtained from SDP.getNewMedia. Cntains SSRCs to add/remove.
  89. * @param sid session identifier that will be put into the IQ.
  90. * @param initiator initiator identifier.
  91. * @param toJid destination Jid
  92. * @param isAdd indicates if this is remove or add operation.
  93. */
  94. SessionBase.prototype.sendSSRCUpdateIq = function(sdpMediaSsrcs, sid, initiator, toJid, isAdd) {
  95. var self = this;
  96. var modify = $iq({to: toJid, type: 'set'})
  97. .c('jingle', {
  98. xmlns: 'urn:xmpp:jingle:1',
  99. action: isAdd ? 'addsource' : 'removesource',
  100. initiator: initiator,
  101. sid: sid
  102. }
  103. );
  104. // FIXME: only announce video ssrcs since we mix audio and dont need
  105. // the audio ssrcs therefore
  106. var modified = false;
  107. Object.keys(sdpMediaSsrcs).forEach(function(channelNum){
  108. modified = true;
  109. var channel = sdpMediaSsrcs[channelNum];
  110. modify.c('content', {name: channel.mediaType});
  111. // FIXME: not completly sure this operates on blocks and / or handles different ssrcs correctly
  112. // generate sources from lines
  113. Object.keys(channel.ssrcs).forEach(function(ssrcNum) {
  114. var mediaSsrc = channel.ssrcs[ssrcNum];
  115. modify.c('source', { xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
  116. modify.attrs({ssrc: mediaSsrc.ssrc});
  117. // iterate over ssrc lines
  118. mediaSsrc.lines.forEach(function (line) {
  119. var idx = line.indexOf(' ');
  120. var kv = line.substr(idx + 1);
  121. modify.c('parameter');
  122. if (kv.indexOf(':') == -1) {
  123. modify.attrs({ name: kv });
  124. } else {
  125. modify.attrs({ name: kv.split(':', 2)[0] });
  126. modify.attrs({ value: kv.split(':', 2)[1] });
  127. }
  128. modify.up(); // end of parameter
  129. });
  130. modify.up(); // end of source
  131. });
  132. modify.up(); // end of content
  133. });
  134. if (modified) {
  135. self.connection.sendIQ(modify,
  136. function (res) {
  137. console.info('got modify result', res);
  138. },
  139. function (err) {
  140. console.error('got modify error', err);
  141. }
  142. );
  143. } else {
  144. console.log('modification not necessary');
  145. }
  146. };
  147. // SDP-based mute by going recvonly/sendrecv
  148. // FIXME: should probably black out the screen as well
  149. SessionBase.prototype.hardMuteVideo = function (muted) {
  150. this.peerconnection.hardMuteVideo(muted);
  151. this.connection.jingle.localVideo.getVideoTracks().forEach(function (track) {
  152. track.enabled = !muted;
  153. });
  154. };