AppController.java
Upload User: lizhi6181
Upload Date: 2014-10-02
Package Size: 8848k
Code Size: 138k
Category:

VOIP program

Development Platform:

Java

  1. /*
  2.  * Open Source Exemplar Software
  3.  *
  4.  * Copyright (C) 2005 University of Wisconsin (Trace R&D Center)
  5.  * Copyright (C) 2005 Omnitor AB
  6.  *
  7.  * This reference design was developed under funding from the National
  8.  * Institute on Disability and Rehabilitation Research US Dept of Education
  9.  * and the European Commission.
  10.  *
  11.  * This piece of software is a part of a package that was developed as a joint
  12.  * effort of Omnitor AB and the Trace Center - University of Wisconsin and is
  13.  * released to the public domain with only the following restrictions:
  14.  *
  15.  * 1) That the following acknowledgement be included in the source code and
  16.  * documentation for the program or package that use this code
  17.  *
  18.  * "Parts of this program were based on reference designs developed by
  19.  * Omnitor AB and the Trace Center, University of Wisconsin-Madison under
  20.  * funding from the National Institute on Disability and Rehabilitation
  21.  * Research US Dept of Education and the European Commission."
  22.  *
  23.  * 2) That this program not be modified unless it is plainly marked as
  24.  * modified from the original distributed by Trace/Omnitor.
  25.  *
  26.  * (NOTE: This release applies only to the files that contain this notice -
  27.  * not necesarily to any other code or libraries associated with this file.
  28.  * Please check individual files and libraries for the rights to use each)
  29.  *
  30.  * THIS PIECE OF THE SOFTWARE PACKAGE IS EXPERIMENTAL/DEMONSTRATION IN NATURE.
  31.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  32.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  33.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
  34.  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
  35.  * BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
  36.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  37.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  38.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  39.  * SOFTWARE.
  40.  *
  41.  */
  42. package se.omnitor.tipcon1;
  43. import ca.beq.util.win32.registry.RegistryKey;
  44. import ca.beq.util.win32.registry.RootKey;
  45. import ca.beq.util.win32.registry.RegistryValue;
  46. import java.io.BufferedReader;
  47. import java.io.File;
  48. import java.io.FileWriter;
  49. import java.io.InputStreamReader;
  50. import java.io.IOException;
  51. import java.net.DatagramSocket;
  52. import java.net.DatagramPacket;
  53. import java.net.InetAddress;
  54. import java.net.SocketException;
  55. import java.net.UnknownHostException;
  56. import java.net.SocketTimeoutException;
  57. import java.util.Collection;
  58. import java.util.Properties;
  59. import java.util.Random;
  60. import java.util.Vector;
  61. import java.util.Iterator;
  62. import java.awt.Color;
  63. import java.awt.Font;
  64. import javax.media.CaptureDeviceInfo;
  65. import javax.media.CaptureDeviceManager;
  66. import javax.media.Codec;
  67. import javax.media.ControllerClosedEvent;
  68. import javax.media.ControllerEvent;
  69. import javax.media.ControllerListener;
  70. import javax.media.Format;
  71. import javax.media.MediaLocator;
  72. import javax.media.NoProcessorException;
  73. import javax.media.PackageManager;
  74. import javax.media.PlugInManager;
  75. import javax.media.Processor;
  76. import javax.media.control.TrackControl;
  77. import javax.media.format.AudioFormat;
  78. import javax.media.format.VideoFormat;
  79. import javax.media.protocol.ContentDescriptor;
  80. import javax.media.protocol.DataSource;
  81. import javax.media.protocol.SourceCloneable;
  82. import javax.media.rtp.RTPManager;
  83. import javax.naming.NameNotFoundException;
  84. import javax.naming.NamingException;
  85. import javax.sound.sampled.AudioFileFormat;
  86. import javax.sound.sampled.AudioInputStream;
  87. import javax.sound.sampled.AudioSystem;
  88. import javax.sound.sampled.Clip;
  89. import javax.sound.sampled.Line;
  90. import javax.xml.parsers.DocumentBuilder;
  91. import javax.xml.parsers.DocumentBuilderFactory;
  92. import org.w3c.dom.Document;
  93. import org.w3c.dom.Element;
  94. import org.w3c.dom.Node;
  95. import org.w3c.dom.NodeList;
  96. import se.omnitor.media.protocol.text.t140.TextFormat;
  97. import se.omnitor.tipcon1.gui.AudioVideoPlayer;
  98. import se.omnitor.tipcon1.gui.DialogFactory;
  99. import se.omnitor.tipcon1.gui.ProgramWindow;
  100. import se.omnitor.tipcon1.gui.SplashScreen;
  101. import se.omnitor.tipcon1.gui.ThreadedDialog;
  102. import se.omnitor.tipcon1.rtp.RTPPayloadConstants;
  103. import se.omnitor.tipcon1.sip.SipRegistrarInfo;
  104. import se.omnitor.protocol.rtp.text.SyncBuffer;
  105. import se.omnitor.protocol.t140.T140TextArea;
  106. import se.omnitor.protocol.t140.T140Panel;
  107. import se.omnitor.protocol.t140.T140Packetizer;
  108. import se.omnitor.protocol.t140.T140DePacketizer;
  109. import se.omnitor.util.FifoBuffer;
  110. import se.omnitor.protocol.sip.AuthInfo;
  111. import se.omnitor.protocol.sip.FromAddress;
  112. import se.omnitor.protocol.sip.SipControllerListener;
  113. import se.omnitor.protocol.sip.SipController;
  114. import se.omnitor.protocol.sip.call.IncomingCallDialog;
  115. import se.omnitor.protocol.sip.call.IncomingReferDialog;
  116. import se.omnitor.protocol.sip.call.OutgoingCallDialog;
  117. import se.omnitor.protocol.sip.call.CallProcessor;
  118. import se.omnitor.protocol.sip.register.RegisterProcessor;
  119. import se.omnitor.protocol.sip.register.RegisterDialog;
  120. import se.omnitor.protocol.sdp.SdpManager;
  121. import se.omnitor.protocol.sdp.SdpMedia;
  122. import se.omnitor.protocol.sdp.media.CustomMedia;
  123. import se.omnitor.protocol.sdp.format.CustomFormat;
  124. import se.omnitor.protocol.sdp.format.T140Format;
  125. import se.omnitor.protocol.sdp.format.RedFormat;
  126. import se.omnitor.protocol.stun.StunStack;
  127. import se.omnitor.protocol.stun.StunStackException;
  128. import javax.sdp.SdpException;
  129. // import LogClasses and Classes
  130. import java.util.logging.Level;
  131. import java.util.logging.Logger;
  132. //import net.sf.fmj.media.cdp.civil.CaptureDevicePlugger;
  133. import java.awt.Dimension;
  134. import javax.media.Control;
  135. /**
  136.  * The main class for a multimedia SIP user client.
  137.  *
  138.  * This class connects RTP, SIP and GUI. How this program works is described
  139.  * in a document at Omnitor AB.
  140.  *
  141.  * @author Andreas Piirimets, Omnitor AB
  142.  * @author Erik Zetterstrom, Omnitor AB
  143.  */
  144. public class AppController implements SipControllerListener {
  145.     // A registrarion's status
  146.     private static final int FAIL = 1;
  147.     private static final int TRYING = 2;
  148.     private static final int OK = 3;
  149.     private static final int NOT_REG = 4;
  150.     // Semaphore
  151.     private Integer stateLock = new Integer(0);
  152.     // The local video
  153.     private AudioVideoPlayer avPlayer = null;
  154.     // General RTP variables
  155.     private boolean processorChangeFailed;
  156.     private DataSource transmitVideoDataSource = null;
  157.     private Vector supportedMedia;
  158.     // RTP Text transmit variables
  159.     private boolean firstRun = true;
  160.     private boolean redFlagOutgoing = false;
  161.     private int maxIncomingCps;
  162.     //private int localTextPort;
  163.     private boolean textIsActivated;
  164.     private int nbrOfTextDevices = 1;
  165.     // Video RTP transmit variables
  166.     //private int localVideoPort;
  167.     private VideoFormat[] videoFormat;
  168.     //private VideoFormat videoFormatToUse;
  169.     private Vector videoCodecs;
  170.     private int videoDevice;
  171.     private boolean videoIsActivated;
  172.     private int nbrOfVideoDevices;
  173.     private String[] videoLocator;
  174.     private int videofps = 25;
  175.     // Audio RTP transmit variables
  176.     //private int localAudioPort;
  177.     private AudioFormat[] audioFormat;
  178.     private Vector audioCodecs;
  179.     private int audioDevice;
  180.     private boolean audioIsActivated;
  181.     private int nbrOfAudioDevices;
  182.     private String[] audioLocator;
  183.     private boolean isMuted;
  184.     // RTP Text receive variables
  185.     private boolean redFlagIncoming = false;
  186.     // GUI dialogs, windows and labels
  187.     protected ProgramWindow gui;
  188.     private ThreadedDialog incomingCallDialog;
  189.     private ThreadedDialog outgoingCallDialog;
  190.     // SIP variables
  191.     protected SipController sc;
  192.     private String remoteUserAddress;
  193.     private RegisterProcessor[] registerProcessor;
  194.     private CallProcessor callProcessor;
  195.     private int[] sipRegistrarStatus;
  196.     boolean sipCompatibleNatIsProbed = false;
  197.     boolean isBehindSipCompatibleNat = false;
  198.     Thread sipStarterThread = null;
  199.     Integer sipStartStopMutex;
  200.     boolean sipSystemIsRunning = false;
  201.     boolean queuedSipSystemRestart;
  202.     // SDP
  203.     private SdpManager currentSdpManager;
  204.     private Vector negotiatedMedia;
  205.     private int sdpCallCounter;
  206.     // Network
  207.     private String localIpAddress = null;
  208.     private String localHostAddress;
  209.     private String dnsServer = null;
  210.     private int nextFreePort = 1024;
  211.     private boolean isSipCompatibleNatDetected = false;
  212.     private String sipCompatibleNatName = null;
  213.     // Runtime variables
  214.     // These variables control system settings during runtime, these settings
  215.     // may and should differ from settings saved to disk.
  216.     private boolean runtimeIsStunActivated;
  217.     private SyncBuffer txTextBuffer;
  218.     private FifoBuffer rxTextBuffer;
  219.     private T140Panel t140Panel;
  220.     private T140Packetizer t140Packetizer;
  221.     private T140DePacketizer t140DePacketizer;
  222.     private String classRoot;
  223.     private AppConstants appConstants;
  224.     private Properties language;
  225.     private MediaManager mediaManager;
  226.     private boolean outgoingCallProgressReported;
  227.     private boolean isEconf351 = false;
  228.     private AppSettings appSettings;
  229.     private StunStack stunStack;
  230.     private boolean tipcon1Mode;
  231.     private String configurationTypeString;
  232.     //private static CertCallback certCallback = new CertCallback();
  233.     //************************************************************************
  234.     // declare package and classname
  235.     public final static String CLASS_NAME = AppController.class.getName();
  236.     // get an instance of Logger
  237.     private static Logger logger = Logger.getLogger(CLASS_NAME);
  238.     /**
  239.      * Register a payload type to JMF.
  240.      *
  241.      * @param payloadType The payload type number to register
  242.      * @param codec The codec to assign to this payload type number
  243.      */
  244.     private void registerPayloadType(int payloadType, String codec) {
  245.         TextFormat textFormat = new TextFormat(codec);
  246.         RTPManager rtpManager = RTPManager.newInstance();
  247.         rtpManager.addFormat(textFormat, payloadType);
  248.     }
  249.     /**
  250.      * Registers the text plug-in to JMF.
  251.      *
  252.      */
  253.     private void registerTextPlugIn() {
  254.         // Name of the new plugin
  255.         String packageString = new String("se.omnitor.media.protocol.rtptext");
  256.         // Add new package prefix
  257.         Vector packagePrefix = PackageManager.getProtocolPrefixList();
  258.         String myPackagePrefix = new String("se.omnitor");
  259.         if (packagePrefix.indexOf(myPackagePrefix) == -1) {
  260.             packagePrefix.addElement(myPackagePrefix);
  261.             PackageManager.setProtocolPrefixList(packagePrefix);
  262.             PackageManager.commitProtocolPrefixList();
  263.         }
  264.         // Add new content prefix
  265.         Vector contentPrefix = PackageManager.getContentPrefixList();
  266.         if (contentPrefix.indexOf(myPackagePrefix) == -1) {
  267.             contentPrefix.addElement(myPackagePrefix);
  268.             PackageManager.setContentPrefixList(contentPrefix);
  269.             PackageManager.commitContentPrefixList();
  270.         }
  271.         // Save the changes to the plug-in registry
  272.         try {
  273.             PlugInManager.commit();
  274.         } catch (java.io.IOException ioe) {
  275.             ioe.printStackTrace();
  276.         }
  277.         // Register Packetizer
  278.         /*
  279.                TextPacketizer textPacketizer = new TextPacketizer(0,0);
  280.                try {
  281.          PlugInManager.removePlugIn(textPacketizer.getClass().getName(),
  282.                                               PlugInManager.CODEC);
  283.                    PlugInManager.addPlugIn(textPacketizer.getClass().getName(),
  284.          textPacketizer.getSupportedInputFormats(),
  285.                                            textPacketizer.
  286.                                            getSupportedOutputFormats(null),
  287.                                            PlugInManager.CODEC);
  288.                    PlugInManager.commit();
  289.                } catch (Exception e2) {
  290.                    if (DEBUG) {
  291.          System.err.println("Cannot register TextPacketizer: " + e2);
  292.                    }
  293.                }
  294.                if (DEBUG) {
  295.                    System.out.println("TextPacketizer registered.");
  296.                }
  297.          */
  298.         // Register DePacketizer
  299.         /*
  300.          TextDePacketizer textDePacketizer = new TextDePacketizer(0, false);
  301.                try {
  302.          PlugInManager.removePlugIn(textDePacketizer.getClass().getName(),
  303.                                               PlugInManager.CODEC);
  304.          PlugInManager.addPlugIn(textDePacketizer.getClass().getName(),
  305.                                            textDePacketizer.
  306.                                            getSupportedInputFormats(),
  307.                                            textDePacketizer.
  308.                                            getSupportedOutputFormats(null),
  309.                                            PlugInManager.CODEC);
  310.                    PlugInManager.commit();
  311.                } catch (Exception e2) {
  312.                    if (DEBUG) {
  313.          System.err.println("Cannot register TextDePacketizer: " + e2);
  314.                    }
  315.                }
  316.                if (DEBUG) {
  317.                    System.out.println("TextDePacketizer registered.");
  318.                }
  319.          */
  320.         // Register player
  321.         /*
  322.                TextPlayer textPlayer= new TextPlayer();
  323.                try {
  324.                    PlugInManager.removePlugIn(textPlayer.getClass().getName(),
  325.                                               PlugInManager.RENDERER);
  326.                    PlugInManager.addPlugIn(textPlayer.getClass().getName(),
  327.          textPlayer.getSupportedInputFormats(),
  328.          textPlayer.getSupportedOutputFormats(null),
  329.                                            PlugInManager.RENDERER);
  330.                    PlugInManager.commit();
  331.                } catch (Exception e2) {
  332.                    if (DEBUG) {
  333.          System.err.println("Cannot register TextDePacketizer: " + e2);
  334.                    }
  335.                }
  336.                if (DEBUG) {
  337.                    System.out.println("TextPlayer registered.");
  338.                }
  339.          */
  340.     }
  341.     /**
  342.      * Registers the H263 mode A effect to JMF.
  343.      *
  344.      */
  345. /*
  346.      private void registerH263ModeAEffect() {
  347.       H263ModeAEffect effect = new H263ModeAEffect();
  348.       String name = effect.getClass().getName();
  349.         try {
  350.             PlugInManager.removePlugIn(name, PlugInManager.EFFECT);
  351.             PlugInManager.addPlugIn(name,
  352.                                     effect.getSupportedInputFormats(),
  353.                                     effect.getSupportedOutputFormats(null),
  354.                                     PlugInManager.EFFECT);
  355.             PlugInManager.commit();
  356.         }
  357.       catch (Exception e2) {
  358.             if (DEBUG) {
  359.                 System.err.println("Cannot register H263 mode A effect: " +
  360.        e2);
  361.        e2.printStackTrace();
  362.             }
  363.         }
  364.         if (DEBUG) {
  365.             System.out.println("H263 mode A effect registered.");
  366.         }
  367.      }
  368. */
  369.     /**
  370.      * Initializes text plugin, creates SipController, and creates GUI.
  371.      * It also reports the status to the given splash screen through all the
  372.      * tasks.
  373.      *
  374.      * @param splash The splash screen which should receive all the reports
  375.      */
  376.     public AppController(Properties aLanguage, SplashScreen splash,
  377.                          String classRoot,
  378.                          String customSettingsFile, String customHelpsetPath) {
  379.         // write methodname
  380.         final String METHOD =
  381.                 "AppController(Properties language, SplashScreen splash, String classRoot)";
  382.         // log when entering a method
  383.         logger.entering(CLASS_NAME, METHOD, new Object[] {aLanguage, splash,
  384.                         classRoot});
  385.         try {
  386.            appConstants =
  387.                    (AppConstants) Class.forName(classRoot + ".AppConstants").
  388.                    newInstance();
  389.            appConstants.setConstants(customSettingsFile, customHelpsetPath);
  390.        } catch (Exception e) {
  391.            logger.throwing(this.getClass().getName(), "<init>", e);
  392.            DialogFactory.showErrorMessageDialog
  393.                    (aLanguage.getProperty("se.omnitor.tipcon1.AppController." +
  394.                                          "GUI_ERROR"));
  395.            System.exit( -1);
  396.        }
  397.         this.classRoot = classRoot;
  398.         sipStartStopMutex = new Integer(0);
  399.         appSettings = new AppSettings(appConstants.SETTINGS_DATA_FILE_URL);
  400.      if (appSettings.getLanguageCode() == AppConstants.ENGLISH) {
  401.             language = new English();
  402.         }
  403.         else if (appSettings.getLanguageCode() == AppConstants.SWEDISH) {
  404.             language = new Swedish();
  405.         }
  406.         tipcon1Mode = appSettings.getTipcon1Mode();
  407.         configurationTypeString = appSettings.getConfigurationString();
  408.         DialogFactory.registerLanguage(language);
  409.         sdpCallCounter = 1;
  410.         isMuted = false;
  411.         // Initialize text plug-in
  412.         splash.changeText(language.getProperty("se.omnitor.tipcon1." +
  413.                                                "AppController.INIT_TEXT"));
  414.         registerTextPlugIn();
  415.         // Initialize text plug-in
  416.         /*
  417.           splash.changeText("Initializing video transmission");
  418.                registerH263ModeAEffect();
  419.          */
  420.         // Get the local IP address
  421.         splash.changeText(language.getProperty("se.omnitor.tipcon1." +
  422.                                                "AppController.INIT_NETWORK"));
  423.         if (!detectLocalIp()) {
  424.             DialogFactory.showErrorMessageDialog
  425.                     (language.getProperty("se.omnitor.tipcon1.AppController." +
  426.                                           "NETWORK_ERROR"));
  427.         }
  428.         /*
  429.           catch (UnknownHostException uhe) {
  430.             logger.throwing(this.getClass().getName(), "<init>", uhe);
  431.             DialogFactory.showErrorMessageDialog
  432.          (language.getProperty("se.omnitor.tipcon1.AppController." +
  433.                  "SIP_ERROR"));
  434.                    System.exit(-1);
  435.           }
  436.          */
  437.         try {
  438.             // Retrieve all supported media types of the local computer
  439.             splash.changeText(language.getProperty("se.omnitor.tipcon1." +
  440.                     "AppController." +
  441.                     "INIT_CAPTURE"));
  442.             supportedMedia = (Vector) initializeSupportedMedia();
  443.             if (supportedMedia.isEmpty()) {
  444.                 splash.changeText(language.getProperty("se.omnitor.tipcon1." +
  445.                         "AppController." +
  446.                         "SETUP_NA"));
  447.                 detectDevices();
  448.                 supportedMedia = (Vector) initializeSupportedMedia();
  449.             }
  450.         } catch (Exception e1) {
  451.             splash.changeText(language.getProperty("se.omnitor.tipcon1." +
  452.                     "AppController." +
  453.                     "DEVICE_CHANGE"));
  454.             detectDevices();
  455.             supportedMedia = (Vector) initializeSupportedMedia();
  456.         }
  457.         // Create text transport
  458.         txTextBuffer = new SyncBuffer(appSettings.getRedundantRtpGenerations(),
  459.                                       (int) appSettings.getBufferTime());
  460.         logger.finer("buffertime is :" + appSettings.getBufferTime());
  461.         // Initialize the GUI
  462.         splash.changeText(language.getProperty("se.omnitor.tipcon1." +
  463.                                                "AppController.CREATE_GUI"));
  464.         t140Packetizer = new T140Packetizer(0);
  465.         t140Panel = new T140Panel(t140Packetizer,
  466.                                   appSettings.isRealtimePreviewEnabled(),
  467.                                   language.getProperty("se.omnitor.tipcon1.gui.t140.LOGWINDOW"),
  468.                                   language.getProperty("se.omnitor.tipcon1.gui.t140.RECEIVEWINDOW"),
  469.                                   language.getProperty("se.omnitor.tipcon1.gui.t140.SENDWINDOW"),
  470.                                   language);
  471.         t140Packetizer.setOutBuffer(txTextBuffer);
  472.         rxTextBuffer = new FifoBuffer();
  473.         t140DePacketizer = new T140DePacketizer(0);
  474.         t140DePacketizer.setInBuffer(rxTextBuffer);
  475.         t140DePacketizer.setEventHandler(t140Panel);
  476.         t140DePacketizer.start();
  477.         setupT140panel();
  478.         // Get settings
  479.         splash.changeText(language.getProperty("se.omnitor.tipcon1." +
  480.                                                "AppController.LOAD_SETTINGS"));
  481.         restoreSavedSettings();
  482.         try {
  483.             Class cls = Class.forName(classRoot + ".gui.ProgramWindow");
  484.             gui = (ProgramWindow) cls.newInstance();
  485.             logger.logp(Level.FINER, CLASS_NAME, METHOD, "SipController sc is",
  486.                         sc);
  487.             gui.init(sc, this, appSettings);
  488.             deploySettings(); // to use  don't use this line (here)
  489.             gui.prepare();
  490.         } catch (Exception cnfe) {
  491.             logger.throwing(this.getClass().getName(), "<init>", cnfe);
  492.             DialogFactory.showErrorMessageDialog
  493.                     (language.getProperty("se.omnitor.tipcon1.AppController." +
  494.                                           "GUI_ERROR"));
  495.             System.exit( -1);
  496.         }
  497.         // Initialize the SIP client
  498.         splash.changeText(language.getProperty("se.omnitor.tipcon1." +
  499.                                                "AppController.INIT_SIP"));
  500.         threadedStartSipSystem();
  501.         deploySettings();
  502.         logger.exiting(CLASS_NAME, METHOD);
  503.     }
  504.     private void restoreSavedSettings() {
  505.         appSettings.load();
  506.         txTextBuffer.setRedGen(appSettings.getRedundantRtpGenerations());
  507.         setTextBufferTime(appSettings.getBufferTime());
  508.         t140Panel.useMsrpSmoother(appSettings.isMsrpSmootherActive());
  509.         txTextBuffer.setSendOnCR(appSettings.useSendOnCR());
  510.         txTextBuffer.setBufferTime(100);
  511.         maxIncomingCps = 0;
  512.         textIsActivated = true;
  513.         videoIsActivated = true;
  514.         //videoIsActivated = false;
  515.         audioIsActivated = true;
  516.         if(appSettings.getTipcon1Mode()) {
  517.             restoreSavedVideoSettings();
  518.         }
  519.         restoreSavedAudioSettings();
  520.     }
  521.     private void createGui() {
  522.     }
  523.     /**
  524.      * Gets the local IP address and the local host name. These values are
  525.      * stored in a global variable in the system. If the local IP address is
  526.      * 127.0.0.1, the function assumes that no network is present and false
  527.      * will be returned.
  528.      *
  529.      * @return True if an address was retrieved, false if not.
  530.      */
  531.     private boolean detectLocalIp() {
  532.         String oldLocalIp = localIpAddress;
  533.         try {
  534.             localIpAddress = InetAddress.getLocalHost().getHostAddress();
  535.             localHostAddress = InetAddress.getLocalHost().getHostName();
  536.         } catch (UnknownHostException uhe) {
  537.             return false;
  538.         }
  539.         if (!localIpAddress.equals(oldLocalIp) && oldLocalIp != null) {
  540.             if (localIpAddress.equals("127.0.0.1")) {
  541.                 sc.stop();
  542.             } else if (oldLocalIp.equals("127.0.0.1")) {
  543.                 try {
  544.                     sc.start();
  545.                 } catch (Exception e) {
  546.                     return false;
  547.                 }
  548.             } else {
  549.                 try {
  550.                     sc.stop();
  551.                     sc.start();
  552.                 } catch (Exception e) {
  553.                     return false;
  554.                 }
  555.             }
  556.         }
  557.         if (localIpAddress.equals("127.0.0.1")) {
  558.             return false;
  559.         }
  560.         return true;
  561.     }
  562.     public void setupT140panel() {
  563.         t140Panel.useMsrpSmoother(true);
  564.         t140Panel.setTaFont
  565.                 (new Font(appSettings.getLocalFont(), Font.PLAIN,
  566.                           appSettings.getLocalTextSize()));
  567.         /*
  568.               t140Panel.setRemoteFont
  569.            (new Font(remoteFont, Font.PLAIN, remoteTextSize));
  570.          */
  571.         try {
  572.             t140Panel.setTaFontColor(appSettings.getLocalTextColor());
  573.         } catch (NumberFormatException nfe) {
  574.         }
  575.         /*
  576.               t140Panel.setRemoteFontColor
  577.            (new Color(Integer.parseInt(remoteTextColor[0]),
  578.          Integer.parseInt(remoteTextColor[1]),
  579.          Integer.parseInt(remoteTextColor[2])));
  580.          */
  581.         try {
  582.             t140Panel.setTaFontBackground(appSettings.getLocalBgColor());
  583.         } catch (NumberFormatException nfe) {
  584.         }
  585.         /*
  586.               t140Panel.setRemoteFontBackground
  587.            (new Color(Integer.parseInt(remoteBgColor[0]),
  588.          Integer.parseInt(remoteBgColor[1]),
  589.          Integer.parseInt(remoteBgColor[2])));
  590.          */
  591.         /*
  592.            if (dataCnt != pLength) {
  593.          Object[][] correctedData = new Object[dataCnt][2];
  594.          System.arraycopy(data, 0, correctedData, 0, dataCnt);
  595.          data = correctedData;
  596.            }
  597.          */
  598.         t140Panel.setTaFont
  599.                 (new Font("Arial Unicode MS", Font.PLAIN, 12));
  600.         /*
  601.           t140Panel.setRemoteFont
  602.           (new Font("Arial Unicode MS", Font.PLAIN, 12));
  603.          */
  604.         t140Panel.setTaFontColor(new Color(0, 0, 0));
  605.         //t140Panel.setRemoteFontColor(new Color(0, 0, 0));
  606.         t140Panel.setTaFontBackground(new Color(255, 255, 255));
  607.         //t140Panel.setRemoteFontBackground(new Color(255, 255, 255));
  608.     }
  609.     /**
  610.      * Restores saved audio settings. At this moment, this function just
  611.      * sets default settings for audio. Save and restore to harddrive has
  612.      * not been implemented yet.
  613.      *
  614.      */
  615.     public void restoreSavedAudioSettings() {
  616.         int cnt;
  617.         int fcnt;
  618.         // Count devices
  619.         audioCodecs = new Vector(0, 1);
  620.         // Set formats and codecs
  621.         audioFormat = new AudioFormat[nbrOfAudioDevices];
  622.         audioLocator = new String[nbrOfAudioDevices];
  623.         Format[] captureFormat;
  624.         int audioCnt = 0;
  625.         int videoCnt = 0;
  626.         Vector outputFormats;
  627.         DeviceContainer tempDc;
  628.         int smSize;
  629.         if (supportedMedia == null) {
  630.             smSize = 0;
  631.         } else {
  632.             smSize = supportedMedia.size();
  633.         }
  634.         for (cnt = 0; cnt < smSize; cnt++) {
  635.             tempDc = (DeviceContainer) supportedMedia.get(cnt);
  636.             captureFormat = tempDc.getCaptureFormats();
  637.             outputFormats = (Vector) tempDc.getOutputFormats();
  638.             if (tempDc.getType().equals("audio")) {
  639.                 if (captureFormat != null) {
  640.                     for (fcnt = 0; fcnt < captureFormat.length; fcnt++) {
  641.                         if (audioFormat[audioCnt] == null) {
  642.                             audioFormat[audioCnt] =
  643.                                     (AudioFormat) captureFormat[fcnt];
  644.                         } else {
  645.                             if (((AudioFormat) captureFormat[fcnt]).
  646.                                 getSampleSizeInBits() >
  647.                                 audioFormat[audioCnt].getSampleSizeInBits()) {
  648.                                 audioFormat[audioCnt] =
  649.                                         (AudioFormat) captureFormat[fcnt];
  650.                             }
  651.                         }
  652.                     }
  653.                 }
  654.                 if (outputFormats != null) {
  655.                     int ofSize = outputFormats.size();
  656.                     for (fcnt = 0; fcnt < ofSize; fcnt++) {
  657.                         if (!audioCodecs.contains
  658.                             ((String) outputFormats.get(fcnt))) {
  659.                             audioCodecs.add((String) outputFormats.get(fcnt));
  660.                         }
  661.                     }
  662.                 }
  663.                 audioLocator[audioCnt] = tempDc.getLocator();
  664.                 audioCnt++;
  665.             }
  666.         }
  667.     }
  668.     /**
  669.      * Restores saved video settings.
  670.      *
  671.      */
  672.     public void restoreSavedVideoSettings() {
  673.         int cnt;
  674.         int fcnt;
  675.         // Count devices
  676.         videoCodecs = new Vector(0, 1);
  677.         // Set formats and codecs
  678.         videoFormat = new VideoFormat[nbrOfVideoDevices];
  679.         videoLocator = new String[nbrOfVideoDevices];
  680.         Format[] captureFormat;
  681.         int videoCnt = 0;
  682.         Vector outputFormats;
  683.         DeviceContainer tempDc;
  684.         boolean vfIsSet = false;
  685.         int smSize;
  686.         if (supportedMedia == null) {
  687.             smSize = 0;
  688.         } else {
  689.             smSize = supportedMedia.size();
  690.         }
  691.         for (cnt = 0; cnt < smSize; cnt++) {
  692.             tempDc = (DeviceContainer) supportedMedia.get(cnt);
  693.             captureFormat = tempDc.getCaptureFormats();
  694.             outputFormats = (Vector) tempDc.getOutputFormats();
  695.             if (tempDc.getType().equals("video")) {
  696.                 System.out.println("restoreSavedVideoSettings()");
  697.                 if (captureFormat != null) {
  698.                     for (fcnt = 0; fcnt < captureFormat.length; fcnt++) {
  699.                         if (videoFormat[videoCnt] == null) {
  700.                             videoFormat[videoCnt] = (VideoFormat) captureFormat[fcnt];
  701.                             //VideoFormat[] vf = new VideoFormat[1];
  702.                             //vf[0] = new VideoFormat("YUV", new Dimension(176,144),Format.NOT_SPECIFIED,null, 25.0F);
  703.                             //setVideoFormat(vf);
  704.                         } else {
  705.                             // 188 kbit/s is a suitable speed for video
  706.                             // transmission. Try to find a format as close as
  707.                             // possible to 188 kbit/s.
  708.                             //System.out.println(appSettings.getResolution() + ":" +formatToString(captureFormat[fcnt]));
  709.                             String resolution = appSettings.getResolution();
  710.                             //if (resolution.equals("176x144 (yuv)")) {
  711.                             //    VideoFormat[] vf = new VideoFormat[1];
  712.                             //    vf[0] = new VideoFormat("YUV", new Dimension(176,144),Format.NOT_SPECIFIED,null, 25.0F);
  713.                             //    setVideoFormat(vf);
  714.                             //    vfIsSet = true;
  715.                             //}
  716.                             //else
  717.                             if (resolution.equalsIgnoreCase(formatToString(captureFormat[fcnt]))) {
  718.                                 VideoFormat[] vf = new VideoFormat[1];
  719.                                 vf[0] = (VideoFormat) captureFormat[fcnt];
  720.                                 setVideoFormat(vf);
  721.                                 vfIsSet = true;
  722.                             } else if (Math.abs(((VideoFormat) captureFormat[fcnt]).
  723.                                          getMaxDataLength()) <
  724.                                 Math.abs(videoFormat[videoCnt].
  725.                              getMaxDataLength() - 316000) && !vfIsSet) {
  726.                                 if (((VideoFormat) captureFormat[fcnt]).
  727.                                     getEncoding().equals("yuv")) {
  728.                                     VideoFormat[] vf = new VideoFormat[1];
  729.                                     vf[0] = (VideoFormat) captureFormat[fcnt];
  730.                                     setVideoFormat(vf);
  731.                                     //videoFormat[videoCnt] = (VideoFormat) captureFormat[fcnt];
  732.                                 }
  733.                             }
  734.                         }
  735.                     }
  736.                 }
  737.                 if (outputFormats != null) {
  738.                     int ofSize = outputFormats.size();
  739.                     for (fcnt = 0; fcnt < ofSize; fcnt++) {
  740.                         if (!videoCodecs.contains
  741.                             ((String) outputFormats.get(fcnt))) {
  742.                             videoCodecs.add((String) outputFormats.get(fcnt));
  743.                         }
  744.                     }
  745.                 }
  746.                 videoLocator[videoCnt] = tempDc.getLocator();
  747.                 videoCnt++;
  748.             }
  749.         }
  750.     }
  751.     /**
  752.      * This function is aimed to be used after all settings has been entered
  753.      * to this class. This function will insert all codecs into the SIP
  754.      * controller and, if activated, restart the local video image.
  755.      *
  756.      */
  757.     public void deploySettings() {
  758.         // write methodname
  759.         final String METHOD = "deploySettings()";
  760.         // log when entering a method
  761.         logger.entering(CLASS_NAME, METHOD);
  762.         // Now, all SDP settings are deployed immediately before calling or
  763.         // answering a call in order to allow STUN requests probe for port
  764.         // mappings.
  765.         //deploySdpSettings(true);
  766.          if(appSettings.getTipcon1Mode()) {
  767.              deployVideoSettings();
  768.          }
  769.         logger.exiting(CLASS_NAME, METHOD);
  770.     }
  771.     /**
  772.      * Deploy video settings. The video is restarted.
  773.      *
  774.      */
  775.     public void deployVideoSettings() {
  776.         Thread t = new Thread() {
  777.             public void run() {
  778.                 restartVideo();
  779.             }
  780.         };
  781.         t.setName("Video restarter");
  782.         t.start();
  783.     }
  784.     /**
  785.      * Deploys the current SDP settings, which are read from the variables.
  786.      * This function should be run after the variables has been read from the
  787.      * settings XML file or after the user has committed changes.
  788.      *
  789.      */
  790.     public void deploySdpSettings(boolean useTextIfActivated) {
  791.         // write methodname
  792.         final String METHOD = "deploySdpSettings(boolean useTextIfActivated)";
  793.         // log when entering a method
  794.         logger.entering(CLASS_NAME, METHOD);
  795.         int plType;
  796.         String plName;
  797.         long plClockRate;
  798.         RTPPayloadConstants constants = new RTPPayloadConstants();
  799.         int cnt;
  800.         String codecName;
  801.         // Higher than 98 since Allan eC requires text to use 98
  802.         int nextDynamicPayloadType = 99;
  803.         SdpManager sdpm;
  804.         try {
  805.             logger.logp(Level.INFO, CLASS_NAME, METHOD, "userRealName is",
  806.                         appSettings.getUserRealName());
  807.             if (isRuntimeStunActivated()) {
  808.                 sdpm = new SdpManager(appSettings.getUserRealName().replace(' ',
  809.                         '_'),
  810.                                       "" + sdpCallCounter,
  811.                                       "" + sdpCallCounter,
  812.                                       "IN",
  813.                                       "IP4",
  814.                                       stunStack.getExternalIp());
  815.             } else {
  816.                 sdpm = new SdpManager(appSettings.getUserRealName().replace(' ',
  817.                         '_'),
  818.                                       "" + sdpCallCounter,
  819.                                       "" + sdpCallCounter,
  820.                                       "IN",
  821.                                       "IP4",
  822.                                       localIpAddress);
  823.             }
  824.         } catch (SdpException se) {
  825.             logger.throwing(this.getClass().getName(), "deploySdpSettings",
  826.                             se);
  827.             return;
  828.         }
  829.         SdpMedia sdpMedia;
  830.         se.omnitor.protocol.sdp.Format format;
  831.         Vector formats;
  832.         // Video descriptors
  833.         if (videoIsActivated && appSettings.getTipcon1Mode()) {
  834.             if (videoCodecs != null &&
  835.                 videoCodecs.size() > 0) {
  836.                 int port = -1;
  837.                 if (isRuntimeStunActivated()) {
  838.                     int mappedPort = 1;
  839.                     try {
  840.                         // Do five attempts finding an even mapped port (as RTP should be sent from an even port)
  841.                         for (int mcnt=0; mcnt<5 && (mappedPort%2 == 1); mcnt++) {
  842.                             port = getFreePort();
  843.                             mappedPort = stunStack.getMappedPort(port);
  844.                         }
  845.                         sdpMedia = new CustomMedia("video",
  846.                                                    mappedPort,
  847.                                                    "RTP/AVP");
  848.                         // As the NAT often picks port numbers in series,
  849.                         // lets force it to hold a port open for the incoming
  850.                         // RTCP.
  851.                         stunStack.getMappedPort(port+1);
  852.                     } catch (StunStackException se) {
  853.                         sdpMedia = new CustomMedia("video", port, "RTP/AVP");
  854.                         setRuntimeStunActivated(false);
  855.                         DialogFactory.showErrorMessageDialog
  856.                                 (language.getProperty(
  857.                                         "se.omnitor.tipcon1.AppController." +
  858.                                         "STUN_ERROR"));
  859.                     }
  860.                 } else {
  861.                     port = getFreePort();
  862.                     sdpMedia = new CustomMedia("video", port, "RTP/AVP");
  863.                 }
  864.                 sdpMedia.setPhysicalPort(port);
  865.                 formats = new Vector(0, 1);
  866.                 int vcSize = videoCodecs.size();
  867.                 for (cnt = 0; cnt < vcSize; cnt++) {
  868.                     codecName = (String) videoCodecs.get(cnt);
  869.                     plType = constants.getPayloadType(codecName);
  870.                     if (plType != -1) {
  871.                         if (plType == constants.DYNAMIC) {
  872.                             plType = nextDynamicPayloadType;
  873.                             nextDynamicPayloadType++;
  874.                             plClockRate = constants.getClockRate(codecName);
  875.                             if (plClockRate == constants.VARIABLE) {
  876.                                 plClockRate = 8000; // Check this!?
  877.                             }
  878.                             plName = constants.getSdpName(codecName);
  879.                             format = new CustomFormat(plType,
  880.                                     plName,
  881.                                     (int) plClockRate);
  882.                         } else {
  883.                             format =
  884.                                     se.omnitor.protocol.sdp.Format.
  885.                                     getFormat(plType);
  886.                         }
  887.                         if (format != null) {
  888.                             formats.add(format);
  889.                         }
  890.                     }
  891.                 }
  892.                 sdpMedia.setFormats(formats);
  893.                 sdpm.addMedia(sdpMedia);
  894.             }
  895.             else {
  896.                 // TODO:
  897.                 // Set these to receive only!
  898.                 //formats.add(FOrmat.getFormat(34));
  899.                 //formats.add(Format.getFormat(26));
  900.             }
  901.         }
  902.         // Audio descriptors
  903.         if (audioIsActivated &&
  904.             audioCodecs != null &&
  905.             audioCodecs.size() > 0) {
  906.             int port = -1;
  907.             if (isRuntimeStunActivated()) {
  908.                 int mappedPort = 1;
  909.                 try {
  910.                     stunStack.getMappedPort(5059);
  911.                     // Do five attempts finding an even mapped port (as RTP should be sent from an even port)
  912.                     for (int mcnt=0; mcnt<5 && (mappedPort%2 == 1); mcnt++) {
  913.                         port = getFreePort();
  914.                         mappedPort = stunStack.getMappedPort(port);
  915.                     }
  916.                     sdpMedia = new CustomMedia("audio",
  917.                                                mappedPort,
  918.                                                "RTP/AVP");
  919.                     // As the NAT often picks port numbers in series,
  920.                     // lets force it to hold a port open for the incoming
  921.                     // RTCP.
  922.                     stunStack.getMappedPort(port+1);
  923.                 } catch (StunStackException se) {
  924.                     sdpMedia = new CustomMedia("audio", port, "RTP/AVP");
  925.                     setRuntimeStunActivated(false);
  926.                     DialogFactory.showErrorMessageDialog
  927.                             (language.getProperty(
  928.                                     "se.omnitor.tipcon1.AppController." +
  929.                                     "STUN_ERROR"));
  930.                 }
  931.             } else {
  932.                 port = getFreePort();
  933.                 sdpMedia = new CustomMedia("audio", port, "RTP/AVP");
  934.             }
  935.             sdpMedia.setPhysicalPort(port);
  936.             formats = new Vector(0, 1);
  937.             int acSize = audioCodecs.size();
  938.             for (cnt = 0; cnt < acSize; cnt++) {
  939.                 codecName = (String) audioCodecs.get(cnt);
  940.                 plType = constants.getPayloadType(codecName);
  941.                 if (plType != -1) {
  942.                     if (plType == constants.DYNAMIC) {
  943.                         plType = nextDynamicPayloadType;
  944.                         nextDynamicPayloadType++;
  945.                         plClockRate = constants.getClockRate(codecName);
  946.                         if (plClockRate == constants.VARIABLE) {
  947.                             plClockRate = 8000; // Check this!?
  948.                         }
  949.                         plName = constants.getSdpName(codecName);
  950.                         format = new CustomFormat(plType,
  951.                                                   plName,
  952.                                                   (int) plClockRate);
  953.                     } else {
  954.                         format =
  955.                                 se.omnitor.protocol.sdp.Format.getFormat(plType);
  956.                     }
  957.                     if (format != null) {
  958.                         formats.add(format);
  959.                     }
  960.                 }
  961.             }
  962.             sdpMedia.setFormats(formats);
  963.             sdpm.addMedia(sdpMedia);
  964.         }
  965.         // Text descriptors
  966.         if (textIsActivated && useTextIfActivated) {
  967.             int port = -1;
  968.             if (isRuntimeStunActivated()) {
  969.                 int mappedPort = 1;
  970.                 try {
  971.                     // Do five attempts finding an even mapped port (as RTP should be sent from an even port)
  972.                     for (int mcnt=0; mcnt<5 && (mappedPort%2 == 1); mcnt++) {
  973.                         port = getFreePort();
  974.                         mappedPort = stunStack.getMappedPort(port);
  975.                     }
  976.                     sdpMedia = new CustomMedia("text",
  977.                                                mappedPort,
  978.                                                "RTP/AVP");
  979.                     // As the NAT often picks port numbers in series,
  980.                     // lets force it to hold a port open for the incoming
  981.                     // RTCP.
  982.                     stunStack.getMappedPort(port+1);
  983.                 } catch (StunStackException se) {
  984.                     sdpMedia = new CustomMedia("text", port, "RTP/AVP");
  985.                     setRuntimeStunActivated(false);
  986.                     DialogFactory.showErrorMessageDialog
  987.                             (language.getProperty(
  988.                                     "se.omnitor.tipcon1.AppController." +
  989.                                     "STUN_ERROR"));
  990.                 }
  991.             } else {
  992.                 port = getFreePort();
  993.                 sdpMedia = new CustomMedia("text", port, "RTP/AVP");
  994.             }
  995.             sdpMedia.setPhysicalPort(port);
  996.             formats = new Vector(0, 1);
  997.             plType = constants.getPayloadType("T140");
  998.             if (plType != -1) {
  999.                 if (plType == constants.DYNAMIC) {
  1000.                     plType = nextDynamicPayloadType;
  1001.                     nextDynamicPayloadType++;
  1002.                 }
  1003.                 T140Format tf = new T140Format(plType);
  1004.                 RedFormat rf = null;
  1005.                 if (appSettings.getRedundantRtpGenerations() > 0) {
  1006.                     rf = new RedFormat(nextDynamicPayloadType);
  1007.                     nextDynamicPayloadType++;
  1008.                     rf.setGenerations(appSettings.getRedundantRtpGenerations());
  1009.                     tf.setRedFormat(rf);
  1010.                     rf.setFormat(tf);
  1011.                     formats.add(rf);
  1012.                 }
  1013.                 formats.add(tf);
  1014.                 /*
  1015.                    plClockRate = constants.getClockRate("T140");
  1016.                    if (plClockRate == constants.VARIABLE) {
  1017.                     plClockRate = 1000; // Check this!?
  1018.                    }
  1019.                    plName = constants.getSdpName("T140");
  1020.                    format = new T140Format(plType, (int)plClockRate);
  1021.                    if (format != null) {
  1022.                     formats.add(format);
  1023.                    }
  1024.                  */
  1025.                 /*
  1026.                    try {
  1027.                     if (maxIncomingCps > 0) {
  1028.                     sc.addMedia("",
  1029.                   plName,
  1030.                   "T140",
  1031.                   "text",
  1032.                   plType,
  1033.                   plClockRate,
  1034.                   redundantGenerations != 0,
  1035.                   "cps=" + maxIncomingCps);
  1036.                     }
  1037.                     else {
  1038.                  sc.addMedia("",
  1039.                       plName,
  1040.                       "T140",
  1041.                       "text",
  1042.                       plType,
  1043.                       plClockRate,
  1044.                       redundantGenerations != 0);
  1045.                     }
  1046.                    }
  1047.                    catch (Exception e) {
  1048.                     // Ignore any errors, as there is nothing to do about it.
  1049.                    }
  1050.                  */
  1051.             }
  1052.             sdpMedia.setFormats(formats);
  1053.             sdpm.addMedia(sdpMedia);
  1054.         }
  1055.         currentSdpManager = sdpm;
  1056.         logger.exiting(CLASS_NAME, METHOD);
  1057.     }
  1058.     private int getFreePort() {
  1059.         for (int cnt=nextFreePort; cnt<65535; cnt+=2) {
  1060.             try {
  1061.                 DatagramSocket dgs = new DatagramSocket(cnt);
  1062.                 dgs.close();
  1063.                 dgs = new DatagramSocket(cnt+1);
  1064.                 dgs.close();
  1065.                 nextFreePort = cnt+2;
  1066.                 return cnt;
  1067.             } catch (SocketException se) {
  1068.                 // Try next port
  1069.             }
  1070.         }
  1071.         for (int cnt=1024; cnt<nextFreePort; cnt+=2) {
  1072.             try {
  1073.                 DatagramSocket dgs = new DatagramSocket(cnt);
  1074.                 dgs.close();
  1075.                 nextFreePort = cnt+2;
  1076.                 return cnt;
  1077.             } catch (SocketException se) {
  1078.                 // Try next port
  1079.             }
  1080.         }
  1081.         return -1;
  1082.     }
  1083.     /**
  1084.      * Sets the number of redundant generations in the outgoing RTP Text
  1085.      * packets.
  1086.      *
  1087.      * @param red The number of generations.
  1088.      */
  1089.     /*
  1090.          public void xxsetTextRedundantGenerations(int red) {
  1091.         redundantRtpGenerations = red;
  1092.         txTextBuffer.setRedGen(red);
  1093.          }
  1094.      */
  1095.     /**
  1096.      * Activates the whole program. Shows the GUI and starts to listen for
  1097.      * incoming SIP packets.
  1098.      *
  1099.      */
  1100.     public void start() {
  1101.         // The program is ready for user input, show the GUI.
  1102.         gui.setVisible(true);
  1103.     }
  1104.     /**
  1105.      * Starts all SIP handing in a new thread (sipStarterThread).
  1106.      *
  1107.      */
  1108.     private void threadedStartSipSystem() {
  1109.         final Thread oldThread = sipStarterThread;
  1110.         sipStarterThread = new Thread() {
  1111.             public void run() {
  1112.                 // Wait until last SIP starter thread stops, 20 seconds
  1113.                 if (oldThread != null) {
  1114.                     for (int cnt = 0; cnt < 30 && oldThread.isAlive(); cnt++) {
  1115.                         try {
  1116.                             Thread.sleep(1000);
  1117.                         } catch (InterruptedException ie) {
  1118.                                 // Do nothing
  1119.                             }
  1120.                         }
  1121.                         // Finally, interrupt it if still not stopped after 20 secs
  1122.                         if (oldThread.isAlive()) {
  1123.                             oldThread.interrupt();
  1124.                         }
  1125.                 }
  1126.                 startSipSystem();
  1127.             }
  1128.         };
  1129.         sipStarterThread.setName("SIP starter thread");
  1130.         sipStarterThread.start();
  1131.     }
  1132.     /**
  1133.      * Starts all SIP handing in a new thread (sipStarterThread).
  1134.      *
  1135.      */
  1136.     public void threadedRestartSipSystem() {
  1137.         final Thread oldThread = sipStarterThread;
  1138.         sipStarterThread = new Thread() {
  1139.             public void run() {
  1140.                 // Wait until last SIP starter thread stops, 20 seconds
  1141.                 if (oldThread != null) {
  1142.                     for (int cnt = 0; cnt < 30 && oldThread.isAlive(); cnt++) {
  1143.                         try {
  1144.                             Thread.sleep(1000);
  1145.                         } catch (InterruptedException ie) {
  1146.                                 // Do nothing
  1147.                             }
  1148.                         }
  1149.                         // Finally, interrupt it if still not stopped after 20 secs
  1150.                         if (oldThread.isAlive()) {
  1151.                             oldThread.interrupt();
  1152.                         }
  1153.                 }
  1154.                 stopSipSystem();
  1155.                 startSipSystem();
  1156.             }
  1157.         };
  1158.         sipStarterThread.setName("SIP restarter thread");
  1159.         sipStarterThread.start();
  1160.     }
  1161.     private void startSipSystem() {
  1162.         synchronized (sipStartStopMutex) {
  1163.             gui.setRegDetecting("Detecting SIP environment");
  1164.             int stunMode = appSettings.getStunMode();
  1165.             if (stunMode == AppSettings.STUN_DISABLED) {
  1166.                 setRuntimeStunActivated(false);
  1167.             } else {
  1168.                 setRuntimeStunActivated(true);
  1169.             }
  1170.             isSipCompatibleNatDetected = false;
  1171.             boolean possibleSipNat = false;
  1172.             // If STUN is activated, but no STUN server is chosen, try to find a
  1173.             // STUN server by looking att the register settings.
  1174.             if (isRuntimeStunActivated() &&
  1175.                 (appSettings.getStunServerAddress() == null ||
  1176.                  appSettings.getStunServerAddress().trim().equals(""))) {
  1177.                 gui.setRegDetecting("Finding STUN server");
  1178.                 boolean foundStunServer = false;
  1179.                 if (appSettings.getSipRegistrarInfo() != null) {
  1180.                     for (int cnt = 0;
  1181.                                    (cnt < appSettings.getSipRegistrarInfo().length) &&
  1182.                                    !foundStunServer;
  1183.                                    cnt++) {
  1184.                         String host = appSettings.getSipRegistrarInfo()[cnt].
  1185.                                       getRegistrarHost();
  1186.                         String stunServerAddress = findStunServer(host);
  1187.                         if (stunServerAddress != null) {
  1188.                             foundStunServer = true;
  1189.                             appSettings.setStunServerAddress(stunServerAddress);
  1190.                         }
  1191.                     }
  1192.                 }
  1193.                 if (!foundStunServer) {
  1194.                     appSettings.setStunServerAddress(AppConstants.PUBLIC_STUN_SERVER);
  1195.                     /*
  1196.                     DialogFactory.showErrorMessageDialog(language.getProperty(
  1197.                             "se.omnitor.tipcon1.AppController." +
  1198.                             "STUN_SERVER_NOT_FOUND"));
  1199.                     setRuntimeStunActivated(false);
  1200.                     if (possibleSipNat) {
  1201.                         isSipCompatibleNatDetected = true;
  1202.                     }
  1203. */
  1204.                 }
  1205.             }
  1206.             // Do STUN tests
  1207.             if (appSettings.getStunServerAddress() != null &&
  1208.                 !appSettings.getStunServerAddress().trim().equals("") &&
  1209.                 isRuntimeStunActivated()) {
  1210.                 // First check if we might have a SIP compatible NAT here
  1211.                 possibleSipNat = detectSipCompatibleNat();
  1212.                 stunStack = new StunStack(getLocalIpAddress(),
  1213.                                           appSettings.getStunServerAddress());
  1214.                 try {
  1215.                     gui.setRegDetecting(language.getProperty("se.omnitor.tipcon1.AppController.DETECT"));
  1216.                     stunStack.start();
  1217.                     if (stunStack.getNatType().equals(StunStack.OPEN_INTERNET)) {
  1218.                         if (stunMode == AppSettings.STUN_AUTO) {
  1219.                             setRuntimeStunActivated(false);
  1220.                         }
  1221.                         isSipCompatibleNatDetected = false;
  1222.                     } else {
  1223.                         if (possibleSipNat) {
  1224.                             isSipCompatibleNatDetected = true;
  1225.                             if (stunMode == AppSettings.STUN_AUTO) {
  1226.                                 setRuntimeStunActivated(false);
  1227.                             }
  1228.                         } else if (stunStack.getNatType().equals(StunStack.
  1229.                                 UDP_BLOCKING_FIREWALL)) {
  1230.                             if (stunMode == AppSettings.STUN_AUTO) {
  1231.                                 setRuntimeStunActivated(false);
  1232.                             }
  1233.                             DialogFactory.showErrorMessageDialog(language.
  1234.                                     getProperty(
  1235.                                             "se.omnitor.tipcon1.AppController." +
  1236.                                             "UDP_BLOCKING_FW_FOUND"));
  1237.                         } else if (stunStack.getNatType().equals(StunStack.
  1238.                                 SYMMETRIC_NAT) ||
  1239.                                    stunStack.getNatType().equals(StunStack.
  1240.                                 SYMMETRIC_UDP_FIREWALL)) {
  1241.                             if (stunMode == AppSettings.STUN_AUTO) {
  1242.                                 setRuntimeStunActivated(false);
  1243.                             }
  1244.                             DialogFactory.showErrorMessageDialog(language.
  1245.                                     getProperty(
  1246.                                             "se.omnitor.tipcon1.AppController." +
  1247.                                             "SYMMETRIC_FW_FOUND"));
  1248.                         }
  1249.                     }
  1250.                 } catch (StunStackException sse) {
  1251.                     if (stunMode == AppSettings.STUN_AUTO) {
  1252.                         setRuntimeStunActivated(false);
  1253.                     }
  1254.                     if (possibleSipNat) {
  1255.                         if (stunMode == AppSettings.STUN_AUTO) {
  1256.                             isSipCompatibleNatDetected = true;
  1257.                         }
  1258.                     } else {
  1259.                         DialogFactory.showErrorMessageDialog(language.getProperty(
  1260.                                 "se.omnitor.tipcon1.AppController." +
  1261.                                 "STUN_ERROR"));
  1262.                     }
  1263.                 }
  1264.             }
  1265.             gui.setRegDetecting("Initializing SIP");
  1266.             if (isRuntimeStunActivated()) {
  1267.                 sc = new SipController(this, localIpAddress,
  1268.                                        appSettings.getOutboundProxy(),
  1269.                                        stunStack);
  1270.             } else {
  1271.                 sc = new SipController(this, localIpAddress,
  1272.                                        appSettings.getOutboundProxy(), null);
  1273.             }
  1274.             try {
  1275.                 sc.start();
  1276.             } catch (javax.sip.InvalidArgumentException iae) {
  1277.                 logger.throwing(this.getClass().getName(), "startSip", iae);
  1278.             }
  1279.             sc.setPrimarySipAddress("unknown@" + localIpAddress);
  1280.             sc.setAuthInfo(convertToAuthInfo(appSettings.getSipRegistrarInfo()));
  1281.             sc.setFromAddressList(convertToFromAddress(appSettings.
  1282.                                                        getSipRegistrarInfo()));
  1283.             gui.setRegNa();
  1284.             sipRegisterAll();
  1285.             sipSystemIsRunning = true;
  1286.         }
  1287.     }
  1288.     /**
  1289.      * Finds a STUN server by looking at STUN SRV records of a given host name.
  1290.      *
  1291.      * @param host The host name to search SRV records on
  1292.      * @return STUN server address. Null if no server was found.
  1293.      */
  1294.     private String findStunServer(String host) {
  1295.         if (findDns() == null) {
  1296.             return null;
  1297.         }
  1298.         boolean foundStunServer = false;
  1299.         String ssa = null;
  1300.         try {
  1301.             java.util.Hashtable env = new java.util.Hashtable();
  1302.             env.put("java.naming.factory.initial",
  1303.                     "com.sun.jndi.dns.DnsContextFactory");
  1304.             env.put("java.naming.provider.url",
  1305.                     "dns://" + findDns());
  1306.             javax.naming.directory.DirContext ctx = new javax.naming.directory.
  1307.                     InitialDirContext(env);
  1308.             javax.naming.directory.Attributes attrs = ctx.getAttributes(
  1309.                     "_stun._udp." + host, new String[] {"SRV"});
  1310.             for (javax.naming.NamingEnumeration ae = attrs.getAll();
  1311.                     ae.hasMoreElements() &&
  1312.                     !foundStunServer; ) {
  1313.                 javax.naming.directory.Attribute attr = (javax.naming.directory.
  1314.                         Attribute) ae.next();
  1315.                 if (attr.getID().equals("SRV")) {
  1316.                     for (java.util.Enumeration vals = attr.getAll();
  1317.                             vals.hasMoreElements(); ) {
  1318.                         String e = (String) vals.nextElement();
  1319.                         String el[] = e.split(" ");
  1320.                         if (el.length > 3) {
  1321.                             if (el[3].endsWith(".")) {
  1322.                                 ssa = el[3].substring(0, el[3].length() - 1);
  1323.                             } else {
  1324.                                 ssa = el[3];
  1325.                             }
  1326.                             foundStunServer = true;
  1327.                         }
  1328.                     }
  1329.                 }
  1330.             }
  1331.             ctx.close();
  1332.         }
  1333.         catch (NameNotFoundException nnfe) {
  1334.             // DNS name not found, just continue
  1335.         }
  1336.         catch (NamingException ne) {
  1337.             // DNS problems just continue
  1338.         }
  1339.         /*catch (Exception e) {
  1340.             System.err.println("Problem querying DNS: " + e);
  1341.             e.printStackTrace();
  1342.         }*/
  1343.         return ssa;
  1344.     }
  1345.     /**
  1346.      * Returns the IP of a DNS server.
  1347.      *
  1348.      * @return IP of DNS server, null if no DNS server was found.
  1349.      */
  1350.     private String findDns() {
  1351.         int delayTime = -1000;
  1352.         for (int cnt=0; cnt<2; cnt++) {
  1353.             delayTime += 3000;
  1354.             // If this function has been run before, return the cached result to
  1355.             // speed up the application.
  1356.             if (dnsServer != null) {
  1357.                 return dnsServer;
  1358.             }
  1359.             try {
  1360.                 // Run nslookup and look at the printout to achieve system's DNS
  1361.                 // server setting. There seems not to be any better solution! If
  1362.                 // there is, please replace this.
  1363.                 Process p = Runtime.getRuntime().exec("nslookup");
  1364.                 // Sleep for 2 secs in order to wait for nslooup to start and
  1365.                 // generate output.
  1366.                 Thread.sleep(delayTime);
  1367.                 p.destroy();
  1368.                 // Read the output of nslookup
  1369.                 BufferedReader in = new BufferedReader(new InputStreamReader(p.
  1370.                         getInputStream()));
  1371.                 String readerString = "";
  1372.                 boolean foundDnsServer = false;
  1373.                 while (((readerString = in.readLine()) != null)) {
  1374.                     String spl[] = readerString.split("Address:");
  1375.                     if (spl.length > 1) {
  1376.                         return spl[1].trim();
  1377.                     }
  1378.                 }
  1379.             } catch (IOException ioe) {
  1380.                 ioe.printStackTrace();
  1381.             } catch (InterruptedException ie) {
  1382.                 ie.printStackTrace();
  1383.             }
  1384.         }
  1385.         return null;
  1386.     }
  1387.     /**
  1388.      * Ends the program by shutting down the SIP client and then exiting.
  1389.      *
  1390.      */
  1391.     public void stop() {
  1392.         // Hide the frame
  1393.         gui.setTitle(gui.getTitle() + " - " +
  1394.                      language.getProperty("se.omnitor.tipcon1.AppController." +
  1395.                                           "CLOSING"));
  1396.         gui.setVisible(false);
  1397.         // Stop the local video
  1398.         if (appSettings.getTipcon1Mode() && avPlayer != null) {
  1399.             avPlayer.close();
  1400.             avPlayer = null;
  1401.         }
  1402.         /*
  1403.         try {
  1404.             Thread.sleep(2000);
  1405.         } catch (Exception e) {
  1406.             // Ignore interruptions
  1407.         }*/
  1408.         // If detect is caused to program start, wait for it
  1409.         if (sipStarterThread != null && sipStarterThread.isAlive()) {
  1410.             for (int cnt=0; cnt<30&&sipStarterThread.isAlive(); cnt++) {
  1411.                 try {
  1412.                     Thread.sleep(1000);
  1413.                 }
  1414.                 catch (InterruptedException ie) {
  1415.                     // Ignore
  1416.                 }
  1417.             }
  1418.             if (sipStarterThread.isAlive()) {
  1419.                 sipStarterThread.interrupt();
  1420.             }
  1421.         }
  1422.         // If detect is caused by SIP settings dialog, wait for it
  1423.         while (!sipSystemIsRunning || isQueuedSipSystemRestart()) {
  1424.             try {
  1425.                 Thread.sleep(500);
  1426.             }
  1427.             catch (InterruptedException ie) {
  1428.                     // Ignore
  1429.             }
  1430.         }
  1431.         stopSipSystem();
  1432.         // End the program
  1433.         System.exit(0);
  1434.     }
  1435.     /**
  1436.      * Stops the SIP controller, disconnects any call and unregisters.
  1437.      *
  1438.      */
  1439.     private void stopSipSystem() {
  1440.         synchronized (sipStartStopMutex) {
  1441.             gui.setRegDetecting("Stopping SIP");
  1442.             sipSystemIsRunning = false;
  1443.             // Disconnect
  1444.             if (callProcessor != null) {
  1445.                 callProcessor.bye();
  1446.                 callProcessor = null;
  1447.             }
  1448.             // Unregister
  1449.             sipUnregisterAll();
  1450.             // Allow 2 seconds for the unregister process
  1451.             try {
  1452.                 Thread.sleep(2000);
  1453.             } catch (InterruptedException ie) {
  1454.                 // Ignore this.
  1455.             }
  1456.             // Stop the SIP client
  1457.             if (sc != null) {
  1458.                 sc.stop();
  1459.                 sc = null;
  1460.             }
  1461.             // Stop the STUN stack
  1462.             if (stunStack != null) {
  1463.                 stunStack.stop();
  1464.             }
  1465.             gui.setRegNa();
  1466.         }
  1467.     }
  1468.     /**
  1469.      * Handles incoming call.
  1470.      *
  1471.      */
  1472.     public void signalIncomingCall(IncomingCallDialog call) {
  1473.         if (call.getSdp().indexOf("eConf 3.5.1") > 0) {
  1474.             isEconf351 = true;
  1475.         }
  1476.         if (callProcessor != null) {
  1477.             call.busy();
  1478.             return;
  1479.         }
  1480.         callProcessor = call.getCallProcessor();
  1481.         remoteUserAddress = call.getRemoteUserAddress();
  1482.         // Show a popup dialog to the user
  1483.         gui.toFront();
  1484.         incomingCallDialog =
  1485.                 DialogFactory.showAnswerDialog(remoteUserAddress);
  1486.         if (appSettings.isAlertingEnabled()) {
  1487.             System.out.println("Activating the Alert processn");
  1488.             Alert();
  1489.         }
  1490.         Thread ringThread = new Thread() {
  1491.             public void run() {
  1492.                 try {
  1493.                     while (true) {
  1494.                         try {
  1495.                             AudioInputStream ais =
  1496.                                     AudioSystem.getAudioInputStream
  1497.                                     (new File(appConstants.RING_SOUND_URL));
  1498.                             javax.sound.sampled.AudioFormat format =
  1499.                                     ais.getFormat();
  1500.                             Line.Info info =
  1501.                                     new Line.Info(Clip.class);
  1502.                             Clip clip =
  1503.                                     (Clip) AudioSystem.getLine(info);
  1504.                             clip.open(ais);
  1505.                             clip.start();
  1506.                         } catch (Exception e) {
  1507.                             logger.throwing(this.getClass().getName(),
  1508.                                             "run", e);
  1509.                             // If something fails,
  1510.                             // just don't play the clip.
  1511.                         }
  1512.                         Thread.sleep(4000);
  1513.                     }
  1514.                 } catch (InterruptedException e) {
  1515.                     // Jump out from the thread when interrupted.
  1516.                 }
  1517.             }
  1518.         };
  1519.         ringThread.setName("Ring signal");
  1520.         ringThread.start();
  1521.         call.ringing();
  1522.         int result = incomingCallDialog.getResult();
  1523.         ringThread.interrupt();
  1524.         // Handle the result
  1525.         if (result == ThreadedDialog.YES) {
  1526.             gui.clearTextAreas();
  1527.             gui.changeInfoLabel(language.getProperty
  1528.                                 ("se.omnitor.tipcon1.AppController." +
  1529.                                  "MEDIA_SETUP"));
  1530.             negotiatedMedia = new Vector(0, 1);
  1531.             System.out.println("<<signalIncomingCall::" + call.getSdp() + ">>");
  1532.             if (call.getSdp().indexOf("eConf 3.5.1") > 0) {
  1533.                 isEconf351 = true;
  1534.             }
  1535.             try {
  1536.                 deploySdpSettings(true);
  1537.                 String sdp =
  1538.                         currentSdpManager.negotiate(call.getSdp(),
  1539.                         negotiatedMedia);
  1540.                 call.answer("application", "sdp", sdp);
  1541.                 int a = negotiatedMedia.size();
  1542.                 SdpMedia m;
  1543.                 Vector v;
  1544.                 for (int cnt = 0; cnt < a; cnt++) {
  1545.                     m = (SdpMedia) negotiatedMedia.elementAt(cnt);
  1546.                     v = m.getFormats();
  1547.                     System.out.println("Media " + cnt + ": " + v);
  1548.                     System.out.println("(PP = " + m.getPhysicalPort() + ")");
  1549.                 }
  1550.             } catch (SdpException se) {
  1551.                 logger.throwing(this.getClass().getName(),
  1552.                                 "signalIncomingCall",
  1553.                                 se);
  1554.                 call.badRequest("SDP parse error");
  1555.                 DialogFactory.showErrorMessageDialog
  1556.                         (language.getProperty("se.omnitor.tipcon1." +
  1557.                                               "AppController." +
  1558.                                               "SIP_SEND_PROBLEM"));
  1559.                 callProcessor = null;
  1560.                 gui.setTerminatedGui();
  1561.             }
  1562.             /* Error handling should be done here, see below for example.
  1563.                   catch (Exception see) {
  1564.                try {
  1565.              sc.sipCancel();
  1566.                }
  1567.                catch (Exception e) {
  1568.              // Ignore exceptions here, there is anyway nothing
  1569.              // here to do if an error occurs.
  1570.                }
  1571.                DialogFactory.showErrorMessageDialog
  1572.              (language.getProperty("se.omnitor.tipcon1." +
  1573.               "AppController." +
  1574.               "SIP_SEND_PROBLEM"));
  1575.                gui.setTerminatedGui();
  1576.                   }
  1577.              */
  1578.         } else if (result == ThreadedDialog.NO ||
  1579.                    result == ThreadedDialog.USER_CLOSED_WINDOW) {
  1580.             call.decline();
  1581.             callProcessor = null;
  1582.         }
  1583.     }
  1584.     public String getRemoteUserAddress() {
  1585.         return remoteUserAddress;
  1586.     }
  1587.     /**
  1588.      * Handles an established call.
  1589.      *
  1590.      */
  1591.     public void signalEstablishedCall(CallProcessor cp) {
  1592.         this.callProcessor = cp;
  1593.         System.out.println("<<signalEstablishedCall::" + cp.getRemoteSdp() +
  1594.                            ">>");
  1595.         // n鋜 client ringer sipcon blir d nullpexception
  1596.         String cpString = cp.getRemoteSdp();
  1597.         if (cpString != null && cpString.indexOf("eConf 3.5.1") > 0) {
  1598.             isEconf351 = true;
  1599.         }
  1600.         System.out.println("<<signalEstablishedCall::isEconf351" + isEconf351 +
  1601.                            ">>");
  1602.         gui.setPendingGui();
  1603.         // Inform the user
  1604.         if (outgoingCallDialog != null) {
  1605.             outgoingCallDialog.setInfoText
  1606.                     (language.getProperty("se.omnitor.tipcon1.AppController." +
  1607.                                           "MEDIA_SETUP"));
  1608.         }
  1609.         // Store the remote address
  1610.         if (appSettings.isRealtimePreviewEnabled()) {
  1611.             // Get a nice name which can be presented in GUI
  1612.             String addr = cp.getNiceRemoteName();
  1613.             if (addr == null || addr.trim().equals("")) {
  1614.                 addr = "You";
  1615.             }
  1616.             else {
  1617.                 int ix1 = addr.indexOf("<");
  1618.                 int ix2 = addr.indexOf(">");
  1619.                 if (ix1 < ix2 && (ix2-ix1 > 1)) {
  1620.                     addr = addr.substring(ix1+1, ix2-ix1);
  1621.                 }
  1622.                 if (addr.startsWith("sip:")) {
  1623.                     addr = addr.substring(4);
  1624.                 }
  1625.                 addr = addr.split("@")[0];
  1626.                 String[] addrSplit = addr.split("\.");
  1627.                 if (addrSplit.length == 4) {
  1628.                     addr = "You";
  1629.                 }
  1630.                 else {
  1631.                     addr = addrSplit[0];
  1632.                 }
  1633.             }
  1634.             t140Panel.setRemoteLogName(addr);
  1635.         }
  1636.         // An outgoing call has no negotiated media (as negotiation was taken
  1637.         // place at remote's side)
  1638.         if (negotiatedMedia == null) {
  1639.             try {
  1640.                 negotiatedMedia = SdpManager.getFormats(cp.getRemoteSdp());
  1641.                 if (negotiatedMedia == null) {
  1642.                     // We want to get into the catch clause.
  1643.                     throw new SdpException("Dummy exception");
  1644.                 }
  1645.                 // Now, move the psysical ports from local config to current
  1646.                 // negotiated media.
  1647.                 int len = negotiatedMedia.size();
  1648.                 for (int cnt=0; cnt<len; cnt++) {
  1649.                     SdpMedia m1 = (SdpMedia) negotiatedMedia.get(cnt);
  1650.                     SdpMedia m2 = currentSdpManager.getMedia(m1.getType());
  1651.                     if (m1 != null && m2 != null) {
  1652.                         m1.setPhysicalPort(m2.getPhysicalPort());
  1653.                     }
  1654.                 }
  1655.             } catch (SdpException e) {
  1656.                 logger.throwing(this.getClass().getName(),
  1657.                                 "signalEstablishedCall", e);
  1658.                 // TODO:
  1659.                 // Strange SDP from remote, disconnect call here!
  1660.                 negotiatedMedia = null;
  1661.                 outgoingCallDialog.dispose();
  1662.                 DialogFactory.showErrorMessageDialog(language.getProperty("se.omnitor.tipcon1.AppController." +
  1663.                                           "SDP_PARSE_ERROR"));
  1664.                 cp.bye();
  1665.                 return;
  1666.             }
  1667.         }
  1668.         startMedia();
  1669.         if (outgoingCallDialog != null) {
  1670.             outgoingCallDialog.dispose();
  1671.         }
  1672.         // Change GUI
  1673.         gui.setEstablishedGui();
  1674.         gui.setRemoteUserInfo(cp.getNiceRemoteName());
  1675.         gui.changeInfoLabel(language.getProperty("se.omnitor.tipcon1." +
  1676.                                                  "AppController." +
  1677.                                                  "CONNECTED"));
  1678.     }
  1679.     /**
  1680.      * Handles incoming cancellation.
  1681.      *
  1682.      */
  1683.     public void signalCancelledIncomingCall(IncomingCallDialog dialog) {
  1684.         // Hide call popup
  1685.         if (incomingCallDialog != null) {
  1686.             incomingCallDialog.dispose();
  1687.         }
  1688.         // Inform the user
  1689.         gui.changeInfoLabel
  1690.                 (language.getProperty("se.omnitor.tipcon1.AppController." +
  1691.                                       "MISSED_CALL_FROM") + " " +
  1692.                  remoteUserAddress);
  1693.         callProcessor = null;
  1694.     }
  1695.     /**
  1696.      * Handles terminated call signal.
  1697.      *
  1698.      */
  1699.     public void signalTerminatedCall(CallProcessor cp) {
  1700.         // Change GUI
  1701.         gui.setTerminatedGui();
  1702.         gui.changeInfoLabel(language.getProperty("se.omnitor." +
  1703.                                                  "tipcon1." +
  1704.                                                  "AppController." +
  1705.                                                  "TERMINATED"));
  1706.         isMuted = false;
  1707.         gui.setMute(false);
  1708.         gui.repaint();
  1709.         if (mediaManager != null) {
  1710.             mediaManager.stopAll();
  1711.             mediaManager = null;
  1712.         }
  1713.         negotiatedMedia = null;
  1714.         callProcessor = null;
  1715.         // Remove the remote address
  1716.         remoteUserAddress = null;
  1717.          if(appSettings.getTipcon1Mode()) {
  1718.              restartVideo();
  1719.          }
  1720.         //settingsDialog.actionPerformed
  1721.         // (new ActionEvent(new Button("OK"), 666,"OK"));
  1722.         //deploySdpSettings(true);
  1723.     }
  1724.     /**
  1725.      * Handles call progress signal.
  1726.      *
  1727.      */
  1728.     public void signalOutgoingCallProgress(CallProcessor cp, int statusCode) {
  1729.         System.out.println("<<signalOutgoingCallProgress::" + cp.getRemoteSdp() +
  1730.                            ">>");
  1731.         switch (statusCode) {
  1732.         case 100:
  1733.             // Inform the user only if nothing has been informed yet (NIST
  1734.             // SIP tends to turn the order of 100 and 180, so that 100 comes
  1735.             // after 180).
  1736.             if (outgoingCallDialog != null && !outgoingCallProgressReported) {
  1737.                 outgoingCallDialog.setInfoText
  1738.                         (language.getProperty(
  1739.                                 "se.omnitor.tipcon1.AppController." +
  1740.                                 "HOST_CONTACTED"));
  1741.             }
  1742.             break;
  1743.         case 182:
  1744.             // Inform the user