/** * This is a simple test application for JVoIP. * * Copy/include the JVoIP.jar file to your project required libraries list! * Demo download: https://www.mizu-voip.com/Portals/0/Files/JVoIP.zip * (It is also recommended to copy the mediaench libraries near your jar or class files: https://www.mizu-voip.com/Portals/0/Files/mediaench.zip) */ package JVoIPTestPackage; //you might change this after your app package name import webphone.*; //import JVoIP. You will have an error here if you haven't added the JVoIP.jar to your project public class JVoIPTest { webphone wobj = null; /** * Construct and show the application. */ public JVoIPTest() { Go(); } /** * Application entry point. */ public static void main(String[] args) { try { new JVoIPTest(); }catch(Exception e) { System.out.println("Exception at main: "+e.getMessage()+"\r\n"+e.getStackTrace()); } } /** * This is the important function where all the real work is done. * In this example we start the JVoIP (a webphone instance), set parameters and make an outbound call. */ void Go() { try{ //create a JVoIP instance (a webphone class instance) Log("init..."); wobj = new webphone("startsipstack=0"); //the startsipstack=0 parameter means that the SIP stack will not be started automatically. We will start it below with the API_Start() function (otherwise might start with previous/cached settings) //subscribe to notification events MyNotificationListener listener = new MyNotificationListener(this); wobj.API_SetNotificationListener(listener); //configure the SIP library (set parameters): //wobj.API_SetParameter("logtoconsole", 0); //if the loglevel is set to 5 then a log window might appear automatically if not headless. it can be disabled with this setting. wobj.API_SetParameter("loglevel", 1); //for test/development you should set the loglevel to 5. for production you might set the loglevel to 1 by default. wobj.API_SetParameter("serveraddress", "voip.mizu-voip.com"); //your sip server domain or IP:port (the port number must be set only if not the standard 5060) wobj.API_SetParameter("username", "jvoiptest"); wobj.API_SetParameter("password", "jvoiptestpwd"); //wobj.API_SetParameter("proxyaddress", "x.x.x.x"); //set this only if you have a (outbound) proxy (which is different from the serveraddress) //wobj.API_SetParameter("transport", "udp"); //the default transport for signaling is -1/auto (UDP with failover to TCP). Set to 0 or udp if your server is listening on UDP only, 1 or tcp if you need TCP or to 2 or tls if you need TLS //wobj.API_SetParameter("register", 1); //auto register (set to 0 if you don't need to register or if you wish to call the API_Register explicitely later or set to 2 if must register) //wobj.API_SetParameter("enableautoaccept", 3); //auto accept all incoming calls //wobj.API_SetParameter("voicerecording", 1); //enable call recording to local file //wobj.API_SetParameter("announcement_file", "welcome.wav"); //play an announcement at the beginning of each call //wobj.API_SetParameter("ai_provider", 1); //enable OpenAI ChatGPT realtime API built-in AI integration //wobj.API_SetParameter("ai_api_key", "YOUR_OPENAI_API_KEY"); //you might set any other required parameters here as required for your use-case. See the parameter list in the documentation. //start the SIP stack Log("start..."); //wobj.API_StartGUI(); //you might uncomment this line if you wish to use the built-in user interface instead wobj.API_Start(); /* //you might use one of the below lines if you wish to wait for the startup to complete before any further interaction with the SIP stack: wobj.API_WaitForNotification(SIPNotification.NOTIFICATION_START,"sip",1000); //optionally wait for the sip stack to fully initialize (this will block the thread, so you should use the onStart SIPNotification.Start.START_SIP notification instead from event driven apps) //wobj.API_WaitForNotification(SIPNotification.NOTIFICATION_REGISTER,"Success",5000); //optionally wait for successful registration (use the onRegister event instead) //Thread.sleep(200); //optionally you might just wait a bit for the sip stack to initialize (not recommended to use sleep from your main UI thread) */ /* //register to sip server (optional) //if the serveraddress/username/password are set, then JVoIP will register automatically at API_Start so this is commented out (you can disable this behavior if you wish by setting the "register" parameter to 0) Log("registering..."); wobj.API_Register(); */ Log("SIP stack initialized. Press enter to make a call"); WaitForEnterKeyPress(); //send a IM text message to evelin //wobj.API_SendChat("evelin", "Hi!"); //make an outbound call Log("calling..."); wobj.API_Call("testivr3"); /* //normally you will write even-driven app logic and your app logic will continue at the SIPNotificationListener below (usully from the onStatus/STATUS events) //once the call is connected, you can send DTMF messages like this //wobj.API_Dtmf(-1, "5"); //once the call is connected, you might transfer the call to +44123456789 like this //wobj.API_Transfer(-1, "+44123456789"); */ Log("Call initiated. Press enter to hangup"); WaitForEnterKeyPress(); //disconnect the call and stop the SIP stack Log("terminate..."); wobj.API_Hangup(-1); //disconnect the call wobj.API_Stop(); //stop the sip stack (this will also unregister) wobj = null; Log("Finished. Press enter to exit"); WaitForEnterKeyPress(); System.exit(0); //exit the JVM }catch(Exception e) { Log("Go", e); } } /** * helper function to simplify logging */ void Log(String msg) { System.out.println(msg); //pass it also to JVoIP so it will be easier to follow the JVoIP logs: if(wobj != null) { try{ wobj.API_Log(msg); } catch(Throwable e){} } } void Log(String msg, Exception e) { Log("ERROR, exception at "+msg+" "+e.getMessage()+"\r\n"+e.getStackTrace()); } /** * helper function used to wait for a key press before to continue */ void WaitForEnterKeyPress() { try{ //skip existing (old) input int avail = System.in.available(); if(avail > 0) System.in.read(new byte[avail]); }catch(Exception e) {} try{ //wait for enter press while (true) { int ch = System.in.read(); if(ch == '\n') break; } }catch(Exception e) {} } } /** * You will receive the notification events from JVoIP in this class by overriding the SIPNotificationListener base class member functions. * Don't block or wait in the overwritten functions for too long. * See the "Notifications" chapter in the documentation and/or the following javadoc for the details: * https://www.mizu-voip.com/Portals/0/Files/jvoip_javadoc/index.html */ class MyNotificationListener extends SIPNotificationListener { JVoIPTest app = null; //useful if we wish to refer to our main app class from here public MyNotificationListener(JVoIPTest app_in) { app = app_in; } //here are some examples about how to handle the notifications: public void onAll(SIPNotification e) { //we receive all notifications (also) here. we can just print them here to better understand the event flow emitted by JVoIP: //app.Log("\t\t\t"+e.getNotificationTypeText()+" notification received: " + e.toString()); } //handle connection (REGISTER) state public void onRegister( SIPNotification.Register e) { //check if/when we are registered to the SIP server if(!e.getIsMain()) return; //we ignore secondary accounts here switch(e.getStatus()) { case SIPNotification.Register.STATUS_INPROGRESS: app.Log("\tRegister state is: In progress..."); break; case SIPNotification.Register.STATUS_SUCCESS: app.Log("\tRegister state is: Registered successfully."); break; case SIPNotification.Register.STATUS_FAILED: app.Log("\tRegister state is: Failed because "+e.getReason()); break; case SIPNotification.Register.STATUS_UNREGISTERED: app.Log("\tRegister state is: Unregistered."); break; } } //STATUS (endpoint/global state change) handling example public void onStatus( SIPNotification.Status e) { if(e.getLine() == -1) //-1 means global state { //display then ignore the global state in this example app.Log("\tState: "+ e.getStatusText()); return; } //log call state if(e.getStatus() >= SIPNotification.Status.STATUS_CALL_SETUP && e.getStatus() <= SIPNotification.Status.STATUS_CALL_FINISHED) { app.Log("\tCall state is: "+ e.getStatusText()); } //catch outgoing call connect if(e.getStatus() == SIPNotification.Status.STATUS_CALL_CONNECT && e.getEndpointType() == SIPNotification.Status.DIRECTION_OUT) { app.Log("\tOutgoing call connected to "+ e.getPeer()); /* //there are many things we can do on call connect. for example: app.wobj.API_Dtmf(e.getLine(),"1"); //send DTMF digit 1 app.wobj.API_PlaySound(e.getLine(),"welcome.wav"); //steam an audio file to the connected peer */ } //catch incoming calls else if(e.getStatus() == SIPNotification.Status.STATUS_CALL_RINGING && e.getEndpointType() == SIPNotification.Status.DIRECTION_IN) { app.Log("\tIncoming call from "+ e.getPeerDisplayname()); //auto accepting the incoming call (instead of auto accept, you might present an Accept/Reject button for the user and call API_Accept / API_Reject) app.wobj.API_Accept(e.getLine()); //note: you might use the enableautoaccept parameter instead if you wish to accept all incoming calls } //catch incoming call connect else if(e.getStatus() == SIPNotification.Status.STATUS_CALL_CONNECT && e.getEndpointType() == SIPNotification.Status.DIRECTION_IN) { app.Log("\tIncoming call connected"); } } //print important events (EVENT) public void onEvent( SIPNotification.Event e) { app.Log("\tImportant event: "+e.getText()); } //wait for SIP start started before any other SIP stack function call (such as call attempts) public void onStart( SIPNotification.Start e) { if(e.getWhat() == SIPNotification.Start.START_SIP) { app.Log("\tSIP stack started"); //you should do any SIP operation only after this notification have been triggered (such as API_Call or API_SendChat) } } //IM handling public void onChat( SIPNotification.Chat e) { app.Log("\tMessage from "+e.getPeer()+": "+e.getMsg()); //auto answer app.wobj.API_SendChat(e.getPeer(),"Received"); } //change the above function bodies after your app logic requirements and handle any other notifications as required for your use-case /* //here is a template to handle all notifications //uncomment and replace the function bodies after your needs (by default it will just log the events, using most of the SIPNotification class member functions) public void onAll( SIPNotification e) { app.Log("\tANY notification received. type: "+Integer.toString(e.getNotificationType())+"/"+e.getNotificationTypeText()+", as string: "+e.toString()); } public void onLog( SIPNotification.Log e) { app.Log("\tLOG notification received. type: "+Integer.toString(e.getType())+"/"+e.getTypeText()+", message: "+e.getText()+", as string: "+e.toString()); } public void onEvent( SIPNotification.Event e) { app.Log("\tEVENT notification received. type: "+Integer.toString(e.getType())+"/"+e.getTypeText()+", message: "+e.getText()+", as string: "+e.toString()); } public void onPopup( SIPNotification.Popup e) { app.Log("\tPOPUP notification received. message: "+e.getText()+", as string: "+e.toString()); } public void onLine( SIPNotification.Line e) { app.Log("\tLINE notification received. line: "+Integer.toString(e.getLine())+", as string: "+e.toString()); } public void onStatus( SIPNotification.Status e) { app.Log("\tSTATUS notification received. line: "+Integer.toString(e.getLine())+", status: "+Integer.toString(e.getStatus())+"/"+e.getStatusText()+", peer: "+e.getPeer()+"/"+e.getPeerDisplayname()+", local: "+e.getLocalname()+", eptype: "+Integer.toString(e.getEndpointType())+"/"+e.getEndpointTypeText()+", callid: "+e.getCallID()+", online: "+Integer.toString(e.getOnline())+"/"+e.getOnlineText()+", registered: "+Integer.toString(e.getRegistered())+"/"+e.getRegisteredText()+", incall: "+Integer.toString(e.getIncall())+"/"+e.getIncallText()+", mute: "+Integer.toString(e.getMute())+"/"+e.getMuteText()+", hold: "+Integer.toString(e.getHold())+"/"+e.getHoldText()+", encryption: "+Integer.toString(e.getEncrypted())+"/"+e.getEncryptedText()+", video: "+Integer.toString(e.getVideo())+"/"+e.getVideodText()+", group: "+e.getGroup()+", rtp_sent: "+Common.LongToStr(e.getRtpsent())+", rtp_rec: "+Common.LongToStr(e.getRtprec())+", rtp_lost: "+Common.LongToStr(e.getRtploss())+"/"+Common.LongToStr(e.getRtplosspercent())+"%, video_hold: "+Integer.toString(e.getVideoHold())+"/"+e.getVideoHoldText()+", video_rtp_sent: "+Common.LongToStr(e.getVideoRtpsent())+", video_rtp_rec: "+Common.LongToStr(e.getVideoRtprec())+", serverstats: "+e.getServerstats()+", as string: "+e.toString()); } public void onRegister( SIPNotification.Register e) { app.Log("\tREGISTER notification received. line: "+Integer.toString(e.getLine())+", status: "+Integer.toString(e.getStatus())+"/"+e.getText()+"/"+e.getReason()+", ismain: "+Common.BoolToString(e.getIsMain())+", isfcm: "+Integer.toString(e.getFcm())+", user: "+e.getUser()+", as string: "+e.toString()); } public void onPresence( SIPNotification.Presence e) { app.Log("\tPRESENCE notification received. peer: "+e.getPeer()+"/"+e.getPeerDisplayname()+"/"+e.getEmail()+", status: "+Integer.toString(e.getStatus())+"/"+e.getStatusText()+"/"+e.getDetails()+", as string: "+e.toString()); } public void onBLF( SIPNotification.BLF e) { app.Log("\tBLF notification received. peer: "+e.getPeer()+"/"+e.getCallid()+" "+Integer.toString(e.getDirecton())+"/"+e.getDirectionText()+", status: "+Integer.toString(e.getStatus())+"/"+e.getStatusText()+", as string: "+e.toString()); } public void onDTMF( SIPNotification.DTMF e) { app.Log("\tDTMF notification received. line: "+Integer.toString(e.getLine())+", message: "+e.getMsg()+", as string: "+e.toString()); } public void onINFO( SIPNotification.INFO e) { app.Log("\tINFO notification received. line: "+Integer.toString(e.getLine())+", peer: "+e.getPeer()+", type: "+Integer.toString(e.getType())+"/"+e.getTypeText()+" message: "+e.getText()+", as string: "+e.toString()); } public void onUSSD( SIPNotification.USSD e) { app.Log("\tUSSD notification received. line: "+Integer.toString(e.getLine())+", status: "+Integer.toString(e.getStatus())+"/"+e.getStatusText()+", message: "+e.getText()+", as string: "+e.toString()); } public void onChat( SIPNotification.Chat e) { app.Log("\tCHAT notification received. line: "+Integer.toString(e.getLine())+", peer: "+e.getPeer()+", message: "+e.getMsg()+", as string: "+e.toString()); } public void onChatReport( SIPNotification.ChatReport e) { app.Log("\tCHATREPORT notification received. line: "+Integer.toString(e.getLine())+", peer: "+e.getPeer()+", status: "+Integer.toString(e.getStatus())+"/"+e.getStatusText()+", group: "+e.getGroup()+", md5: "+e.getMD5()+", id: "+Integer.toString(e.getID())+", as string: "+e.toString()); } public void onChatComposing( SIPNotification.ChatComposing e) { app.Log("\tCHATCOMPOSING notification received. line: "+Integer.toString(e.getLine())+", peer: "+e.getPeer()+", status: "+e.getStatus()+"/"+e.getStatusText()+", as string: "+e.toString()); } public void onCDR( SIPNotification.CDR e) { app.Log("\tCDR notification received. line: "+Integer.toString(e.getLine())+", peer: "+e.getPeer()+"/"+e.getPeerAddress()+", caller: "+e.getCaller()+", called: "+e.getCalled()+", connect: "+Common.LongToStr(e.getConnectTime())+" msec, duration: "+Common.LongToStr(e.getDuration())+" msec, disc_by: "+Integer.toString(e.getDiscParty())+"/"+e.getDiscPartyText()+", disc_reason: "+e.getDiscReason()+", as string: "+e.toString()); } public void onStart( SIPNotification.Start e) { app.Log("\tSTART notification received. what: "+Integer.toString(e.getWhat())+"/"+e.getWhatText()+", as string: "+e.toString()); } public void onStop( SIPNotification.Stop e) { app.Log("\tSTOP notification received. what: "+Integer.toString(e.getWhat())+"/"+e.getWhatText()+", as string: "+e.toString()); } public void onShouldReset( SIPNotification.ShouldReset e) { app.Log("\tSHOULDRESET notification received. reason: "+e.getReason()+", as string: "+e.toString()); } public void onPlayReady( SIPNotification.PlayReady e) { app.Log("\tPLAYREADY notification received. line: "+Integer.toString(e.getLine())+", callid: "+e.getCallID()+", as string: "+e.toString()); } public void onSRS( SIPNotification.SRS e) { app.Log("\tSRS notification received. line: "+Integer.toString(e.getLine())+", siprec session: "+e.getSessionID()+", call-id: "+e.getCallID()+", sipsession1: "+e.getSIPSessionID1()+", user1: "+e.getUserID1()+", aor1: "+e.getAOR1()+", name1: "+e.getName1()+", sipsession2: "+e.getSIPSessionID2()+", user2: "+e.getUserID2()+", aor2: "+e.getAOR2()+", name2: "+e.getName2()+", codec: "+e.getCodec()+", as string: "+e.toString()); } public void onSIP( SIPNotification.SIP e) { app.Log("\tSIP notification received. dir: "+Integer.toString(e.getDirection())+"/"+e.getDirectionText()+", address: "+e.getAddress()+", message: "+e.getMessage()+", as string: "+e.toString()); } public void onBlock( SIPNotification.Block e) { app.Log("\tBLOCK notification received. type: "+Integer.toString(e.getType())+"/"+e.getTypeText()+", message: "+e.getMessage()+", as string: "+e.toString()); } public void onVAD( SIPNotification.VAD e) { app.Log("\tVAD notification received. line: "+Integer.toString(e.getLine())+", "+ (e.getLocalValid() ? "LOCAL: avg: "+Common.LongToString(e.getLocalAvg())+" max: "+Common.LongToString(e.getLocalMax())+" speaking: "+Common.BoolToString(e.getLocalSpeaking()) : "")+ (e.getRemoteValid() ? " REMOTE: avg: "+Common.LongToString(e.getRemoteAvg())+" max: "+Common.LongToString(e.getRemoteMax())+" speaking: "+Common.BoolToString(e.getRemoteSpeaking()) : "") +", as string: "+e.toString()); } public void onRTPE( SIPNotification.RTPE e) { app.Log("\tRTPE notification received. profile: "+Integer.toString(e.getProfile())+", extension: "+e.getExtension()+", as string: "+e.toString()); } public void onRTPT( SIPNotification.RTPT e) { app.Log("\tRTPT notification received. type: "+Integer.toString(e.getType())+"/"+e.getTypeText()+", SQU: "+Common.BoolToString(e.getSQU())+", id: "+Common.IntToString(e.getID())+", SCT: "+Common.BoolToString(e.getSCT())+", VF: "+Common.BoolToString(e.getVF())+", extension: "+e.getExtension()+", as string: "+e.toString()); } public void onRTPStat( SIPNotification.RTPStat e) { app.Log("\tRTPSTAT notification received. quality: "+Integer.toString(e.getQuality())+"/"+e.getQualityText()+", sent: "+Common.LongToString(e.getSent())+", rec: "+Common.LongToString(e.getRec())+", issues: "+Common.LongToString(e.getIssues())+", lost: "+Common.LongToString(e.getLoss())+", as string: "+e.toString()); } public void onCredit( SIPNotification.Credit e) { app.Log("\tCREDIT notification received. message: "+e.getText()+", as string: "+e.toString()); } public void onRating( SIPNotification.Rating e) { app.Log("\tRATING notification received. message: "+e.getText()+", as string: "+e.toString()); } public void onServerContacts( SIPNotification.ServerContacts e) { app.Log("\tSERVERCONTACTS notification received. message: "+e.getText()+", as string: "+e.toString()); } public void onMWI( SIPNotification.MWI e) { app.Log("\tMWI notification received. has: "+Common.BoolToString(e.getHasMessage())+", vmnumber: "+e.getVMNumber()+", to: "+e.getTo()+", count: "+Integer.toString(e.getCount())+", message: "+e.getMessage()+", as string: "+e.toString()); } public void onNewContact( SIPNotification.NewContact e) { app.Log("\tNEWUSER notification received. username: "+e.getUsername()+", displayname: "+e.getDisplayname()+", as string: "+e.toString()); } public void onAnswer( SIPNotification.Answer e) { app.Log("\tANSWER notification received. answer: "+e.getResult()+", request: "+e.getRequest()+", as string: "+e.toString()); } public void onVideo( SIPNotification.Video e) { app.Log("\tVIDEO notification received. startstop: "+Integer.toString(e.getStartOrStop())+"/"+e.getStartOrStopText()+", type: "+Integer.toString(e.getType())+"/"+e.getTypeText()+", line: "+Integer.toString(e.getLine())+", reason: "+e.getReason()+", ip: "+e.getIp()+", port: "+Integer.toString(e.getPort())+", codec: "+e.getCodec()+", payload: "+Integer.toString(e.getPayload())+", quality: "+Integer.toString(e.getQuality())+", bw: "+Integer.toString(e.getBw())+", max_bw: "+Integer.toString(e.getMaxBw())+", fps: "+Integer.toString(e.getFps())+", max_fps: "+Integer.toString(e.getMaxFps())+", width: "+Integer.toString(e.getWidth())+", height: "+Integer.toString(e.getHeight())+", profilelevelid: "+Integer.toString(e.getProfilelevelid())+", profile: "+e.getProfile()+", pixelfmt: "+e.getPixelfmt()+", level: "+e.getLevel()+", pm: "+e.getPm()+", sprop: "+e.getSprop()+", srtp_alg: "+e.getSrtpAlg()+", srtp_key: "+e.getSrtpKey()+", srtp_remotekey: "+e.getSrtpRemoteKey()+", device: "+e.getDevice()+", fmtp: "+e.getFmtp()+", as string: "+e.toString()); } public void onAI( SIPNotification.AI e) { app.Log("\tAI notification received. line: "+Integer.toString(e.getLine())+", callid: "+e.getCallID()+", peer: "+e.getPeer()+", status: "+Integer.toString(e.getStatus())+"/"+e.getStatusText()+", as string: "+e.toString()); } */ }