package uk.co.mmscomputing.device.capi.samples;
import java.io.*;
import java.util.*;
import java.text.*;
import javax.sound.sampled.*;
import uk.co.mmscomputing.concurrent.*;
import uk.co.mmscomputing.util.*;
import uk.co.mmscomputing.util.metadata.*;
import uk.co.mmscomputing.device.capi.*;
import uk.co.mmscomputing.device.capi.ncc.*;
import uk.co.mmscomputing.device.capi.protocol.*;
import uk.co.mmscomputing.device.capi.exception.*;
import uk.co.mmscomputing.device.capi.parameter.*;
import uk.co.mmscomputing.device.capi.facility.*;
public class AnswerPhone implements MetadataListener, Runnable{
static private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss_");
private CapiMetadata md;
private File voicedir,faxdir;
private CapiServerApplication server = null;
public AnswerPhone()throws IOException{
File userhome=new File(System.getProperty("user.home"),"mmsc");
voicedir = new File(userhome,"phone");
voicedir.mkdirs();
faxdir = new File(userhome,"fax"+File.separator+"received");
faxdir.mkdirs();
// CapiEnumerator e=new CapiEnumerator();
// System.out.println("CapiEnumerator:\n\n"+e.toString()+"\n\n");
md=new CapiMetadata();
md.useMaxLogicalConnections(CapiEnumerator.getNoOfBChannels());
md.useALaw(); // set some defaults
md.use64kBit();
md.acceptAllCalls();
md.useController(2);
md.useLocalNo("0123456789");
md.useFaxHeader("my mmsc fax machine :) ");
md.putInt("pickupTime",3000);
md.putInt("recordTime",20000);
md.putInt("timeout",30000);
md.putString("startmsg","uk/co/mmscomputing/sounds/startmsg.wav");
md.putString("endmsg","uk/co/mmscomputing/sounds/endmsg.wav");
md.addListener(this);
System.out.println("create server...");
server=new CapiServerApplication(md);
new Thread(server).start();
}
private void send(final CapiCallApplication server,final String phoneno,final String srcfile){
new Thread(){
public void run(){
try{
int timeout=md.getInt("timeout");
CapiChannel channel=server.connect(phoneno,timeout);
AudioInputStream in = AudioSystem.getAudioInputStream(new File(srcfile));
channel.writeToOutput(in);
in.close();
channel.close(); // initiate disconnect
System.out.println("CLOSED SEND WRITE THREAD");
}catch(Exception ioe){
ioe.printStackTrace();
}
}
}.start();
}
private void answer(final CapiChannel channel,final File destfile){
final Thread[] t=new Thread[2];
new Thread(){ // send start msg
public void run(){
Thread.currentThread().setName(getClass().getName()+".startmsg.0x"+Integer.toHexString(channel.getLineID()));
AudioInputStream in=null;
try{
File startmsg=new JarFile(md.getString("startmsg"));
in=AudioSystem.getAudioInputStream(startmsg);
channel.writeToOutput(in);
}catch(Exception e){
e.printStackTrace();
try{
channel.close();
}catch(Exception ee){
ee.printStackTrace();
}
}finally{
try{
if(in!=null){in.close();}
System.err.println("STOPPED STARTMSG 0x"+Integer.toHexString(channel.getLineID()));
}catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
t[1]=new CapiFaxDetector(channel);t[1].start(); // if we receive 3 fax cng-tones then assume analogue group 3 fax
t[0]=new Thread(){
public void run(){
Thread.currentThread().setName(getClass().getName()+".wait_endmsg.0x"+Integer.toHexString(channel.getLineID()));
AudioInputStream in=null;
try{
sleep(md.getInt("recordTime")); // record 'recordTime' secs (includes time of startmsg)
System.err.println("STOPPED SLEEPING 0x"+Integer.toHexString(channel.getLineID()));
File endmsg=new JarFile(md.getString("endmsg"));
in=AudioSystem.getAudioInputStream(endmsg);
channel.writeToOutput(in);
}catch(InterruptedException ie){
System.err.println("INTERRUPTED CHANNEL 0x"+Integer.toHexString(channel.getLineID()));
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(in!=null){in.close();}
System.err.println("ANSWERPHONE CLOSE CHANNEL 0x"+Integer.toHexString(channel.getLineID()));
channel.close(); // initiate disconnect
System.err.println("ANSWERPHONE CLOSED CHANNEL 0x"+Integer.toHexString(channel.getLineID()));
}catch(Exception e){
e.printStackTrace();
}
}
}
};t[0].start();
new Thread(){ // read capi input as pcm audio data
public void run(){ // and save as pcm wav file
AudioInputStream in=null;
Thread.currentThread().setName(getClass().getName()+".record.0x"+Integer.toHexString(channel.getLineID()));
try{
in=channel.getAudioInputStream();
AudioSystem.write(in,AudioFileFormat.Type.WAVE,destfile);
in.close();
System.err.println("STOPPED RECORDING 0x"+Integer.toHexString(channel.getLineID()));
t[0].interrupt();t[1].interrupt();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(in!=null){in.close();}
channel.close(); // initiate disconnect
}catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
}
private void receivefax(final CapiChannel channel,final File destfile){
new Thread(){ // read capi input as byte data
public void run(){ // and save as binary (sff) file
try{
channel.writeInputTo(new FileOutputStream(destfile));
}catch(Exception ioe){
ioe.printStackTrace();
}
}
}.start();
}
public void update(Object data, Metadata metadata){
if(data instanceof DTMFInd){
System.out.println(getClass().getName()+".update : \n\tRECEIVED DTMF DIGITS : "+((DTMFInd)data).getDigits());
}else if(data instanceof NCPI){
System.out.println(getClass().getName()+".update : \n\tRECEIVED NCPI\n"+data);
}else if(data instanceof CapiMetadata.Indication){
handleIndication((CapiMetadata.Indication)data);
}else if(data instanceof CapiException){
System.out.println(data);
}else if(data instanceof Exception){
System.out.println(data);
// System.out.println(((Exception)data).getMessage());
((Exception)data).printStackTrace();
// }else if(data instanceof String){
}else{
System.err.println(data);
}
}
public void handleIndication(CapiMetadata.Indication mdi){
System.out.println("local no = "+mdi.localno);
System.out.println("remote no = "+mdi.remoteno);
mdi.setAccept(md.getInt("pickupTime"));
}
public void run(){
Thread.currentThread().setName(getClass().getName());
System.out.println("Started running...");
try{
while(true){
System.out.println("wait for call...");
CapiChannel channel=server.accept();
if(channel==null){break;}
BProtocol protocol=channel.getProtocol();
String rno=channel.getRemoteNo();
rno=rno.replaceAll("\\*\\*",""); // PBX: internal dialling
String nostr=channel.getLocalNo()+"_"+rno;
if(protocol instanceof SpeechProtocol){
answer(channel,new File(voicedir,sdf.format(new Date())+nostr+".wav"));
}else{
receivefax(channel,new File(faxdir,sdf.format(new Date())+nostr+".sff"));
}
}
}catch(Exception e){
e.printStackTrace();
}
System.out.println("Stopped running...");
}
public void close(){
server.close();
}
static private void RedirectSystemOut(String logfilename){
try{
PrintStream ps=new PrintStream(new FileOutputStream(logfilename));
// System.setErr(ps);
System.setOut(ps);
}catch(IOException ioe){
ioe.printStackTrace();
}
}
static private void showThreads()throws InterruptedException{
Thread thread=Thread.currentThread();
ThreadGroup threadgroup=thread.getThreadGroup();
int len=threadgroup.activeCount();
Thread[] threads=new Thread[len];
len=threadgroup.enumerate(threads);
System.err.println("\n\n\nThread group count = "+len);
for(int j=0;j<len;j++){
System.err.println("Thread name = "+threads[j].getName());
System.err.println("Thread class name = "+threads[j].getClass().getName());
if(!threads[j].getName().startsWith("main")){
// threads[j].interrupt();
}
}
}
public static void main(String[] args){
// RedirectSystemOut("/var/log/mmsc-answerphone.log");
try{
final AnswerPhone app=new AnswerPhone();
new Thread(app).start();
BufferedReader is=new BufferedReader(new InputStreamReader(System.in));
String inputline;
while((inputline=is.readLine())!=null){
System.out.println("input: "+inputline);
if(inputline.equals("quit")){ // type 'quit' on command line to quit:)
showThreads();
app.close();
break;
}
}
is.close();
System.out.println("Stopped Answerphone.");
showThreads();
}catch(Exception e){
System.out.println(e);
}
}
}