From 1538f28016178a4ce0fa00a18d7ef35cc0e98b97 Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Fri, 19 Oct 2012 22:21:34 +0000 Subject: [PATCH] Prevents multiple dialing sounds from being played for multiple peers in a single call/telephony conference or for a peer who is being added to a telephony conference when there are other peers there already. --- .../NotificationManager.java | 175 ++++++++++++++---- 1 file changed, 143 insertions(+), 32 deletions(-) diff --git a/src/net/java/sip/communicator/plugin/notificationwiring/NotificationManager.java b/src/net/java/sip/communicator/plugin/notificationwiring/NotificationManager.java index d2022e399..6cb0231a9 100644 --- a/src/net/java/sip/communicator/plugin/notificationwiring/NotificationManager.java +++ b/src/net/java/sip/communicator/plugin/notificationwiring/NotificationManager.java @@ -7,6 +7,7 @@ package net.java.sip.communicator.plugin.notificationwiring; import java.awt.image.*; +import java.lang.ref.*; import java.net.*; import java.util.*; import java.util.concurrent.*; @@ -493,6 +494,77 @@ private static boolean isPrivate(ChatRoom chatRoom) return false; } + /** + * Determines whether the DIALING sound notification should be + * played for a specific CallPeer. + * + * @param weakPeer the CallPeer for which it is to be determined + * whether the DIALING sound notification is to be played + * @return true if the DIALING sound notification should + * be played for the specified callPeer; otherwise, false + */ + private static boolean shouldPlayDialingSound( + WeakReference weakPeer) + { + CallPeer peer = weakPeer.get(); + + if (peer == null) + return false; + + Call call = peer.getCall(); + + if (call == null) + return false; + + CallConference conference = call.getConference(); + + if (conference == null) + return false; + + boolean play = false; + + for (Call aCall : conference.getCalls()) + { + Iterator peerIter = aCall.getCallPeers(); + + while (peerIter.hasNext()) + { + CallPeer aPeer = peerIter.next(); + + /* + * The peer is still in a call/telephony conference so the + * DIALING sound may need to be played. + */ + if (peer == aPeer) + play = true; + + CallPeerState state = peer.getState(); + + if (CallPeerState.INITIATING_CALL.equals(state) + || CallPeerState.CONNECTING.equals(state)) + { + /* + * The DIALING sound should be played for the first CallPeer + * only. + */ + if (peer != aPeer) + return false; + } + else + { + /* + * The DIALING sound should not be played if there is a + * CallPeer which does not require the DIALING sound to be + * played. + */ + return false; + } + } + } + + return play; + } + /** * Stops all sounds for the given event type. * @@ -525,15 +597,20 @@ public static void stopSound(NotificationData data) /** * Implements CallListener.callEnded. Stops sounds that are playing at * the moment if there're any. - * @param event the CallEvent + * + * @param ev the CallEvent */ - public void callEnded(CallEvent event) + public void callEnded(CallEvent ev) { try { // Stop all telephony related sounds. // stopAllTelephonySounds(); - stopSound(callNotifications.get(event.getSourceCall())); + NotificationData notification + = callNotifications.get(ev.getSourceCall()); + + if (notification != null) + stopSound(notification); // Play the hangup sound. fireNotification(HANG_UP); @@ -846,7 +923,7 @@ public void incomingCallReceived(CallEvent ev) { try { - final Call call = ev.getSourceCall(); + Call call = ev.getSourceCall(); CallPeer peer = call.getCallPeers().next(); Map peerInfo = new HashMap(); String peerName = peer.getDisplayName(); @@ -856,6 +933,14 @@ public void incomingCallReceived(CallEvent ev) peerInfo.put("caller.name", peerName); peerInfo.put("caller.id", peer.getPeerID()); + /* + * The loopCondition will stay with the notification sound until the + * latter is stopped. If by any chance the sound fails to stop by + * the time the call is no longer referenced, do try to stop it + * then. That's why the loopCondition will weakly reference the + * call. + */ + final WeakReference weakCall = new WeakReference(call); NotificationData notification = fireNotification( INCOMING_CALL, @@ -869,6 +954,11 @@ public void incomingCallReceived(CallEvent ev) { public Boolean call() { + Call call = weakCall.get(); + + if (call == null) + return false; + /* * INCOMING_CALL should be played for a Call * only while there is a CallPeer in the @@ -1254,7 +1344,7 @@ public void peerStateChanged(CallPeerChangeEvent ev) { try { - final CallPeer peer = ev.getSourceCallPeer(); + CallPeer peer = ev.getSourceCallPeer(); Call call = peer.getCall(); CallPeerState newState = (CallPeerState) ev.getNewValue(); CallPeerState oldState = (CallPeerState) ev.getOldValue(); @@ -1264,29 +1354,40 @@ public void peerStateChanged(CallPeerChangeEvent ev) if ((newState == CallPeerState.INITIATING_CALL) || (newState == CallPeerState.CONNECTING)) { - NotificationData notification - = fireNotification( - DIALING, - new Callable() - { - public Boolean call() - { - CallPeerState state = peer.getState(); + /* + * The loopCondition will stay with the notification sound until + * the latter is stopped. If by any chance the sound fails to + * stop by the time the peer is no longer referenced, do try to + * stop it then. That's why the loopCondition will weakly + * reference the peer. + */ + final WeakReference weakPeer + = new WeakReference(peer); - return - CallPeerState.INITIATING_CALL.equals( - state) - || CallPeerState.CONNECTING.equals( - state); - } - }); + /* We want to play the dialing once for multiple CallPeers. */ + if (shouldPlayDialingSound(weakPeer)) + { + NotificationData notification + = fireNotification( + DIALING, + new Callable() + { + public Boolean call() + { + return shouldPlayDialingSound(weakPeer); + } + }); - if (notification != null) - callNotifications.put(call, notification); + if (notification != null) + callNotifications.put(call, notification); + } } else { - stopSound(callNotifications.get(call)); + NotificationData notification = callNotifications.get(call); + + if (notification != null) + stopSound(notification); } if (newState == CallPeerState.ALERTING_REMOTE_SIDE @@ -1295,6 +1396,8 @@ public Boolean call() //need to fire a notification here. && oldState != CallPeerState.CONNECTING_WITH_EARLY_MEDIA) { + final WeakReference weakPeer + = new WeakReference(peer); NotificationData notification = fireNotification( OUTGOING_CALL, @@ -1302,9 +1405,13 @@ public Boolean call() { public Boolean call() { + CallPeer peer = weakPeer.get(); + return - CallPeerState.ALERTING_REMOTE_SIDE - .equals(peer.getState()); + (peer != null) + && CallPeerState + .ALERTING_REMOTE_SIDE + .equals(peer.getState()); } }); @@ -1316,6 +1423,8 @@ else if (newState == CallPeerState.BUSY) // We start the busy sound only if we're in a simple call. if (!isConference(call)) { + final WeakReference weakPeer + = new WeakReference(peer); NotificationData notification = fireNotification( BUSY_CALL, @@ -1323,9 +1432,12 @@ else if (newState == CallPeerState.BUSY) { public Boolean call() { + CallPeer peer = weakPeer.get(); + return - CallPeerState.BUSY.equals( - peer.getState()); + (peer != null) + && CallPeerState.BUSY.equals( + peer.getState()); } }); @@ -1444,13 +1556,12 @@ private void registerDefaultNotifications() false, true, false)); // Register dial notifications. - SoundNotificationAction dialSoundHandler - = new SoundNotificationAction( - SoundProperties.DIALING, -1, false, true, false); - notificationService.registerDefaultNotificationForEvent( DIALING, - dialSoundHandler); + new SoundNotificationAction( + SoundProperties.DIALING, + -1, + false, true, false)); // Register the hangup sound notification. notificationService.registerDefaultNotificationForEvent(