package uk.co.mmscomputing.device.capi; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; import uk.co.mmscomputing.util.metadata.*; import uk.co.mmscomputing.concurrent.*; import uk.co.mmscomputing.device.capi.ctrl.*; import uk.co.mmscomputing.device.capi.plc.*; import uk.co.mmscomputing.device.capi.ncc.*; import uk.co.mmscomputing.device.capi.protocol.*; import uk.co.mmscomputing.device.capi.q931.*; import uk.co.mmscomputing.device.capi.parameter.*; import uk.co.mmscomputing.device.capi.exception.*; import uk.co.mmscomputing.device.capi.facility.*; public class CapiApplication extends Thread implements CapiConstants{ protected int appid=-1; protected int maxLogicalCon=-1; protected boolean listeningToSupServices=false; // listen to Supplementary Services protected Metadata md=null; private boolean running=true; private Semaphore rs=new Semaphore(0,true); private Vector plcs=new Vector(); // set of active physical connections public CapiApplication(Metadata md)throws CapiException{ this.md=md; md.getInt(capiSpeechCodingID,LAYER1USERINFO_ALAW); // use A-Law, if not set maxLogicalCon=md.getInt(capiMaxLogicalConnectionsID,2); // use two b-channels, if not set jcapi.checkInstalled(); appid=jcapi.register(maxLogicalCon,MaxNumB3DataBlocks,DefaultB3DataBlockSize); } public int getApplID(){ return appid;} public boolean isRunning(){ return running;} public boolean isListeningToSupService(){ return listeningToSupServices;} /*synchronized*/public void put(MsgOut msg)throws CapiException{// THE ONLY place where we send our capi req or resp if(!running){return;} // if(msg.cmd!=CAPI_DATA_B3){md.fireListenerUpdate(msg);} // testing; tell listeners; somebody might want to know. jcapi.putMessage(appid,msg.getBytes()); } public void close(){ if(!running){return;} try{ // int cntrl=md.getInt(capiControllerID,1); // put(new ListenReq(appid,cntrl,0)); // stop listening closePLCs(); running=false; MsgOut msg=new ListenReq(appid,1,0); // send dummy message to unblock jcapi.waitForMessage jcapi.putMessage(appid,msg.getBytes()); // cannot use put here! running is false try{rs.acquire();}catch(InterruptedException ie){} System.err.println(getClass().getName()+".close: RELEASED CAPI APPLICATION "+appid); }catch(Exception ce){ System.err.println(getClass().getName()+".close:\n\t"+ce); md.fireListenerUpdate("9\b"+getClass().getName()+".close:\n\t"+ce); } } public CapiPLC getPLC(int plci)throws CapiException{ plci&=0x0000FFFF; if(plci<256){return null;} // msg for controller only for(Enumeration e=plcs.elements();e.hasMoreElements();){ CapiPLC plc=(CapiPLC)e.nextElement(); if(plc.lineid==plci){ return plc; } } throw new CapiException(getClass().getName()+".getPLC("+plci+")\n\tCannot find PLC with plci = 0x"+Integer.toHexString(plci)+" !"); } private CapiPLC newPLC(ConnectInd msg){ CapiPLC plc=new CapiPLC(this,msg);plcs.add(plc);return plc; } protected CapiPLC newPLC(ConnectReq msg){ CapiPLC plc=new CapiPLC(this,msg);plcs.add(plc);return plc; } private CapiPLC getPLC(ConnectConf msg)throws CapiException{ int msgno = msg.msgno; for(Enumeration e=plcs.elements();e.hasMoreElements();){ CapiPLC plc=(CapiPLC)e.nextElement(); if(plc.getMsgno()==msgno){ plc.setLineid(msg.lineid); return plc; } } throw new CapiException(getClass().getName()+".getPLC("+msgno+")\n\tCannot find PLC with connect msgno = "+msgno+" !"); } public void closePLCs(){ CapiPLC[] lines=(CapiPLC[])plcs.toArray(new CapiPLC[0]); for(int i=0;i