aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallManager.java110
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java227
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java7
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallRenderer.java7
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java60
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java51
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java2
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/UIVideoHandler.java444
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java9
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java163
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java132
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceMemberPanel.java6
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java23
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java140
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java3
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java2
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java2
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java16
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java26
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java20
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java19
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java28
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java50
-rw-r--r--src/net/java/sip/communicator/service/neomedia/MediaStream.java8
-rw-r--r--src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java11
-rw-r--r--src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java2
-rw-r--r--src/net/java/sip/communicator/service/protocol/AbstractConferenceMember.java43
-rw-r--r--src/net/java/sip/communicator/service/protocol/ConferenceMember.java11
-rw-r--r--src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java45
-rw-r--r--src/net/java/sip/communicator/service/protocol/event/VisualComponentResolveEvent.java79
-rw-r--r--src/net/java/sip/communicator/service/protocol/event/VisualComponentResolveListener.java29
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java80
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java109
-rw-r--r--src/net/java/sip/communicator/util/swing/VideoContainer.java10
-rw-r--r--src/net/java/sip/communicator/util/swing/VideoLayout.java26
35 files changed, 1411 insertions, 589 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java b/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
index c9d9244..9c90765 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
@@ -1222,6 +1222,116 @@ public class CallManager
}
/**
+ * Determines whether two specific addresses refer to one and the same
+ * peer/resource/contact.
+ * <p>
+ * <b>Warning</b>: Use the functionality sparingly because it assumes that
+ * an unspecified service is equal to any service.
+ * </p>
+ *
+ * @param a one of the addresses to be compared
+ * @param b the other address to be compared to <tt>a</tt>
+ * @return <tt>true</tt> if <tt>a</tt> and <tt>b</tt> name one and the same
+ * peer/resource/contact; <tt>false</tt>, otherwise
+ */
+ public static boolean addressesAreEqual(String a, String b)
+ {
+ if (a.equals(b))
+ return true;
+
+ int aProtocolIndex = a.indexOf(':');
+ if(aProtocolIndex > -1)
+ a = a.substring(aProtocolIndex + 1);
+
+ int bProtocolIndex = b.indexOf(':');
+ if(bProtocolIndex > -1)
+ b = b.substring(bProtocolIndex + 1);
+
+ if (a.equals(b))
+ return true;
+
+ int aServiceBegin = a.indexOf('@');
+ String aUserID;
+ String aService;
+
+ if (aServiceBegin > -1)
+ {
+ aUserID = a.substring(0, aServiceBegin);
+
+ int slashIndex = a.indexOf("/");
+ if (slashIndex > 0)
+ aService = a.substring(aServiceBegin + 1, slashIndex);
+ else
+ aService = a.substring(aServiceBegin + 1);
+ }
+ else
+ {
+ aUserID = a;
+ aService = null;
+ }
+
+ int bServiceBegin = b.indexOf('@');
+ String bUserID;
+ String bService;
+
+ if (bServiceBegin > -1)
+ {
+ bUserID = b.substring(0, bServiceBegin);
+ int slashIndex = b.indexOf("/");
+
+ if (slashIndex > 0)
+ bService = b.substring(bServiceBegin + 1, slashIndex);
+ else
+ bService = b.substring(bServiceBegin + 1);
+ }
+ else
+ {
+ bUserID = b;
+ bService = null;
+ }
+
+ boolean userIDsAreEqual;
+
+ if ((aUserID == null) || (aUserID.length() < 1))
+ userIDsAreEqual = ((bUserID == null) || (bUserID.length() < 1));
+ else
+ userIDsAreEqual = aUserID.equals(bUserID);
+ if (!userIDsAreEqual)
+ return false;
+
+ boolean servicesAreEqual;
+
+ /*
+ * It's probably a veeery long shot but it's assumed here that an
+ * unspecified service is equal to any service. Such a case is, for
+ * example, RegistrarLess SIP.
+ */
+ if (((aService == null) || (aService.length() < 1))
+ || ((bService == null) || (bService.length() < 1)))
+ servicesAreEqual = true;
+ else
+ servicesAreEqual = aService.equals(bService);
+
+ return servicesAreEqual;
+ }
+
+ /**
+ * Indicates if the given <tt>ConferenceMember</tt> corresponds to the local
+ * user.
+ *
+ * @param conferenceMember the conference member to check
+ */
+ public static boolean isLocalUser(ConferenceMember conferenceMember)
+ {
+ String localUserAddress
+ = conferenceMember.getConferenceFocusCallPeer()
+ .getProtocolProvider().getAccountID().getAccountAddress();
+
+ return CallManager.addressesAreEqual(
+ conferenceMember.getAddress(), localUserAddress);
+ }
+
+ /**
* Adds a missed call notification.
*
* @param peerName the name of the peer
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
index ed0c8e4..84ed128 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
@@ -270,11 +270,6 @@ public class CallPanel
= new Vector<CallTitleListener>();
/**
- * Indicates if the video interface is enabled.
- */
- private boolean isVideoInterfaceEnabled = false;
-
- /**
* Creates an empty constructor allowing to extend this panel.
*/
public CallPanel() {}
@@ -292,6 +287,24 @@ public class CallPanel
this.call = call;
this.callWindow = callWindow;
+ holdButton = new HoldButton(call);
+ recordButton = new RecordButton(call);
+ videoButton = new LocalVideoButton(call);
+ showHideVideoButton = new ShowHideVideoButton(call);
+ desktopSharingButton = new DesktopSharingButton(call);
+ transferCallButton = new TransferCallButton(call);
+ fullScreenButton = new FullScreenButton(this);
+ chatButton = new SIPCommButton(
+ ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
+ ImageLoader.getImage(ImageLoader.CHAT_BUTTON_SMALL_WHITE));
+ localLevel = new InputVolumeControlButton(
+ call,
+ ImageLoader.MICROPHONE,
+ ImageLoader.MUTE_BUTTON,
+ false, true, false);
+ remoteLevel = new OutputVolumeControlButton(
+ ImageLoader.VOLUME_CONTROL_BUTTON, false, true);
+
this.callDurationTimer = new Timer(1000, new CallTimerListener());
this.callDurationTimer.setRepeats(true);
@@ -304,12 +317,7 @@ public class CallPanel
if (isLastConference)
{
- if (CallManager.isVideoStreaming(call))
- callPanel = new VideoConferenceCallPanel(
- CallPanel.this, call);
- else
- callPanel = new ConferenceCallPanel(
- CallPanel.this, call);
+ enableConferenceInterface(CallManager.isVideoStreaming(call));
}
else
{
@@ -347,10 +355,6 @@ public class CallPanel
hangupButton = new SIPCommButton(
ImageLoader.getImage(ImageLoader.HANGUP_BUTTON_BG));
- holdButton = new HoldButton(call);
- recordButton = new RecordButton(call);
- videoButton = new LocalVideoButton(call);
- showHideVideoButton = new ShowHideVideoButton(call);
holdButton.setIndex(2);
recordButton.setIndex(3);
videoButton.setIndex(11);
@@ -381,29 +385,16 @@ public class CallPanel
}
});
- desktopSharingButton = new DesktopSharingButton(call);
- transferCallButton = new TransferCallButton(call);
- fullScreenButton = new FullScreenButton(this);
desktopSharingButton.setIndex(8);
transferCallButton.setIndex(5);
fullScreenButton.setIndex(10);
- chatButton = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.CHAT_BUTTON_SMALL_WHITE));
chatButton.setName(CHAT_BUTTON);
chatButton.setToolTipText(
GuiActivator.getResources().getI18NString("service.gui.CHAT"));
chatButton.addActionListener(this);
chatButton.setIndex(19);
- localLevel = new InputVolumeControlButton(
- call,
- ImageLoader.MICROPHONE,
- ImageLoader.MUTE_BUTTON,
- false, true, false);
- remoteLevel = new OutputVolumeControlButton(
- ImageLoader.VOLUME_CONTROL_BUTTON, false, true);
localLevel.setIndex(6);
remoteLevel.setIndex(7);
@@ -819,13 +810,15 @@ public class CallPanel
= call.getProtocolProvider();
if (protocolProvider.getOperationSet(
- OperationSetTelephonyConferencing.class) != null)
+ OperationSetTelephonyConferencing.class) != null
+ && conferenceButton != null)
{
conferenceButton.setEnabled(enable);
}
if (protocolProvider.getOperationSet(OperationSetVideoTelephony.class)
- != null)
+ != null
+ && videoButton != null)
{
videoButton.setEnabled(enable);
}
@@ -843,13 +836,17 @@ public class CallPanel
if (protocolProvider.getOperationSet(
OperationSetAdvancedTelephony.class)
- != null)
+ != null
+ && transferCallButton != null)
{
transferCallButton.setEnabled(enable);
}
if (protocolProvider.getOperationSet(
- OperationSetVideoTelephony.class) != null)
+ OperationSetVideoTelephony.class) != null
+ && fullScreenButton != null
+ && videoButton != null
+ && desktopSharingButton != null)
{
fullScreenButton.setEnabled(enable);
videoButton.setEnabled(enable);
@@ -878,8 +875,26 @@ public class CallPanel
{
if (isLastConference)
{
- ((ConferenceCallPanel) callPanel)
- .addCallPeerPanel(callPeer);
+ if (CallManager.isVideoStreaming(call))
+ {
+ if (!(callPanel instanceof VideoConferenceCallPanel))
+ {
+ enableConferenceInterface(true);
+ }
+ else
+ ((VideoConferenceCallPanel) callPanel)
+ .addCallPeerPanel(callPeer);
+ }
+ else
+ {
+ if(callPanel instanceof VideoConferenceCallPanel)
+ {
+ enableConferenceInterface(false);
+ }
+ else
+ ((ConferenceCallPanel) callPanel)
+ .addCallPeerPanel(callPeer);
+ }
}
else
{
@@ -889,18 +904,8 @@ public class CallPanel
// conference.
if (isLastConference)
{
- remove(callPanel);
-
- ConferenceCallPanel callPanel;
- if (CallManager.isVideoStreaming(call))
- callPanel = new VideoConferenceCallPanel(
- CallPanel.this, call);
- else
- callPanel = new ConferenceCallPanel(
- CallPanel.this, call);
-
- updateCurrentCallPanel(callPanel);
- add(callPanel, BorderLayout.CENTER);
+ enableConferenceInterface(
+ CallManager.isVideoStreaming(call));
}
// We're still in one-to-one call and we receive the
// remote peer.
@@ -958,29 +963,19 @@ public class CallPanel
{
public void run()
{
- if (!isLastConference)
- {
- isLastConference = isConference();
-
- // We've been in one-to-one call and we're now in a
- // conference.
- if (isLastConference)
- {
- removeOneToOneSpecificComponents();
- remove(callPanel);
-
- ConferenceCallPanel callPanel;
- if (CallManager.isVideoStreaming(call))
- callPanel = new VideoConferenceCallPanel(
- CallPanel.this, call);
- else
- callPanel = new ConferenceCallPanel(
- CallPanel.this, call);
-
- updateCurrentCallPanel(callPanel);
- add(callPanel, BorderLayout.CENTER);
- }
- }
+// if (!isLastConference)
+// {
+// isLastConference = isConference();
+//
+// // We've been in one-to-one call and we're now in a
+// // conference.
+// if (isLastConference)
+// {
+// removeOneToOneSpecificComponents();
+// enableConferenceInterface(
+// CallManager.isVideoStreaming(call));
+// }
+// }
refreshContainer();
}
@@ -1161,12 +1156,8 @@ public class CallPanel
CallRenderer callRenderer
= (CallRenderer) callPanel;
- CallPeerRenderer currentPeerRenderer
- = callRenderer
- .getCallPeerRenderer(singlePeer);
-
UIVideoHandler videoHandler
- = currentPeerRenderer.getVideoHandler();
+ = callRenderer.getVideoHandler();
// If we have already a video handler, try to
// initiate the new UI with the current video
@@ -1326,10 +1317,6 @@ public class CallPanel
if (callPanel instanceof OneToOneCallPanel)
{
- // If we have been in a video conference interface
- if (isVideoInterfaceEnabled)
- isVideoInterfaceEnabled = false;
-
removeConferenceSpecificComponents();
addOneToOneSpecificComponents();
}
@@ -1343,48 +1330,46 @@ public class CallPanel
/**
* Enables or disables the video conference interface.
*
- * @param enable <tt>true</tt> to enable conference interface,
+ * @param isVideo <tt>true</tt> to enable conference interface,
* <tt>false</tt> to disable it
*/
- public void enableVideoConferenceInterface(final boolean enable)
+ public void enableConferenceInterface(final boolean isVideo)
{
- isVideoInterfaceEnabled = enable;
-
- SwingUtilities.invokeLater(new Runnable()
+ if (!SwingUtilities.isEventDispatchThread())
{
- public void run()
+ SwingUtilities.invokeLater(new Runnable()
{
- // We've been in one-to-one call and we're now in a
- // conference.
- if (enable)
- {
- remove(callPanel);
- updateCurrentCallPanel(new VideoConferenceCallPanel(
- CallPanel.this, call));
- add(callPanel, BorderLayout.CENTER);
- }
- else
+ public void run()
{
- remove(callPanel);
- updateCurrentCallPanel(new ConferenceCallPanel(
- CallPanel.this, call));
- add(callPanel, BorderLayout.CENTER);
+ enableConferenceInterface(isVideo);
}
+ });
+ return;
+ }
- refreshContainer();
- }
- });
- }
+ UIVideoHandler videoHandler = null;
+ if (callPanel != null)
+ videoHandler = ((CallRenderer) callPanel).getVideoHandler();
- /**
- * Indicates if the conference interface is enabled.
- *
- * @return <tt>true</tt> if the conference interface is enabled, otherwise
- * returns <tt>false</tt>
- */
- public boolean isVideoConferenceInterfaceEnabled()
- {
- return isVideoInterfaceEnabled;
+ if (callPanel != null)
+ remove(callPanel);
+
+ // We've been in one-to-one call and we're now in a
+ // conference.
+ if (isVideo)
+ {
+ updateCurrentCallPanel(new VideoConferenceCallPanel(
+ CallPanel.this, call, videoHandler));
+ }
+ else
+ {
+ updateCurrentCallPanel(new ConferenceCallPanel(
+ CallPanel.this, call, videoHandler, false));
+ }
+
+ add(callPanel, BorderLayout.CENTER);
+
+ refreshContainer();
}
/**
@@ -1393,22 +1378,28 @@ public class CallPanel
private void removeOneToOneSpecificComponents()
{
// Disable desktop sharing.
- if (desktopSharingButton.isSelected())
+ if (desktopSharingButton != null && desktopSharingButton.isSelected())
desktopSharingButton.doClick();
// Disable full screen.
- if (fullScreenButton.isSelected())
+ if (fullScreenButton != null && fullScreenButton.isSelected())
fullScreenButton.doClick();
- settingsPanel.remove(videoButton);
- settingsPanel.remove(showHideVideoButton);
+ if (videoButton != null)
+ settingsPanel.remove(videoButton);
+
+ if (showHideVideoButton != null)
+ settingsPanel.remove(showHideVideoButton);
if(resizeVideoButton != null)
settingsPanel.remove(resizeVideoButton);
- settingsPanel.remove(desktopSharingButton);
- settingsPanel.remove(transferCallButton);
- settingsPanel.remove(fullScreenButton);
+ if (desktopSharingButton != null)
+ {
+ settingsPanel.remove(desktopSharingButton);
+ settingsPanel.remove(transferCallButton);
+ settingsPanel.remove(fullScreenButton);
+ }
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java
index 14188b3..044d49c 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRenderer.java
@@ -163,13 +163,6 @@ public interface CallPeerRenderer
public boolean isLocalVideoVisible();
/**
- * Returns the video handler associated with this call peer renderer.
- *
- * @return the video handler associated with this call peer renderer
- */
- public UIVideoHandler getVideoHandler();
-
- /**
* Shows/hides the security panel.
*
* @param isVisible <tt>true</tt> to show the security panel, <tt>false</tt>
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallRenderer.java b/src/net/java/sip/communicator/impl/gui/main/call/CallRenderer.java
index 55dd0f5..133efe3 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallRenderer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallRenderer.java
@@ -81,4 +81,11 @@ public interface CallRenderer
*/
public void conferenceMemberRemoved(CallPeer callPeer,
ConferenceMember conferenceMember);
+
+ /**
+ * Returns the video handler associated with this call peer renderer.
+ *
+ * @return the video handler associated with this call peer renderer
+ */
+ public UIVideoHandler getVideoHandler();
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
index 60d0bf5..8a4796b 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
@@ -93,6 +93,8 @@ public class OneToOneCallPanel
*/
private JPanel southPanel;
+ private final UIVideoHandler videoHandler;
+
/**
* Creates a call panel for the corresponding call, by specifying the
* call type (incoming or outgoing) and the parent dialog.
@@ -127,9 +129,18 @@ public class OneToOneCallPanel
this.call = call;
this.callPeer = callPeer;
+ if (videoHandler == null)
+ this.videoHandler = new UIVideoHandler(this, videoContainers);
+ else
+ {
+ this.videoHandler = videoHandler;
+ videoHandler.setVideoContainersList(videoContainers);
+ videoHandler.setCallRenderer(this);
+ }
+
this.setTransferHandler(new CallTransferHandler(call));
- this.addCallPeerPanel(callPeer, videoHandler);
+ this.addCallPeerPanel(callPeer);
this.setPreferredSize(new Dimension(400, 400));
}
@@ -139,15 +150,14 @@ public class OneToOneCallPanel
*
* @param peer the call peer
*/
- public void addCallPeerPanel(CallPeer peer, UIVideoHandler videoHandler)
+ public void addCallPeerPanel(CallPeer peer)
{
if (peerPanel == null)
{
- if (videoHandler != null)
- peerPanel = new OneToOneCallPeerPanel(
- this, peer, videoContainers, videoHandler);
- else
- peerPanel = new OneToOneCallPeerPanel(
+ videoHandler.addVideoListener(callPeer);
+ videoHandler.addRemoteControlListener(callPeer);
+
+ peerPanel = new OneToOneCallPeerPanel(
this, peer, videoContainers);
/* Create the main Components of the UI. */
@@ -180,16 +190,6 @@ public class OneToOneCallPanel
}
/**
- * Creates and adds a panel for a call peer.
- *
- * @param peer the call peer
- */
- public void addCallPeerPanel(CallPeer peer)
- {
- addCallPeerPanel(peer, null);
- }
-
- /**
* Enters full screen mode. Initializes all components for the full screen
* user interface.
*/
@@ -630,7 +630,21 @@ public class OneToOneCallPanel
* @param conferenceMember the member that was added
*/
public void conferenceMemberAdded(CallPeer callPeer,
- ConferenceMember conferenceMember) {}
+ ConferenceMember conferenceMember)
+ {
+ // We don't want to add the local member to the list of members.
+ if (CallManager.isLocalUser(conferenceMember))
+ return;
+
+ if (CallManager.addressesAreEqual(
+ conferenceMember.getAddress(), callPeer.getAddress()))
+ {
+ return;
+ }
+
+ getCallContainer().enableConferenceInterface(
+ CallManager.isVideoStreaming(call));
+ }
/**
* Indicates that the given conference member has been removed from the
@@ -641,4 +655,14 @@ public class OneToOneCallPanel
*/
public void conferenceMemberRemoved(CallPeer callPeer,
ConferenceMember conferenceMember) {}
+
+ /**
+ * Returns the video handler associated with this call peer renderer.
+ *
+ * @return the video handler associated with this call peer renderer
+ */
+ public UIVideoHandler getVideoHandler()
+ {
+ return videoHandler;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
index 2501f0d..a1bfc7c 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
@@ -163,20 +163,16 @@ public class OneToOneCallPeerPanel
*/
private final JLabel photoLabel;
- private final UIVideoHandler videoHandler;
-
/**
* Creates a <tt>CallPeerPanel</tt> for the given call peer.
*
* @param callRenderer the renderer of the call
* @param callPeer the <tt>CallPeer</tt> represented in this panel
* @param videoContainers the video <tt>Container</tt> list
- * @param vHandler the <tt>UIVideoHandler</tt>
*/
public OneToOneCallPeerPanel( CallRenderer callRenderer,
CallPeer callPeer,
- List<Container> videoContainers,
- UIVideoHandler vHandler)
+ List<Container> videoContainers)
{
this.callRenderer = callRenderer;
this.callPeer = callPeer;
@@ -184,18 +180,6 @@ public class OneToOneCallPeerPanel
this.videoContainers = videoContainers;
this.securityPanel = SecurityPanel.create(this, callPeer, null);
- if (vHandler == null)
- videoHandler
- = new UIVideoHandler(callRenderer, videoContainers);
- else
- {
- videoHandler = vHandler;
- videoHandler.setVideoContainersList(videoContainers);
- }
-
- videoHandler.addVideoListener(callPeer);
- videoHandler.addRemoteControlListener(callPeer);
-
photoLabel = new JLabel(getPhotoLabelIcon());
center = createCenter(videoContainers);
statusBar = createStatusBar();
@@ -242,20 +226,6 @@ public class OneToOneCallPeerPanel
}
/**
- * Creates a <tt>CallPeerPanel</tt> for the given call peer.
- *
- * @param callRenderer the renderer of the call
- * @param callPeer the <tt>CallPeer</tt> represented in this panel
- * @param videoContainers the video <tt>Container</tt> list
- */
- public OneToOneCallPeerPanel( CallRenderer callRenderer,
- CallPeer callPeer,
- List<Container> videoContainers)
- {
- this(callRenderer, callPeer, videoContainers, null);
- }
-
- /**
* Creates the <code>Component</code> hierarchy of the central area of this
* <code>CallPeerPanel</code> which displays the photo of the
* <code>CallPeer</code> or the video if any.
@@ -295,7 +265,8 @@ public class OneToOneCallPeerPanel
photoLabels.remove(photoLabel);
}
if (changed)
- videoHandler.handleVideoEvent(callPeer, null);
+ callRenderer.getVideoHandler()
+ .handleVideoEvent(callPeer.getCall(), null);
}
}
}
@@ -327,7 +298,7 @@ public class OneToOneCallPeerPanel
if (oldParent != null)
oldParent.remove(noVideoComponent);
- return new VideoContainer(noVideoComponent);
+ return new VideoContainer(noVideoComponent, false);
}
/**
@@ -898,7 +869,7 @@ public class OneToOneCallPeerPanel
*/
public void setLocalVideoVisible(boolean isVisible)
{
- videoHandler.setLocalVideoVisible(isVisible);
+ callRenderer.getVideoHandler().setLocalVideoVisible(isVisible);
}
/**
@@ -909,7 +880,7 @@ public class OneToOneCallPeerPanel
*/
public boolean isLocalVideoVisible()
{
- return videoHandler.isLocalVideoVisible();
+ return callRenderer.getVideoHandler().isLocalVideoVisible();
}
/**
@@ -933,16 +904,6 @@ public class OneToOneCallPeerPanel
}
/**
- * Returns the video handler associated with this call peer renderer.
- *
- * @return the video handler associated with this call peer renderer
- */
- public UIVideoHandler getVideoHandler()
- {
- return videoHandler;
- }
-
- /**
* Initializes the security status label, shown in the call status bar.
*/
private void initSecurityStatusLabel()
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java b/src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java
index ad657c2..961fdd3 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java
@@ -278,7 +278,7 @@ public class SelectScreenDialog
*/
private static JComponent createVideoContainer(Component noVideoComponent)
{
- return new VideoContainer(noVideoComponent);
+ return new VideoContainer(noVideoComponent, false);
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/UIVideoHandler.java b/src/net/java/sip/communicator/impl/gui/main/call/UIVideoHandler.java
index 71c38b4..3bd9caa 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/UIVideoHandler.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/UIVideoHandler.java
@@ -14,6 +14,7 @@ import java.util.List;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
+import net.java.sip.communicator.impl.gui.main.call.conference.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
@@ -58,6 +59,9 @@ public class UIVideoHandler
private final LocalVideoMouseListener localVideoListener
= new LocalVideoMouseListener();
+ /**
+ * Indicates if the local video is visible.
+ */
private boolean localVideoVisible = true;
/**
@@ -69,7 +73,7 @@ public class UIVideoHandler
/**
* The renderer of the call.
*/
- private final CallRenderer callRenderer;
+ private CallRenderer callRenderer;
/**
* The close local video button.
@@ -82,19 +86,24 @@ public class UIVideoHandler
private List<Container> videoContainers;
/**
- * The video telephony listener.
+ * The operation set through which we do all video operations.
*/
- private VideoTelephonyListener videoTelephonyListener;
+ private OperationSetVideoTelephony videoTelephony;
/**
- * The operation set through which we do all video operations.
+ * A map of peer, video toolbar pair.
*/
- private OperationSetVideoTelephony videoTelephony;
+ private final Map<CallPeer, Component> peerToolbars;
/**
- * A list of peer, video tool bar pair.
+ * A map of conference member, video toolbar component.
*/
- private final Map<CallPeer, Component> videoToolbars;
+ private final Map<ConferenceMember, Component> memberToolbars;
+
+ /**
+ * A map of conference member, visual component.
+ */
+ private final Map<ConferenceMember, Component> memberVisualComponents;
/**
* The local video tool bar.
@@ -117,7 +126,10 @@ public class UIVideoHandler
{
this.callRenderer = callRenderer;
this.videoContainers = videoContainers;
- this.videoToolbars = new Hashtable<CallPeer, Component>();
+ this.peerToolbars = new Hashtable<CallPeer, Component>();
+ this.memberToolbars = new Hashtable<ConferenceMember, Component>();
+ this.memberVisualComponents
+ = new Hashtable<ConferenceMember, Component>();
}
/**
@@ -144,11 +156,46 @@ public class UIVideoHandler
public void setVideoContainersList(List<Container> videoContainers)
{
this.videoContainers = videoContainers;
+
+ localVideoToolbar = null;
+ peerToolbars.clear();
+ memberToolbars.clear();
+ }
+
+ public void setCallRenderer(CallRenderer callRenderer)
+ {
+ this.callRenderer = callRenderer;
}
public void addVideoToolbar(CallPeer callPeer, Component videoToolbar)
{
- videoToolbars.put(callPeer, videoToolbar);
+ Component peerToolbar = peerToolbars.get(callPeer);
+
+ if (peerToolbar == null)
+ {
+ peerToolbars.put(callPeer, videoToolbar);
+ }
+ }
+
+ public void addVideoToolbar(ConferenceMember conferenceMember,
+ Component videoToolbar)
+ {
+ Component peerToolbar = memberToolbars.get(conferenceMember);
+
+ if (peerToolbar == null)
+ {
+ memberToolbars.put(conferenceMember, videoToolbar);
+ }
+ }
+
+ public void removeVideoToolbar(CallPeer callPeer)
+ {
+ peerToolbars.remove(callPeer);
+ }
+
+ public void removeVideoToolbar(ConferenceMember conferenceMember)
+ {
+ memberToolbars.remove(conferenceMember);
}
public void setLocalVideoToolbar(Component videoToolbar)
@@ -178,7 +225,8 @@ public class UIVideoHandler
if (telephony == null)
return null;
- videoTelephonyListener = new VideoTelephonyListener(callPeer);
+ final VideoTelephonyListener videoTelephonyListener
+ = new VideoTelephonyListener(callPeer);
/**
* The video is only available while the #callPeer is in a Call
@@ -192,6 +240,9 @@ public class UIVideoHandler
telephony.addVideoListener(
callPeer, videoTelephonyListener);
+ telephony.addVisualComponentResolveListener(
+ callPeer, videoTelephonyListener);
+
if (!isLocalVideoListenerAdded)
{
telephony.addPropertyChangeListener(
@@ -204,7 +255,7 @@ public class UIVideoHandler
{
videoTelephony = telephony;
- handleVideoEvent(callPeer, null);
+ handleVideoEvent(call, null);
handleLocalVideoStreamingChange(
callPeer, videoTelephonyListener);
@@ -245,7 +296,8 @@ public class UIVideoHandler
if (callPeer.equals(event.getSourceCallPeer()))
{
if (callPeer.getCall() != null)
- removeVideoListener(event.getSourceCallPeer());
+ removeVideoListener(event.getSourceCallPeer(),
+ videoTelephonyListener);
}
}
@@ -269,7 +321,7 @@ public class UIVideoHandler
if (CallState.CALL_ENDED.equals(newCallState))
{
- removeVideoListener(callPeer);
+ removeVideoListener(callPeer, videoTelephonyListener);
call.removeCallChangeListener(this);
if(allowRemoteControl)
@@ -294,7 +346,9 @@ public class UIVideoHandler
/**
* Removes the video listener
*/
- public void removeVideoListener(CallPeer callPeer)
+ public void removeVideoListener(
+ CallPeer callPeer,
+ VideoTelephonyListener videoTelephonyListener)
{
final Call call = callPeer.getCall();
if (call == null)
@@ -312,6 +366,9 @@ public class UIVideoHandler
telephony.removeVideoListener(
callPeer, videoTelephonyListener);
+ telephony.removeVisualComponentResolveListener(
+ callPeer, videoTelephonyListener);
+
if (!CallManager.isVideoStreaming(call) && isLocalVideoListenerAdded)
{
telephony.removePropertyChangeListener(
@@ -340,11 +397,19 @@ public class UIVideoHandler
Container videoContainer
= videoContainers.get(videoContainerCount - 1);
- handleVideoEvent(callPeer, null, videoContainer);
+ handleVideoEvent(callPeer.getCall(), null, videoContainer);
}
}
- videoToolbars.remove(callPeer);
+ peerToolbars.remove(callPeer);
+
+ if (memberToolbars != null)
+ {
+ for (ConferenceMember member : callPeer.getConferenceMembers())
+ {
+ memberToolbars.remove(member);
+ }
+ }
callRenderer.exitFullScreen();
}
@@ -356,7 +421,8 @@ public class UIVideoHandler
*/
private class VideoTelephonyListener
implements PropertyChangeListener,
- VideoListener
+ VideoListener,
+ VisualComponentResolveListener
{
private final CallPeer callPeer;
@@ -440,12 +506,12 @@ public class UIVideoHandler
CallPanel callContainer = callRenderer.getCallContainer();
if (callContainer.isConference()
- && !callContainer.isVideoConferenceInterfaceEnabled())
+ && !(callRenderer instanceof VideoConferenceCallPanel))
{
- callContainer.enableVideoConferenceInterface(true);
+ callContainer.enableConferenceInterface(true);
}
- handleVideoEvent(callPeer, event);
+ handleVideoEvent(callPeer.getCall(), event);
}
/**
@@ -457,12 +523,12 @@ public class UIVideoHandler
if (callContainer.isConference()
&& callPeer.getCall() != null
&& !CallManager.isVideoStreaming(callPeer.getCall())
- && callContainer.isVideoConferenceInterfaceEnabled())
+ && (callRenderer instanceof VideoConferenceCallPanel))
{
- callContainer.enableVideoConferenceInterface(false);
+ callContainer.enableConferenceInterface(false);
}
- handleVideoEvent(callPeer, event);
+ handleVideoEvent(callPeer.getCall(), event);
}
/**
@@ -470,7 +536,31 @@ public class UIVideoHandler
*/
public void videoUpdate(VideoEvent event)
{
- handleVideoEvent(callPeer, event);
+ handleVideoEvent(callPeer.getCall(), event);
+ }
+
+ /**
+ * Notifies that a visual <tt>Component</tt> representing video has been
+ * resolved to be corresponding to a given <tt>ConferenceMember</tt>.
+ *
+ * @param event a <tt>VisualComponentResolveEvent</tt> describing the
+ * resolved component and the corresponding <tt>ConferenceMember</tt>
+ */
+ public void visualComponentResolved(VisualComponentResolveEvent event)
+ {
+ ConferenceMember confMember = event.getConferenceMember();
+ CallPeer focusCallPeer = confMember.getConferenceFocusCallPeer();
+
+ // If the member is already added in the call we refresh the
+ // the video container, otherwise it will be refreshed when added.
+ if ((CallManager.addressesAreEqual( confMember.getAddress(),
+ focusCallPeer.getAddress())
+ && peerToolbars.containsKey(focusCallPeer))
+ || memberToolbars.containsKey(event.getConferenceMember()))
+ {
+ handleVideoEvent(
+ confMember.getConferenceFocusCallPeer().getCall(), null);
+ }
}
}
@@ -482,7 +572,7 @@ public class UIVideoHandler
* <tt>Component</tt> representing video and the provider it was added into
* or <tt>null</tt> if such information is not available
*/
- public void handleVideoEvent( final CallPeer callPeer,
+ public void handleVideoEvent( final Call call,
final VideoEvent event)
{
if (event != null && logger.isTraceEnabled())
@@ -545,7 +635,7 @@ public class UIVideoHandler
{
public void run()
{
- handleVideoEvent(callPeer, event);
+ handleVideoEvent(call, event);
}
});
return;
@@ -561,7 +651,7 @@ public class UIVideoHandler
Container videoContainer
= videoContainers.get(videoContainerCount - 1);
- handleVideoEvent(callPeer, event, videoContainer);
+ handleVideoEvent(call, event, videoContainer);
}
}
}
@@ -571,6 +661,7 @@ public class UIVideoHandler
* <tt>Component</tt> depicting video knowing that it is to be displayed or
* is already displayed in a specific <tt>Container</tt>.
*
+ * @param call the call, for which the video event is handled
* @param videoEvent the <tt>VideoEvent</tt> describing the visual
* <tt>Component</tt> which was added, removed or updated
* @param videoContainer the <tt>Container</tt> which is to contain or
@@ -578,9 +669,9 @@ public class UIVideoHandler
* <tt>videoEvent</tt>
*/
private void handleVideoEvent(
- CallPeer callPeer,
- VideoEvent videoEvent,
- Container videoContainer)
+ final Call call,
+ final VideoEvent videoEvent,
+ final Container videoContainer)
{
if (videoEvent != null)
{
@@ -638,6 +729,9 @@ public class UIVideoHandler
videoContainer.removeAll();
+ // Remove all previously added member visual components.
+ memberVisualComponents.clear();
+
// REMOTE
/*
* UIVideoHandlers share a single VideoContainer in a Call i.e. there is
@@ -645,7 +739,6 @@ public class UIVideoHandler
* the videos of a single CallPeer, each UIVideoHandler adds all videos
* of a Call.
*/
- Call call = callPeer.getCall();
Iterator<? extends CallPeer> callPeerIter = call.getCallPeers();
List<Component> remoteVideos = new LinkedList<Component>();
@@ -656,79 +749,135 @@ public class UIVideoHandler
List<Component> visualComponents
= videoTelephony.getVisualComponents(peer);
- Component videoToolbar = videoToolbars.get(peer);
-
- if (videoToolbar != null)
- {
- Container toolbarParent = videoToolbar.getParent();
-
- if (toolbarParent != null)
- toolbarParent.remove(videoToolbar);
- }
-
+ boolean peerVisualComponentAdded = false;
if (visualComponents != null && visualComponents.size() > 0)
{
+ callRenderer.getCallContainer()
+ .addRemoteVideoSpecificComponents(peer);
+
for (int i = 0; i < visualComponents.size(); i++)
{
Component visualComponent = visualComponents.get(i);
-
- if (videoToolbar != null
- && callRenderer.getCallContainer()
- .isVideoConferenceInterfaceEnabled())
+
+ // Remove visual component parent if it exists.
+ Container remoteVideoParent
+ = visualComponent.getParent();
+
+ if (remoteVideoParent != null)
+ remoteVideoParent.remove(visualComponent);
+
+ // Get conference member toolbar if the visual component
+ // does not correspond to the peer.
+ ConferenceMember conferenceMember = videoTelephony
+ .getConferenceMember(peer, visualComponent);
+
+ Component peerToolbar = null;
+
+ if (callRenderer instanceof VideoConferenceCallPanel)
+ {
+ if (call.isConferenceFocus()
+ || (conferenceMember == null
+ && peer.isConferenceFocus())
+ || (conferenceMember != null
+ && CallManager.addressesAreEqual(
+ conferenceMember.getAddress(),
+ peer.getAddress())))
+ {
+ peerToolbar = peerToolbars.get(peer);
+ peerVisualComponentAdded = true;
+ }
+ else if (conferenceMember != null)
+ {
+ peerToolbar = memberToolbars.get(conferenceMember);
+ memberVisualComponents.put(
+ conferenceMember, visualComponent);
+ }
+ else
+ {
+ peerToolbar = createDefaultVideoToolbar(peer);
+ }
+ }
+
+ // Add the corresponding components to the remote videos.
+ if (peerToolbar != null)
{
- Container remoteVideoParent
- = visualComponent.getParent();
+ Container toolbarParent = peerToolbar.getParent();
- if (remoteVideoParent != null)
- remoteVideoParent.remove(visualComponent);
+ if (toolbarParent != null)
+ toolbarParent.remove(peerToolbar);
JPanel remoteVideoPanel
= new TransparentPanel(new BorderLayout());
remoteVideoPanel.add(visualComponent);
- remoteVideoPanel.add(videoToolbar, BorderLayout.SOUTH);
+ remoteVideoPanel
+ .add(peerToolbar, BorderLayout.SOUTH);
remoteVideos.add(remoteVideoPanel);
}
else
remoteVideos.add(visualComponent);
}
+
+ if (callRenderer instanceof VideoConferenceCallPanel)
+ {
+ if (!peerVisualComponentAdded)
+ {
+ remoteVideos.add(createDefaultPhotoPanel(
+ peer,
+ peerToolbars.get(peer)));
+ }
+
+ for (ConferenceMember member : peer.getConferenceMembers())
+ {
+ if (memberVisualComponents.get(member) == null)
+ {
+ Component defaultPhotoPanel = null;
+ if (!CallManager.isLocalUser(member)
+ && !CallManager.addressesAreEqual(
+ member.getAddress(), peer.getAddress())
+ && memberToolbars.get(member) != null)
+ {
+ defaultPhotoPanel = createDefaultPhotoPanel(
+ member,
+ memberToolbars.get(member));
+ }
+
+ if (defaultPhotoPanel != null)
+ remoteVideos.add(defaultPhotoPanel);
+ }
+ }
+ }
}
- else if (videoToolbar != null && callRenderer.getCallContainer()
- .isVideoConferenceInterfaceEnabled())
+ else if (callRenderer instanceof VideoConferenceCallPanel)
{
- Component defaultPhotoPanel
- = createDefaultPhotoPanel(callPeer, videoToolbar);
+ remoteVideos.add(
+ createDefaultPhotoPanel(peer, peerToolbars.get(peer)));
- remoteVideos.add(defaultPhotoPanel);
+ for (ConferenceMember member : peer.getConferenceMembers())
+ {
+ if (!CallManager.isLocalUser(member)
+ && !CallManager.addressesAreEqual(
+ member.getAddress(), peer.getAddress()))
+ {
+ remoteVideos.add(createDefaultPhotoPanel(
+ member,
+ memberToolbars.get(member)));
+ }
+ }
}
}
if (remoteVideos.isEmpty())
{
- callRenderer
- .getCallContainer()
- .removeRemoteVideoSpecificComponents();
+ callRenderer.getCallContainer()
+ .removeRemoteVideoSpecificComponents();
}
else
{
for (Component remoteVideo : remoteVideos)
{
- Container remoteVideoParent = remoteVideo.getParent();
-
- if (remoteVideoParent != null)
- {
- remoteVideoParent.remove(remoteVideo);
- Container parent = remoteVideoParent.getParent();
-
- if (parent != null)
- parent.remove(remoteVideoParent);
- }
-
videoContainer.add(
remoteVideo, VideoLayout.CENTER_REMOTE, 0);
}
-
- callRenderer.getCallContainer().addRemoteVideoSpecificComponents(
- callPeer);
}
// LOCAL
@@ -753,13 +902,13 @@ public class UIVideoHandler
if (localVideoVisible)
{
- if (localVideoToolbar != null && callRenderer.getCallContainer()
- .isVideoConferenceInterfaceEnabled())
+ if (localVideoToolbar != null
+ && (callRenderer instanceof VideoConferenceCallPanel))
{
JPanel localVideoPanel
= new TransparentPanel(new BorderLayout());
- localVideoPanel.add(localVideo);
+ localVideoPanel.add(localVideo, BorderLayout.CENTER);
localVideoPanel.add(localVideoToolbar, BorderLayout.SOUTH);
videoContainer.add(localVideoPanel, VideoLayout.LOCAL, 0);
@@ -776,6 +925,13 @@ public class UIVideoHandler
}
}
}
+ else if ((callRenderer instanceof VideoConferenceCallPanel)
+ && localVideoToolbar != null)
+ {
+ videoContainer.add(createDefaultPhotoPanel(
+ call.getProtocolProvider(), localVideoToolbar),
+ VideoLayout.LOCAL, 0);
+ }
videoContainer.validate();
@@ -1486,4 +1642,142 @@ public class UIVideoHandler
return defaultPanel;
}
+
+ /**
+ * Creates the default photo panel.
+ *
+ * @param callPeer the corresponding call peer
+ * @param videoToolbar the corresponding video tool bar
+ * @return
+ */
+ private Component createDefaultPhotoPanel(
+ ConferenceMember conferenceMember,
+ Component videoToolbar)
+ {
+ JPanel defaultPanel = new TransparentPanel(new BorderLayout());
+
+ JPanel photoPanel = new TransparentPanel(new BorderLayout())
+ {
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void paintComponent(Graphics g)
+ {
+ super.paintComponent(g);
+
+ g = g.create();
+
+ try
+ {
+ AntialiasingManager.activateAntialiasing(g);
+
+ g.setColor(Color.GRAY);
+ g.fillRoundRect(
+ 0, 0, this.getWidth(), this.getHeight(), 6, 6);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+ };
+
+ JLabel photoLabel = new JLabel(new ImageIcon(
+ ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO)));
+ photoPanel.add(photoLabel);
+ photoPanel.setPreferredSize(new Dimension(320, 240));
+
+ defaultPanel.add(photoPanel, BorderLayout.CENTER);
+ defaultPanel.add(videoToolbar, BorderLayout.SOUTH);
+
+ return defaultPanel;
+ }
+
+ /**
+ * Creates the default photo panel.
+ *
+ * @param callPeer the corresponding call peer
+ * @param videoToolbar the corresponding video tool bar
+ * @return
+ */
+ private Component createDefaultPhotoPanel( ProtocolProviderService pps,
+ Component videoToolbar)
+ {
+ JPanel defaultPanel = new TransparentPanel(new BorderLayout());
+
+ JPanel photoPanel
+ = new TransparentPanel(new FlowLayout(FlowLayout.CENTER))
+ {
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void paintComponent(Graphics g)
+ {
+ super.paintComponent(g);
+
+ g = g.create();
+
+ try
+ {
+ AntialiasingManager.activateAntialiasing(g);
+
+ g.setColor(Color.GRAY);
+ g.fillRoundRect(
+ 0, 0, this.getWidth(), this.getHeight(), 6, 6);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+ };
+
+ JLabel photoLabel = new JLabel();
+
+ final OperationSetServerStoredAccountInfo accountInfoOpSet
+ = pps.getOperationSet(
+ OperationSetServerStoredAccountInfo.class);
+
+ if (accountInfoOpSet != null)
+ {
+ byte[] accountImage
+ = AccountInfoUtils.getImage(accountInfoOpSet);
+
+ // do not set empty images
+ if ((accountImage != null)
+ && (accountImage.length > 0))
+ {
+ photoLabel.setIcon(new ImageIcon(accountImage));
+ }
+ }
+
+ if (photoLabel.getIcon() == null)
+ {
+ photoLabel.setIcon(new ImageIcon(
+ ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO)));
+ }
+
+ photoPanel.add(photoLabel);
+ photoLabel.setPreferredSize(new Dimension(320, 240));
+
+ defaultPanel.add(photoPanel, BorderLayout.CENTER);
+ defaultPanel.add(localVideoToolbar, BorderLayout.SOUTH);
+
+ return defaultPanel;
+ }
+
+ private Component createDefaultVideoToolbar(CallPeer callPeer)
+ {
+ ConferencePeerPanel peerPanel
+ = new ConferencePeerPanel( (ConferenceCallPanel)callRenderer,
+ callRenderer.getCallContainer(),
+ callPeer,
+ true);
+
+ peerPanel.setPeerName(peerPanel.getParticipantName() + " unresolved");
+
+ return peerPanel;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java
index c4ce446..2f0f3d2 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/BasicConferenceParticipantPanel.java
@@ -291,6 +291,15 @@ public abstract class BasicConferenceParticipantPanel
}
/**
+ * Sets the name of the participant.
+ * @param participantName the name of the participant
+ */
+ public String getParticipantName()
+ {
+ return nameLabel.getText();
+ }
+
+ /**
* Sets the state of the participant.
* @param participantState the state of the participant
*/
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java
index afa4123..9d6d042 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java
@@ -7,7 +7,6 @@
package net.java.sip.communicator.impl.gui.main.call.conference;
import java.awt.*;
-import java.awt.event.*;
import java.util.*;
import java.util.List;
@@ -56,6 +55,11 @@ public class ConferenceCallPanel
private JScrollPane scrollPane;
/**
+ * Video handler for the conference call.
+ */
+ private UIVideoHandler videoHandler;
+
+ /**
* The panel which contains ConferencePeerPanels.
*/
private final TransparentPanel mainPanel;
@@ -119,7 +123,25 @@ public class ConferenceCallPanel
* @param callPanel the call panel which contains this panel
* @param c the conference call object
*/
- public ConferenceCallPanel(CallPanel callPanel, Call c, boolean isVideo)
+ public ConferenceCallPanel( CallPanel callPanel,
+ Call c,
+ boolean isVideo)
+ {
+ this(callPanel, c, null, isVideo);
+ }
+
+ /**
+ * Creates an instance of <tt>ConferenceCallPanel</tt>.
+ *
+ * @param callPanel the call panel which contains this panel
+ * @param c the conference call object
+ * @param videoHandler the UI video handler
+ * @param isVideo indicates if this is used as a video conference renderer
+ */
+ public ConferenceCallPanel( CallPanel callPanel,
+ Call c,
+ UIVideoHandler videoHandler,
+ boolean isVideo)
{
super(new GridBagLayout());
@@ -128,6 +150,15 @@ public class ConferenceCallPanel
mainPanel = new TransparentPanel();
+ if (videoHandler == null)
+ this.videoHandler = new UIVideoHandler(this, videoContainers);
+ else
+ {
+ this.videoHandler = videoHandler;
+ videoHandler.setVideoContainersList(videoContainers);
+ videoHandler.setCallRenderer(this);
+ }
+
// If we're in a video view we have nothing more to do here.
if (isVideo)
return;
@@ -155,8 +186,6 @@ public class ConferenceCallPanel
mainPanel.setTransferHandler(new CallTransferHandler(call));
- addVideoContainer();
-
/*
* XXX Call addCallPeerPanel(CallPeer) after calling addVideoContainer()
* because the video may already be flowing between the CallPeers.
@@ -185,113 +214,6 @@ public class ConferenceCallPanel
}
/**
- * Initializes a new <tt>VideoContainer</tt> instance which is to contain
- * the visual/video <tt>Component</tt>s of {@link #call}.
- */
- protected void addVideoContainer()
- {
- final VideoContainer videoContainer = new VideoContainer(null);
-
- videoContainer.setPreferredSize(new Dimension(0, 0));
-
- GridBagConstraints videoContainerGridBagConstraints
- = new GridBagConstraints();
-
- videoContainerGridBagConstraints.fill = GridBagConstraints.BOTH;
- videoContainerGridBagConstraints.gridx = 0;
- videoContainerGridBagConstraints.gridy = 0;
- videoContainerGridBagConstraints.weightx = 0;
- videoContainerGridBagConstraints.weighty = 1;
- add(videoContainer, videoContainerGridBagConstraints);
- /*
- * When the videoContainer is empty i.e. it has nothing to show, don't
- * show it.
- */
- videoContainer.addContainerListener(
- new ContainerListener()
- {
- public void componentAdded(ContainerEvent e)
- {
- GridBagLayout layout = (GridBagLayout) getLayout();
- boolean videoContainerIsVisible
- = (videoContainer.getComponentCount() > 0);
-
- for (Component component : getComponents())
- {
- GridBagConstraints constraints
- = layout.getConstraints(component);
-
- if (videoContainerIsVisible)
- {
- constraints.weightx
- = (component == videoContainer) ? 1 : 0;
- scrollPane.setPreferredSize(
- SCROLL_PANE_PREFERRED_SIZE_IF_VIDEO);
- }
- else
- {
- constraints.weightx
- = (component == videoContainer) ? 0 : 1;
-
- if (SCROLL_PANE_PREFERRED_SIZE_IF_VIDEO.equals(
- scrollPane.getPreferredSize()))
- scrollPane.setPreferredSize(null);
- }
- layout.setConstraints(component, constraints);
- }
-
- /*
- * When the first visual/video Component gets added, this
- * videoContainer is still not accommodated by the frame
- * size because it has just become visible. So try to resize
- * the frame to accommodate this videoContainer.
- */
- if (e.getID() == ContainerEvent.COMPONENT_ADDED)
- {
- Component component = e.getComponent();
- Dimension preferredSize = component.getPreferredSize();
-
- if ((preferredSize != null)
- && (preferredSize.width > 0)
- && (preferredSize.height > 0))
- {
- ensureSize(
- component,
- preferredSize.width, preferredSize.height);
- }
- else
- {
- /*
- * XXX The method ensureSize is supposed to know
- * that it should not apply the specified size to
- * the videoContainer.
- */
- int s
- = Math.max(
- SCROLL_PANE_PREFERRED_SIZE_IF_VIDEO
- .width,
- SCROLL_PANE_PREFERRED_SIZE_IF_VIDEO
- .height);
-
- ensureSize(videoContainer, s, s);
- }
- }
- }
-
- public void componentRemoved(ContainerEvent e)
- {
- /*
- * It's all the same with respect to the purpose of this
- * ContainerListener.
- */
- componentAdded(e);
- }
- });
-
- videoContainers.add(videoContainer);
- }
-
- /**
* Returns the vertical <tt>JScrollBar</tt>.
*
* @return the vertical <tt>JScrollBar</tt>
@@ -348,16 +270,13 @@ public class ConferenceCallPanel
ConferenceCallPeerRenderer confPeerRenderer;
- UIVideoHandler videoHandler
- = new UIVideoHandler(this, videoContainers);
-
videoHandler.addVideoListener(peer);
videoHandler.addRemoteControlListener(peer);
if (peer.getConferenceMemberCount() > 0)
{
confPeerRenderer = new ConferenceFocusPanel(
- this, callPanel, peer, videoHandler);
+ this, callPanel, peer);
peer.addConferenceMembersSoundLevelListener(confPeerRenderer.
getConferenceMembersSoundLevelListener());
peer.addStreamSoundLevelListener(confPeerRenderer.
@@ -367,7 +286,7 @@ public class ConferenceCallPanel
{
confPeerRenderer
= new ConferencePeerPanel(
- this, callPanel, peer, videoHandler, false);
+ this, callPanel, peer, false);
//peer.addConferenceMembersSoundLevelListener(
// confPeerRenderer.getConferenceMembersSoundLevelListener());
@@ -414,7 +333,7 @@ public class ConferenceCallPanel
if (confPeerRenderer == null)
return;
- confPeerRenderer.getVideoHandler().removeRemoteControlListener(peer);
+ getVideoHandler().removeRemoteControlListener(peer);
// first remove the listeners as after removing the panel
// we may still receive sound level indicators and there are
@@ -837,4 +756,14 @@ public class ConferenceCallPanel
addCallPeerPanel(callPeer);
}
}
+
+ /**
+ * Returns the video handler associated with this call peer renderer.
+ *
+ * @return the video handler associated with this call peer renderer
+ */
+ public UIVideoHandler getVideoHandler()
+ {
+ return videoHandler;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java
index 4d69092..c50b83c 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java
@@ -67,11 +67,6 @@ public class ConferenceFocusPanel
private ConferencePeerPanel focusPeerPanel;
/**
- * The video handler for this peer.
- */
- private UIVideoHandler videoHandler;
-
- /**
* Creates an instance of <tt>ConferenceFocusPanel</tt> by specifying the
* parent call renderer, the call panel and the peer represented by this
* conference focus panel.
@@ -83,13 +78,11 @@ public class ConferenceFocusPanel
*/
public ConferenceFocusPanel(ConferenceCallPanel callRenderer,
CallPanel callPanel,
- CallPeer callPeer,
- UIVideoHandler videoHandler)
+ CallPeer callPeer)
{
this.focusPeer = callPeer;
this.callRenderer = callRenderer;
this.callPanel = callPanel;
- this.videoHandler = videoHandler;
this.setLayout(new GridBagLayout());
@@ -109,7 +102,7 @@ public class ConferenceFocusPanel
{
focusPeerPanel
= new ConferencePeerPanel(
- callRenderer, callPanel, focusPeer, videoHandler, false);
+ callRenderer, callPanel, focusPeer, false);
GridBagConstraints constraints = new GridBagConstraints();
@@ -133,18 +126,12 @@ public class ConferenceFocusPanel
*/
public void addConferenceMemberPanel(ConferenceMember member)
{
- String localUserAddress
- = focusPeer.getProtocolProvider().getAccountID().
- getAccountAddress();
-
- boolean isLocalMember
- = addressesAreEqual(member.getAddress(), localUserAddress);
-
// We don't want to add the local member to the list of members.
- if (isLocalMember)
+ if (CallManager.isLocalUser(member))
return;
- if (addressesAreEqual(member.getAddress(), focusPeer.getAddress()))
+ if (CallManager.addressesAreEqual(
+ member.getAddress(), focusPeer.getAddress()))
return;
// It's already there.
@@ -152,7 +139,7 @@ public class ConferenceFocusPanel
return;
ConferenceMemberPanel memberPanel
- = new ConferenceMemberPanel(callRenderer, member);
+ = new ConferenceMemberPanel(callRenderer, member, false);
member.addPropertyChangeListener(memberPanel);
@@ -190,7 +177,8 @@ public class ConferenceFocusPanel
this.remove(memberPanel);
conferenceMembersPanels.remove(member);
- if (!addressesAreEqual(member.getAddress(), focusPeer.getAddress()))
+ if (!CallManager.addressesAreEqual(
+ member.getAddress(), focusPeer.getAddress()))
member.removePropertyChangeListener(
(ConferenceMemberPanel) memberPanel);
@@ -488,100 +476,6 @@ public class ConferenceFocusPanel
}
/**
- * Determines whether two specific addresses refer to one and the same
- * peer/resource/contact.
- * <p>
- * <b>Warning</b>: Use the functionality sparingly because it assumes that
- * an unspecified service is equal to any service.
- * </p>
- *
- * @param a one of the addresses to be compared
- * @param b the other address to be compared to <tt>a</tt>
- * @return <tt>true</tt> if <tt>a</tt> and <tt>b</tt> name one and the same
- * peer/resource/contact; <tt>false</tt>, otherwise
- */
- private static boolean addressesAreEqual(String a, String b)
- {
- if (a.equals(b))
- return true;
-
- int aProtocolIndex = a.indexOf(':');
- if(aProtocolIndex > -1)
- a = a.substring(aProtocolIndex + 1);
-
- int bProtocolIndex = b.indexOf(':');
- if(bProtocolIndex > -1)
- b = b.substring(bProtocolIndex + 1);
-
- if (a.equals(b))
- return true;
-
- int aServiceBegin = a.indexOf('@');
- String aUserID;
- String aService;
-
- if (aServiceBegin > -1)
- {
- aUserID = a.substring(0, aServiceBegin);
-
- int slashIndex = a.indexOf("/");
- if (slashIndex > 0)
- aService = a.substring(aServiceBegin + 1, slashIndex);
- else
- aService = a.substring(aServiceBegin + 1);
- }
- else
- {
- aUserID = a;
- aService = null;
- }
-
- int bServiceBegin = b.indexOf('@');
- String bUserID;
- String bService;
-
- if (bServiceBegin > -1)
- {
- bUserID = b.substring(0, bServiceBegin);
- int slashIndex = b.indexOf("/");
-
- if (slashIndex > 0)
- bService = b.substring(bServiceBegin + 1, slashIndex);
- else
- bService = b.substring(bServiceBegin + 1);
- }
- else
- {
- bUserID = b;
- bService = null;
- }
-
- boolean userIDsAreEqual;
-
- if ((aUserID == null) || (aUserID.length() < 1))
- userIDsAreEqual = ((bUserID == null) || (bUserID.length() < 1));
- else
- userIDsAreEqual = aUserID.equals(bUserID);
- if (!userIDsAreEqual)
- return false;
-
- boolean servicesAreEqual;
-
- /*
- * It's probably a veeery long shot but it's assumed here that an
- * unspecified service is equal to any service. Such a case is, for
- * example, RegistrarLess SIP.
- */
- if (((aService == null) || (aService.length() < 1))
- || ((bService == null) || (bService.length() < 1)))
- servicesAreEqual = true;
- else
- servicesAreEqual = aService.equals(bService);
-
- return servicesAreEqual;
- }
-
- /**
* Returns the listener instance and created if needed.
* @return the conferenceMembersSoundLevelListener
*/
@@ -619,16 +513,6 @@ public class ConferenceFocusPanel
}
/**
- * Returns the video handler associated with this call peer renderer.
- *
- * @return the video handler associated with this call peer renderer
- */
- public UIVideoHandler getVideoHandler()
- {
- return videoHandler;
- }
-
- /**
* Updates according sound level indicators to reflect the new member sound
* level.
*/
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceMemberPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceMemberPanel.java
index 5eaa02b..3522bfa 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceMemberPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceMemberPanel.java
@@ -41,11 +41,13 @@ public class ConferenceMemberPanel
*
* @param callRenderer the parent call renderer
* @param member the <tt>ConferenceMember</tt> shown in this panel
+ * @param isVideo indicates if the video conference interface is enabled.
*/
public ConferenceMemberPanel( CallRenderer callRenderer,
- ConferenceMember member)
+ ConferenceMember member,
+ boolean isVideo)
{
- super(callRenderer, false);
+ super(callRenderer, false, isVideo);
this.member = member;
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java
index 018571b..c091ac0 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java
@@ -93,30 +93,25 @@ public class ConferencePeerPanel
private StreamSoundLevelListener streamSoundLevelListener = null;
/**
- * The video handler associated with this peer.
- */
- private UIVideoHandler videoHandler;
-
- /**
* Creates a <tt>ConferencePeerPanel</tt> by specifying the parent
* <tt>callDialog</tt>, containing it and the corresponding
* <tt>protocolProvider</tt>.
*
* @param callRenderer the renderer of the corresponding call
- * @param callPanel the call panel containing this peer panel
+ * @param callContainer the call panel containing this peer panel
* @param protocolProvider the <tt>ProtocolProviderService</tt> for the
* call
* @param isVideo indicates if the video interface is enabled
*/
public ConferencePeerPanel( ConferenceCallPanel callRenderer,
- CallPanel callPanel,
+ CallPanel callContainer,
ProtocolProviderService protocolProvider,
boolean isVideo)
{
super(callRenderer, true, isVideo);
this.callRenderer = callRenderer;
- this.callPanel = callPanel;
+ this.callPanel = callContainer;
this.callPeer = null;
// Try to set the same image as the one in the main window. This way
@@ -153,7 +148,6 @@ public class ConferencePeerPanel
public ConferencePeerPanel( ConferenceCallPanel callRenderer,
CallPanel callContainer,
CallPeer callPeer,
- UIVideoHandler videoHandler,
boolean isVideo)
{
super(callRenderer, false, isVideo);
@@ -161,7 +155,6 @@ public class ConferencePeerPanel
this.callRenderer = callRenderer;
this.callPanel = callContainer;
this.callPeer = callPeer;
- this.videoHandler = videoHandler;
this.securityPanel = SecurityPanel.create(this, callPeer, null);
@@ -581,16 +574,6 @@ public class ConferencePeerPanel
}
/**
- * Returns the video handler associated with this call peer renderer.
- *
- * @return the video handler associated with this call peer renderer
- */
- public UIVideoHandler getVideoHandler()
- {
- return videoHandler;
- }
-
- /**
* Returns <tt>CallPeer</tt> contact address.
*
* @return <tt>CallPeer</tt> contact address
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java
index 08b00db..f44bc8b 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java
@@ -22,11 +22,6 @@ public class VideoConferenceCallPanel
extends ConferenceCallPanel
{
/**
- * Handles video events and components.
- */
- private final UIVideoHandler videoHandler;
-
- /**
* The contained call.
*/
private final Call call;
@@ -38,22 +33,35 @@ public class VideoConferenceCallPanel
callPeerPanels = new Hashtable<CallPeer, ConferenceCallPeerRenderer>();
/**
+ * A mapping of a member and its renderer.
+ */
+ private final Map<ConferenceMember, ConferenceMemberPanel>
+ conferenceMembersPanels
+ = new Hashtable<ConferenceMember, ConferenceMemberPanel>();
+
+ public VideoConferenceCallPanel(CallPanel callPanel,
+ Call call)
+ {
+ this(callPanel, call, null);
+ }
+
+ /**
* Creates an instance of <tt>VideoConferenceCallPanel</tt>.
*
* @param callPanel the call panel which contains this panel
* @param call the conference call object
*/
- public VideoConferenceCallPanel(CallPanel callPanel, Call call)
+ public VideoConferenceCallPanel(CallPanel callPanel,
+ Call call,
+ UIVideoHandler videoHandler)
{
- super(callPanel, call, true);
+ super(callPanel, call, videoHandler, true);
this.call = call;
addVideoContainer();
- videoHandler = new UIVideoHandler(this, videoContainers);
-
- videoHandler.setLocalVideoToolbar(createLocalVideoToolBar());
+ getVideoHandler().setLocalVideoToolbar(createLocalVideoToolBar());
Iterator<? extends CallPeer> iterator;
@@ -64,7 +72,12 @@ public class VideoConferenceCallPanel
ConferenceCallPeerRenderer peerRenderer = createVideoToolBar(peer);
- videoHandler.addVideoToolbar(peer, peerRenderer.getComponent());
+ getVideoHandler().addVideoToolbar(peer, peerRenderer.getComponent());
+
+ for (ConferenceMember member : peer.getConferenceMembers())
+ {
+ conferenceMemberAdded(peer, member, true);
+ }
// Map the call peer to its renderer.
callPeerPanels.put(peer, peerRenderer);
@@ -77,7 +90,12 @@ public class VideoConferenceCallPanel
ConferenceCallPeerRenderer peerRenderer = createVideoToolBar(peer);
- videoHandler.addVideoToolbar(peer, peerRenderer.getComponent());
+ getVideoHandler().addVideoToolbar(peer, peerRenderer.getComponent());
+
+ for (ConferenceMember member : peer.getConferenceMembers())
+ {
+ conferenceMemberAdded(peer, member, true);
+ }
// Map the call peer to its renderer.
callPeerPanels.put(peer, peerRenderer);
@@ -118,17 +136,73 @@ public class VideoConferenceCallPanel
return callPeerPanels.get(callPeer);
}
+ public void conferenceMemberAdded( CallPeer callPeer,
+ ConferenceMember member)
+ {
+ // It's already there.
+ if (conferenceMembersPanels.containsKey(member))
+ return;
+
+ conferenceMemberAdded(callPeer, member, false);
+
+ getVideoHandler().handleVideoEvent(call, null);
+ }
+
/**
*
*/
- public void conferenceMemberAdded(CallPeer callPeer,
- ConferenceMember conferenceMember) {}
+ public void conferenceMemberAdded( CallPeer callPeer,
+ ConferenceMember member,
+ boolean isInitialAdd)
+ {
+ // We don't want to add the local member to the list of members.
+ if (CallManager.isLocalUser(member))
+ return;
+
+ if (CallManager.addressesAreEqual(
+ member.getAddress(), callPeer.getAddress()))
+ {
+ return;
+ }
+
+ // It's already there.
+ if (conferenceMembersPanels.containsKey(member))
+ return;
+
+ ConferenceMemberPanel memberVideoToolbar = createVideoToolBar(member);
+
+ member.addPropertyChangeListener(memberVideoToolbar);
+
+ getVideoHandler().addVideoToolbar(member, memberVideoToolbar);
+ conferenceMembersPanels.put(member, memberVideoToolbar);
+ }
/**
*
*/
public void conferenceMemberRemoved(CallPeer callPeer,
- ConferenceMember conferenceMember) {}
+ ConferenceMember member)
+ {
+ // We don't want to add the local member to the list of members.
+ if (CallManager.isLocalUser(member))
+ return;
+
+ if (CallManager.addressesAreEqual(
+ member.getAddress(), callPeer.getAddress()))
+ {
+ return;
+ }
+
+ getVideoHandler().removeVideoToolbar(member);
+
+ ConferenceMemberPanel memberPanel = conferenceMembersPanels.get(member);
+
+ if (memberPanel != null)
+ {
+ member.removePropertyChangeListener(memberPanel);
+ conferenceMembersPanels.remove(member);
+ }
+ }
/**
* Creates and adds a <tt>CallPeerRenderer</tt> for the given <tt>peer</tt>.
@@ -139,12 +213,14 @@ public class VideoConferenceCallPanel
{
ConferenceCallPeerRenderer peerRenderer = createVideoToolBar(peer);
- videoHandler.addVideoToolbar(peer, peerRenderer.getComponent());
+ getVideoHandler().addVideoToolbar(peer, peerRenderer.getComponent());
// Map the call peer to its renderer.
callPeerPanels.put(peer, peerRenderer);
addCallPeerPanel(peer, peerRenderer);
+
+ getVideoHandler().handleVideoEvent(call, null);
}
/**
@@ -153,11 +229,11 @@ public class VideoConferenceCallPanel
* @param peer the added peer
* @param peer the peer for which to create a renderer
*/
- private void addCallPeerPanel( CallPeer peer,
+ private void addCallPeerPanel( CallPeer peer,
ConferenceCallPeerRenderer peerRenderer)
{
- videoHandler.addVideoListener(peer);
- videoHandler.addRemoteControlListener(peer);
+ getVideoHandler().addVideoListener(peer);
+ getVideoHandler().addRemoteControlListener(peer);
if (peer.getConferenceMemberCount() > 0)
{
@@ -199,7 +275,13 @@ public class VideoConferenceCallPanel
if (confPeerRenderer == null)
return;
- confPeerRenderer.getVideoHandler().removeRemoteControlListener(peer);
+ getVideoHandler().removeRemoteControlListener(peer);
+ getVideoHandler().removeVideoToolbar(peer);
+
+ for (ConferenceMember member : peer.getConferenceMembers())
+ {
+ getVideoHandler().removeVideoToolbar(member);
+ }
// first remove the listeners as after removing the panel
// we may still receive sound level indicators and there are
@@ -247,7 +329,20 @@ public class VideoConferenceCallPanel
private ConferenceCallPeerRenderer createVideoToolBar(CallPeer callPeer)
{
return new ConferencePeerPanel(
- this, getCallContainer(), callPeer, videoHandler, true);
+ this, getCallContainer(), callPeer, true);
+ }
+
+ /**
+ * Initializes the video tool bar.
+ *
+ * @param callPeer the <tt>CallPeer</tt> for which we create a video toolbar
+ * @return the created component
+ */
+ private ConferenceMemberPanel createVideoToolBar(
+ ConferenceMember conferenceMember)
+ {
+ return new ConferenceMemberPanel(
+ this, conferenceMember, true);
}
/**
@@ -268,7 +363,8 @@ public class VideoConferenceCallPanel
return;
}
- final VideoContainer videoContainer = new VideoContainer(null);
+ final VideoContainer videoContainer
+ = new VideoContainer(new JLabel(), true);
videoContainer.setPreferredSize(new Dimension(0, 0));
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
index fe33ba7..d38df5e 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
@@ -9,7 +9,6 @@ package net.java.sip.communicator.impl.gui.main.contactlist;
import java.awt.*;
import java.awt.event.*;
-import java.awt.image.*;
import java.util.*;
import java.util.List;
@@ -572,7 +571,7 @@ public class ContactListTreeCellRenderer
if (contact instanceof ShowMoreContact)
preferredSize.height = 18;
else if (isSelected)
- preferredSize.height = 55;
+ preferredSize.height = 70;
else
preferredSize.height = 30;
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java b/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java
index 23fb8ef..f8bae04 100644
--- a/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java
+++ b/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java
@@ -839,7 +839,7 @@ public class MediaConfiguration
*/
private static JComponent createVideoContainer(Component noVideoComponent)
{
- return new VideoContainer(noVideoComponent);
+ return new VideoContainer(noVideoComponent, false);
}
/**
diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java
index 655dea5..a701474 100644
--- a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java
@@ -930,7 +930,7 @@ public class MediaServiceImpl
noPreview.setHorizontalAlignment(SwingConstants.CENTER);
noPreview.setVerticalAlignment(SwingConstants.CENTER);
- final JComponent videoContainer = new VideoContainer(noPreview);
+ final JComponent videoContainer = new VideoContainer(noPreview, false);
if ((preferredWidth > 0) && (preferredHeight > 0))
videoContainer.setPreferredSize(
diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
index de3bbf5..e48941c 100644
--- a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
@@ -783,6 +783,7 @@ public class MediaStreamImpl
}
csrcArray[csrcArray.length - 1] = getLocalSourceID();
+
this.localContributingSourceIDList = csrcArray;
}
@@ -1117,6 +1118,17 @@ public class MediaStreamImpl
}
/**
+ * Gets the synchronization source (SSRC) identifiers of the remote peers.
+ *
+ * @return the synchronization source (SSRC) identifiers of the remote peers
+ * @see MediaStream#getRemoteSourceIDs()
+ */
+ public List<Long> getRemoteSourceIDs()
+ {
+ return Collections.unmodifiableList(remoteSourceIDs);
+ }
+
+ /**
* Gets the <tt>RTPConnector</tt> through which this instance sends and
* receives RTP and RTCP traffic.
*
@@ -2097,7 +2109,7 @@ public class MediaStreamImpl
+ receiveStreamSSRC);
}
- setRemoteSourceID(receiveStreamSSRC);
+ addRemoteSourceID(receiveStreamSSRC);
synchronized (receiveStreams)
{
@@ -2279,7 +2291,7 @@ public class MediaStreamImpl
* @param remoteSourceID the SSRC identifier that this stream will be using
* in outgoing RTP packets from now on.
*/
- protected void setRemoteSourceID(long remoteSourceID)
+ protected void addRemoteSourceID(long remoteSourceID)
{
Long oldValue = getRemoteSourceID();
diff --git a/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java
index 5c1077f..ad582fc 100644
--- a/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java
@@ -640,6 +640,28 @@ public class VideoMediaStreamImpl
}
/**
+ * Gets the visual <tt>Component</tt>s rendering the <tt>ReceiveStream</tt>
+ * corresponding to the given ssrc.
+ *
+ * @param ssrc the src-id of the receive stream, which visual
+ * <tt>Component</tt> we're looking for
+ * @return the visual <tt>Component</tt> rendering the
+ * <tt>ReceiveStream</tt> corresponding to the given ssrc
+ */
+ public Component getVisualComponent(long ssrc)
+ {
+ MediaDeviceSession deviceSession = getDeviceSession();
+
+ if (deviceSession instanceof VideoMediaDeviceSession)
+ {
+ return ((VideoMediaDeviceSession) deviceSession)
+ .getVisualComponent(ssrc);
+ }
+
+ return null;
+ }
+
+ /**
* Removes a specific <tt>VideoListener</tt> from this
* <tt>VideoMediaStream</tt> in order to have to no longer receive
* notifications when visual/video <tt>Component</tt>s are being added and
@@ -968,9 +990,9 @@ public class VideoMediaStreamImpl
* @param ssrc remote SSRC
*/
@Override
- protected void setRemoteSourceID(long ssrc)
+ protected void addRemoteSourceID(long ssrc)
{
- super.setRemoteSourceID(ssrc);
+ super.addRemoteSourceID(ssrc);
((VideoMediaDeviceSession) getDeviceSession()).setRemoteSSRC(ssrc);
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java
index 8922067..64841be 100644
--- a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java
+++ b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java
@@ -1013,6 +1013,26 @@ public class MediaDeviceSession
}
/**
+ * Gets the <tt>Player</tt>s rendering the <tt>ReceiveStream</tt>
+ * corresponding to the given ssrc.
+ *
+ * @param ssrc the src-id of the receive stream, which player we're
+ * looking for
+ * @return the <tt>Player</tt>s rendering the <tt>ReceiveStream</tt>
+ * corresponding to the given ssrc
+ */
+ protected Player getPlayer(long ssrc)
+ {
+ synchronized (playbacks)
+ {
+ for (Playback playback : playbacks)
+ if (playback.receiveStream.getSSRC() == ssrc)
+ return playback.player;
+ }
+ return null;
+ }
+
+ /**
* Gets the JMF <tt>Processor</tt> which transcodes the <tt>MediaDevice</tt>
* of this instance into the format of this instance.
*
diff --git a/src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java b/src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java
index a8a9ae2..74368f2 100644
--- a/src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java
+++ b/src/net/java/sip/communicator/impl/neomedia/device/VideoMediaDeviceSession.java
@@ -856,6 +856,25 @@ public class VideoMediaDeviceSession
}
/**
+ * Gets the visual <tt>Component</tt>s rendering the <tt>ReceiveStream</tt>
+ * corresponding to the given ssrc.
+ *
+ * @param ssrc the src-id of the receive stream, which visual
+ * <tt>Component</tt> we're looking for
+ * @return the visual <tt>Component</tt> rendering the
+ * <tt>ReceiveStream</tt> corresponding to the given ssrc
+ */
+ public Component getVisualComponent(long ssrc)
+ {
+ Player player = getPlayer(ssrc);
+
+ if (player != null)
+ return player.getVisualComponent();
+
+ return null;
+ }
+
+ /**
* Gets the visual <tt>Component</tt> of a specific <tt>Player</tt> if it
* has one and ignores the failure to access it if the specified
* <tt>Player</tt> is unrealized.
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
index 2283345..6c12388 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
@@ -672,7 +672,8 @@ public class OperationSetTelephonyConferencingJabberImpl
List<EndpointPacketExtension> endpoints =
u.getChildExtensionsOfType(EndpointPacketExtension.class);
String endpointStatus = null;
- String ssrc = null;
+ String audioSsrc = null;
+ String videoSsrc = null;
if(endpoints.size() > 0)
{
@@ -694,7 +695,13 @@ public class OperationSetTelephonyConferencingJabberImpl
if(media.getType().equalsIgnoreCase(
MediaType.AUDIO.toString()))
{
- ssrc = media.getSrcID();
+ audioSsrc = media.getSrcID();
+ }
+
+ if(media.getType().equalsIgnoreCase(
+ MediaType.VIDEO.toString()))
+ {
+ videoSsrc = media.getSrcID();
}
}
}
@@ -702,13 +709,22 @@ public class OperationSetTelephonyConferencingJabberImpl
existingConferenceMember.setDisplayName(displayName);
existingConferenceMember.setEndpointStatus(endpointStatus);
- if (ssrc != null)
+ if (audioSsrc != null)
+ {
+ long newSsrc = Long.parseLong(audioSsrc);
+ if(existingConferenceMember.getAudioSsrc() != newSsrc)
+ changed = true;
+
+ existingConferenceMember.setAudioSsrc(newSsrc);
+ }
+
+ if (videoSsrc != null)
{
- long newSsrc = Long.parseLong(ssrc);
- if(existingConferenceMember.getSSRC() != newSsrc)
+ long newSsrc = Long.parseLong(videoSsrc);
+ if(existingConferenceMember.getVideoSsrc() != newSsrc)
changed = true;
- existingConferenceMember.setSSRC(newSsrc);
+ existingConferenceMember.setVideoSsrc(newSsrc);
}
if (addConferenceMember)
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java
index 41cedc1..7575135 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java
@@ -6,11 +6,14 @@
*/
package net.java.sip.communicator.impl.protocol.sip;
+import java.awt.*;
import java.io.*;
import java.text.*;
import java.util.*;
+import java.util.List;
import javax.sip.*;
+import javax.sip.Dialog;
import javax.sip.address.*;
import javax.sip.header.*;
import javax.sip.message.*;
@@ -1046,7 +1049,8 @@ public class OperationSetTelephonyConferencingSipImpl
int userChildCount = userChildList.getLength();
String displayName = null;
String endpointStatus = null;
- String ssrc = null;
+ String audioSsrc = null;
+ String videoSsrc = null;
for (int userChildIndex = 0;
userChildIndex < userChildCount;
@@ -1060,20 +1064,50 @@ public class OperationSetTelephonyConferencingSipImpl
else if (ELEMENT_ENDPOINT.equals(userChildName))
{
endpointStatus = getEndpointStatus(userChild);
- ssrc = getEndpointMediaSrcId(
- userChild,
- MediaType.AUDIO);
+ audioSsrc = getEndpointMediaSrcId(
+ userChild,
+ MediaType.AUDIO);
+ videoSsrc = getEndpointMediaSrcId(
+ userChild,
+ MediaType.VIDEO);
}
}
existingConferenceMember.setDisplayName(displayName);
existingConferenceMember.setEndpointStatus(endpointStatus);
- if (ssrc != null)
+ if (audioSsrc != null)
{
- long newSsrc = Long.parseLong(ssrc);
- if(existingConferenceMember.getSSRC() != newSsrc)
+ long newSsrc = Long.parseLong(audioSsrc);
+ if(existingConferenceMember.getAudioSsrc() != newSsrc)
changed = true;
- existingConferenceMember.setSSRC(newSsrc);
+ existingConferenceMember.setAudioSsrc(newSsrc);
+ }
+
+ if (videoSsrc != null)
+ {
+ long newSsrc = Long.parseLong(videoSsrc);
+ long currentSsrc
+ = existingConferenceMember.getVideoSsrc();
+
+ if (currentSsrc != -1 && currentSsrc == newSsrc)
+ continue;
+
+ if(existingConferenceMember.getVideoSsrc() != newSsrc)
+ changed = true;
+
+ existingConferenceMember.setVideoSsrc(newSsrc);
+
+ VideoMediaStream peerVideoStream
+ = (VideoMediaStream) callPeer.getMediaHandler()
+ .getStream(MediaType.VIDEO);
+
+ Component visualComponent
+ = peerVideoStream.getVisualComponent(newSsrc);
+
+ if (visualComponent != null)
+ callPeer.getMediaHandler()
+ .fireVisualComponentResolveEvent(
+ visualComponent, existingConferenceMember);
}
if (addConferenceMember)
diff --git a/src/net/java/sip/communicator/service/neomedia/MediaStream.java b/src/net/java/sip/communicator/service/neomedia/MediaStream.java
index bd42432..00dcc76 100644
--- a/src/net/java/sip/communicator/service/neomedia/MediaStream.java
+++ b/src/net/java/sip/communicator/service/neomedia/MediaStream.java
@@ -116,6 +116,14 @@ public interface MediaStream
public long getRemoteSourceID();
/**
+ * Gets the synchronization source (SSRC) identifiers of the remote peers.
+ *
+ * @return the synchronization source (SSRC) identifiers of the remote peers
+ * @see MediaStream#getRemoteSourceIDs()
+ */
+ public List<Long> getRemoteSourceIDs();
+
+ /**
* Returns the synchronization source (SSRC) identifier of the local
* participant or <tt>-1</tt> if that identifier is not yet known at this
* point.
diff --git a/src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java b/src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java
index 524da5b..851ac94 100644
--- a/src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java
+++ b/src/net/java/sip/communicator/service/neomedia/VideoMediaStream.java
@@ -62,6 +62,17 @@ public interface VideoMediaStream
public List<Component> getVisualComponents();
/**
+ * Gets the visual <tt>Component</tt>s rendering the <tt>ReceiveStream</tt>
+ * corresponding to the given ssrc.
+ *
+ * @param ssrc the src-id of the receive stream, which visual
+ * <tt>Component</tt> we're looking for
+ * @return the visual <tt>Component</tt> rendering the
+ * <tt>ReceiveStream</tt> corresponding to the given ssrc
+ */
+ public Component getVisualComponent(long ssrc);
+
+ /**
* Adds a specific <tt>VideoListener</tt> to this <tt>VideoMediaStream</tt>
* in order to receive notifications when visual/video <tt>Component</tt>s
* are being added and removed.
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java b/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
index 745bb91..7eb43a8 100644
--- a/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
+++ b/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
@@ -829,7 +829,7 @@ public abstract class AbstractCallPeer<T extends Call,
{
ConferenceMember mmbr = conferenceMembers.get(i);
- if (mmbr.getSSRC() == ssrc)
+ if (mmbr.getAudioSsrc() == ssrc)
return mmbr;
}
return null;
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractConferenceMember.java b/src/net/java/sip/communicator/service/protocol/AbstractConferenceMember.java
index a3a2bc6..739a03a 100644
--- a/src/net/java/sip/communicator/service/protocol/AbstractConferenceMember.java
+++ b/src/net/java/sip/communicator/service/protocol/AbstractConferenceMember.java
@@ -44,9 +44,14 @@ public class AbstractConferenceMember
private ConferenceMemberState state = ConferenceMemberState.UNKNOWN;
/**
- * The SSRC value if transmitted by the focus of the conference.
+ * The audio SSRC value if transmitted by the focus of the conference.
*/
- private long ssrc = -1;
+ private long audioSsrc = -1;
+
+ /**
+ * The video SSRC value if transmitted by the focus of the conference.
+ */
+ private long videoSsrc = -1;
/**
* Creates an instance of <tt>AbstractConferenceMember</tt> by specifying
@@ -157,20 +162,40 @@ public class AbstractConferenceMember
/**
* Returns the SSRC value associated with this participant;
*
- * @return the ssrc
+ * @return the audio ssrc id
+ */
+ public long getAudioSsrc()
+ {
+ return audioSsrc;
+ }
+
+ /**
+ * Sets the audio SSRC identifier of this member.
+ *
+ * @param ssrc the audio SSRC ID to set for this member.
+ */
+ public void setAudioSsrc(long ssrc)
+ {
+ this.audioSsrc = ssrc;
+ }
+
+ /**
+ * Returns the SSRC value associated with this participant;
+ *
+ * @return the video ssrc id
*/
- public long getSSRC()
+ public long getVideoSsrc()
{
- return ssrc;
+ return videoSsrc;
}
/**
- * Sets the SSRC identifier of this member.
+ * Sets the video SSRC identifier of this member.
*
- * @param ssrc the SSRC ID to set for this member.
+ * @param ssrc the video SSRC ID to set for this member.
*/
- public void setSSRC(long ssrc)
+ public void setVideoSsrc(long ssrc)
{
- this.ssrc = ssrc;
+ this.videoSsrc = ssrc;
}
}
diff --git a/src/net/java/sip/communicator/service/protocol/ConferenceMember.java b/src/net/java/sip/communicator/service/protocol/ConferenceMember.java
index 1550df3..1afe8f2 100644
--- a/src/net/java/sip/communicator/service/protocol/ConferenceMember.java
+++ b/src/net/java/sip/communicator/service/protocol/ConferenceMember.java
@@ -108,5 +108,14 @@ public interface ConferenceMember
* @return the ssrc associated with the RTP stream that this participant
* is transmitting or <tt>null</tt> if this value is not currently known.
*/
- public long getSSRC();
+ public long getAudioSsrc();
+
+ /**
+ * Returns the SSRC value associated with this participant or <tt>null</tt>
+ * if the value is not currently known.;
+ *
+ * @return the ssrc associated with the RTP stream that this participant
+ * is transmitting or <tt>null</tt> if this value is not currently known.
+ */
+ public long getVideoSsrc();
}
diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java b/src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java
index 6870764..a6119bd 100644
--- a/src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java
+++ b/src/net/java/sip/communicator/service/protocol/OperationSetVideoTelephony.java
@@ -12,6 +12,7 @@ import java.text.*;
import java.util.List;
import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.event.*;
/**
@@ -287,4 +288,48 @@ public interface OperationSetVideoTelephony
* @return the implemented quality control.
*/
public QualityControl getQualityControl(CallPeer peer);
+
+ /**
+ * Adds a specific <tt>VisualComponentResolveListener</tt> to this telephony
+ * in order to receive notifications when visual/video <tt>Component</tt>s
+ * are being resolved to correspond to a particular
+ * <tt>ConferenceMember</tt>.
+ *
+ * @param callPeer the <tt>CallPeer</tt>, which visual components we're
+ * listening to
+ * @param listener the <tt>VisualComponentResolveListener</tt> to be
+ * notified when visual/video <tt>Component</tt>s are being resolved to
+ * correspond to a particular <tt>ConferenceMember</tt>.
+ */
+ public void addVisualComponentResolveListener(
+ CallPeer callPeer,
+ VisualComponentResolveListener listener);
+
+ /**
+ * Removes a <tt>VisualComponentResolveListener</tt> from this video
+ * telephony operation set, which was previously added in order to receive
+ * notifications when visual/video <tt>Component</tt>s are being resolved to
+ * be corresponding to a particular <tt>ConferenceMember</tt>.
+ *
+ * @param callPeer the <tt>CallPeer</tt>, which visual components we're
+ * listening to
+ * @param listener the <tt>VisualComponentResolveListener</tt> to be
+ * removed
+ */
+ public void removeVisualComponentResolveListener(
+ CallPeer callPeer,
+ VisualComponentResolveListener listener);
+
+ /**
+ * Returns the <tt>ConferenceMember</tt> corresponding to the given
+ * <tt>visualComponent</tt>.
+ *
+ * @param peer the parent <tt>CallPeer</tt>
+ * @param visualComponent the visual <tt>Component</tt>, which corresponding
+ * <tt>ConferenceMember</tt> we're looking for
+ * @return the <tt>ConferenceMember</tt> corresponding to the given
+ * <tt>visualComponent</tt>.
+ */
+ public ConferenceMember getConferenceMember(CallPeer peer,
+ Component visualComponent);
}
diff --git a/src/net/java/sip/communicator/service/protocol/event/VisualComponentResolveEvent.java b/src/net/java/sip/communicator/service/protocol/event/VisualComponentResolveEvent.java
new file mode 100644
index 0000000..d9479fc
--- /dev/null
+++ b/src/net/java/sip/communicator/service/protocol/event/VisualComponentResolveEvent.java
@@ -0,0 +1,79 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.service.protocol.event;
+
+import java.awt.*;
+import java.util.*;
+
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * In a conference call notifies that a visual <tt>Component</tt> representing
+ * video has been resolved to be corresponding to a given
+ * <tt>ConferenceMember</tt>. The event contains information about the concerned
+ * visual component and it's corresponding member.
+ *
+ * @author Yana Stamcheva
+ */
+public class VisualComponentResolveEvent
+ extends EventObject
+{
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * The visual component that has been resolved.
+ */
+ private final ConferenceMember conferenceMember;
+
+ /**
+ * The visual <tt>Component</tt> depicting video which had its availability
+ * changed and which this <tt>VideoEvent</tt> notifies about.
+ */
+ private final Component visualComponent;
+
+ /**
+ *
+ * @param source the source of the new <tt>VideoEvent</tt> and the provider
+ * of the visual <tt>Component</tt> depicting video
+ */
+ public VisualComponentResolveEvent( Object source,
+ Component visualComponent,
+ ConferenceMember resolvedMember)
+ {
+ super(source);
+
+ this.visualComponent = visualComponent;
+ this.conferenceMember = resolvedMember;
+ }
+
+ /**
+ * Gets the visual <tt>Component</tt> depicting video which had its
+ * availability changed and which this <tt>VideoEvent</tt> notifies about.
+ *
+ * @return the visual <tt>Component</tt> depicting video which had its
+ * availability changed and which this <tt>VideoEvent</tt> notifies about
+ */
+ public Component getVisualComponent()
+ {
+ return visualComponent;
+ }
+
+ /**
+ * Gets the <tt>ConferenceMember</tt> that was resolved to be corresponding
+ * to the source visual component.
+ *
+ * @return the <tt>ConferenceMember</tt> that was resolved to be
+ * corresponding to the source visual component
+ */
+ public ConferenceMember getConferenceMember()
+ {
+ return conferenceMember;
+ }
+}
diff --git a/src/net/java/sip/communicator/service/protocol/event/VisualComponentResolveListener.java b/src/net/java/sip/communicator/service/protocol/event/VisualComponentResolveListener.java
new file mode 100644
index 0000000..c475b07
--- /dev/null
+++ b/src/net/java/sip/communicator/service/protocol/event/VisualComponentResolveListener.java
@@ -0,0 +1,29 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.service.protocol.event;
+
+import java.util.*;
+
+/**
+ * In a conference call notifies that a visual <tt>Component</tt> representing
+ * video has been resolved to be corresponding to a given
+ * <tt>ConferenceMember</tt>.
+ *
+ * @author Yana Stamcheva
+ */
+public interface VisualComponentResolveListener
+ extends EventListener
+{
+ /**
+ * Notifies that a visual <tt>Component</tt> representing video has been
+ * resolved to be corresponding to a given <tt>ConferenceMember</tt>.
+ *
+ * @param event a <tt>VisualComponentResolveEvent</tt> describing the
+ * resolved component and the corresponding <tt>ConferenceMember</tt>
+ */
+ public void visualComponentResolved(VisualComponentResolveEvent event);
+}
diff --git a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java
index 43da709..9e9074e 100644
--- a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java
+++ b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetVideoTelephony.java
@@ -13,6 +13,7 @@ import java.util.List;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.event.*;
/**
@@ -155,6 +156,41 @@ public abstract class AbstractOperationSetVideoTelephony<
}
/**
+ * Returns the <tt>ConferenceMember</tt> corresponding to the given
+ * <tt>visualComponent</tt>.
+ *
+ * @param peer the parent <tt>CallPeer</tt>
+ * @param visualComponent the visual <tt>Component</tt>, which corresponding
+ * <tt>ConferenceMember</tt> we're looking for
+ * @return the <tt>ConferenceMember</tt> corresponding to the given
+ * <tt>visualComponent</tt>.
+ */
+ @SuppressWarnings("unchecked") // work with MediaAware* in media package
+ public ConferenceMember getConferenceMember(CallPeer peer,
+ Component visualComponent)
+ {
+ VideoMediaStream peerVideoStream
+ = (VideoMediaStream) ((W)peer).getMediaHandler()
+ .getStream(MediaType.VIDEO);
+
+ if (peerVideoStream == null)
+ return null;
+
+ for (ConferenceMember member : peer.getConferenceMembers())
+ {
+ Component memberComponent = peerVideoStream
+ .getVisualComponent(member.getVideoSsrc());
+
+ if (memberComponent != null
+ && memberComponent.equals(visualComponent))
+ {
+ return member;
+ }
+ }
+ return null;
+ }
+
+ /**
* Delegates to the <tt>CallPeerMediaHandler</tt> of the specified
* <tt>CallPeer</tt> because the video is provided by it.
*
@@ -503,4 +539,48 @@ public abstract class AbstractOperationSetVideoTelephony<
delegate.videoUpdate(event);
}
}
+
+ /**
+ * Adds a specific <tt>VisualComponentResolveListener</tt> to this telephony
+ * in order to receive notifications when visual/video <tt>Component</tt>s
+ * are being resolved to correspond to a particular
+ * <tt>ConferenceMember</tt>.
+ *
+ * @param callPeer the <tt>CallPeer</tt>, which visual components we're
+ * listening to
+ * @param listener the <tt>VisualComponentResolveListener</tt> to be
+ * notified when visual/video <tt>Component</tt>s are being resolved to
+ * correspond to a particular <tt>ConferenceMember</tt>.
+ */
+ @SuppressWarnings("unchecked") // work with MediaAware* in media package
+ public void addVisualComponentResolveListener(
+ CallPeer callPeer,
+ VisualComponentResolveListener listener)
+ {
+ if (listener == null)
+ throw new NullPointerException("listener");
+
+ ((W)callPeer).getMediaHandler().addVisualComponentResolveListener(
+ listener);
+ }
+
+ /**
+ * Removes a <tt>VisualComponentResolveListener</tt> from this video
+ * telephony operation set, which was previously added in order to receive
+ * notifications when visual/video <tt>Component</tt>s are being resolved to
+ * be corresponding to a particular <tt>ConferenceMember</tt>.
+ *
+ * @param callPeer the <tt>CallPeer</tt>, which visual components we're
+ * listening to
+ * @param listener the <tt>VisualComponentResolveListener</tt> to be
+ * removed
+ */
+ @SuppressWarnings("unchecked") // work with MediaAware* in media package
+ public void removeVisualComponentResolveListener(
+ CallPeer callPeer,
+ VisualComponentResolveListener listener)
+ {
+ ((W)callPeer).getMediaHandler().removeVisualComponentResolveListener(
+ listener);
+ }
}
diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
index a38b332..3affd16 100644
--- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
+++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
@@ -17,6 +17,7 @@ import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.neomedia.event.*;
import net.java.sip.communicator.service.neomedia.format.*;
import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.event.*;
/**
@@ -184,6 +185,18 @@ public abstract class CallPeerMediaHandler
};
/**
+ * The <tt>Object</tt> to synchronize the access to
+ * {@link #localUserAudioLevelListeners}.
+ */
+ private final Object visualComponentResolveSyncRoot = new Object();
+
+ /**
+ * The list of <tt>VisualComponentResolveListener</tt>s interested in
+ * visual component resolve events.
+ */
+ private List<VisualComponentResolveListener> visualComponentResolveListeners;
+
+ /**
* The state of this instance which may be shared with multiple other
* <tt>CallPeerMediaHandler</tt>s.
*/
@@ -1474,4 +1487,100 @@ public abstract class CallPeerMediaHandler
}
}
}
+
+ /**
+ * Adds a specific <tt>VisualComponentResolveListener</tt> to this telephony
+ * in order to receive notifications when visual/video <tt>Component</tt>s
+ * are being resolved to correspond to a particular
+ * <tt>ConferenceMember</tt>.
+ *
+ * @param listener the <tt>VisualComponentResolveListener</tt> to be
+ * notified when visual/video <tt>Component</tt>s are being resolved to
+ * correspond to a particular <tt>ConferenceMember</tt>.
+ */
+ public void addVisualComponentResolveListener(
+ VisualComponentResolveListener listener)
+ {
+ if (listener == null)
+ throw new NullPointerException("listener");
+
+ synchronized (visualComponentResolveSyncRoot)
+ {
+ if ((visualComponentResolveListeners == null)
+ || visualComponentResolveListeners.isEmpty())
+ {
+ visualComponentResolveListeners
+ = new ArrayList<VisualComponentResolveListener>();
+ }
+
+ visualComponentResolveListeners.add(listener);
+ }
+ }
+
+ /**
+ * Removes a <tt>VisualComponentResolveListener</tt> from this video
+ * telephony operation set, which was previously added in order to receive
+ * notifications when visual/video <tt>Component</tt>s are being resolved to
+ * be corresponding to a particular <tt>ConferenceMember</tt>.
+ *
+ * @param listener the <tt>VisualComponentResolveListener</tt> to be
+ * removed
+ */
+ public void removeVisualComponentResolveListener(
+ VisualComponentResolveListener listener)
+ {
+ synchronized (visualComponentResolveSyncRoot)
+ {
+ if ((visualComponentResolveListeners != null)
+ && !visualComponentResolveListeners.isEmpty())
+ {
+ visualComponentResolveListeners.remove(listener);
+ }
+ }
+ }
+
+ /**
+ * Notifies all registered <tt>VisualComponentResolveListener</tt> that a
+ * visual <tt>Component</tt> has been resolved.
+ *
+ * @param visualComponent the visual <tt>Component</tt> that has been
+ * resolved
+ * @param conferenceMember the resolved <tt>ConferenceMember</tt>
+ */
+ public void fireVisualComponentResolveEvent(
+ Component visualComponent,
+ ConferenceMember conferenceMember)
+ {
+ List<VisualComponentResolveListener> visualComponentResolveListeners;
+
+ synchronized (visualComponentResolveSyncRoot)
+ {
+ /*
+ * Since the localUserAudioLevelListeners field of this
+ * MediaAwareCall is implemented as a copy-on-write storage, just
+ * get a reference to it and it should be safe to iterate over it
+ * without ConcurrentModificationExceptions.
+ */
+ visualComponentResolveListeners
+ = this.visualComponentResolveListeners;
+ }
+
+ if (visualComponentResolveListeners != null)
+ {
+ /*
+ * Iterate over localUserAudioLevelListeners using an index rather
+ * than an Iterator in order to try to reduce the number of
+ * allocations (as the number of audio level changes is expected to
+ * be very large).
+ */
+ int visualComponentResolveListenerCount
+ = visualComponentResolveListeners.size();
+
+ for(int i = 0; i < visualComponentResolveListenerCount; i++)
+ visualComponentResolveListeners.get(i).visualComponentResolved(
+ new VisualComponentResolveEvent(this,
+ visualComponent,
+ conferenceMember));
+ }
+ }
}
diff --git a/src/net/java/sip/communicator/util/swing/VideoContainer.java b/src/net/java/sip/communicator/util/swing/VideoContainer.java
index 164cc3d..aed90a1 100644
--- a/src/net/java/sip/communicator/util/swing/VideoContainer.java
+++ b/src/net/java/sip/communicator/util/swing/VideoContainer.java
@@ -72,10 +72,12 @@ public class VideoContainer
*
* @param noVideoComponent the component to be displayed when no remote
* video is available
+ * @param isConference indicates if this <tt>VideoLayout</tt> is dedicated
+ * to a conference interface.
*/
- public VideoContainer(Component noVideoComponent)
+ public VideoContainer(Component noVideoComponent, boolean isConference)
{
- setLayout(new VideoLayout());
+ setLayout(new VideoLayout(isConference));
this.noVideoComponent = noVideoComponent;
@@ -162,7 +164,9 @@ public class VideoContainer
{
if (VideoLayout.CENTER_REMOTE.equals(constraints)
&& (noVideoComponent != null)
- && !noVideoComponent.equals(comp))
+ && !noVideoComponent.equals(comp)
+ || (comp.equals(noVideoComponent)
+ && noVideoComponent.getParent() != null))
{
remove(noVideoComponent);
validate();
diff --git a/src/net/java/sip/communicator/util/swing/VideoLayout.java b/src/net/java/sip/communicator/util/swing/VideoLayout.java
index 714d0f9..fb7ba7c 100644
--- a/src/net/java/sip/communicator/util/swing/VideoLayout.java
+++ b/src/net/java/sip/communicator/util/swing/VideoLayout.java
@@ -83,6 +83,26 @@ public class VideoLayout extends FitLayout
private float remoteAlignmentX = Component.CENTER_ALIGNMENT;
/**
+ * Indicates if this <tt>VideoLayout</tt> is dedicated to a conference
+ * interface.
+ */
+ private final boolean isConference;
+
+ /**
+ * Creates an instance of <tt>VideoLayout</tt> by also indicating if this
+ * video layout is dedicated to a conference interface.
+ *
+ * @param isConference indicates if this <tt>VideoLayout</tt> is dedicated
+ * to a conference interface.
+ */
+ public VideoLayout(boolean isConference)
+ {
+ super();
+
+ this.isConference = isConference;
+ }
+
+ /**
* Adds the given component in this layout on the specified by name
* position.
*
@@ -216,7 +236,7 @@ public class VideoLayout extends FitLayout
Dimension parentSize = parent.getSize();
parentSize.width -= remoteCount*10;
- if (remoteCount == 1)
+ if (remoteCount == 1 && !isConference)
{
super.layoutContainer(parent,
(local == null)
@@ -266,7 +286,7 @@ public class VideoLayout extends FitLayout
* If the local visual/video Component is not displayed as if it is
* a remote one, it will be placed on top of a remote one.
*/
- if (!remotes.contains(local))
+ if (!remotes.contains(local) && !isConference)
{
Component remote0 = remotes.isEmpty() ? null : remotes.get(0);
int localX;
@@ -421,8 +441,6 @@ public class VideoLayout extends FitLayout
int columns = calculateColumnCount(remotes);
int rows = (remoteCount + columns - 1) / columns;
-System.out.println("EHIIIIII WIDTH=========" + maxWidth * columns
- + "EHIIIIIIIII HEIGHT========" + maxHeight * rows);
return new Dimension(maxWidth * columns, maxHeight * rows);
}
}