├── .github └── workflows │ └── job.yml ├── .gitignore ├── Jenkinsfile ├── README.md ├── app.json ├── chromeExten-plivo ├── README.md ├── background.js ├── css │ ├── bootstrap.min.css │ └── newstyle.css ├── icon.png ├── img │ └── plivo-logo.png ├── index.html ├── js │ └── customclient.js ├── lib │ ├── bootstrap.min.js │ └── jquery.min.js └── manifest.json ├── ci └── config.yml ├── electronApp-plivo ├── LICENSE.md ├── README.md ├── css │ ├── despic.png │ └── newstyle.css ├── img │ ├── favicon.png │ ├── micdenied.png │ └── plivo-logo.png ├── index.html ├── js │ └── customclient.js ├── lib │ ├── jquery-ui.min.js │ └── jquery.min.js ├── main.js └── package.json ├── example.html ├── img ├── audiodevice.png ├── audiodevicechange.png ├── callscreen.png ├── feedback.png ├── login.png ├── login_jwt.png ├── metrics.png ├── plivobrowserSdKLogin.png ├── settings.png └── volume.png ├── package-lock.json ├── package.json ├── server.js └── webApp-plivo ├── gulpfile.js ├── public ├── .DS_Store ├── css │ ├── intlTelInput.css │ ├── newstyle.css │ └── notify.css ├── img │ ├── PlivoIcon.png │ ├── background.svg │ ├── favicon.png │ ├── flags.png │ ├── flags@2x.png │ ├── micdenied.png │ ├── plivo-logo-new.png │ └── plivo-logo.png ├── js │ ├── customclient.js │ ├── plivowebsdk.js │ ├── processor.js │ └── utils.js ├── lib │ ├── intlTelInput.min.js │ ├── jquery.min.js │ └── notify.js ├── media │ └── us-ring.mp3 └── patches │ └── intlTelInput.patch └── views └── index.ejs /.github/workflows/job.yml: -------------------------------------------------------------------------------- 1 | name: Test npm install 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - beta 8 | pull_request: 9 | branches: 10 | - master 11 | - beta 12 | 13 | jobs: 14 | test: 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [11, 12, 14, 16, 18, 'node'] 20 | 21 | steps: 22 | - name: Checkout code 23 | uses: actions/checkout@v3 24 | 25 | - name: Setup Node.js 26 | uses: actions/setup-node@v3 27 | with: 28 | node-version: ${{ matrix.node-version }} 29 | 30 | - name: Install dependencies 31 | run: npm install 32 | 33 | - name: Verify npm install success 34 | run: echo "npm install succeeded for Node.js version ${{ matrix.node-version }}" 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!groovy 2 | 3 | @Library('plivo_standard_libs@support-ecs-tasks') _ 4 | 5 | deliveryPipeline ([ 6 | disableQAStages: true 7 | ]) 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Plivo Browser SDK v2.1 Example 2 | *This Plivo example shows how to use all the features in Plivo Browser SDK 2.1 using a simple webphone demo. This demo helps in making phone calls from web browser to both sip addresses and PSTN phone numbers without installing any plugins.* 3 | 4 |  5 | 6 | --- 7 | *To use the [live web phone demo](https://s3.amazonaws.com/plivobrowsersdk/v2/example.html)* 8 | 9 | *a. Sign up for a Plivo account here: https://console.plivo.com/accounts/register/* 10 | 11 | *b. Create a Plivo Endpoint here: https://console.plivo.com/voice/endpoints/add/* 12 | 13 | *c. Use this Plivo endpoint to login after deploying the application* 14 | 15 | --- 16 | 17 | ### Automatically Deploy to Heroku 18 | 19 | - Create a [Plivo account](https://console.plivo.com/accounts/register/) 20 | - Create and **verify** a Heroku account if you don't have one then click the button below. 21 | 22 | [](https://heroku.com/deploy) 23 | 24 | ### Deploying the application on your local setup 25 | 26 | ``` 27 | git clone https://github.com/plivo/plivo-browser-sdk2-examples.git 28 | npm install 29 | npm start 30 | ``` 31 | 32 | ### Initialization 33 | Include 34 | ```js 35 | 36 | ``` 37 | in the `
` tag before you include other javascript files dependent on the SDK. 38 | 39 | Lets create a `customclient.js` file and declare a variable `var plivoBrowserSdk;` 40 | This is where we initialise a new Plivo object by passing `options` as `plivoBrowserSdk = new window.Plivo(options);`. The application can set up listeners for events as shown in the `initPhone` function below. 41 | 42 | ```js 43 | var plivoBrowserSdk; 44 | function initPhone(username, password){ 45 | var options = refreshSettings(); 46 | plivoBrowserSdk = new window.Plivo(options); 47 | 48 | 49 | plivoBrowserSdk.client.on('onWebrtcNotSupported', onWebrtcNotSupported); 50 | plivoBrowserSdk.client.on('onLogin', onLogin); 51 | plivoBrowserSdk.client.on('onLogout', onLogout); 52 | plivoBrowserSdk.client.on('onLoginFailed', onLoginFailed); 53 | plivoBrowserSdk.client.on('onCallRemoteRinging', onCallRemoteRinging); 54 | plivoBrowserSdk.client.on('onIncomingCallCanceled', onIncomingCallCanceled); 55 | plivoBrowserSdk.client.on('onCallFailed', onCallFailed); 56 | plivoBrowserSdk.client.on('onCallAnswered', onCallAnswered); 57 | plivoBrowserSdk.client.on('onCallTerminated', onCallTerminated); 58 | plivoBrowserSdk.client.on('onCalling', onCalling); 59 | plivoBrowserSdk.client.on('onIncomingCall', onIncomingCall); 60 | plivoBrowserSdk.client.on('onMediaPermission', onMediaPermission); 61 | plivoBrowserSdk.client.on('mediaMetrics',mediaMetrics); 62 | plivoBrowserSdk.client.on('audioDeviceChange',audioDeviceChange); 63 | plivoBrowserSdk.client.on('onConnectionChange', onConnectionChange); 64 | plivoBrowserSdk.client.on('volume', volume); 65 | plivoBrowserSdk.client.setRingTone(true); 66 | plivoBrowserSdk.client.setRingToneBack(true); 67 | console.log('initPhone ready!') 68 | } 69 | ``` 70 | In the demo, `options` can be set from UI in the CONFIG menu. Once the CONFIG is updated clicking on LOGIN will boot the phone again. 71 | 72 | ### Document ready state 73 | 74 | >If you're directly calling login on page load, please make sure you do that only after HTML document ready. 75 | 76 | ```html 77 | 84 | ``` 85 | ### Login 86 |  87 | ```js 88 | function login(username, password) { 89 | if(username && password) { 90 | //start UI load spinner 91 | kickStartNow(); 92 | plivoBrowserSdk.client.login(username, password); 93 | } else { 94 | console.error('username/password missing!') 95 | } 96 | } 97 | 98 | $('#clickLogin').click(function(e){ 99 | var userName = $('#loginUser').val(); 100 | var password = $('#loginPwd').val(); 101 | login(userName, password); 102 | }); 103 | ``` 104 | 105 | ### Options 106 | *Options allow to disable tracking, setting codec type, enabling and disabling AEC/AGC etc. The list of all the settings can be found in the documentation page.* 107 |  108 | 109 | ```js 110 | var defaultSettings = { "debug":"DEBUG", "permOnClick":true, "codecs":["OPUS","PCMU"], "enableIPV6":false, "audioConstraints":{"optional":[{"googAutoGainControl":false}, {"googEchoCancellation":false}]}, "enableTracking":true, "closeProtection":false, "maxAverageBitrate":48000} 111 | function resetSettings(){ 112 | document.getElementById('loglevelbtn').value = "INFO" 113 | document.getElementById('onpageload').checked = true 114 | document.getElementById('monitorquality').checked = true 115 | document.getElementById('dontcloseprotect').checked = true 116 | document.getElementById('allowdscp').checked = true 117 | document.getElementById('noincoming').checked = true 118 | document.getElementById('msregionbtn').value = "AUTO" 119 | document.getElementById('averagebitrate').value = 48000 120 | localStorage.setItem('plivosettings',JSON.stringify(defaultSettings)); 121 | } 122 | 123 | function updateSettings(val){ 124 | let loglevel = document.getElementById('loglevelbtn').value; 125 | val.debug = loglevel; 126 | changeVal(val, document.getElementById('onpageload').checked, 'permOnClick', true); 127 | changeVal(val, document.getElementById('monitorquality').checked, "enableTracking", false); 128 | changeVal(val, document.getElementById('dontcloseprotect').checked, "closeProtection", true); 129 | changeVal(val, document.getElementById('allowdscp').checked, "dscp", false); 130 | changeVal(val, document.getElementById('noincoming').checked, "allowMultipleIncomingCalls", true); 131 | let clientRegion = document.getElementById('msregionbtn').value; 132 | if(clientRegion!='AUTO') { 133 | val.clientRegion = clientRegion; 134 | } 135 | let averagebitrate = document.getElementById('averagebitrate').value; 136 | val.maxAverageBitrate = parseInt(averagebitrate); 137 | localStorage.setItem('plivosettings',JSON.stringify(val)); 138 | console.log('plivosettings updated!') 139 | } 140 | // From UI triggers 141 | $('#updateSettings').click(function(e){ 142 | updateSettings(defaultSettings); 143 | }); 144 | 145 | $('#resetSettings').click(function(e){ 146 | resetSettings(); 147 | }); 148 | ``` 149 | ### Registration 150 | The following snippet shows how to handle registration related events in the application 151 | ```js 152 | function onReady(){ 153 | $('#phonestatus').html('trying to login...'); 154 | console.info('Ready'); 155 | } 156 | 157 | function onLogin(){ 158 | $('#phonestatus').html('online'); 159 | console.info('Logged in'); 160 | $('#makecall').attr('class', 'btn btn-success btn-block flatbtn'); 161 | $('#loginContainer').hide(); 162 | $('#callContainer').show(); 163 | } 164 | 165 | function onLoginFailed(reason){ 166 | console.info('onLoginFailed ',reason); 167 | customAlert('Login failure :',reason, 'warn'); 168 | } 169 | 170 | function onLogout(){ 171 | console.info('onLogout'); 172 | $('#loginContainer').show(); 173 | $('#callContainer').hide(); 174 | } 175 | ``` 176 | ### Outgoing call 177 | Given a number or SIP URI, this snippet shows how to make an outgoing call. The following snippet takes input from the dial pad UI. 178 | ```js 179 | $('#makecall').click(function(e){ 180 | var to = $('#toNumber').val().replace(" ",""); 181 | var callEnabled = $('#makecall').attr('class').match('disabled'); 182 | if(!to || !plivoBrowserSdk || !!callEnabled){return}; 183 | console.info('Click make call : ',to); 184 | plivoBrowserSdk.client.call(to); 185 | $('.phone').hide(); 186 | $('.AfterAnswer').show(); 187 | $('#boundType').html('Outgoing : '+to); 188 | $('#callDuration').html('00:00:00'); 189 | $('.callinfo').show(); 190 | }); 191 | ``` 192 | #### Outgoing call with dynamic caller ID 193 | There are cases where you need to set different caller ID for each campaign or some different reasons, then you can start using extraHeaders in `.call()` method 194 | ```js 195 | $('#makecall').click(function(e){ 196 | var to = $('#toNumber').val(); 197 | // pass caller Id 198 | var extraHeaders={}, 199 | customCallerId = localStorage.getItem('callerId'); // get the dynamic caller id 200 | if(customCallerId) { 201 | extraHeaders = {'X-PH-callerId': customCallerId}; 202 | } 203 | console.info('Click make call : ',to); 204 | plivoBrowserSdk.client.call(to, extraHeaders); 205 | }); 206 | ``` 207 | Capture this extraHeader in application side and use `callerId` attribute to set the callerId in [Dial](https://www.plivo.com/docs/xml/dial/) Element 208 | 209 | 210 | ### Handling Incoming calls 211 | By creating the `onIncomingCall` listener, the `plivoBrowserSdk` object can handle incoming calls to the Plivo Endpoint. 212 | 213 | ```js 214 | function onIncomingCall(callerName, extraHeaders){ 215 | console.info(callerName, extraHeaders); 216 | $('#boundType').html('Incomming :'); 217 | $('#callNum').html(callerName); 218 | $('#callDuration').html('00:00:00'); 219 | $('.callinfo').show(); 220 | $('.callScreen').show(); 221 | $('.inboundBeforeAnswer').show(); 222 | } 223 | function onIncomingCallCanceled(){ 224 | console.info('onIncomingCallCanceled'); 225 | callOff(); 226 | } 227 | ``` 228 | The following snippet shows how to answer an incoming call 229 | ```js 230 | $('.answerIncoming').click(function(){ 231 | console.info('Call accept clicked'); 232 | plivoBrowserSdk.client.answer(); 233 | $('.incomingCallDefault').hide(); 234 | $('.callinfo').show(); 235 | }); 236 | ``` 237 | The following snippet shows how to reject an incoming call 238 | ```js 239 | $('.rejectIncoming').click(function(){ 240 | console.info('Call rejected'); 241 | plivoBrowserSdk.client.reject(); 242 | $('.incomingCallDefault').hide(); 243 | }); 244 | ``` 245 | The following snippet shows how to ignore an incoming call 246 | ```js 247 | $('.ignoreIncoming').click(function(){ 248 | console.info('Call ignored'); 249 | plivoBrowserSdk.client.ignore(); 250 | $('.incomingCallDefault').hide(); 251 | }); 252 | ``` 253 | ### Terminating a call 254 | This code may be used to terminate a call. 255 | ```js 256 | $('.hangup').click(function(){ 257 | console.info('Hangup'); 258 | if(plivoBrowserSdk.client.callSession) { 259 | plivoBrowserSdk.client.hangup(); 260 | }else { 261 | callOff(); 262 | } 263 | }); 264 | ``` 265 | ### Implementing MediaMetrics 266 | 267 | This snippet shows how to handle network or media related events from the SDK. A simple dynamic UI to show notifications when some warning events get emitted from Plivo SDK 268 | 269 |  270 | 271 | Please check Chrome or Firefox console to see the complete info of the event. 272 | ```js 273 | function mediaMetrics(obj){ 274 | console.table([obj]); 275 | $(".alertmsg").prepend( 276 | '58 | ABC
59 | 60 |68 | DEF
69 | 70 |78 | GHI
79 | 80 |88 | JKL
89 | 90 |98 | MNO
99 | 100 |108 | PQRS
109 | 110 |118 | TUV
119 | 120 |128 | WXYZ
129 | 130 |145 | +
146 | 147 |179 | Answer
180 | 181 |185 | Reject
186 | 187 |191 | Hangup
192 | 193 |197 | Hangup
198 | 199 |203 | Microphone
204 | 205 |62 | ABC
63 | 64 |72 | DEF
73 | 74 |82 | GHI
83 | 84 |92 | JKL
93 | 94 |102 | MNO
103 | 104 |112 | PQRS
113 | 114 |122 | TUV
123 | 124 |132 | WXYZ
133 | 134 |149 | +
150 | 151 |183 | Answer
184 | 185 |189 | Reject
190 | 191 |195 | Hangup
196 | 197 |201 | Hangup
202 | 203 |207 | Microphone
208 | 209 |