📄 station.java
字号:
// Station: Manage MSI stations
// $Id: Station.java,v 1.7 2003/11/13 11:55:18 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;
import java.util.*;
/**
* Station:
* First API was clearly targetted at a resource for a channel, with:
* assign (to channel and route audio) and connect/disconnect with channel
* audio.
* Now the API is extended to cope with autonomous (kind of) behaviour,
* implementing assign(channel, boolean route) to do light attaching
*/
public class Station extends Device implements Resource, ResourceServer
{
// Class variables
private static Hashtable extensions;
private static Vector stationAtDev;
private static StationServerThread stationServerThread;
private static LinkedList events;
static {
extensions = new Hashtable();
stationAtDev = new Vector(5,4);
stationServerThread = new StationServerThread();
stationServerThread.setName("Stations service thread");
events = new LinkedList();
stationServerThread.start();
}
// Instance variables
private String extension; // my address
private boolean hookState; // I know my hookstate
private boolean onHook; // my hook state
private boolean ringing; // am I ringing ?
private int ts; // my TX ts
private Channel channel; // talking to channel
private boolean routedRx; // Have we done routing of audio rx at attach time
private boolean routedTx; // Have we done routing of audio tx via connect
private StationServer server; // what takes care of my dialing
private ResourceServer xserver; // who activelly looks after me (i.e. gets all events)
private Thread serviceThread; // the thread for this station server
private ThreadGroup serviceGroup; // a group for this station server
private Channel serviceChannel; // a channel bound to this station server
/** Open an MSI station device */
public Station(String name, String extension)
{
super(null, name);
// msiBnCm
if (! name.substring(0, 4).equals("msiB"))
throw new RuntimeException("Station: bad name");
device = Dialogic.ms_open(name, 0);
// Extensions table
this.extension = extension;
extensions.put(extension, this);
// Device lookup
if (stationAtDev.size() <= device) {
stationAtDev.setSize(device + 1);
}
stationAtDev.setElementAt(this, device);
// etc...
ts = Dialogic.ms_getxmitslot(device);
onHook = (Dialogic.ATMS_TSSGBIT(device) == 0);
hookState = true;
channel = null;
routedRx = false;
routedTx = false;
server = null;
xserver = null;
serviceThread = null;
serviceGroup = new ThreadGroup(name + " group");
serviceChannel = null;
Channel.register(this, device);
// Let us know onhook/offhook/flash events
Dialogic.ms_setevtmsk(device, Dialogic.DTG_SIGEVT,
Dialogic.MSMM_ONHOOK|Dialogic.MSMM_OFFHOOK|Dialogic.MSMM_HOOKFLASH, Dialogic.DTA_SETMSK);
register();
}
// Get a reference to an extension by name. Kind of protect busy (offHook) extensions
public static Station getStation(String anExtension) {
Station stat = (Station)extensions.get(anExtension);
if (stat == null)
throw new RuntimeException("Unknown extension");
if (!stat.onHook)
throw new BusyException("Busy extension");
return stat;
}
// Start ringing
public void ring()
{
if (onHook() && !ringing) {
Dialogic.ms_genring(device, 100, Dialogic.EV_ASYNC);
ringing = true;
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println(this.toString() + " ringing!");
}
}
}
// Stop ringing
public void ringOff()
{
if (onHook() && ringing) {
Dialogic.ms_stopfn(device, Dialogic.MTF_RING);
ringing = false;
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println(this.toString() + " stop ringing!");
}
}
}
// Answer my hook state
public boolean onHook()
{
if (!hookState)
onHook = (Dialogic.ATMS_TSSGBIT(device) == 0);
return onHook;
}
// Answer my tx TS
public int getTs() {
return ts;
}
// Answer my tx TS, resource interface version (ours does not depend on Channel)
public int getTs(Channel aChannel) {
return ts;
}
// Listen to a device
public void listen(Device source) {
if (source != null)
Dialogic.ms_listen(device, source.getTs());
else
Dialogic.ms_unlisten(device);
}
// Listen to a resource ???
public void listen(Channel ch, Resource res) {
int ts = res.getTs(ch);
if (ts < 0)
Dialogic.ms_unlisten(device);
else
Dialogic.ms_listen(device, ts);
}
public void finalize() throws Throwable
{
close();
super.finalize();
}
public void close()
{
if (channel != null && routedTx)
disconnect(channel);
listen(null);
Dialogic.ms_setevtmsk(device, Dialogic.DTG_SIGEVT,
0, Dialogic.DTA_SETMSK);
super.close();
extensions.remove(extension);
stationAtDev.setElementAt(null, device);
}
/**
* assign: Assign to channel
* This can optionally route (default) audio from channel to station
*/
public void assign(Channel ch) {
assign(ch, true);
}
public void assign(Channel ch, boolean route) {
if (channel != null)
free(channel);
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println(this.toString() + " assigned to " + ch + (route ? "(routed)":""));
}
channel = ch;
routedRx = route;
if (routedRx)
Dialogic.ms_listen(device, ch.getNetwork().getTs());
ch.attach(this);
}
// Channel getting cleared
public void free(Channel ch) {
if (channel != ch)
return;
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println(this.toString() + " deassigned from " + ch);
}
if (routedTx)
disconnect(ch);
routedTx = false;
channel = null;
ch.dettach(this);
listen(null);
routedRx = false;
}
// Talk to channel
public void connect(Channel ch) {
if (channel != ch)
return;
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println(this.toString() + " connected to " + ch);
}
ch.listen(this);
routedTx = true;
}
// Stop talking to channel
public void disconnect(Channel ch) {
if (channel != ch)
return;
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println(this.toString() + " disconnected from " + ch);
}
ch.getNetwork().listen(ch.getVoice());
routedTx = false;
}
public String toString() {
StringBuffer desc = new StringBuffer();
desc.append("MSI Station " + extension);
return desc.toString();
}
public boolean service(EVT evt) {
if (evt.type == EVT.DTEV_SIG) {
if ((evt.data & Dialogic.DTC_ABIT) != 0) {
if ((evt.data & Dialogic.DTB_ABIT) == 0)
onHook = true;
else
onHook = false;
hookState = true;
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0)
System.out.println(this.toString() + (onHook?" OnHook":" OffHook"));
}
// chain to xserver, deal if none or not serviced by it
if (xserver == null || !xserver.service(evt)) {
if (channel != null)
channel.newEvent(evt);
else
newEvent(evt);
}
return true;
} else if (evt.type == EVT.MSEV_RING || evt.type == EVT.MSEV_NORING) {
ringing = false;
// Carefull, usually hook state changed
// but we are at interrupt time now... so wait for next user action
// onHook = (Dialogic.ATMS_TSSGBIT(device) == 0);
hookState = false;
// chain to xserver, deal if none or not serviced by it
if (xserver == null || !xserver.service(evt)) {
if (channel != null)
channel.newEvent(evt);
else
newEvent(evt);
}
return true;
}
return false;
}
public void setServer(StationServer aServer) {
server = aServer;
}
public void register(ResourceServer aServer) {
xserver = aServer;
}
public void setServiceChannel(Channel ch) {
serviceChannel = ch;
}
private void newEvent(EVT evt) {
synchronized(events) {
events.add(evt);
events.notifyAll();
}
}
private static class StationServerThread extends Thread {
// Run: Keep looking for station unclaimed events, dispatch new servers
public void run()
{
EVT evt;
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println("Station thread started");
}
while (true) {
synchronized(events) {
while (events.size() == 0) {
try {
events.wait();
} catch (InterruptedException ie) {}
}
evt = (EVT)events.removeFirst();
}
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println("Station thread: " + evt);
}
if (evt.type == EVT.DTEV_SIG && (evt.data & Dialogic.DTB_ABIT) != 0) {
// Offhook
Station stat = (Station)stationAtDev.elementAt(evt.dev);
if (stat == null) continue; // ??
if (stat.server == null) continue; // No server code
if (stat.serviceChannel != null) {
stat.serviceChannel.newEvent(evt);
continue;
}
if (stat.serviceThread != null) continue; // Already being served ???
stat.serviceThread = new StationThread(stat);
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println("Station thread: firing server for station "+stat.extension);
}
stat.serviceThread.start();
} else if (evt.type == EVT.DTEV_SIG && (evt.data & Dialogic.DTB_ABIT) == 0) {
// OnHook
Station stat = (Station)stationAtDev.elementAt(evt.dev);
if (stat == null) continue; // ??
if (stat.serviceChannel != null) {
stat.serviceChannel.newEvent(evt);
continue;
}
if (stat.serviceThread != null) {
// Has a server...
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println("Station thread: killing server for station "+stat.extension);
}
stat.serviceThread.interrupt();
}
}
}
}
}
// Give service (e.g. dialtone) to an offhook station
private static class StationThread extends Thread {
Station myStation;
StationThread(Station aStation) {
super(aStation.serviceGroup, "Station " + aStation.extension + " thread");
myStation = aStation;
}
public void run()
{
try {
myStation.server.service(myStation);
} finally {
myStation.serviceThread = null;
myStation.serviceChannel = null;
myStation.listen(null);
if ((Dialogic.debug & Dialogic.DEBUG_STATION) != 0) {
System.out.println("Station thread: finished!");
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -