package net.sourceforge.gjtapi.raw.njiax.peer; import iax.protocol.peer.Peer; import iax.protocol.peer.PeerListener; import iax.protocol.user.command.UserCommandFacade; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Timer; import javax.telephony.ConnectionEvent; import javax.telephony.Event; import net.sourceforge.gjtapi.raw.njiax.NjIaxCallId; import net.sourceforge.gjtapi.raw.njiax.NjIaxProvider; /** * <p>Title: NjIaxAgent</p> * * <p>Description: </p> * * <p>Copyright: Copyright (c) 2008</p> * * <p>Company: L2F | INESC-ID</p> * * @author D�rio Marcelino * @version 1.0 */ public class NjIaxPeer implements PeerListener { NjIaxProvider provider; Peer peer; NjIaxCallId currentCall; NjIaxCallId transferedCall; String userName; Object callLock = new Object(); InputStreamAdapter inStream = new InputStreamAdapter(); OutputStreamAdapter outStream = new OutputStreamAdapter(); public NjIaxPeer(NjIaxProvider provider, String userName, String password, String host, boolean register, int maxCalls) { this.provider = provider; this.userName = userName; // peer = new Peer(this, userName, password, host, register, maxCalls); // This is a forked version of the constructor -- See njiax-gjtapi-1.0.0.jar // Renato Cassaca's note: // "I had to change a lot of files in NjIax source so I copied _all_ njiax files no gjtapi/src/njiax. // That means that gjtapi has a fork of njiax. I think that it makes sense because I tried to contact // several time njiax developers and I didn't get any feedback. They had some "solutions" that I didn't // like so much, like create a new thread each time 160 bytes of audio have to be sent to Asterisk.... // To work around this unwanted feature I added a PoolExecutor. The problem is that it's only available // in Java6...." peer = new Peer(this, userName, password, host, register, maxCalls, outStream, inStream); } public void setCallId(NjIaxCallId id) { currentCall = id; } public NjIaxCallId getCallId() { return currentCall; } public void answerCall(NjIaxCallId call) { UserCommandFacade.answerCall(peer, call.getCallParticipant()); /** When an ingoing call has been accepted */ provider.connectionConnected(currentCall, call.getCallParticipant(), ConnectionEvent.CAUSE_NORMAL); provider.callActive(currentCall, Event.CAUSE_NORMAL); } public NjIaxCallId newCall(NjIaxCallId callID, String calledNumber) { //System.out.println("New call to "+ calledNumber +" (" + callID.getId() + ")"); callID.setCallParticipant(calledNumber); if (currentCall == null) { currentCall = callID; //System.out.println("NjIaxPeer, " + userName + " calling " + calledNumber); UserCommandFacade.newCall(peer, calledNumber); } else transferedCall = callID; return callID; } public void release() { //System.out.println("Release call"); synchronized (callLock) { if (currentCall != null && currentCall != transferedCall) { UserCommandFacade.hangupCall(peer, currentCall.getCallParticipant()); currentCall = null; } } } // ****************************** Media **************************** public void play(InputStream src, long duration) { //System.out.println("NjIaxPeer, play: starting"); Timer timer; if (duration != javax.telephony.media.ResourceConstants.v_Forever) { timer = new Timer("PlayDuration"); timer.schedule(new StopPlayTask(this), duration); //System.out.println("Play: Duration set to: " + duration); } inStream.setInputStream(src); inStream.waitForEnd(); //System.out.println("NjIaxPeer, play: finished"); } public void record(OutputStream dest, long duration) { //System.out.println("NjIaxPeer, record: starting"); Timer timer; if (duration != javax.telephony.media.ResourceConstants.v_Forever) { timer = new Timer("RecordDuration"); timer.schedule(new StopRecordTask(this), duration); //System.out.println("Record: Duration set to: " + duration); } outStream.setOutputStream(dest); outStream.waitForEnd(); //System.out.println("NjIaxPeer, record: finished"); } public void stopRecord() { try { if (outStream != null) { outStream.close(); outStream.waitForEnd(); } } catch (IOException e) { e.printStackTrace(); } } public void stopPlay() { try { if (inStream != null) { int prevAvail = -1; int stalledCounter = 0; do { int avail = inStream.available(); if (avail < 1) break; else { if (prevAvail < 0) { prevAvail = avail; stalledCounter = 0; } else { if (avail < prevAvail) { stalledCounter = 0; //Consuming.... try { Thread.sleep(20); } catch (InterruptedException ex) { } } else if (avail > prevAvail) { stalledCounter = 0; //Still receiving audio try { Thread.sleep(50); } catch (InterruptedException ex1) { } } else if (avail == prevAvail) { stalledCounter += 1; if (stalledCounter == 5) { System.err.println("NjIAX stopPlay: stopping because data is stalled @ " + avail); break; } try { Thread.sleep(50); } catch (InterruptedException ex2) { } } prevAvail = avail; } } } while (true); inStream.close(); inStream.waitForEnd(); } } catch (IOException e) { e.printStackTrace(); } } public void stop() { //System.out.println("GJTAPI: Media stop"); stopPlay(); stopRecord(); } // *************************** Call Control ************************* public void hold(NjIaxCallId callID) { //System.out.println("NjIaxPeer, holding call with " + callID.getCallParticipant()); //UserCommandFacade.holdCall(peer, callID.getCallParticipant()); } public void unHold(NjIaxCallId callID) { //System.out.println("NjIaxPeer, unholding call with " + callID.getCallParticipant()); UserCommandFacade.unHoldCall(peer, callID.getCallParticipant()); } public void transfer(NjIaxCallId callID1, NjIaxCallId callID2) { transferedCall = callID1; //System.out.println("NjIaxProvider, Transfering " + callID1.getCallParticipant() + " to " + callID2.getCallParticipant()); UserCommandFacade.transferCall(peer, callID1.getCallParticipant(), callID2.getCallParticipant()); } // *************************** PeerListener ************************* public void hungup(String calledNumber) { //System.out.println(calledNumber + " Hungup."); /** When a call has been locally or remotely closed */ synchronized (callLock) { if (currentCall != null) { provider.connectionDisconnected(currentCall, calledNumber, Event.CAUSE_NORMAL); currentCall = null; } } } public void recvCall(String callingName, String callingNumber) { //System.out.println(userName + " peer received call from " + callingName + " (" + callingNumber + ")"); currentCall = new NjIaxCallId(); currentCall.setCallParticipant(callingNumber); provider.terminalConnectionRinging(currentCall, userName, userName, ConnectionEvent.CAUSE_NORMAL); provider.connectionInProgress(currentCall, userName, Event.CAUSE_NORMAL); provider.connectionAlerting(currentCall, userName, ConnectionEvent.CAUSE_NORMAL); } public void registered() { //System.out.println(userName + " has registered."); } public void waiting() { //System.out.println(userName + " is waiting for calls."); } public void unregistered() { //System.out.println(userName + " has unregistered."); } public void exited() { //System.out.println(userName + " has exited."); } public void answered(String calledNumber) { //System.out.println(calledNumber + " has answered the call from " + userName); /** When an outgoing call has been accepted */ provider.connectionConnected(currentCall, calledNumber, ConnectionEvent.CAUSE_NORMAL); provider.callActive(currentCall, Event.CAUSE_NORMAL); } public void playWaitTones(String calledNumber) { //System.out.println(calledNumber + " is ringing, call from " + userName); /** When an outgoing call is remotly ringing */ provider.terminalConnectionCreated(currentCall, calledNumber, calledNumber, ConnectionEvent.CAUSE_NORMAL); provider.connectionInProgress(currentCall, calledNumber, Event.CAUSE_NORMAL); provider.connectionAlerting(currentCall, calledNumber, ConnectionEvent.CAUSE_NORMAL); } public void stopWaitTones(String calledNumber) { throw new RuntimeException("stopWaitTones: NOT IMPLEMENTED"); } }