/** * $RCSfile: ,v $ * $Revision: $ * $Date: $ * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sipmack.softphone; import java.awt.Component; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; import javax.sdp.MediaDescription; import javax.sdp.SessionDescription; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import net.java.sipmack.common.DialSoundManager; import net.java.sipmack.common.Log; import net.java.sipmack.events.UserActionListener; import net.java.sipmack.media.AudioMediaSession; import net.java.sipmack.media.AudioReceiverChannel; import net.java.sipmack.media.JmfMediaManager; import net.java.sipmack.media.MediaException; import net.java.sipmack.media.VideoMediaSession; import net.java.sipmack.sip.Call; import net.java.sipmack.sip.CommunicationsException; import net.java.sipmack.sip.Interlocutor; import net.java.sipmack.sip.InterlocutorUI; import net.java.sipmack.sip.NetworkAddressManager; import net.java.sipmack.sip.SIPConfig; import net.java.sipmack.sip.SipManager; import net.java.sipmack.sip.SipRegisterStatus; import net.java.sipmack.sip.event.CallEvent; import net.java.sipmack.sip.event.CallListener; import net.java.sipmack.sip.event.CallRejectedEvent; import net.java.sipmack.sip.event.CallStateEvent; import net.java.sipmack.sip.event.CommunicationsErrorEvent; import net.java.sipmack.sip.event.CommunicationsListener; import net.java.sipmack.sip.event.MessageEvent; import net.java.sipmack.sip.event.RegistrationEvent; import net.java.sipmack.sip.event.UnknownMessageEvent; import net.java.sipmack.softphone.gui.DefaultGuiManager; import net.java.sipmack.softphone.gui.GuiManager; import net.java.sipmack.softphone.listeners.InterlocutorListener; import net.java.sipmack.softphone.listeners.RegisterEvent; import net.java.sipmack.softphone.listeners.SoftPhoneListener; import org.jivesoftware.resource.Res; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.provider.ProviderManager; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.packet.VCard; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.phone.PhoneManager; import org.jivesoftware.spark.plugin.phone.resource.PhoneRes; import org.jivesoftware.spark.preference.PreferenceManager; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; import org.jivesoftware.sparkplugin.calllog.LogManager; import org.jivesoftware.sparkplugin.calllog.LogManagerImpl; import org.jivesoftware.sparkplugin.calllog.LogPacket; import org.jivesoftware.sparkplugin.preferences.SipPreference; import org.jivesoftware.sparkplugin.preferences.SipPreferences; import org.jivesoftware.sparkplugin.sipaccount.SipAccount; import org.jivesoftware.sparkplugin.sipaccount.SipAccountPacket; import org.jivesoftware.sparkplugin.ui.call.MissedCalls; /** * Title: SIPark * Description:JAIN-SIP Audio/Video phone application * * @author Thiago Rocha Camargo (thiago@jivesoftware.com) The * <code>SoftPhoneManager</code> class that Manage SIP Stack, Sessions * and Calls * Use getInstance() to get a SoftPhone instance to use * @version 1.0, 20/07/2006 */ public class SoftPhoneManager implements CommunicationsListener, CallListener, UserActionListener, SoftPhone { private static SoftPhoneManager singleton; private static final Object LOCK = new Object(); private SipAccount saccount; private final List<SoftPhoneListener> softPhoneListeners = new CopyOnWriteArrayList<SoftPhoneListener>(); // TODO REMOVE @SuppressWarnings("unused") private SoftPhoneMedia softPhoneMedia = null; private SoftPhoneSecurity softPhoneSecurity = null; private SipManager sipManager = null; private JmfMediaManager mediaManager = null; private GuiManager guiManager = null; private String authUserName = ""; private String username = ""; private String password = null;// new char[10]; public String server = ""; protected String msgBuffer = ""; protected Integer unregistrationLock = Integer.valueOf(0); private SipRegisterStatus status = SipRegisterStatus.Unregistered; public static final String userAgent = "SIPSpark"; public String callTo = ""; private LogManager logManager; private SipPreferences preferences; private SipPreference preference; // private int lines = 1; private DialSoundManager dtmfSounds; private MissedCalls missedCalls; // Define UIs private JCheckBoxMenuItem registerMenu; private Map<Component, CallRoomState> callRooms = new HashMap<Component, CallRoomState>(); /** * Private constructor of the class. */ private SoftPhoneManager() { mediaManager = new JmfMediaManager(); } /** * 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); } /** * Type of states a jingle call can be in. */ public static enum CallRoomState { /** * The component is in a call. */ inCall, /** * The components call has ended. */ callWasEnded, /** * The call is muted. */ muted, /** * The call is on hold. */ onHold } /** * Returns the singleton instance of <CODE>SoftPhoneManager</CODE>, * creating it if necessary. * <p/> * * @return the singleton instance of <Code>SoftPhoneManager</CODE> */ public static SoftPhoneManager getInstance() { // Synchronize on LOCK to ensure that we don't end up creating // two singletons. synchronized (LOCK) { if (null == singleton) { SoftPhoneManager controller = new SoftPhoneManager(); singleton = controller; controller.initializePhone(); return controller; } } return singleton; } /** * Add SoftPhoneListener * * @param softPhoneListener the listener. */ public void addSoftPhoneListener(SoftPhoneListener softPhoneListener) { softPhoneListeners.add(softPhoneListener); } /** * Add InterlocutorListener * * @param interlocutorListener the listener. */ public void addInterlocutorListener(InterlocutorListener interlocutorListener) { guiManager.addInterlocutorListener(interlocutorListener); } /** * Remove InterlocutorListener * * @param interlocutorListener the listener */ public void removeInterlocutorListener(InterlocutorListener interlocutorListener) { guiManager.removeInterlocutorListener(interlocutorListener); } /** * Return the DefaultGuiManager */ public DefaultGuiManager getDefaultGuiManager() { return guiManager; } /** * 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); } } /** * Destroys the softphone handlers and stack */ public void destroySoftPhone() { try { sipManager.stop(); } catch (Exception exc) { Log.error("destroySoftPhone", exc); } } /** * Return the current SIP connection status * * @return status */ public SipRegisterStatus getStatus() { return status; } /** * Gets the current username * * @return The current connection username */ public String getUsername() { return username; } /** * Gets the current server * * @return The current connection server */ public String getServer() { return server; } /** * Handle an UnregisterRequest */ public void handleUnregisterRequest() { if (sipManager != null) { try { sipManager.endAllCalls(); sipManager.unregister(); } catch (Exception e) { Log.error("handleUnregisterRequest", 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 an RegisterRequest * * @param username username * @param password password */ public void handleRegisterRequest(String username, String password) { handleRegisterRequest(username, null, password); } /** * 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); } } /** * Add a CommunicationsListener * * @param communicationsListener CommunicationsListener */ public void addCommunicationsListener(CommunicationsListener communicationsListener) { sipManager.addCommunicationsListener(communicationsListener); } /** * Fired when a call ends * * @param evt CallEvent */ public void callEnded(CallEvent evt) { AudioMediaSession audioMediaSession = evt.getSourceCall().getAudioMediaSession(); if (audioMediaSession != null) { audioMediaSession.close(); } } /** * 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); } } /** * Fired when a message is received * * @param evt MessageEvent */ public void messageReceived(MessageEvent evt) { for (SoftPhoneListener sfl : softPhoneListeners) { sfl.messageReceived(evt); } } /** * Fired when a call is rejected locally * * @param evt CallRejectedEvent */ public void callRejectedLocally(CallRejectedEvent evt) { // String reason = evt.getReason(); // String detailedReason = evt.getDetailedReason(); } /** * Fired when a call is rejected remotly * * @param evt CallRejectedEvent */ public void callRejectedRemotely(CallRejectedEvent evt) { for (SoftPhoneListener softPhoneListener : softPhoneListeners) { softPhoneListener.callRejectedRemotely(evt); } } /** * Fired when softphone is register sucessfully * * @param evt RegistrationEvent */ public void registered(RegistrationEvent evt) { status = SipRegisterStatus.Registered; preferences.setPreferredAddress(NetworkAddressManager.getLocalHost().getHostAddress()); //preference.commit(); registerStatusChanged(new RegisterEvent(this, SipRegisterStatus.Registered, evt.getReason())); if (callTo.length() > 2) { handleDialRequest(callTo); } registerMenu.setSelected(true); } public void registrationFailed(RegistrationEvent evt) { status = SipRegisterStatus.RegistrationFailed; registerStatusChanged(new RegisterEvent(this, SipRegisterStatus.RegistrationFailed, evt.getReason())); registerMenu.setSelected(false); } /** * Fired when softphone is registering * * @param evt RegistrationEvent */ public void registering(RegistrationEvent evt) { status = SipRegisterStatus.Registering; registerStatusChanged(new RegisterEvent(this, SipRegisterStatus.Registering, evt.getReason())); } /** * 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); } } /** * 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); } } } private void registerStatusChanged(RegisterEvent evt) { for (SoftPhoneListener sfl : softPhoneListeners) { sfl.registerStatusChanged(evt); } } /** * Returns the current interlocutors * * @return List<InterlocutorUI> */ public List<InterlocutorUI> getInterlocutors() { return guiManager.getInterlocutors(); } /** * Fired when softphone receive a unknown sip message * * @param evt RegistrationEvent */ public void receivedUnknownMessage(UnknownMessageEvent evt) { // TODO Do something with the error. } /** * Fired when communications Errors Occurred * * @param evt CommunicationsErrorEvent */ public void communicationsErrorOccurred(CommunicationsErrorEvent evt) { } /** * 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(); } 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(); } } } 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); 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(); 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); } } /** * 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(); } /** * 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); } } public void handleTransfer(int callID, String callee) { sipManager.transfer(callID, callee); } /** * 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 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); } } /** * 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 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; } /** * 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); } } /** * 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; } /** * Register the softPhone with the Spark preferrence settings */ public void register() { Thread registerThread = new Thread(new Runnable() { public void run() { if (preferences != null) { String user = preferences.getUserName(); String authUser = preferences.getAuthUserName(); String server = preferences.getServer(); String pass = preferences.getPassword(); try { createSoftPhone(server); } catch (MediaException e) { Log.error("Media Exception", e); } handleRegisterRequest(user, authUser, pass); } } }); registerThread.start(); } /** * Loads Preferences, either from server or locally. */ private void loadPreferences() { boolean serverPluginInstalled = SipAccountPacket.isSoftPhonePluginInstalled(SparkManager.getConnection()); if (serverPluginInstalled) { setupRemotePreferences(SparkManager.getConnection()); } } /** * Returns the LogManager associated with this SoftPhone. * * @return the LogManager. */ public LogManager getLogManager() { return logManager; } /** * Set the LogManager associated with this SoftPhone. */ public void setLogManager(LogManager logmanager) { // removes the existing listener softPhoneListeners.remove(this.logManager); logManager = logmanager; } /** * Setup the Preferences according to remote server * * @param con XMPPConnection connection */ private void setupRemotePreferences(XMPPConnection con) { try { ProviderManager.getInstance().addIQProvider(SipAccountPacket.ELEMENT_NAME, SipAccountPacket.NAMESPACE, new SipAccountPacket.Provider()); ProviderManager.getInstance().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); } } private void loadLocalPreferences() { preference = new SipPreference(); PreferenceManager pm = SparkManager.getPreferenceManager(); pm.addPreference(preference); preferences = (SipPreferences) preference.getData(); SIPConfig.setUseStun(preferences.isUseStun()); SIPConfig.setStunServer(preferences.getStunServer()); SIPConfig.setStunPort(preferences.getStunPort()); SIPConfig.setPreferredNetworkAddress(preferences.getPreferredAddress()); preference.setCommitSettings(true); if (preferences.isRegisterAtStart()) { register(); } } /** * Calls an individual user by their VCard information. * * @param jid the users JID. */ public void callByJID(String jid) { if (getStatus() == SipRegisterStatus.Registered) { final VCard vcard = SparkManager.getVCardManager().getVCard(StringUtils.parseBareAddress(jid)); if (vcard != null) { String number = vcard.getPhoneWork("VOICE"); if (!ModelUtil.hasLength(number)) { number = vcard.getPhoneHome("VOICE"); } if (ModelUtil.hasLength(number)) { getDefaultGuiManager().dial(number); } } } } /** * Returns the SoundManager for Dial Tones. * * @return the SoundManager. */ public DialSoundManager getDTMFSounds() { if (dtmfSounds == null) { dtmfSounds = new DialSoundManager(); } return dtmfSounds; } public SipPreference getPreference() { return preference; } public MissedCalls getMissedCalls() { return missedCalls; } public static String getNumbersFromPhone(String number) { if (number == null) { return null; } number = number.replace("-", ""); number = number.replace("(", ""); number = number.replace(")", ""); number = number.replace(" ", ""); if (number.startsWith("1")) { number = number.substring(1); } return number; } public SipAccount getSipAccount() { return saccount; } /** * Adds a new CallRoomState. * * @param component the component where the call is taking place. * @param state the state of the call. */ public void addCallSession(Component component, CallRoomState state) { callRooms.put(component, state); } /** * Removes a CallRoomState. * * @param component the component where the call is taking place. */ public void removeCallSession(Component component) { callRooms.remove(component); } /** * Returns the state of a <code>Component</code>. If no call is taking place, * this method will return null. * * @param component the <code>Component</code>. * @return the CallRoomState. */ public CallRoomState getCallRoomState(Component component) { return callRooms.get(component); } /** * Returns true if the user is connected. * * @return true if the user is connected. */ public boolean isPhoneEnabled() { return getPreference() != null; } public JmfMediaManager getJmfMediaManager() { return mediaManager; } }