/** Handle a exit request */
 public void handleExitRequest() {
   if (mediaManager != null) {}
   // SIP unregister
   if (sipManager != null) {
     try {
       sipManager.endAllCalls();
     } catch (CommunicationsException exc) {
       Log.error("handleExitRequest", exc);
     } catch (Throwable exc) {
       Log.error("handleExitRequest", exc);
     }
     try {
       sipManager.unregister();
     } catch (CommunicationsException exc) {
       Log.error("handleExitRequest", exc);
     } catch (Throwable exc) {
       Log.error("handleExitRequest", exc);
     }
     try {
       sipManager.stop();
     } catch (Exception exc) {
       Log.error("handleExitRequest", exc);
     }
   }
   NetworkAddressManager.shutDown();
 }
  /** Create the softphone handlers and stack */
  public void createSoftPhone(String server) throws MediaException {

    this.server = server;
    SIPConfig.setServer(server);

    if (sipManager != null) {
      destroySoftPhone();
    }

    sipManager = new SipManager();
    softPhoneMedia = new SoftPhoneMedia();
    softPhoneSecurity = new SoftPhoneSecurity();

    sipManager.addCommunicationsListener(this);
    sipManager.setSecurityAuthority(softPhoneSecurity);

    try {
      // put in a seperate thread
      sipManager.start();
      if (sipManager.isStarted()) {
        Log.debug("createSoftPhone", "SIP STARTED");
      }
    } catch (CommunicationsException exc) {
      Log.error("createSoftPhone", exc);
    }
  }
  /** Handle a answer request */
  public boolean handleAnswerRequest(Interlocutor interlocutor) {

    // cancel call request if no Media Locator
    if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) {
      return false;
    }

    PhoneManager.setUsingMediaLocator(true);

    SessionDescription sdpData = null;
    try {
      sdpData = mediaManager.generateSdpDescription();
      interlocutor.getCall().setLocalSdpDescription(sdpData);
    } catch (MediaException ex) {
      try {
        sipManager.sendServerInternalError(interlocutor.getID());
      } catch (CommunicationsException ex1) {
        Log.error("handleAnswerRequest", ex1);
      }
      return false;
    }
    try {
      sipManager.answerCall(interlocutor.getID(), sdpData.toString());
    } catch (CommunicationsException exc) {
      Log.error("handleAnswerRequest", exc);
      return false;
    }
    return true;
  }
  /**
   * Fired when softphone is unregistering
   *
   * @param evt RegistrationEvent
   */
  public void unregistering(RegistrationEvent evt) {
    status = SipRegisterStatus.Unregistered;

    registerStatusChanged(
        new RegisterEvent(this, SipRegisterStatus.Unregistering, evt.getReason()));

    int waitUnreg = SIPConfig.getWaitUnregistration();
    if (waitUnreg != -1) {
      try {
        int delay = waitUnreg;
        // we get here through a _synchronous_ call from shutdown so
        // let's try
        // and wait for unregistrations confirmation in case the
        // registrar has requested authorization
        // before conriming unregistration
        if (delay > 0)
          synchronized (unregistrationLock) {
            unregistrationLock.wait(delay);
          }
      } catch (InterruptedException ex) {
        Log.error("unregistering", ex);
      } catch (NumberFormatException ex) {
        Log.error("unregistering", ex);
      }
    }
  }
  /** Initializes the core phone objects. */
  private void initializePhone() {
    // Load Preferences
    loadPreferences();

    if (preferences == null) {
      return;
    }

    guiManager = new GuiManager();
    guiManager.addUserActionListener(this);
    logManager = new LogManagerImpl(this);

    this.getLogManager().setRemoteLogging(true);

    try {
      EventQueue.invokeAndWait(
          new Runnable() {
            @Override
            public void run() {
              registerMenu = new JCheckBoxMenuItem(PhoneRes.getIString("phone.enabled"));
            }
          });
    } catch (Exception e) {
      Log.error(e);
    }

    registerMenu.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent actionEvent) {
            if (getStatus() == SipRegisterStatus.Unregistered
                || getStatus() == SipRegisterStatus.RegistrationFailed) {

              register();
            } else {
              handleUnregisterRequest();
            }
          }
        });

    SIPConfig.setPreferredNetworkAddress(preferences.getPreferredAddress());
    NetworkAddressManager.start();

    try {
      EventQueue.invokeAndWait(
          new Runnable() {
            @Override
            public void run() {
              // Initialize Missed calls
              missedCalls = new MissedCalls();
            }
          });
    } catch (Exception e) {
      Log.error(e);
    }

    final JMenu actionsMenu =
        SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.actions"));
    actionsMenu.add(registerMenu);
  }
  /** Handle a dial request */
  public void handleDialRequest(String phoneNumber) {
    try {

      System.err.println(
          "Audio Static:"
              + PhoneManager.isUseStaticLocator()
              + " Using:"
              + PhoneManager.isUsingMediaLocator());

      // cancel call request if no Media Locator
      if (PhoneManager.isUseStaticLocator() && PhoneManager.isUsingMediaLocator()) {
        return;
      }

      PhoneManager.setUsingMediaLocator(true);

      SessionDescription sdpData = mediaManager.generateSdpDescription();

      Call call = sipManager.establishCall(phoneNumber, sdpData.toString());

      if (call == null) return;

      call.setLocalSdpDescription(sdpData);

      call.addStateChangeListener(this);
      Interlocutor interlocutor = new Interlocutor();
      interlocutor.setCall(call);

      guiManager.addInterlocutor(interlocutor);
    } catch (Exception e) {
      Log.error("handleDialRequest", e);
    }
  }
 /**
  * Send the dtmf digit to the sip server.
  *
  * @param callID the caller id
  * @param digit the digit typed.
  */
 void sendDTMFDigit(int callID, String digit) {
   try {
     sipManager.sendDTMF(callID, digit);
   } catch (CommunicationsException exc) {
     Log.error("sendDTMFDigit", exc);
   }
 }
 /**
  * Handle when users press a dtmf button
  *
  * @param iui the InterlocutorUI
  */
 public void handleDTMF(InterlocutorUI iui, String digit) {
   try {
     sendDTMFDigit(iui.getID(), digit);
   } catch (Exception e) {
     Log.error("sendDTMFDigit", e);
   }
 }
  /** Destroys the softphone handlers and stack */
  public void destroySoftPhone() {

    try {
      sipManager.stop();
    } catch (Exception exc) {
      Log.error("destroySoftPhone", exc);
    }
  }
 /**
  * Handle a Mute request
  *
  * @param iui the InterlocutorUI
  * @param mic true to place on mute.
  */
 public void handleMute(InterlocutorUI iui, boolean mic) {
   try {
     AudioMediaSession audioMediaSession = iui.getCall().getAudioMediaSession();
     if (audioMediaSession != null) audioMediaSession.setTrasmit(mic);
   } catch (Exception e) {
     Log.error("handleHold", e);
   }
 }
 /**
  * Handle a Re-Register Request. This method will only have effect if the user has successfully
  * registered beforeat least once before.
  */
 public void handleReRegisterRequest() {
   if (this.password != null && !this.username.equals("")) {
     try {
       sipManager.startRegisterProcess(username, authUserName, password);
     } catch (CommunicationsException exc) {
       Log.error("handleRegisterRequest", exc);
     }
   }
 }
  /**
   * Handle a Hold request
   *
   * @param iui the InterlocutorUI
   * @param mic true to place on hold.
   * @param cam true to place camera on hold.
   */
  public void handleHold(InterlocutorUI iui, boolean mic, boolean cam) {

    try {
      sipManager.hold(
          iui.getID(), mediaManager.generateHoldSdpDescription(mic, mic, iui.getCall()), mic, cam);
    } catch (Exception e) {
      Log.error("handleHold", e);
    }
  }
 /** Handle an UnregisterRequest */
 public void handleUnregisterRequest() {
   if (sipManager != null) {
     try {
       sipManager.endAllCalls();
       sipManager.unregister();
     } catch (Exception e) {
       Log.error("handleUnregisterRequest", e);
     }
   }
 }
 /** Handle a hangup request */
 public boolean handleHangupRequest(Interlocutor interlocutor) {
   boolean hangupOk = true;
   try {
     sipManager.endCall(interlocutor.getID());
   } catch (CommunicationsException exc) {
     guiManager.remove(interlocutor);
     hangupOk = false;
     Log.error("handleHangupRequest", exc);
   }
   return hangupOk;
 }
 /**
  * Fired when a call is received
  *
  * @param evt CallEvent
  */
 public void callReceived(CallEvent evt) {
   try {
     Call call = evt.getSourceCall();
     Interlocutor interlocutor = new Interlocutor();
     interlocutor.setCall(call);
     guiManager.addInterlocutor(interlocutor);
     call.addStateChangeListener(this);
     // handleAnswerRequest(interlocutor);
   } catch (Exception e) {
     Log.error("callReceived", e);
   }
 }
  /**
   * Handle an RegisterRequest
   *
   * @param username username
   * @param authUserName Authorization username
   * @param password password
   */
  public void handleRegisterRequest(String username, String authUserName, String password) {

    this.authUserName = authUserName;
    this.username = username;
    this.password = password;

    try {
      sipManager.startRegisterProcess(username, authUserName, password);
    } catch (CommunicationsException exc) {
      Log.error("handleRegisterRequest", exc);
    }
  }
  /**
   * Fired when softphone is unregistered sucessfully
   *
   * @param evt RegistrationEvent
   */
  public void unregistered(RegistrationEvent evt) {
    try {
      status = SipRegisterStatus.Unregistered;

      registerStatusChanged(
          new RegisterEvent(this, SipRegisterStatus.Unregistered, evt.getReason()));

      // we could now exit
      synchronized (unregistrationLock) {
        unregistrationLock.notifyAll();
      }

      destroySoftPhone();
      registerMenu.setSelected(false);
    } catch (Exception e) {
      Log.error("unregistered", e);
    }
  }
  /**
   * Setup the Preferences according to remote server
   *
   * @param con XMPPConnection connection
   */
  private void setupRemotePreferences(XMPPConnection con) {

    try {
      ProviderManager.addIQProvider(
          SipAccountPacket.ELEMENT_NAME,
          SipAccountPacket.NAMESPACE,
          new SipAccountPacket.Provider());

      ProviderManager.addIQProvider(
          LogPacket.ELEMENT_NAME, LogPacket.NAMESPACE, new LogPacket.Provider());

      SipAccountPacket sp = SipAccountPacket.getSipSettings(con);

      if (sp != null) {

        SipAccount sipAccount = sp.getSipAccount();

        if (sipAccount != null) {
          this.saccount = sipAccount;
          preference = new SipPreference();
          preference.setShowGUI(false);
          preference.setCommitSettings(false);

          preferences = new SipPreferences();

          preferences.setUserName(sipAccount.getSipUsername());
          preferences.setAuthUserName(sipAccount.getAuthUsername());
          preferences.setServer(sipAccount.getServer());
          preferences.setPassword(sipAccount.getPassword());
          preferences.setRegisterAtStart(true);

          preferences.setStunServer(sipAccount.getStunServer());
          preferences.setStunPort(sipAccount.getStunPort());
          preferences.setUseStun(sipAccount.isUseStun());
          preferences.setVoicemail(sipAccount.getVoiceMailNumber());
          preferences.setOutboundproxy(sipAccount.getOutboundproxy());
          preferences.setPromptCredentials(sipAccount.isPromptCredentials());

          SIPConfig.setUseStun(preferences.isUseStun());
          SIPConfig.setStunServer(preferences.getStunServer());
          SIPConfig.setStunPort(preferences.getStunPort());
          SIPConfig.setOutboundProxy(preferences.getOutboundproxy());

          preference.setData(preferences);
          SIPConfig.setPreferredNetworkAddress(
              NetworkAddressManager.getLocalHost(false).getHostAddress());

          if (preferences.isRegisterAtStart()) {
            register();
          }

          if (preferences.isPromptCredentials()) {
            loadLocalPreferences();
          }

        } else {

        }
      }

    } catch (Exception e) {
      Log.error("setupRemotePreferences", e);
    }
  }
  /**
   * Fired when call state changes
   *
   * @param evt CallStateEvent
   */
  public void callStateChanged(CallStateEvent evt) {
    try {

      for (SoftPhoneListener sfl : softPhoneListeners) {
        sfl.callStateChanged(evt);
      }

      Call call = evt.getSourceCall();
      Log.debug("callStateChanged", evt.getOldState() + " -> " + evt.getNewState());
      if (evt.getNewState() == Call.CONNECTED) {
        // sipManager.setBusy(true);

        if (call.getAudioReceiverChannel() != null) call.getAudioReceiverChannel().stop();

        if (evt.getOldState() == Call.MOVING_REMOTELY) {
          AudioMediaSession audioMediaSession = evt.getSourceCall().getAudioMediaSession();
          if (call.getAudioReceiverChannel() != null) call.getAudioReceiverChannel().stop();

          if (audioMediaSession != null) {
            audioMediaSession.stopTrasmit();
            audioMediaSession.stopReceive();
          }
          VideoMediaSession videoMediaSession = evt.getSourceCall().getVideoMediaSession();
          if (videoMediaSession != null) {
            videoMediaSession.stopTrasmit();
            videoMediaSession.stopReceive();
          }
          PhoneManager.setUsingMediaLocator(false);
        }

        int localAudioPort = -1;
        int localVideoPort = -1;

        Vector<MediaDescription> mediaDescriptions =
            call.getLocalSdpDescription().getMediaDescriptions(true);
        for (MediaDescription mediaDescription : mediaDescriptions) {
          if (mediaDescription.getMedia().getMediaType().equals("audio"))
            localAudioPort = mediaDescription.getMedia().getMediaPort();
          else if (mediaDescription.getMedia().getMediaType().equals("video"))
            localVideoPort = mediaDescription.getMedia().getMediaPort();
        }

        AudioMediaSession audioMediaSession =
            mediaManager.createAudioMediaSession(
                call.getRemoteSdpDescription().toString(), localAudioPort);
        call.setAudioMediaSession(audioMediaSession);

        if (audioMediaSession != null) {
          audioMediaSession.startTrasmit();
          audioMediaSession.startReceive();
        }

        // If remote client have video
        if (localVideoPort > 0) {
          if (SettingsManager.getLocalPreferences().getVideoDevice() != null
              && !"".equals(SettingsManager.getLocalPreferences().getVideoDevice())) {
            VideoMediaSession videoMediaSession =
                mediaManager.createVideoMediaSession(
                    call.getRemoteSdpDescription().toString(), localVideoPort);
            if (videoMediaSession != null) {
              videoMediaSession.startTrasmit();
              videoMediaSession.startReceive();
              call.setVideoMediaSession(videoMediaSession);
            }
          }
        }

        evt.getSourceCall().start();

        Log.debug("MEDIA STREAMS OPENED");

      } else if (evt.getNewState() == Call.RINGING) {

        if (call.getRemoteSdpDescription() != null && !call.getRemoteSdpDescription().equals("")) {

          Log.debug("STATE", call.getRemoteSdpDescription().toString());

          int localPort =
              ((MediaDescription) (call.getLocalSdpDescription().getMediaDescriptions(true).get(0)))
                  .getMedia()
                  .getMediaPort();
          int destPort =
              ((MediaDescription)
                      (call.getRemoteSdpDescription().getMediaDescriptions(true).get(0)))
                  .getMedia()
                  .getMediaPort();
          String destIp = call.getRemoteSdpDescription().getConnection().getAddress();

          AudioReceiverChannel audioReceiverChannel =
              mediaManager.createAudioReceiverChannel(localPort, destIp, destPort, (destPort + 1));
          call.setAudioReceiverChannel(audioReceiverChannel);

          if (audioReceiverChannel != null) audioReceiverChannel.start();
        }

      } else if (evt.getNewState() == Call.DISCONNECTED) {
        sipManager.setBusy(false);

        AudioMediaSession audioMediaSession = evt.getSourceCall().getAudioMediaSession();
        if (audioMediaSession != null) {
          audioMediaSession.stopTrasmit();
          audioMediaSession.stopReceive();
        }
        if (call.getAudioReceiverChannel() != null) call.getAudioReceiverChannel().stop();
        VideoMediaSession videoMediaSession = evt.getSourceCall().getVideoMediaSession();
        if (videoMediaSession != null) {
          videoMediaSession.stopTrasmit();
          videoMediaSession.stopReceive();
        }

        PhoneManager.setUsingMediaLocator(false);

      } else if (evt.getNewState() == Call.FAILED) {
        call.setState(Call.DISCONNECTED);
        if (call.getAudioReceiverChannel() != null) call.getAudioReceiverChannel().stop();

        CallRejectedEvent rejectEvt =
            new CallRejectedEvent("Disconnected", call.getLastRequest(), call);

        for (SoftPhoneListener softPhoneListener : softPhoneListeners) {
          softPhoneListener.callRejectedRemotely(rejectEvt);
        }

        PhoneManager.setUsingMediaLocator(false);
      }
    } catch (Exception e) {
      Log.error("callStateChanged", e);
    }
  }