📄 genericmediaservice.java
字号:
package net.sourceforge.gjtapi.media;
/*
Copyright (c) 2002 8x8 Inc. (www.8x8.com)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies of
the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
of the copyright holder.
*/
import javax.telephony.callcontrol.*;
import javax.telephony.*;
import javax.telephony.media.*;
import java.util.*;
import net.sourceforge.gjtapi.*;
/**
* Implements MediaService and the basic Resource interfaces.
* Resource methods are delegated to the bound MediaGroup.
* <p>
* This class understands about binding and configuration,
* and knows how to delegate resource methods to whatever
* object or objects are bound to this one. And conversely
* understand how to register Listeners for each resource,
* and dispatch events from any of the resources
* to all of the ResourceListeners.
* <p>
* The Resource methods in BasicMediaService are documented
* in the associated Resource interface definition.
*/
public class GenericMediaService implements MediaService, MediaServiceListener, Player, PlayerListener, Recorder, RecorderListener, SignalDetector, SignalDetectorListener, SignalGenerator, MediaServiceHolder {
/** The Provider and media service manager to work with */
private GenericProvider provider = null;
private MediaMgr mgr = null;
/** Vector of MediaListeners (MediaServiceListener,
ResourceListener (PlayerListener, RecorderListener, SignalDetectorListener)) */
protected static Vector theListeners = new Vector();
private GenericMediaGroup mediaGroup = null;
/**
* Create an unbound MediaService,
* using the installation default MediaProvider.
*/
public GenericMediaService() throws JtapiPeerUnavailableException, ProviderUnavailableException {
super();
Provider prov = JtapiPeerFactory.getJtapiPeer(null).getProvider(null);
if (prov instanceof MediaProvider)
this.initMediaService((MediaProvider) prov);
else
throw new ProviderUnavailableException("Default Provider not a MediaProvider");
}
/**
* Create an unbound MediaService, using services identified
* by the two String arguments.
*
* @param peerName the name of a Class that implements JtapiPeer.
* @param providerString a "login" string for that JtapiPeer.
*
* @throws ClassNotFoundException if JtapiPeer class is not found
* @throws IllegalAccessException if JtapiPeer class is not accessible
* @throws InstantiationException if JtapiPeer class does not instantiate
* @throws ProviderUnavailableException if Provider is not available
* @throws ClassCastException if Provider instance is not a MediaProvider
*/
public GenericMediaService(String peerName, String providerString)
throws ClassNotFoundException,
InstantiationException, // hope to remove in Jtapi-2.0
IllegalAccessException, // hope to remove in Jtapi-2.0
ProviderUnavailableException {
initMediaService(findMediaProvider(peerName, providerString));
}
/*
* Create an unbound MediaService, using services associated
* with the given MediaProvider object.
* The MediaProvider object may be a JTAPI Provider,
* or may be some other object obtained by other vendor-specific means.
*
* @param provider a MediaProvider instance
*/
public GenericMediaService(MediaProvider provider) {
initMediaService(provider);
}
/**
* Add a MediaListener to this MediaService.
* <p>
* Events generated by this MediaService are dispatched to the
* given listener if it implements the appropriate Listener interface.
* @@param listener an object that implements
* one or more of the ResourceListener interfaces and/or
* the MediaServiceListener interface.
*/
public void addMediaListener(MediaListener listener) {
theListeners.add(listener);
}
/*
* bind to an new outbound call.
* @exception MediaBindException one of AlreadyBoundException, BindCancelledException.
* @exception MediaConfigException if MediaGroup can not be configured as requested.
* @exception MediaCallException encapsulates any call processing exceptions
* generated while trying to establish the new Call and Connections.
*/
synchronized
public void bindAndConnect(ConfigSpec configSpec,
String origAddr,
String dialDigits)
throws MediaBindException, MediaConfigException, MediaCallException {
if(this.getMediaGroup() != null) throw new AlreadyBoundException();
// find a media terminal
GenericProvider gp = this.getProvider();
Address addr = null;
try {
addr = gp.getAddress(origAddr);
} catch (InvalidArgumentException iae) {
throw new MediaCallException("Originating Address unknown");
}
Terminal[] terms = addr.getTerminals();
MediaTerminal term = null;
for (int i = 0; i < terms.length && term == null; i++) {
if (terms[i] instanceof MediaTerminal) {
term = (MediaTerminal)terms[i];
break;
}
}
if (term == null) { // no media terminals
throw new MediaCallException("No media terminal for address " + origAddr);
}
// bind to the terminal
this.bindToTerminal(configSpec, term);
// make the call and connect it
try {
gp.createCall().connect(term, addr, dialDigits);
} catch (Exception e) {
// release the MediaService, since the call failed
this.releaseAndFree();
throw new MediaCallException("Error making call: " + e.toString());
}
}
/*
* Bind this MediaService to a MediaGroup connected to an existing Call.
* This will typically create a new Connection to the Call.
* <p>
* @param configSpec declares configuration requirments for the MediaGroup.
* @param call a JTAPI Call object
*
* @exception MediaBindException one of AlreadyBoundException, BindCancelledException.
* @exception MediaConfigException if MediaGroup can not be configured as requested.
* @exception MediaCallException encapsulates any call processing exceptions
* generated while trying to establish the new Connections.
* @return the Connection between the bound Terminal and the given Call.
*/
synchronized
public Connection bindToCall(ConfigSpec configSpec,
Call call)
throws MediaBindException, MediaConfigException, MediaCallException {
if (this.getMediaGroup() != null)
throw new AlreadyBoundException();
if (call == null)
throw new MediaCallException("Null Call");
MediaTerminal mt = null;
CallControlTerminalConnection tc = null; // for later, if we need it in adding in a new media terminal
// first check if any of the current terminals support media
Connection[] conns = call.getConnections();
Connection mediaConn = null;
for (int i = 0; i < conns.length; i++) {
TerminalConnection[] tcs = conns[i].getTerminalConnections();
if (tcs != null) {
for (int j = 0; j < tcs.length; j++) {
if (tc == null && tcs[j] instanceof CallControlTerminalConnection)
tc = (CallControlTerminalConnection)tcs[j];
if (tcs[j].getTerminal() instanceof MediaTerminal) {
mt = (MediaTerminal)tcs[j].getTerminal();
mediaConn = conns[i];
break;
}
}
}
}
if (mt == null) { // create a new media terminal connection to the call
if (!(call instanceof CallControlCall))
throw new MediaCallException("Call does not support conferencing in new Media Terminals");
if (tc == null)
throw new MediaCallException("No TerminalConnection to make conference from");
CallControlCall ccc = (CallControlCall)call;
// ask the provider for the first known available media terminal
mt = this.getProvider().getAvailableMediaTerminal();
// check if any MediaTerminals found
if (mt == null)
throw new MediaCallException("No available media terminals known");
Connection[] consultCons = null;
try {
// connect to the active call by conferencing the media terminal in
consultCons = ccc.consult(tc, mt.getAddresses()[0].getName());
// answer the other end
boolean answered = false;
TerminalConnection[] newTcs = mt.getTerminalConnections();
for (int i = 0; i < newTcs.length; i++) {
if (newTcs[i].getState() == TerminalConnection.RINGING) {
((CallControlTerminalConnection)newTcs[i]).answer();
// mediaConn = newTcs[i].getConnection(); -- but the conference will break this
answered = true;
break;
}
}
if (!answered) {
for (int i = 0; i < consultCons.length; i++)
consultCons[i].disconnect();
throw new MediaCallException("Could not answer consultation call");
}
// now join things up
ccc.conference(consultCons[0].getCall());
} catch (Exception e) {
if (e instanceof MediaCallException)
throw (MediaCallException)e;
else
throw new MediaCallException("Error making consultation call");
}
}
// now assign the media service to the connected media terminal
this.bindToTerminal(configSpec, mt);
// return the connection between the call and the terminal
if (mediaConn == null) {
conns = call.getConnections();
int sz = conns.length;
for (int i = 0; i < sz; i++) {
TerminalConnection[] tcs = conns[i].getTerminalConnections();
int tcSize = tcs.length;
for (int j = 0; j < tcSize; j++) {
if (tcs[j].getTerminal().equals(mt)) {
mediaConn = conns[i];
break;
}
}
}
}
return mediaConn;
}
/*
* Bind this MediaService with a particular MediaGroup.
* <p>This may be performed by another object in the same package.
*
* @param group The MediaGroup to hook into this MediaService
*
* @exception AlreadyBoundException
*/
synchronized void bindToGroup(GenericMediaGroup group) throws AlreadyBoundException {
if (this.isBound())
throw new AlreadyBoundException();
this.setMediaGroup(group);
this.getMgr().bind(group.getTerminal().getName(), this);
// notify any thread that is waiting for this service to be bound
synchronized(this) {
this.notify();
}
}
/*
* This MediaService is ready for a MediaGroup.
* Waits for a Call to be delivered to this service name.
* <p>
* On return, this MediaService is bound to a MediaGroup,
* and that MediaGroup is configured to configSpec.
* <p>
* if cancelBindRequest() terminates this method,
* this method unblocks, throwing a BindCancelledException.
* <p>
* @param configSpec configure MediaGroup to configspec before binding.
* @param serviceName name under which this MediaService is to be registered.
* @exception MediaBindException one of AlreadyBoundException, BindCancelledException.
*/
// Does not throw MediaConfigException: that exception goes to releaseToService().
/* The logical equivalent of S.100:RequestGroup() */
synchronized
public void bindToServiceName(ConfigSpec configSpec,
String serviceName)
throws MediaBindException {
if(this.getMediaGroup() != null)
throw new AlreadyBoundException();
// place in MediaMgr
this.getMgr().register(serviceName, this);
// wait for service to be invoked
synchronized (this) {
try {
this.wait();
} catch (InterruptedException ie) {
throw new BindCancelledException("Bind Thread Interrupted");
}
// test if the bind was cancelled
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -