Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
  <head>
    <meta name="description" content="Upgrade Direct Call to Conference">
    <title>Circuit JS SDK</title>
    <script src="https://unpkg.com/circuit-sdk@beta"></script>
    <script src="https://rawgit.com/circuit/js-sdk/master/jsbin-template.js"></script>
    <link rel="stylesheet" href="https://rawgit.com/circuit/js-sdk/master/jsbin-template.css"> 
  </head>
  <body>
    <div id="template"></div>
    <div id="main" style="display:none">
      <section>
        <div>
          <input type="email" id="peerUser" placeholder="Callee's Circuit email" value="circuitsdk01@gmail.com"/>
          <button onclick="call()" id="callButton">Call</button>
        </div>
        <div id="addParticipantContainer" style="display: none">
          <input type="email" id="peerUser2" placeholder="3rd participant email" value="circuitsdk02@gmail.com"/>
          <button onclick="addParticipant()">Add participant</button>
        </div>
        <div>
          <button onclick="endCall()" id="endCallButton" style="display: none">End call</button>
        </div>
      </section>
      <section id="output">
        <div>Call state: <span id="callState"></span></div>
        <div>Media: <span id="media"></span></div>
        <div>Conversation ID: <span id="convId"></span></div>
        <div>Call ID: <span id="callId"></span></div>
    </div>
    <audio id="remoteAudio" autoplay="autoplay"></audio>
  </body>
</html>
 
/*jshint esnext: true */
// Create client instance
const client = new Circuit.Client({
  domain: jsBinTpl.domain,       // read domain from url
  client_id: jsBinTpl.client_id, // get client_id for domain
  scope: 'ALL'
});
// Template for Circuit JSBin examples. Builds generic part of page incl. login button.
const {logonButton, logoutButton, print} = jsBinTpl.init(client, template, {
  title: 'Circuit JS SDK: Upgrade Direct Call to Conference',
  description: 'Start a direct call with another Circuit user, then add a 3rd user which automatically creates a group conversation and moves the call to the new conversation',
  apiMethods: ['addParticipant', 'answerCall', 'makeCall', 'endCall'],
  prerequisites: []
});
// Local variables  
var _localUser;
var _call;
Circuit.logger.setLevel(Circuit.Enums.LogLevel.Debug);
logonButton.addEventListener('click', () => {
  !_localUser && addClientEventListeners();
  client.logon()
  .then(user => {
    print(`Successfully authenticated as ${user.displayName}`)
    _localUser = user;
  })
  .catch(err => {
    print(err);
    client.removeAllListeners();
  });
});
logoutButton.addEventListener('click', () => {
  client.logout()
  .catch(print);
});
function resetCallUI() {
  callState.textContent = '';
  media.textContent = '';
  callId.textContent = '';
  convId.textContent = '';
  callButton.style.display = '';
  endCallButton.style.display = 'none';
  remoteAudio.srcObject = null;
  addParticipantContainer.style.display = 'none';
}
function setCallUI(call) {
  _call = call;
  convId.textContent = _call.convId;
  callState.textContent = _call.state;
  callId.textContent = _call.callId;
  media.textContent = (_call.activeMediaType.audio ? 'audio' : '') + (_call.activeMediaType.video ? '+video' : '');
  callButton.style.display = 'none';
  endCallButton.style.display = '';
  if (_call.isEstablished) {
    remoteAudio.srcObject = _call.remoteAudioStream; 
  }
  addParticipantContainer.style.display = _call.isEstablished ? '' : 'none'; 
}
 
function addClientEventListeners() {
  client.addEventListener('callStatus', evt => {
    if (_call && _call.callId === evt.call.callId) {
      print('Received callStatus event - call = ', evt.call);
      setCallUI(evt.call);
    }
  });
  client.addEventListener('callIncoming', evt => {
    print('Received callIncoming event - call = ', evt.call);
    setCallUI(evt.call);
    // Automatically answer the call
    var mediaType = {audio: true, video: enableVideo.checked};
    client.answerCall(_call.callId, mediaType).then(() => {
      print('Call has been answered')
    }).catch(err => {
      print('Failed to answer call. ', err)
    });
  });
  client.addEventListener('callEnded', evt => {
    if (_call && _call.callId === evt.call.callId) {
      print('Received callEnded event - call = ', evt.call);
      _call = null;
      resetCallUI();
    } 
  }); 
}
function call() { 
  if (_call) {
    return;
  } 
  if (!client || !_localUser) { return alert('Caller is not logged in'); }
  if (!peerUser.value) { return alert('Callee email missing'); }
  var mediaType = {audio: true, video: false};
  client.makeCall(peerUser.value, mediaType)
    .then(setCallUI)
    .catch(err => {
      alert(`Error initiating a call with ${peerUser.value}. Error: ${err}`);
      print(err);
    });
}
function updateCall(conv) {  
  if (!conv) {
    return Promise.resolve();
  }
  return new Promise((resolve, reject) => { 
    client.findCall(conv.rtcSessionId)
      .then(call => {
        _call = call;
        resolve();
      })
      .catch(reject);
  });
}
function addParticipant() {
  client.getUserByEmail(peerUser2.value)
    .then(user => client.addParticipant(_call.convId, [user.userId], true))
    .then(updateCall) 
    .catch(err => {
      alert(`Error addding user to call. Error: ${err}`);
      print(err);
    });
}
function endCall() {
  if (_call) {
    client.endCall(_call.callId).then(() => {
      print('Successfully ended call');
      _call = null;
      resetCallUI();
    });
  }
}
Output 300px

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
rogerupro
0viewers