package net.sourceforge.gjtapi.raw.njiax;
import net.sourceforge.gjtapi.raw.njiax.peer.NjIaxPeer;
import net.sourceforge.gjtapi.raw.MediaTpi;
import net.sourceforge.gjtapi.RawSigDetectEvent;
import net.sourceforge.gjtapi.TermData;
import net.sourceforge.gjtapi.CallId;
import net.sourceforge.gjtapi.TelephonyListener;
import net.sourceforge.gjtapi.RawStateException;
import javax.telephony.ProviderUnavailableException;
import javax.telephony.ResourceUnavailableException;
import javax.telephony.InvalidArgumentException;
import javax.telephony.PrivilegeViolationException;
import javax.telephony.MethodNotSupportedException;
import javax.telephony.media.RTC;
import javax.telephony.media.MediaResourceException;
import javax.telephony.InvalidPartyException;
import javax.telephony.media.PlayerConstants;
import javax.telephony.media.RecorderConstants;
import javax.telephony.media.Symbol;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.HashMap;
import java.util.Properties;
import java.util.Dictionary;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import net.sourceforge.gjtapi.raw.CCTpi;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.Semaphore;
/**
* <p>Title: NjIaxProvider</p>
*
* <p>Description: This is a provider that provides IAX support for GJTAPI</p>
*
* <p>Copyright: Copyright (c) 2008</p>
*
* <p>Company: INESC-ID</p>
*
* @author D�rio Marcelino
* @version 1.0
*/
public class NjIaxProvider implements CCTpi, MediaTpi {
//Enabled peers
private HashMap<String, NjIaxPeer> iaxPeers = new HashMap<String, NjIaxPeer>();
private TelephonyListener listener;
private Semaphore playSemaphore;
private Semaphore recSemaphore;
public NjIaxProvider() {
playSemaphore = new Semaphore(1, true);
recSemaphore = new Semaphore(1, true);
}
/**
* {@inheritDoc}
*/
public void initialize(Map props) throws
ProviderUnavailableException {
//Get Peers
for (Object property : props.keySet()) {
//System.out.println((String)property);
if (!((String) property).contains("gjtapi.njiax.njIaxPeer.")) {
continue;
}
String propParts[] = ((String) property).split("[.]");
if (propParts[3].compareToIgnoreCase("default") != 0 &&
((String)
props.get("gjtapi.njiax.njIaxPeer." + propParts[3] +
".enabled")).compareToIgnoreCase("true") == 0 &&
!iaxPeers.containsKey(propParts[3])) {
String password = getProperty(propParts[3], props, "password");
String host = getProperty(propParts[3], props, "host");
Boolean register = Boolean.valueOf(getProperty(propParts[3],
props, "register"));
int maxCalls = Integer.valueOf(getProperty(propParts[3], props,
"maxCalls"));
NjIaxPeer peer = new NjIaxPeer(this, propParts[3], password,
host,
register, maxCalls);
iaxPeers.put(propParts[3], peer);
}
}
}
/**
* {@inheritDoc}
*/
public Properties getCapabilities() {
Properties props = new Properties();
try {
InputStream pIS = Properties.class.getResourceAsStream(
"/GenericCapabilities.props");
props.load(pIS);
pIS.close();
} catch (IOException e) {
e.printStackTrace();
}
return props;
}
/**
* {@inheritDoc}
*/
public String[] getAddresses() throws ResourceUnavailableException {
String[] ret = new String[iaxPeers.size()];
int i = 0;
for (String addresses : iaxPeers.keySet()) {
ret[i] = addresses;
i++;
}
return ret;
}
/**
* {@inheritDoc}
*/
public String[] getAddresses(String terminal) throws
InvalidArgumentException {
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
return new String[] {};
} else {
return new String[] {terminal};
}
}
/**
* {@inheritDoc}
*/
public TermData[] getTerminals() throws ResourceUnavailableException {
TermData[] ret = new TermData[iaxPeers.size()];
int i = 0;
for (String address : iaxPeers.keySet()) {
ret[i] = new TermData(address, true);
i++;
}
return ret;
}
/**
* {@inheritDoc}
*/
public TermData[] getTerminals(String address) throws
InvalidArgumentException {
NjIaxPeer peer = iaxPeers.get(address);
if (peer == null) {
return new TermData[] {};
} else {
return new TermData[] {
new TermData(address, true)
};
}
}
/**
* {@inheritDoc}
*/
public void releaseCallId(CallId id) {
}
/**
* {@inheritDoc}
*/
public void addListener(TelephonyListener ro) {
if (listener == null) {
listener = ro;
} else {
System.err.println("Request to add a TelephonyListener to "
+ this.getClass().getName() +
", but one is already registered");
}
}
/**
* {@inheritDoc}
*/
public void removeListener(TelephonyListener ro) {
if (ro == listener) {
listener = null;
} else {
System.err.println("Request to remove a TelephonyListener from "
+ this.getClass().getName() +
", but it wasn't registered");
}
}
/**
* {@inheritDoc}
*/
public void shutdown() {
for (NjIaxPeer peer : iaxPeers.values()){
peer.release();
}
iaxPeers.clear();
}
// *********************** Basic Call Control **********************
/**
* {@inheritDoc}
*/
public void answerCall(CallId call, String address, String terminal) throws
PrivilegeViolationException, ResourceUnavailableException,
MethodNotSupportedException, RawStateException {
//Get peer
NjIaxPeer peer = iaxPeers.get(address);
if (peer == null) {
throw new ResourceUnavailableException(ResourceUnavailableException.
ORIGINATOR_UNAVAILABLE, "Address not found: " + address);
}
//if (peer.getCallId().equals((Object) call)) {
peer.answerCall((NjIaxCallId)call);
/*} else {
throw new ResourceUnavailableException(ResourceUnavailableException.
UNSPECIFIED_LIMIT_EXCEEDED);
}*/
}
/**
* {@inheritDoc}
*/
public CallId reserveCallId(String address) throws InvalidArgumentException {
//Get peer
NjIaxPeer peer = iaxPeers.get(address);
if (peer == null) {
throw new InvalidArgumentException("Address not found: " + address);
}
NjIaxCallId id = new NjIaxCallId();
return id;
}
/**
* {@inheritDoc}
*/
public CallId createCall(CallId id, String address, String term,
String dest) throws ResourceUnavailableException,
PrivilegeViolationException, InvalidPartyException,
InvalidArgumentException, RawStateException,
MethodNotSupportedException {
NjIaxPeer peer = iaxPeers.get(address);
if (peer == null) {
throw new ResourceUnavailableException(ResourceUnavailableException.
ORIGINATOR_UNAVAILABLE, "Address not found: " + address);
}
return peer.newCall((NjIaxCallId) id, dest);
}
/**
* {@inheritDoc}
*/
public void release(String address, CallId call) throws
PrivilegeViolationException, ResourceUnavailableException,
MethodNotSupportedException, RawStateException {
NjIaxPeer peer = iaxPeers.get(address);
if (peer == null) {
throw new ResourceUnavailableException(ResourceUnavailableException.
ORIGINATOR_UNAVAILABLE, "Address not found: " + address);
}
peer.release();
}
// ******************* TelephonyListener ******************
/**
* {@inheritDoc}
*/
public void callActive(CallId id, int cause) {
listener.callActive(id, cause);
}
/**
* {@inheritDoc}
*/
public void connectionInProgress(CallId id, String address, int cause) {
listener.connectionInProgress(id, address, cause);
}
/**
* {@inheritDoc}
*/
public void connectionAlerting(CallId id, String address, int cause) {
listener.connectionAlerting(id, address, cause);
}
/**
* {@inheritDoc}
*/
public void connectionConnected(CallId id, String address, int cause) {
listener.connectionConnected(id, address, cause);
}
/**
* {@inheritDoc}
*/
public void connectionDisconnected(CallId id, String address, int cause) {
if (listener != null) {
listener.connectionDisconnected(id, address, cause);
}
}
/**
* {@inheritDoc}
*/
public void terminalConnectionCreated(CallId id, String address,
String terminal, int cause) {
listener.terminalConnectionCreated(id, address, terminal, cause);
}
/**
* {@inheritDoc}
*/
public void terminalConnectionRinging(CallId id, String address,
String terminal, int cause) {
listener.terminalConnectionRinging(id, address, terminal, cause);
}
// *************************** Media *************************
/**
* {@inheritDoc}
*/
public boolean allocateMedia(String terminal, int type,
Dictionary resourceArgs) {
return true;
}
/**
* {@inheritDoc}
*/
public boolean freeMedia(String terminal, int type) {
//Get peer
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
return false;
}
peer.stop();
return true;
}
/**
* {@inheritDoc}
*/
public void play(String terminal, String[] streamIds, int offset,
RTC[] rtcs, Dictionary optArgs) throws
MediaResourceException {
int dur = javax.telephony.media.ResourceConstants.v_Forever;
try {
//System.out.println("GJTAPI Play, starting");
do {
try {
playSemaphore.acquire(1);
break;
} catch (InterruptedException ex) {
ex.printStackTrace();
}
} while (true);
//System.out.println("GJTAPI Play, acquired semaphore");
//Get peer
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
playSemaphore.release(1);
throw new MediaResourceException("Terminal not found: " +
terminal);
}
//Process RTC
if (rtcs != null) {
for (RTC rtc : rtcs) {
if (rtc.getTrigger() == PlayerConstants.p_MaxDuration) {
dur = rtc.getAction().hashCode();
}
}
}
for (String streamID : streamIds) {
URI uri = new URI(streamID);
if (uri.getScheme().equals("file")) {
FileInputStream fis = new FileInputStream(uri.getPath());
peer.play(fis, dur);
} else {
URL url = new URL(streamID);
URLConnection c = url.openConnection();
c.connect();
InputStream is = c.getInputStream();
peer.play(is, dur);
is.close();
}
}
} catch (IllegalMonitorStateException e) {
//System.out.println(e.toString());
} catch (Exception e) {
e.printStackTrace();
throw new MediaResourceException();
} finally {
//System.out.println("GJTAPI Play, finished");
playSemaphore.release(1);
}
}
/**
* {@inheritDoc}
*/
public void record(String terminal, String streamId, RTC[] rtcs,
Dictionary optArgs) throws MediaResourceException {
int dur = javax.telephony.media.ResourceConstants.v_Forever;
//System.out.println("GJTAPI Record, starting");
do {
try {
recSemaphore.acquire(1);
break;
} catch (InterruptedException ex) {
ex.printStackTrace();
}
} while (true);
//System.out.println("GJTAPI Record, acquired semaphore");
//Get peer
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
recSemaphore.release(1);
throw new MediaResourceException("Terminal not found: " +
terminal);
}
//Process RTC
if (rtcs != null) {
for (RTC rtc : rtcs) {
if (rtc.getTrigger() == RecorderConstants.p_MaxDuration) {
dur = rtc.getAction().hashCode();
//System.out.println("Dur: " + dur);
}
}
}
try {
URI uri = new URI(streamId);
if (uri.getScheme().equals("file")) {
FileOutputStream fos = new FileOutputStream(uri.getPath());
peer.record(fos, dur);
} else {
URL url = new URL(streamId);
URLConnection c = url.openConnection();
c.connect();
OutputStream os = c.getOutputStream();
peer.record(os, dur);
os.close();
}
} catch (Exception e) {
e.printStackTrace();
throw new MediaResourceException();
} finally {
//System.out.println("GJTAPI Record, finished");
recSemaphore.release(1);
}
}
/**
* {@inheritDoc}
*/
public void stop(String terminal) {
//Get peer
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
return;
}
peer.stop();
}
/**
* {@inheritDoc}
*/
public void triggerRTC(String terminal, Symbol action) {
//Get peer
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
return;
}
if (action.equals(PlayerConstants.rtca_Stop)) {
peer.stopPlay();
} else if (action.equals(RecorderConstants.rtca_Stop)) {
peer.stopRecord();
}
}
/**
* {@inheritDoc}
*/
public boolean isMediaTerminal(String terminal) {
return true;
}
/**
* {@inheritDoc}
*/
public RawSigDetectEvent retrieveSignals(String terminal, int num,
Symbol[] patterns, RTC[] rtcs,
Dictionary optArgs) throws
MediaResourceException {
// TODO Auto-generated method stub
return null;
}
/**
* {@inheritDoc}
*/
public void sendSignals(String terminal, Symbol[] syms, RTC[] rtcs,
Dictionary optArgs) throws MediaResourceException {
// TODO Auto-generated method stub
}
// ******************* Call Control Methods ******************
public void hold(CallId callId, String address, String terminal) throws
PrivilegeViolationException, RawStateException,
MethodNotSupportedException, ResourceUnavailableException {
//Get peer
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
throw new ResourceUnavailableException(ResourceUnavailableException.
ORIGINATOR_UNAVAILABLE, "Address not found: " + address);
}
peer.hold((NjIaxCallId)callId);
}
public CallId join(CallId call1, CallId call2, String address,
String terminal) throws InvalidArgumentException,
PrivilegeViolationException, RawStateException,
MethodNotSupportedException, ResourceUnavailableException {
//System.out.println("1: " + call1 + ", 2:" + call2 + ", addr: " + address);
//Get peer
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
throw new ResourceUnavailableException(ResourceUnavailableException.
ORIGINATOR_UNAVAILABLE, "Address not found: " + address);
}
peer.transfer((NjIaxCallId)call1, (NjIaxCallId)call2);
return null;
}
public void unHold(CallId call, String address, String terminal) throws
PrivilegeViolationException, RawStateException,
MethodNotSupportedException, ResourceUnavailableException {
//Get peer
NjIaxPeer peer = iaxPeers.get(terminal);
if (peer == null) {
throw new ResourceUnavailableException(ResourceUnavailableException.
ORIGINATOR_UNAVAILABLE, "Address not found: " + address);
}
peer.unHold((NjIaxCallId)call);
}
// ******************* Auxiliary Methods ******************
public static String getProperty(String peer, Map props, String property) {
String ret = (String) props.get("gjtapi.njiax.njIaxPeer." + peer + "." +
property);
if (ret == null) {
ret = (String) props.get("gjtapi.njiax.njIaxPeer." + "default" +
"." + property);
}
return ret;
}
}