📄 servicechannel.java
字号:
// local.dialogic.ServiceChannel
// $Id: ServiceChannel.java,v 1.8 2003/09/16 12:23:38 cgm8 Exp $
/*
* Copyright (c) 1999 Carlos G Mendioroz.
*
* This file is part of D4J.
*
* D4J is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* D4J is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Report problems and direct all questions to:
*
* tron@acm.org
*/
package local.dialogic;
/**
* ServiceChennel:
* This is a mess... :-)
* Now seriously, this is a way to have a Voice resource wrapped
* on channel control logic for use by those pesty ill behaved
* resources known as stations...
* Starting at 1.11, there's also a version without Voice!
* That making sense when a call is made from station to station...
* .. in which case we also support multi-binding (2 networks!)
* to get disconnect supervision on any party
*/
public class ServiceChannel extends Channel {
// Constantes
// Variables
Voice voiceDev = null;
Device network = null;
Device network2 = null;
private String mydev;
private String myani; // ANI to be answered by this channel
private int linestate; // An internal linestate for dummy ringback control
private static final int INIT = 0;
private static final int ACCEPTED = 1;
private static final int ANSWERED = 2;
private static final int CLEARED = 3;
/**
* Create a ServiceChannel wrapper on a given voice device name, with fixed ani
*/
public ServiceChannel(String voiceName, String ani) {
super();
if (voiceName == null)
mydev = "NONE";
else
mydev = voiceName;
myani = ani;
if (!mydev.equals("NONE"))
voiceDev = new Voice(this, mydev);
setState(FREE);
linestate = INIT;
}
/**
* Create a ServiceChannel wrapper on a given voice device name
*/
public ServiceChannel(String voiceName) {
this(voiceName, "");
}
/**
* Create a ServiceChannel without resources
*/
public ServiceChannel() {
this("NONE", "");
}
public void close()
{
super.clear();
if (voiceDev != null) {
voiceDev.close();
voiceDev = null;
}
}
public String toString() {
return "ServiceChannel on " + mydev
+ (myani.equals("") ? "" : " for " + myani)
+ ((call == null) ? "" : "(" + call.id() + ")");
}
public Voice getVoice() {
return voiceDev;
}
/**
* Bind: bind this service channel to an MSI station
* good up to next clear() or unbind()
* by default, associate to current thread
*/
public void bind(Station stat) {
bind(stat, true);
}
public void bind(Station stat, boolean setGroup) {
if (voiceDev == null && network != null) {
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0)
System.out.println(this.toString() + " bind2 to " + stat);
network2 = stat;
} else {
network = (Device)stat;
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0)
System.out.println(this.toString() + " bind to " + stat);
}
if (setGroup) setGroup();
stat.setServiceChannel(this);
setState(OUTGOING); // Not really :-)
}
/**
* Unbind: release a binding, reason being call transfer
*/
public void unbind(Station stat) {
if (network == stat || network2 == stat) {
if (network == stat)
network = network2;
network2 = null;
stat.setServiceChannel(null);
}
// Should we do some more checks ?
}
/**
* Return our network device
* If we are bound, then this is usually a station
* if not, answer our voice resource for listen() to hear to it...
*/
public Device getNetwork() {
if (network != null)
return network;
return voiceDev;
}
/**
* Return our network2 device
* If we are bound2, then this is usually a station
* needed to reconnect from either way of an internall call.
*/
public Device getNetwork2() {
return network2;
}
/**
* newCall(dnis)
* Associate a new call object for given dnis
*/
public Call newCall(String dnis) {
linestate = INIT;
call = new Call(this);
call.dnis = dnis;
return call;
}
/**
* newCall(dnis, ani)
* Associate a new call object for given dnis, and set caller ani
*/
public Call newCall(String dnis, String ani) {
linestate = INIT;
call = new Call(this);
call.dnis = dnis;
call.ani = ani;
return call;
}
/**
* Accept: just take note...
*/
void accept() {
linestate = ACCEPTED;
return;
}
/**
* answer()Be easy, some times we want to go on
* for call handlers to work with ServiceChannels
*/
void answer(int rings) {
if (voiceDev != null && (linestate == INIT || linestate == ACCEPTED) && rings > 0) {
boolean flip = false;
TNGEN t1 = new TNGEN(440, -10, 100);
TNGEN t2 = new TNGEN(330, -40, 200);
TPT tpt = new TPT();
voiceDev.playtone(t1, tpt);
EVT evt;
// Ring cycle
while(true) {
evt = serviceWaitEvent();
if (evt.type == EVT.TDX_PLAYTONE) {
if (rings-- <= 0)
break;
if (flip)
voiceDev.playtone(t1, tpt);
else
voiceDev.playtone(t2, tpt);
flip = !flip;
continue;
} else {
voiceDev.stop();
// offHook ?
break;
}
}
}
setState(INCOMING);
linestate = ANSWERED;
return;
}
/**
* reject(reason): throw a BusyException
*/
void reject(int reason) {
if (voiceDev != null) {
TNGEN t1 = new TNGEN(330, -10, 40);
TNGEN t2 = new TNGEN(440, -10, 40);
TNGEN t3 = new TNGEN(600, -10, 40);
TPT tpt = new TPT();
voiceDev.playtone(t1, tpt);
voiceDev.playtone(t2, tpt);
voiceDev.playtone(t3, tpt);
voiceDev.waitIdle();
}
setState(OOS);
linestate = CLEARED;
throw new BusyException();
}
void dial(Call call, String number) {
throw new ChannelException("dial(): wrong state");
}
/**
* ani(): We have a static ani support
*/
String ani() {
return myani;
}
/**
* pulses(): No way to know, return 1 if dialed ?
*/
int pulses() {
return 0;
}
public void clear() {
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0)
System.out.println(this.toString() + " cleared");
linestate = CLEARED;
super.clear();
if (voiceDev != null) {
voiceDev.stop();
voiceDev.listen(null);
voiceDev.clear();
}
// Network is a Station in this version
if (network != null)
((Station)network).setServiceChannel(null);
network = null;
serviceThread = null;
group = null;
call = null;
try {
Thread.sleep(200);
}
catch(InterruptedException ie) {
Thread.currentThread().interrupt();
}
flush();
setState(FREE);
linestate = INIT;
}
// Our line state service fn
protected EVT service(EVT evt) {
if ((network != null && network.source(evt))
|| (network2 != null && network2.source(evt))) {
// my station (or peer) event
if (evt.type == EVT.DTEV_SIG
&& (evt.data & Dialogic.DTC_ABIT) != 0
&& (evt.data & Dialogic.DTB_ABIT) == 0) {
// Station onhook...
if (call != null) call.drop();
if (linestate != CLEARED) // Do not interrupt clearing channel
throw new HangUpException();
} else if (evt.type == EVT.DTEV_SIG
&& (evt.data & Dialogic.DTMM_WINK) != 0) {
// Station flash... same as onhook if reached this far
if (call != null) call.drop();
if (linestate != CLEARED) // Do not interrupt clearing channel
throw new HangUpException();
}
}
return evt;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -