npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

ecmascript-webrtc-sipml

v1.0.11

Published

This is a Webrtc library for Angular based on [Sipml5](https://www.doubango.org/sipml5/). In fact, It's a bridge between [Sipml5](https://www.doubango.org/sipml5/) and Angular.

Readme

Sipml5 webrtc for Ecmascript

Can be used in Angular and React

This is a Webrtc library for Ecmascript based on Sipml5. It's a bridge between Sipml5 and Ecmascript.

Installation

Install via npm

npm i ecmascript-webrtc-sipml

Usage

import SIPmlWebRTC into your component

import SIPml from 'ecmascript-webrtc-sipml';

Add the following tags into your html component (audio tags are used to play voice call or ringtone)

<audio id="audio_remote" autoplay="autoplay"></audio>
<audio id="ringtone" loop src="./../assets/sounds/ringtone.wav"> </audio>
<audio id="ringbacktone" loop src="./../assets/sounds/ringbacktone.wav"> </audio>
<audio id="dtmfTone" src="./../assets/sounds/dtmf.wav"> </audio>
<svg class="voicecall" xmlns="http://www.w3.org/2000/svg" version="1.1" id="microphone" data-container-transform="translate(3)" viewBox="0 0 16 20" x="0px" y="0px"><path d="M4.5 0c-1.4 0-2.5 1.1-2.5 2.5v5c0 1.4 1.1 2.5 2.5 2.5s2.5-1.1 2.5-2.5v-5c0-1.4-1.1-2.5-2.5-2.5zm-4.125 6.188a.5.5 0 0 0-.375.5v.813c0 2.302 1.763 4.184 4 4.438v3.063h-2c-.6 0-1 .4-1 1h7c0-.6-.4-1-1-1h-2v-3.063c2.237-.254 4-2.136 4-4.438v-.813a.5.5 0 1 0-1 0v.813c0 1.927-1.573 3.5-3.5 3.5s-3.5-1.573-3.5-3.5v-.813a.5.5 0 0 0-.563-.5.5.5 0 0 0-.063 0z" transform="translate(3)"/></svg>
<input type="button" class="btn btn-success" id="btnRegister" value="LogIn" (click)='sipRegister();' />
<input type="button" class="btn btn-success" id="sipCall2" value="Audio Call" (click)="sipCall('call-audio')" />
<input type="button" class="btn btn-success" id="btnCall" value="Answer" (click)="sipCall('call-audio')" />
<input type="button" class="btn btn-success" id="sipHangUp" value="Reject" (click)="sipHangUp()" />
<input type="button" class="btn btn-success" id="btnHangup" value="Hang Up" (click)="sipHangUp()" />
<input type="button" class="btn btn-danger" id="btnUnRegister" value="LogOut" (click)='sipUnRegister();' />
<input type="button" class="btn btn-danger" id="btnTransfer" value="Transfer" (click)='sipTransfer();' />

Then, you need to login or register with your information

export class AppComponent implements OnInit {
    sTransferNumber;
    oRingTone; oRingbackTone;
    oSipStack; oSipSessionRegister; oSipSessionCall; oSipSessionTransferCall;
    videoRemote; videoLocal; audioRemote;
    bFullScreen = false;
    oNotifICall;
    bDisableVideo = false;
    viewVideoLocal; viewVideoRemote; viewLocalScreencast; // <video> (webrtc) or <div> (webrtc4all)
    oConfigCall;
    oReadyStateTimer;
    ringtone;ringbacktone;
    constructor(){
        this.ringtone = document.getElementById("ringtone");
        this.ringbacktone = document.getElementById("ringbacktone");

    }
    sipRegister = () => {
        try {
            // enable notifications if not already done
            // if (window.webkitNotifications && window.webkitNotifications.checkPermission() != 0) {
            //     window.webkitNotifications.requestPermission();
            // }

            Notification.requestPermission();
            // save credentials
            //saveCredentials();

            // update debug level to be sure new values will be used if the user haven't updated the page
            SIPml.setDebugLevel((window.localStorage && window.localStorage.getItem('org.doubango.expert.disable_debug') == "true") ? "error" : "info");

            // create SIP stack
            this.oSipStack = new SIPml.Stack({
                realm: "xxx.xxx.xxx.xx",
                impi: "yyyy",
                impu: "sip:[email protected]",
                password: "yyyy",
                display_name: "yyyy",
                websocket_proxy_url: "wss://xxx.xxx.xxx.xx:8089/ws",
                outbound_proxy_url: "",//(window.localStorage ? window.localStorage.getItem('org.doubango.expert.sip_outboundproxy_url') : null),
                ice_servers: "",//(window.localStorage ? window.localStorage.getItem('org.doubango.expert.ice_servers') : null),
                enable_rtcweb_breaker: "",//(window.localStorage ? window.localStorage.getItem('org.doubango.expert.enable_rtcweb_breaker') == "true" : false),
                events_listener: { events: '*', listener: this.onSipEventStack },
                enable_early_ims: "",//(window.localStorage ? window.localStorage.getItem('org.doubango.expert.disable_early_ims') != "true" : true), // Must be true unless you're using a real IMS network
                enable_media_stream_cache: "",//(window.localStorage ? window.localStorage.getItem('org.doubango.expert.enable_media_caching') == "true" : false),
                //bandwidth: (window.localStorage ? tsk_string_to_object(window.localStorage.getItem('org.doubango.expert.bandwidth')) : null), // could be redefined a session-level
                //video_size: (window.localStorage ? tsk_string_to_object(window.localStorage.getItem('org.doubango.expert.video_size')) : null), // could be redefined a session-level
                sip_headers: [
                        { name: 'User-Agent', value: 'IM-client/OMA1.0 sipML5-v1.2016.03.04' },
                        { name: 'Organization', value: 'Doubango Telecom' }
                ]
            }
            );
            if (this.oSipStack.start() != 0) {
                console.log('<b>Failed to start the SIP stack</b>');
            }
            else return;
        }
        catch (e) {
            console.log("<b>2:" + e + "</b>");
        }
        //btnRegister.disabled = false;
       
    }
}

Call Control

Call Transfer

sipTransfer = () => {
    if (this.oSipSessionCall) {
        var s_destination = prompt('Enter destination number', '');
        //if (!tsk_string_is_null_or_empty(s_destination)) {
            //btnTransfer.disabled = true;
            if (this.oSipSessionCall.transfer(s_destination) != 0) {
                console.log('<i>Call transfer failed</i>');
                //btnTransfer.disabled = false;
                return;
            }
            console.log('<i>Transfering the call...</i>');
        //}
    }
}

Start Audio call

this.oSipSessionCall.call("xxxx") start a audio call to xxxx number

sipCall = (s_type) => {
    let audioRemote = document.getElementById("audio_remote");
    this.oConfigCall = {
        audio_remote: audioRemote,
        video_local: null,
        video_remote: null,
        screencast_window_id: 0x00000000, // entire desktop
        bandwidth: { audio: undefined, video: undefined },
        video_size: { minWidth: undefined, minHeight: undefined, maxWidth: undefined, maxHeight: undefined },
        events_listener: { events: '*', listener: this.onSipEventSession },
        sip_caps: [
                        { name: '+g.oma.sip-im' },
                        { name: 'language', value: '\"en,fr\"' }
        ]
    };

    if (this.oSipStack && !this.oSipSessionCall) {
        if (s_type == 'call-screenshare') {
            if (!SIPml.isScreenShareSupported()) {
                alert('Screen sharing not supported. Are you using chrome 26+?');
                return;
            }
            if (!location.protocol.match('https')) {
                if (confirm("Screen sharing requires https://. Do you want to be redirected?")) {
                    this.sipUnRegister();
                    //window.location = 'https://ns313841.ovh.net/call.htm';
                }
                return;
            }
        }
        //btnCall.disabled = true;
        //btnHangUp.disabled = false;

        if (window.localStorage) {
            //oConfigCall.bandwidth = tsk_string_to_object(window.localStorage.getItem('org.doubango.expert.bandwidth')); // already defined at stack-level but redifined to use latest values
            //oConfigCall.video_size = tsk_string_to_object(window.localStorage.getItem('org.doubango.expert.video_size')); // already defined at stack-level but redifined to use latest values
        }
        debugger;

        // create call session
        this.oSipSessionCall = this.oSipStack.newSession(s_type, this.oConfigCall);
        // make call
        if (this.oSipSessionCall.call("xxxx") != 0) {
            this.oSipSessionCall = null;
            console.log('Failed to make call');
            //btnCall.disabled = false;
            //btnHangUp.disabled = true;
            return;
        }
        //saveCallOptions();
    }
    else if (this.oSipSessionCall) {
        console.log('<i>Connecting...</i>');
        this.oSipSessionCall.accept(this.oConfigCall);
    }
}

Logout or signup

sipUnRegister = () => {
    if (this.oSipStack) {
        this.oSipStack.stop(); // shutdown all sessions
    }
}

HangUp

sipHangUp = () => {
    if (this.oSipSessionCall) {
        console.log('<i>Terminating the call...</i>');
        this.oSipSessionCall.hangup({ events_listener: { events: '*', listener: this.onSipEventSession } });
    }
}

Mute / Unmute

    sipToggleMute= () => {
        if (this.oSipSessionCall) {
            var i_ret;
            var bMute = !this.oSipSessionCall.bMute;
            //txtCallStatus.innerHTML = bMute ? '<i>Mute the call...</i>' : '<i>Unmute the call...</i>';
            i_ret = this.oSipSessionCall.mute('audio'/*could be 'video'*/, bMute);
            if (i_ret != 0) {
                //txtCallStatus.innerHTML = '<i>Mute / Unmute failed</i>';
                return;
            }
            this.oSipSessionCall.bMute = bMute;
            //btnMute.value = bMute ? "Unmute" : "Mute";
        }
    }

Other Important functions

startRingTone = () => {

    try { this.ringtone.play(); }
    catch (e) { }
}
stopRingTone = () => {
    try { this.ringtone.pause(); }
    catch (e) { }
}

startRingbackTone = () => {
    try { this.ringbacktone.play(); }
    catch (e) { }
}

stopRingbackTone = () => {
    try { this.ringbacktone.pause(); }
    catch (e) { }
}
onSipEventStack = (e) => {
    console.log('==stack event = ' + e.type);
    switch (e.type) {
        case 'started':
            {
                // catch exception for IE (DOM not ready)
                try {
                    // LogIn (REGISTER) as soon as the stack finish starting
                    this.oSipSessionRegister = this.oSipStack.newSession('register', {
                        expires: 200,
                        events_listener: { events: '*', listener: this.onSipEventSession },
                        sip_caps: [
                                    { name: '+g.oma.sip-im', value: null },
                                    //{ name: '+sip.ice' }, // rfc5768: FIXME doesn't work with Polycom TelePresence
                                    { name: '+audio', value: null },
                                    { name: 'language', value: '\"en,fr\"' }
                        ]
                    });
                    this.oSipSessionRegister.register();
                }
                catch (e) {
                    console.log("<b>1:" + e + "</b>");
                    //btnRegister.disabled = false;
                }
                break;
            }
        case 'stopping': case 'stopped': case 'failed_to_start': case 'failed_to_stop':
            {
                var bFailure = (e.type == 'failed_to_start') || (e.type == 'failed_to_stop');
                this.oSipStack = null;
                this.oSipSessionRegister = null;
                this.oSipSessionCall = null;

                //uiOnConnectionEvent(false, false);

                this.stopRingbackTone();
                this.stopRingTone();

                //uiVideoDisplayShowHide(false);
                //divCallOptions.style.opacity = 0;

                //txtCallStatus.innerHTML = '';
                console.log(bFailure ? "<i>Disconnected: <b>" + e.description + "</b></i>" : "<i>Disconnected</i>")

                break;
            }

        case 'i_new_call':
            {
                if (this.oSipSessionCall) {
                    // do not accept the incoming call if we're already 'in call'
                    e.newSession.hangup(); // comment this line for multi-line support
                }
                else {
                    this.oSipSessionCall = e.newSession;
                    // start listening for events
                    this.oSipSessionCall.setConfiguration(this.oConfigCall);

                    alert("Answer / Reject")
                    console.log("Answer / Reject")
                    //uiBtnCallSetText('Answer');
                    //btnHangUp.value = 'Reject';
                    //btnCall.disabled = false;
                    //btnHangUp.disabled = false;

                    this.startRingTone();

                    var sRemoteNumber = (this.oSipSessionCall.getRemoteFriendlyName() || 'unknown');
                    console.log("<i>Incoming call from [<b>" + sRemoteNumber + "</b>]</i>");
                    //showNotifICall(sRemoteNumber);
                }
                break;
            }

        case 'm_permission_requested':
            {
                //divGlassPanel.style.visibility = 'visible';
                break;
            }
        case 'm_permission_accepted':
        case 'm_permission_refused':
            {
                //divGlassPanel.style.visibility = 'hidden';
                if (e.type == 'm_permission_refused') {
                    //uiCallTerminated('Media stream permission denied');
                }
                break;
            }

        case 'starting': default: break;
    }
}
onSipEventSession = (e) =>{
    console.log('==session event = ' + e.type);

    switch (e.type) {
        case 'connecting': case 'connected':
            {
                var bConnected = (e.type == 'connected');
                if (e.session == this.oSipSessionRegister) {
                    //uiOnConnectionEvent(bConnected, !bConnected);
                    console.log("<i>" + e.description + "</i>");
                }
                else if (e.session == this.oSipSessionCall) {
                    //btnHangUp.value = 'HangUp';
                    //btnCall.disabled = true;
                    //btnHangUp.disabled = false;
                    //btnTransfer.disabled = false;
                    //if (window.btnBFCP) window.btnBFCP.disabled = false;

                    if (bConnected) {
                        this.stopRingbackTone();
                        this.stopRingTone();

                        if (this.oNotifICall) {
                            this.oNotifICall.cancel();
                            this.oNotifICall = null;
                        }
                    }

                    console.log("<i>" + e.description + "</i>");
                    //divCallOptions.style.opacity = bConnected ? 1 : 0;

                    if (SIPml.isWebRtc4AllSupported()) { // IE don't provide stream callback
                        //uiVideoDisplayEvent(false, true);
                        //uiVideoDisplayEvent(true, true);
                    }
                }
                break;
            } // 'connecting' | 'connected'
        case 'terminating': case 'terminated':
            {
                if (e.session == this.oSipSessionRegister) {
                    //uiOnConnectionEvent(false, false);

                    this.oSipSessionCall = null;
                    this.oSipSessionRegister = null;

                    console.log("<i>" + e.description + "</i>");
                }
                else if (e.session == this.oSipSessionCall) {
                    //uiCallTerminated(e.description);
                }
                break;
            } // 'terminating' | 'terminated'

        case 'm_stream_video_local_added':
            {
                if (e.session == this.oSipSessionCall) {
                    //uiVideoDisplayEvent(true, true);
                }
                break;
            }
        case 'm_stream_video_local_removed':
            {
                if (e.session == this.oSipSessionCall) {
                    //uiVideoDisplayEvent(true, false);
                }
                break;
            }
        case 'm_stream_video_remote_added':
            {
                if (e.session == this.oSipSessionCall) {
                    //uiVideoDisplayEvent(false, true);
                }
                break;
            }
        case 'm_stream_video_remote_removed':
            {
                if (e.session == this.oSipSessionCall) {
                    //uiVideoDisplayEvent(false, false);
                }
                break;
            }

        case 'm_stream_audio_local_added':
        case 'm_stream_audio_local_removed':
        case 'm_stream_audio_remote_added':
        case 'm_stream_audio_remote_removed':
            {
                break;
            }

        case 'i_ect_new_call':
            {
                this.oSipSessionTransferCall = e.session;
                break;
            }

        case 'i_ao_request':
            {
                if (e.session == this.oSipSessionCall) {
                    var iSipResponseCode = e.getSipResponseCode();
                    if (iSipResponseCode == 180 || iSipResponseCode == 183) {
                        this.startRingbackTone();
                        console.log('<i>Remote ringing...</i>');
                    }
                }
                break;
            }

        case 'm_early_media':
            {
                if (e.session == this.oSipSessionCall) {
                    this.stopRingbackTone();
                    this.stopRingTone();
                    console.log('<i>Early media started</i>');
                }
                break;
            }

        case 'm_local_hold_ok':
            {
                if (e.session == this.oSipSessionCall) {
                    if (this.oSipSessionCall.bTransfering) {
                        this.oSipSessionCall.bTransfering = false;
                        // this.AVSession.TransferCall(this.transferUri);
                    }
                    //btnHoldResume.value = 'Resume';
                    //btnHoldResume.disabled = false;
                    //txtCallStatus.innerHTML = '<i>Call placed on hold</i>';
                    this.oSipSessionCall.bHeld = true;
                }
                break;
            }
        case 'm_local_hold_nok':
            {
                if (e.session == this.oSipSessionCall) {
                    this.oSipSessionCall.bTransfering = false;
                    //btnHoldResume.value = 'Hold';
                    //btnHoldResume.disabled = false;
                    console.log('<i>Failed to place remote party on hold</i>');
                }
                break;
            }
        case 'm_local_resume_ok':
            {
                if (e.session == this.oSipSessionCall) {
                    this.oSipSessionCall.bTransfering = false;
                    //btnHoldResume.value = 'Hold';
                    //btnHoldResume.disabled = false;
                    //txtCallStatus.innerHTML = '<i>Call taken off hold</i>';
                    this.oSipSessionCall.bHeld = false;

                    if (SIPml.isWebRtc4AllSupported()) { // IE don't provide stream callback yet
                        //uiVideoDisplayEvent(false, true);
                        //uiVideoDisplayEvent(true, true);
                    }
                }
                break;
            }
        case 'm_local_resume_nok':
            {
                if (e.session == this.oSipSessionCall) {
                    this.oSipSessionCall.bTransfering = false;
                    //btnHoldResume.disabled = false;
                    console.log('<i>Failed to unhold call</i>')            
                    }
                break;
            }
        case 'm_remote_hold':
            {
                if (e.session == this.oSipSessionCall) {
                    console.log('<i>Placed on hold by remote party</i>');
                }
                break;
            }
        case 'm_remote_resume':
            {
                if (e.session == this.oSipSessionCall) {
                    console.log('<i>Taken off hold by remote party</i>');
                }
                break;
            }
        case 'm_bfcp_info':
            {
                if (e.session == this.oSipSessionCall) {
                    console.log('BFCP Info: <i>' + e.description + '</i)>');
                }
                break;
            }

        case 'o_ect_trying':
            {
                if (e.session == this.oSipSessionCall) {
                    console.log('<i>Call transfer in progress...</i>')                    }
                break;
            }
        case 'o_ect_accepted':
            {
                if (e.session == this.oSipSessionCall) {
                    console.log('<i>Call transfer accepted</i>')    
                }
                break;
            }
        case 'o_ect_completed':
        case 'i_ect_completed':
            {
                if (e.session == this.oSipSessionCall) {
                    console.log('<i>Call transfer completed</i>')     
                    //btnTransfer.disabled = false;
                    if (this.oSipSessionTransferCall) {
                        this.oSipSessionCall = this.oSipSessionTransferCall;
                    }
                    this.oSipSessionTransferCall = null;
                }
                break;
            }
        case 'o_ect_failed':
        case 'i_ect_failed':
            {
                if (e.session == this.oSipSessionCall) {
                    console.log('<i>Call transfer failed</i>');
                //btnTransfer.disabled = false;
                }
                break;
            }
        case 'o_ect_notify':
        case 'i_ect_notify':
            {
                if (e.session == this.oSipSessionCall) {
                    console.log("<i>Call Transfer: <b>" + e.getSipRespo + " " + e.description + "</b></i>");
                    if (e.getSipResponseCode() >= 300) {
                        if (this.oSipSessionCall.bHeld) {
                            this.oSipSessionCall.resume();
                        }
                        //btnTransfer.disabled = false;
                    }
                }
                break;
            }
        case 'i_ect_requested':
            {
                if (e.session == this.oSipSessionCall) {
                    var s_message = "Do you accept call transfer to [" + e.getTransferDestinationFriendlyName() + "]?";//FIXME
                    if (confirm(s_message)) {
                        console.log("<i>Call transfer in progress...</i>")
                        this.oSipSessionCall.acceptTransfer();
                        break;
                    }
                    this.oSipSessionCall.rejectTransfer();
                }
                break;
            }
    }
}
uiBtnCallSetText = (s_text) =>{
    switch (s_text) {
        case "Call":
            {

                var bDisableCallBtnOptions = (window.localStorage && window.localStorage.getItem('org.doubango.expert.disable_callbtn_options') == "true");
                this.sipCall('call-audio');

                break;
            }
        default:
            {
                this.sipCall('call-audio');
                break;
            }
    }
}

showNotifICall= (s_number) =>{
    // permission already asked when we registered
    //if (window.webkitNotifications && window.webkitNotifications.checkPermission() == 0) {
        if (this.oNotifICall) {
            this.oNotifICall.cancel();
        }
        //this.oNotifICall = Notification.createNotification('images/sipml-34x39.png', 'Incaming call', 'Incoming call from ' + s_number);
        this.oNotifICall.onclose = function () { this.oNotifICall = null; };
        this.oNotifICall.show();
    //}
}