home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-09-10 | 25.4 KB | 726 lines |
- /************************************************************************
- * JT3Rec (by John W. Gibbs)
- *
- * Copyright (c) 1997 Microsoft Corporation, All Rights Reserved.
- ***********************************************************************/
-
- import java.awt.*;
- import java.applet.*;
- import java.util.*;
- import com.ms.com.*;
- import com.ms.ui.*;
- import tapi3.*;
- import AppCtrls;
-
-
- /////////////////////////////////////////////////////////////////////////
- // CLASS: JT3Rec
- //
- // PURPOSE: TAPI 3.0 test program
- // DATE: July 17, 1997
- //
- // DESCRIPTION:
- // Applet/application that allow the user to answer incoming calls
- // using TAPI 3.0.
- //
- /////////////////////////////////////////////////////////////////////////
-
- public class JT3Rec extends Applet
- implements TapiConstants, // misc. constants
- DISCONNECT_CODE // DC_xxx constants
- {
- // Application name.
- public static final String s_strAppName = "Java TAPI 3.0 Receiver";
-
- // True if running as stand alone app.
- public boolean m_fStandAlone = false;
-
- // Parent frame of the app.
- private Frame m_ParentFrame = null;
-
- // Resource Wizard generated UI.
- public final AppCtrls ctrls = new AppCtrls(this);
-
- // Main interface to the TAPI component.
- private ITTAPI m_Tapi = null;
-
- // The currently connected call or null if there isn't one.
- public ITBasicCallControl m_Call = null;
-
- // Stores mediatype identifiers (string GUIDs) for the mediatypes
- // in the mediatypes listbox. If a mediatype is supported by a
- // local address then it will be on this list.
- private Vector m_MediaTypes = new Vector();
-
- // Collection of CallNot objects. One notifier is created for each
- // address when the Listen button is pressed. The notifier will
- // be called by TAPI 3.0 when an incoming call arrives.
- private Vector m_CallNotifiers = new Vector();
-
-
- /////////////////////////////////////////////////////////////////////
- // init
- //
- // Performs applet initialization.
- /////////////////////////////////////////////////////////////////////
- public void init()
- {
- // select a font to use (ctrls needs this)
- Font font = new Font("Dialog", Font.PLAIN, 8);
- this.setFont(font);
-
- // setup the UI generated by the Resource Wizard
- ctrls.CreateControls();
- ctrls.lstMediaTypes.setMultipleSelections(true);
- ctrls.tfStatusBox.setEditable(false);
- DisableControls();
- if (m_fStandAlone) {
- ctrls.btnClose.enable();
- }
-
- // get parent frame to use for message boxes
- Container parent = getParent();
- while ((parent != null) && (!(parent instanceof Frame))) {
- parent = parent.getParent();
- }
- m_ParentFrame = (Frame) parent;
-
- // resize the frame if running as standalone app
- if (m_fStandAlone) {
- m_ParentFrame.pack();
- m_ParentFrame.setResizable(false);
- }
-
- // initialize TAPI component
- SetStatusMessage("Initializing TAPI 3.0...");
- try {
- m_Tapi = new TAPI();
- m_Tapi.Initialize();
- }
- catch (ComException e) {
- DoMessage("Fatal Error: Could not initialize TAPI 3.0");
- m_Tapi = null;
- if (m_fStandAlone) {
- System.exit(0);
- }
- else {
- SetStatusMessage("Could not initialize TAPI 3.0");
- return;
- }
- }
-
- // get initial data and display it
- SetStatusMessage("Enumerating mediatypes...");
- if (!EnumerateMediaTypes()) {
- DoMessage("Warning: Enumeration of mediatypes failed on some address(es)");
- }
- SetStatusMessage("Ready");
-
- // app initialized... enable controls
- ctrls.lstMediaTypes.enable();
- ctrls.btnListen.enable();
- }
-
- /////////////////////////////////////////////////////////////////////
- // stop
- //
- // Called when the user leaves the applet's webpage.
- /////////////////////////////////////////////////////////////////////
- public void stop()
- {
- StopListeningForCalls();
-
- if (m_Call != null) {
- DisconnectTheCall(DC_NORMAL);
- }
-
- ctrls.btnStop.disable();
- ctrls.btnHangup.disable();
- ctrls.btnListen.enable();
- ctrls.lstMediaTypes.enable();
- SetStatusMessage("Ready");
- }
-
- /////////////////////////////////////////////////////////////////////
- // destroy
- //
- // Called when the applet is destroyed by the browser.
- /////////////////////////////////////////////////////////////////////
- public void destroy()
- {
- try {
- if (m_Tapi != null) {
- m_Tapi.Shutdown();
- }
- }
- catch (ComException e) {
- e.printStackTrace();
- DoMessage("An error occurred while trying to shutdown TAPI");
- }
- }
-
- /////////////////////////////////////////////////////////////////////
- // action
- //
- // Event.ACTION_EVENT event handler.
- /////////////////////////////////////////////////////////////////////
- public boolean action(Event evt, Object arg)
- {
- if (arg.equals("Listen")) {
- // listen button pressed
- if (StartListeningForCalls()) {
- ctrls.btnListen.disable();
- ctrls.btnStop.enable();
- ctrls.lstMediaTypes.disable();
- SetStatusMessage("Listening for incoming calls");
- }
- else {
- DoMessage("Could not start listening");
- SetStatusMessage("Calls are not being monitored");
- }
- }
- else if (arg.equals("Stop")) {
- // stop button pressed
- StopListeningForCalls();
- ctrls.btnListen.enable();
- ctrls.btnStop.disable();
- ctrls.lstMediaTypes.enable();
- SetStatusMessage("Calls are not being monitored");
- }
- else if (arg.equals("Answer")) {
- // answer button pressed
- if (AnswerTheCall()) {
- ctrls.btnStop.disable();
- ctrls.btnHangup.enable();
- SetStatusMessage("Connected");
- }
- else {
- ctrls.btnStop.enable();
- DoMessage("The call could not be answered");
- SetStatusMessage("Listening for incoming calls");
- }
- ctrls.btnAnswer.disable();
- ctrls.btnReject.disable();
-
- }
- else if (arg.equals("Reject")) {
- // reject button pressed
- if (DisconnectTheCall(DC_REJECTED)) {
- DoMessage("The call has been rejected");
- }
- else {
- DoMessage("An error occurred while rejecting the " +
- "call, but it will be ignored");
- }
- ctrls.btnAnswer.disable();
- ctrls.btnReject.disable();
- ctrls.btnStop.enable();
- SetStatusMessage("Listening for incoming calls");
- }
- else if (arg.equals("Hangup")) {
- // hangup button pressed
- if (DisconnectTheCall(DC_NORMAL)) {
- DoMessage("The call has been disconnected");
- }
- else {
- DoMessage("An error occurred while disconnecting, " +
- "but it will be ignored");
- }
- ctrls.btnHangup.disable();
- ctrls.btnStop.enable();
- SetStatusMessage("Listening for incoming calls");
- }
- else if (arg.equals("Close")) {
- // close button pressed. This button is enabled only when
- // running as an application. Since a browser would close
- // the applet by calling stop and destroy, we should also.
- this.stop();
- this.destroy();
- System.exit(0);
- }
- else
- return super.action(evt, arg);
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////
- // EnumerateMediaTypes
- //
- // Finds all mediatypes supported by local addresses and adds their
- // description to the mediatypes listbox and their string GUID
- // itentifiers to the m_MediaTypes vector.
- /////////////////////////////////////////////////////////////////////
- private boolean EnumerateMediaTypes()
- {
- Variant var;
- ITCollection itcAddr, itcMedia;
- ITAddress address;
- ITMediaSupport mediaSupp;
- String mediaType;
-
- m_MediaTypes.removeAllElements();
-
- try {
- // get the collection interface for addresses
- var = m_Tapi.getAddresses();
- itcAddr = (ITCollection) var.toDispatch();
-
- // Walk through the collection. Note that collections start
- // at index 1 and end at index itc.getCount().
- for (int i=1; i <= itcAddr.getCount(); i++) {
- // get the next address
- var = itcAddr.getItem(i);
- address = (ITAddress) var.toObject();
- mediaSupp = (ITMediaSupport) address;
-
- // get the collection interface for mediatypes
- var = mediaSupp.getMediaTypes();
- itcMedia = (ITCollection) var.toDispatch();
-
- for (int j=1; j <= itcMedia.getCount(); j++) {
- // get the next mediatype
- mediaType = itcMedia.getItem(j).toString();
-
- // NOTE: currently java receiver applet has only
- // audio media type enabled for beta1
-
- if (mediaType.equals(TAPIMEDIATYPE_String_VideoIn)||
- mediaType.equals(TAPIMEDIATYPE_String_VideoOut))
- continue;
-
- // display the media name and store its string GUID,
- // if we haven't already
- if (!m_MediaTypes.contains(mediaType)) {
- ctrls.lstMediaTypes.addItem(GetMediaName(mediaType));
- m_MediaTypes.addElement(mediaType);
- }
- }
- }
- return true;
- }
- catch (ComException e) {
- e.printStackTrace();
- return false;
- }
- }
-
- /////////////////////////////////////////////////////////////////////
- // StartListeningForCalls
- //
- // Takes the selected mediatypes and sets all addresses to listen
- // for incoming calls using those mediatypes. If at least one
- // address succeeds to start listening then true is returned,
- // otherwise, false is returned.
- /////////////////////////////////////////////////////////////////////
- public boolean StartListeningForCalls()
- {
- Variant var;
- ITCollection itc;
- ITAddress address;
- ITMediaSupport mediaSupp;
- int[] indexes;
- Object temp;
- Vector mediaTypes = new Vector();
- boolean isListening = false;
-
- try {
- // get indexes for selected mediatypes
- indexes = ctrls.lstMediaTypes.getSelectedIndexes();
-
- // get the collection interface for addresses
- var = m_Tapi.getAddresses();
- itc = (ITCollection) var.toDispatch();
-
- for (int i=1; i <= itc.getCount(); i++) {
- // get the next address
- var = itc.getItem(i);
- address = (ITAddress) var.toObject();
- mediaSupp = (ITMediaSupport) address;
-
- // retrieve mediatypes supported by the current address
- for (int j=0; j < indexes.length; j++) {
- temp = m_MediaTypes.elementAt(indexes[j]);
- if (mediaSupp.QueryMediaType((String) temp)) {
- mediaTypes.addElement(temp);
- }
- }
-
- if (ListenOnThisAddress(address, mediaTypes)) {
- isListening = true;
- }
-
- mediaTypes.removeAllElements();
- }
- return isListening;
- }
- catch (ComException e) {
- e.printStackTrace();
- return isListening;
- }
- }
-
- /////////////////////////////////////////////////////////////////////
- // ListenOnThisAddress
- //
- // Performs the steps involved in setting up an address to listen
- // for calls. Setting up an application to listen for calls is a
- // two step process.
- //
- // First, the app must call RegisterCallTypes on the address that
- // it wants calls on. This will tell the address which mediatypes
- // it should listen for.
- //
- // Second, it must register it's implementation of the
- // ITCallNotification interface with the address. This interface
- // specifies only one method, CallEventNotification, which is called
- // by TAPI whenever a call event occurs.
- /////////////////////////////////////////////////////////////////////
- public boolean ListenOnThisAddress(ITAddress address, Vector mediaTypes)
- {
- SafeArray sa;
- Variant var;
- IConnectionPointContainer cpc;
- IConnectionPoint[] cp = new IConnectionPoint[1];
- CallNot callnot;
- int[] dwCookie = new int[1];
-
- if (address == null || !address.getServiceProviderName().equals("h323.tsp") ||
- mediaTypes == null || mediaTypes.size() == 0)
- return false;
-
- try {
- // RegisterCallTypes expects the mediatypes to be placed into
- // a safearray and the safearray into a variant. If null is
- // specified for the array, the address will listen for all
- // of its supported mediatypes.
-
- sa = new SafeArray(Variant.VariantString, mediaTypes.size());
-
- for (int i=0; i < mediaTypes.size(); i++) {
- sa.setString(i, (String) mediaTypes.elementAt(i));
- }
-
- var = new Variant(sa, false);
-
- address.RegisterCallTypes(
- false, // msgs for outgoing calls
- true, // want to be owner
- false, // don't want to be monitor
- var // array of owner mediatypes
- );
-
- // find the connection point for the ITCallNotification
- // interface. Refer to the COM ConnectionPoint documentation
- // for more details.
- cpc = (IConnectionPointContainer) address;
- cpc.FindConnectionPoint(ITCallNotification.iid, cp);
-
- callnot = new CallNot(this);
-
- // if the Advise method succeeds, then the address will start
- // listening for calls.
- cp[0].Advise(
- callnot, // sink object
- dwCookie // connection handle (retval)
- );
-
- // we save the call notification object. When we release
- // it, call notification will stop. Normally we would also
- // save the dwCookie value but since TAPI 3.0 does not
- // support Unadvise for the ITCallNotification interface,
- // we can safely discard it.
- m_CallNotifiers.addElement(callnot);
- return true;
- }
- catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
-
- /////////////////////////////////////////////////////////////////////
- // StopListeningForCalls
- //
- // Sets all addresses to ignore incoming calls. To ignore incoming
- // calls we release the call notification objects for each address.
- /////////////////////////////////////////////////////////////////////
- public void StopListeningForCalls()
- {
- m_CallNotifiers.removeAllElements();
-
- // force a garbage collect. This will ensure that the
- // notification objects are released.
- System.gc();
- }
-
- /////////////////////////////////////////////////////////////////////
- // AnswerTheCall
- //
- // Answers the incoming call.
- /////////////////////////////////////////////////////////////////////
- public boolean AnswerTheCall()
- {
- ITAddress address;
- ITMediaSupport mediaSupp;
- int[] indexes;
- String temp;
- Vector mediaTypes = new Vector();
- SafeArray sa;
- ITMediaTerminal mediaTerm;
- Variant var;
-
- if (m_Call == null)
- return false;
-
- try {
- // get local address participating in the call
- address = ((ITCallInfo) m_Call).getAddress();
-
- // get the media support interface on the address
- mediaSupp = (ITMediaSupport) address;
-
- // get indexes for selected mediatypes
- indexes = ctrls.lstMediaTypes.getSelectedIndexes();
-
- // filter those supported by the current address
- for (int i=0; i < indexes.length; i++) {
- temp = (String) m_MediaTypes.elementAt(indexes[i]);
- if (mediaSupp.QueryMediaType(temp)) {
- mediaTypes.addElement(temp);
- }
- }
-
- // create a safearray to put the media-terminals into
- sa = new SafeArray(Variant.VariantObject, mediaTypes.size());
-
- // create media-terminals, package each in a variant, and
- // store them in the safearray
- for (int i=0; i < mediaTypes.size(); i++) {
- mediaTerm = GetMediaTerminal(address, (String) mediaTypes.elementAt(i));
- if (mediaTerm != null) {
- sa.setVariant(i, new Variant(
- Variant.VariantObject,
- mediaTerm
- ));
- }
- }
-
- // put the safearray in a variant
- var = new Variant(sa, false);
-
- // select the media-terminals and answer
- m_Call.SelectMediaTerminals(var);
- m_Call.Answer();
- return true;
- }
- catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
-
- /////////////////////////////////////////////////////////////////////
- // DisconnectTheCall
- //
- // Disconnects the call using the given disconnect code.
- /////////////////////////////////////////////////////////////////////
- public boolean DisconnectTheCall(int code)
- {
- ITBasicCallControl call;
-
- if (m_Call == null)
- return true;
-
- call = m_Call;
-
- try {
- // during the call to Disconnect, the call notifier will
- // receive a CS_DISCONNECTED state. To indicate that
- // Disconnect has already been called on the local side we
- // set m_Call to null (see CallNot for details).
- m_Call = null;
- call.Disconnect(code);
- return true;
- }
- catch (ComException e) {
- e.printStackTrace();
- return false;
- }
- finally {
- call = null;
-
- // force a garbage collect. This will ensure that terminals
- // get released (unless you have references to them!), etc.
- // If you do not do this you may have effects such as video
- // windows lingering after a call has disconnected.
- System.gc();
- }
- }
-
- /////////////////////////////////////////////////////////////////////
- // GetMediaTerminal
- //
- // Returns a media-terminal for the given mediatype on the specified
- // address. Media-terminals are the association of a terminal
- // (static or dynamic) and the mediatype that it will use.
- //
- // The only dynamic terminal supported by this method is the video
- // window terminal.
- /////////////////////////////////////////////////////////////////////
- public ITMediaTerminal GetMediaTerminal(
- ITAddress address,
- String mediaType
- )
- {
- ITTerminalSupport termSupp;
- ITTerminal terminal;
- String VideoWindowMediaType;
-
- if (address == null || mediaType == null)
- return null;
-
- try {
- termSupp = (ITTerminalSupport) address;
-
- if (mediaType.equals(TAPIMEDIATYPE_String_VideoIn)) {
- terminal = termSupp.CreateTerminal(CLSID_String_VideoWindowTerm);
- }
- else {
- terminal = termSupp.GetDefaultTerminal(mediaType);
- }
-
- // terminal could be null here and CreateMediaTerminal
- // will not complain about it (ie, "null terminals" are
- // valid). We do not want any null terminals.
- if (terminal == null)
- return null;
-
- return m_Tapi.CreateMediaTerminal(mediaType, terminal);
- }
- catch (ComException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- /////////////////////////////////////////////////////////////////////
- // GetMediaName
- //
- // Returns a descriptive name for the given mediatype.
- /////////////////////////////////////////////////////////////////////
- public String GetMediaName(String mediaType)
- {
- if (mediaType.equals(TAPIMEDIATYPE_String_AudioOut))
- return "Audio Out";
-
- if (mediaType.equals(TAPIMEDIATYPE_String_AudioIn))
- return "Audio In";
-
- if (mediaType.equals(TAPIMEDIATYPE_String_VideoOut))
- return "Video Out";
-
- if (mediaType.equals(TAPIMEDIATYPE_String_VideoIn))
- return "Video In";
-
- if (mediaType.equals(TAPIMEDIATYPE_String_DataModem))
- return "Data Modem";
-
- if (mediaType.equals(TAPIMEDIATYPE_String_G3Fax))
- return "Group III Fax";
-
- return "Unknown mediatype"; // just in case
- }
-
- /////////////////////////////////////////////////////////////////////
- // DisableControls
- //
- // Disables all of the app's controls.
- /////////////////////////////////////////////////////////////////////
- private void DisableControls()
- {
- ctrls.lstMediaTypes.disable();
- ctrls.btnListen.disable();
- ctrls.btnStop.disable();
- ctrls.btnAnswer.disable();
- ctrls.btnReject.disable();
- ctrls.btnHangup.disable();
- ctrls.btnClose.disable();
- }
-
- /////////////////////////////////////////////////////////////////////
- // SetStatusMessage
- //
- // Displays messages in the status box.
- /////////////////////////////////////////////////////////////////////
- public synchronized void SetStatusMessage(String msg)
- {
- ctrls.tfStatusBox.setText(msg);
- }
-
- /////////////////////////////////////////////////////////////////////
- // DoMessage
- //
- // Displays messages in a message box.
- /////////////////////////////////////////////////////////////////////
- private void DoMessage(String msg)
- {
- AwtUIMessageBox msgbox = new AwtUIMessageBox(
- m_ParentFrame,
- s_strAppName,
- msg,
- AwtUIMessageBox.EXCLAMATION,
- UIButtonBar.OK
- );
- msgbox.doModal();
- }
-
- /////////////////////////////////////////////////////////////////////
- // main
- //
- // Standalone application entry point. Not called for applets.
- /////////////////////////////////////////////////////////////////////
- public static void main(String[] args)
- {
- JT3Rec applet = new JT3Rec();
-
- AppFrame frame = new AppFrame(s_strAppName, applet);
- frame.show();
-
- applet.m_fStandAlone = true;
- applet.init();
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- // CLASS: AppFrame
- //
- // DESCRIPTION:
- // Frame for standalone application.
- //
- ////////////////////////////////////////////////////////////////////////////////
-
- class AppFrame extends Frame
- {
- private Applet m_App = null;
-
- public AppFrame(String title, Applet applet)
- {
- super(title);
- m_App = applet;
- this.add(applet);
- }
-
- public boolean handleEvent(Event evt)
- {
- if (evt.id == Event.WINDOW_DESTROY) {
- // since a browser would close the applet by calling stop and
- // destroy, we should also.
- m_App.stop();
- m_App.destroy();
- System.exit(0);
- }
-
- return super.handleEvent(evt);
- }
- }