webrtc.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. var util = require('util');
  2. var webrtcSupport = require('webrtcsupport');
  3. var mockconsole = require('mockconsole');
  4. var localMedia = require('localmedia');
  5. var Peer = require('./peer');
  6. function WebRTC(opts) {
  7. var self = this;
  8. var options = opts || {};
  9. var config = this.config = {
  10. debug: false,
  11. // makes the entire PC config overridable
  12. peerConnectionConfig: {
  13. iceServers: [{'urls': 'stun:stun.l.google.com:19302'}]
  14. },
  15. peerConnectionConstraints: {
  16. optional: []
  17. },
  18. receiveMedia: {
  19. offerToReceiveAudio: 1,
  20. offerToReceiveVideo: 1
  21. },
  22. enableDataChannels: true
  23. };
  24. var item;
  25. // We also allow a 'logger' option. It can be any object that implements
  26. // log, warn, and error methods.
  27. // We log nothing by default, following "the rule of silence":
  28. // http://www.linfo.org/rule_of_silence.html
  29. this.logger = function () {
  30. // we assume that if you're in debug mode and you didn't
  31. // pass in a logger, you actually want to log as much as
  32. // possible.
  33. if (opts.debug) {
  34. return opts.logger || console;
  35. } else {
  36. // or we'll use your logger which should have its own logic
  37. // for output. Or we'll return the no-op.
  38. return opts.logger || mockconsole;
  39. }
  40. }();
  41. // set options
  42. for (item in options) {
  43. if (options.hasOwnProperty(item)) {
  44. this.config[item] = options[item];
  45. }
  46. }
  47. // check for support
  48. if (!webrtcSupport.support) {
  49. this.logger.error('Your browser doesn\'t seem to support WebRTC');
  50. }
  51. // where we'll store our peer connections
  52. this.peers = [];
  53. // call localMedia constructor
  54. localMedia.call(this, this.config);
  55. this.on('speaking', function () {
  56. if (!self.hardMuted) {
  57. // FIXME: should use sendDirectlyToAll, but currently has different semantics wrt payload
  58. self.peers.forEach(function (peer) {
  59. if (peer.enableDataChannels) {
  60. var dc = peer.getDataChannel('hark');
  61. if (dc.readyState != 'open') return;
  62. dc.send(JSON.stringify({type: 'speaking'}));
  63. }
  64. });
  65. }
  66. });
  67. this.on('stoppedSpeaking', function () {
  68. if (!self.hardMuted) {
  69. // FIXME: should use sendDirectlyToAll, but currently has different semantics wrt payload
  70. self.peers.forEach(function (peer) {
  71. if (peer.enableDataChannels) {
  72. var dc = peer.getDataChannel('hark');
  73. if (dc.readyState != 'open') return;
  74. dc.send(JSON.stringify({type: 'stoppedSpeaking'}));
  75. }
  76. });
  77. }
  78. });
  79. this.on('volumeChange', function (volume, treshold) {
  80. if (!self.hardMuted) {
  81. // FIXME: should use sendDirectlyToAll, but currently has different semantics wrt payload
  82. self.peers.forEach(function (peer) {
  83. if (peer.enableDataChannels) {
  84. var dc = peer.getDataChannel('hark');
  85. if (dc.readyState != 'open') return;
  86. dc.send(JSON.stringify({type: 'volume', volume: volume }));
  87. }
  88. });
  89. }
  90. });
  91. // log events in debug mode
  92. if (this.config.debug) {
  93. this.on('*', function (event, val1, val2) {
  94. var logger;
  95. // if you didn't pass in a logger and you explicitly turning on debug
  96. // we're just going to assume you're wanting log output with console
  97. if (self.config.logger === mockconsole) {
  98. logger = console;
  99. } else {
  100. logger = self.logger;
  101. }
  102. logger.log('event:', event, val1, val2);
  103. });
  104. }
  105. }
  106. util.inherits(WebRTC, localMedia);
  107. WebRTC.prototype.createPeer = function (opts) {
  108. var peer;
  109. opts.parent = this;
  110. peer = new Peer(opts);
  111. this.peers.push(peer);
  112. return peer;
  113. };
  114. // removes peers
  115. WebRTC.prototype.removePeers = function (id, type) {
  116. this.getPeers(id, type).forEach(function (peer) {
  117. peer.end();
  118. });
  119. };
  120. // fetches all Peer objects by session id and/or type
  121. WebRTC.prototype.getPeers = function (sessionId, type) {
  122. return this.peers.filter(function (peer) {
  123. return (!sessionId || peer.id === sessionId) && (!type || peer.type === type);
  124. });
  125. };
  126. // sends message to all
  127. WebRTC.prototype.sendToAll = function (message, payload) {
  128. this.peers.forEach(function (peer) {
  129. peer.send(message, payload);
  130. });
  131. };
  132. // sends message to all using a datachannel
  133. // only sends to anyone who has an open datachannel
  134. WebRTC.prototype.sendDirectlyToAll = function (channel, message, payload) {
  135. this.peers.forEach(function (peer) {
  136. if (peer.enableDataChannels) {
  137. peer.sendDirectly(channel, message, payload);
  138. }
  139. });
  140. };
  141. module.exports = WebRTC;