Ongoing work on call conference user interface.

Including part of the work of Dilshan Amadoru accomplished during his GSoC program.
cusax-fix
Yana Stamcheva 17 years ago
parent d7be117c09
commit f2915b3305

@ -177,3 +177,12 @@ service.gui.ERROR_FOREGROUND=CC0000
# Foreground color for links in chat window conversation area.
service.gui.CHAT_LINK_COLOR=4A9BDB
# Conference call peer title panel background color.
service.gui.CALL_PEER_NAME_BACKGROUND=A6D6FF
# Conference call member title panel background color.
service.gui.CALL_MEMBER_NAME_BACKGROUND=BDFFA3
# Conference call local user title panel background color.
service.gui.CALL_LOCAL_USER_BACKGROUND=C0C0C0

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

@ -119,6 +119,7 @@ service.gui.CREATE=C&reate
service.gui.CREATE_CHAT_ROOM=&Create chat room...
service.gui.CREATE_CHAT_ROOM_ERROR=Failed to create chat room with name: {0}.
service.gui.CREATE_CHAT_ROOM_WIZARD=Create chat room wizard
service.gui.CREATE_CONFERENCE_CALL=&Create a conference call...
service.gui.CREATE_GROUP=&Create group
service.gui.CREATE_GROUP_NAME=In the field below enter the name of the group you would like to create.
service.gui.CREATE_FIRST_GROUP_WIZARD=Your contact list doesn't contain any groups. Please create a group first (File/Create group).
@ -195,7 +196,8 @@ service.gui.INVITATION_RECEIVED=Invitation received
service.gui.INVITATION_RECEIVED_MSG={0} has invited you to join {1} chat room. You could accept, reject or ignore this invitation.
service.gui.INVITE=&Invite
service.gui.INVITE_CONTACT_MSG=Select the names of the contacts you would like to add to this conversation and then click Invite.
service.gui.INVITE_CONTACT_TO_CHAT=Invite contact to chat
service.gui.INVITE_CONTACT_TO_CHAT=Invite contacts to chat
service.gui.INVITE_CONTACT_TO_CALL=Invite contacts to call
service.gui.INVITE_REASON=Invite reason
service.gui.IS_CALLING=is calling...
service.gui.JOIN=&Join

@ -11,11 +11,15 @@
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
import javax.swing.border.*;
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.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
import net.java.sip.communicator.util.swing.border.*;
@ -27,7 +31,8 @@
public class CallDialog
extends SIPCommFrame
implements ActionListener,
MouseListener
MouseListener,
CallChangeListener
{
private static final String DIAL_BUTTON = "DIAL_BUTTON";
@ -35,7 +40,9 @@ public class CallDialog
private DialpadDialog dialpadDialog;
private final CallPanel callPanel;
private final Container contentPane = getContentPane();
private Component callPanel = null;
private final HoldButton holdButton;
@ -43,16 +50,48 @@ public class CallDialog
private final LocalVideoButton videoButton;
private final Call call;
private boolean isLastConference = false;
private Date callStartDate;
private boolean isCallTimerStarted = false;
private Timer timer;
/**
* Creates a <tt>CallDialog</tt> by specifying the underlying call panel.
* @param call the <tt>call</tt> that this dialog represents
* @param callType the type of the call (incoming or outgoing)
*/
public CallDialog(Call call, String callType)
{
this.setTitle(
GuiActivator.getResources().getI18NString("service.gui.CALL"));
this.call = call;
// The call duration parameter is not known yet.
this.setCallTitle(null);
this.isLastConference = isConference();
if (isLastConference)
{
this.callPanel
= new ConferenceCallPanel(this, call);
}
else
{
CallPeer callPeer = null;
if (call.getCallPeers().hasNext())
callPeer = call.getCallPeers().next();
if (callPeer != null)
this.callPanel = new OneToOneCallPanel(
this, call, callPeer);
}
this.callPanel
= new CallPanel(this, call, GuiCallPeerRecord.INCOMING_CALL);
call.addCallChangeListener(this);
this.setPreferredSize(new Dimension(500, 400));
@ -79,7 +118,6 @@ public CallDialog(Call call, String callType)
dialButton.addActionListener(this);
dialButton.addMouseListener(this);
Container contentPane = getContentPane();
contentPane.add(callPanel, BorderLayout.CENTER);
contentPane.add(buttonsPanel, BorderLayout.SOUTH);
@ -91,13 +129,19 @@ public CallDialog(Call call, String callType)
settingsPanel.add(dialButton);
settingsPanel.add(holdButton);
settingsPanel.add(muteButton);
settingsPanel.add(videoButton);
if (!isLastConference)
settingsPanel.add(videoButton);
buttonsPanel.add(settingsPanel, BorderLayout.WEST);
buttonsPanel.add(hangupButton, BorderLayout.EAST);
buttonsPanel.setBorder(
new ExtendedEtchedBorder(EtchedBorder.LOWERED, 1, 0, 0, 0));
this.timer = new Timer(1000, new CallTimerListener());
this.timer.setRepeats(true);
}
public void actionPerformed(ActionEvent evt)
@ -181,7 +225,7 @@ private void actionPerformedOnHangupButton()
*/
public Call getCall()
{
return (callPanel != null) ? callPanel.getCall() : null;
return call;
}
@Override
@ -192,7 +236,7 @@ protected void close(boolean isEscaped)
actionPerformedOnHangupButton();
}
}
/**
* Returns the <tt>DialpadDialog</tt> corresponding to this CallDialog.
*
@ -200,10 +244,10 @@ protected void close(boolean isEscaped)
*/
private DialpadDialog getDialpadDialog()
{
Call call = callPanel.getCall();
Iterator<CallPeer> callPeers =
(call == null) ? new Vector<CallPeer>().iterator()
: callPanel.getCall().getCallPeers();
(call == null)
? new Vector<CallPeer>().iterator()
: call.getCallPeers();
return new DialpadDialog(callPeers);
}
@ -273,4 +317,176 @@ public void setVideoButtonSelected(boolean isSelected)
{
this.videoButton.setSelected(true);
}
/**
* Implements the <tt>CallChangeListener.callPeerAdded</tt> method.
* Adds the according user interface when a new peer is added to the call.
*/
public void callPeerAdded(CallPeerEvent evt)
{
if (evt.getSourceCall() == call)
{
if (isLastConference)
{
((ConferenceCallPanel) callPanel)
.addCallPeerPanel(evt.getSourceCallPeer());
}
else
{
this.isLastConference = isConference();
// We've been in one-to-one call and we're now in a conference.
if (isLastConference)
{
contentPane.remove(callPanel);
this.callPanel
= new ConferenceCallPanel(this, call);
contentPane.add(callPanel, BorderLayout.CENTER);
contentPane.repaint();
this.isLastConference = true;
}
// We're still in one-to-one call and we receive the remote peer.
else
{
CallPeer callPeer = null;
if (call.getCallPeers().hasNext())
callPeer = call.getCallPeers().next();
if (callPeer != null)
this.callPanel = new OneToOneCallPanel(
this, call, callPeer);
}
}
}
}
/**
* Implements the <tt>CallChangeListener.callPeerRemoved</tt> method.
* Removes all related user interface when a peer is removed from the call.
*/
public void callPeerRemoved(CallPeerEvent evt)
{
if (evt.getSourceCall() == call)
{
if (isLastConference)
{
if (call.getCallPeerCount() > 2)
{
((ConferenceCallPanel) callPanel)
.removeCallPeerPanel(evt.getSourceCallPeer());
}
else
{
contentPane.remove(callPanel);
CallPeer peer = call.getCallPeers().next();
if (peer != null)
callPanel = new OneToOneCallPanel(this, call, peer);
contentPane.add(callPanel, BorderLayout.CENTER);
contentPane.repaint();
this.isLastConference = false;
}
}
else
{
contentPane.remove(callPanel);
}
}
}
public void callStateChanged(CallChangeEvent evt)
{}
/**
* Checks if the contained call is a conference call.
*
* @return <code>true</code> if the contained <tt>Call</tt> is a conference
* call, otherwise - returns <code>false</code>.
*/
private boolean isConference()
{
// If we have more than one peer, we're in a conference call.
if (call.getCallPeerCount() > 1)
return true;
// If one of our peers is a conference focus, we're in a
// conference call.
Iterator<CallPeer> callPeers = call.getCallPeers();
while (callPeers.hasNext())
{
CallPeer callPeer = callPeers.next();
if (callPeer.isConferenceFocus())
return true;
}
return false;
}
/**
* Starts the timer that counts call duration.
*/
public void startCallTimer()
{
this.callStartDate = new Date();
this.timer.start();
this.isCallTimerStarted = true;
}
/**
* Stops the timer that counts call duration.
*/
public void stopCallTimer()
{
this.timer.stop();
}
/**
* Returns <code>true</code> if the call timer has been started, otherwise
* returns <code>false</code>.
* @return <code>true</code> if the call timer has been started, otherwise
* returns <code>false</code>
*/
public boolean isCallTimerStarted()
{
return isCallTimerStarted;
}
/**
* Each second refreshes the time label to show to the user the exact
* duration of the call.
*/
private class CallTimerListener
implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Date time =
GuiUtils.substractDates(new Date(), callStartDate);
setCallTitle(time);
}
}
/**
* Sets the title of this dialog by specifying the call duration.
* @param callDuration the duration of the call represented as Date object
*/
private void setCallTitle(Date callDuration)
{
String titleString
= GuiActivator.getResources().getI18NString("service.gui.CALL")
+ " | ";
if (callDuration != null)
this.setTitle(titleString + GuiUtils.formatTime(callDuration));
else
this.setTitle(titleString + "00:00:00");
}
}

@ -37,6 +37,9 @@ public class CallManager
private static Hashtable<Call, CallDialog> activeCalls
= new Hashtable<Call, CallDialog>();
/**
* A call listener.
*/
public static class GuiCallListener implements CallListener
{
/**
@ -179,15 +182,28 @@ public static void createCall( ProtocolProviderService protocolProvider,
}
/**
* Creates a call to the given list of contacts.
* Creates a call to the contact represented by the given string.
*
* @param protocolProvider the protocol provider to which this call belongs.
* @param contacts the list of contacts to call to
* @param contact the contact to call to
*/
public static void createCall( ProtocolProviderService protocolProvider,
List<Contact> contacts)
Contact contact)
{
new CreateCallThread(protocolProvider, contacts).start();
new CreateCallThread(protocolProvider, contact).start();
}
/**
* Creates a call to the given list of contacts.
*
* @param protocolProvider the protocol provider to which this call belongs.
* @param callees the list of contacts to call to
*/
public static void createConferenceCall(
ProtocolProviderService protocolProvider,
String[] callees)
{
new CreateConferenceCallThread(protocolProvider, callees).start();
}
/**
@ -195,6 +211,7 @@ public static void createCall( ProtocolProviderService protocolProvider,
*
* @param call the call object to pass to the call dialog
* @param callType the call type
* @return the opened call dialog
*/
public static CallDialog openCallDialog(Call call, String callType)
{
@ -213,10 +230,10 @@ public static CallDialog openCallDialog(Call call, String callType)
private static class CreateCallThread
extends Thread
{
List<Contact> contacts;
String stringContact;
Contact contact;
final ProtocolProviderService protocolProvider;
public CreateCallThread(ProtocolProviderService protocolProvider,
@ -227,10 +244,10 @@ public CreateCallThread(ProtocolProviderService protocolProvider,
}
public CreateCallThread(ProtocolProviderService protocolProvider,
List<Contact> contacts)
Contact contact)
{
this.protocolProvider = protocolProvider;
this.contacts = contacts;
this.contact = contact;
}
public void run()
@ -242,27 +259,20 @@ public void run()
if (telephonyOpSet == null)
return;
// NOTE: The multi user call is not yet implemented!
// We just get the first contact and create a call for him.
try
{
if (contacts != null)
{
Contact contact = contacts.get(0);
if (contact != null)
telephonyOpSet.createCall(contact);
}
else
{
else if (stringContact != null)
telephonyOpSet.createCall(stringContact);
}
}
catch (OperationFailedException e)
{
logger.error("The call could not be created: " + e);
new ErrorDialog(null,
GuiActivator.getResources().getI18NString("service.gui.ERROR"),
GuiActivator.getResources()
.getI18NString("service.gui.ERROR"),
e.getMessage(),
ErrorDialog.ERROR).showDialog();
}
@ -271,14 +281,14 @@ public void run()
logger.error("The call could not be created: " + e);
new ErrorDialog(null,
GuiActivator.getResources().getI18NString("service.gui.ERROR"),
GuiActivator.getResources()
.getI18NString("service.gui.ERROR"),
e.getMessage(),
ErrorDialog.ERROR).showDialog();
}
}
}
/**
* Answers all call peers in the given call.
*/
@ -317,6 +327,50 @@ public void run()
}
}
/**
* Creates a conference call from a given list of contact addresses
*/
private static class CreateConferenceCallThread
extends Thread
{
String[] callees;
final ProtocolProviderService protocolProvider;
public CreateConferenceCallThread(
ProtocolProviderService protocolProvider,
String[] callees)
{
this.protocolProvider = protocolProvider;
this.callees = callees;
}
public void run()
{
OperationSetTelephonyConferencing confOpSet
= (OperationSetTelephonyConferencing) protocolProvider
.getOperationSet(OperationSetTelephonyConferencing.class);
if (confOpSet == null)
return;
try
{
confOpSet.createConfCall(callees);
}
catch (OperationNotSupportedException e)
{
logger.error("Failed to create conference call. " + e);
new ErrorDialog(null,
GuiActivator.getResources()
.getI18NString("service.gui.ERROR"),
e.getMessage(),
ErrorDialog.ERROR).showDialog();
}
}
}
/**
* Hangups all call peers in the given call.
*/

@ -1,505 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license. See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
/**
* The <tt>CallPanel</tt> is the panel containing call information. It's created
* and added to the main tabbed pane when user makes or receives calls. It shows
* information about call peers, call duration, etc.
*
* @author Yana Stamcheva
* @author Lubomir Marinov
*/
public class CallPanel
extends TransparentPanel
implements CallChangeListener,
CallPeerListener,
PropertyChangeListener,
CallPeerSecurityListener
{
private final TransparentPanel mainPanel = new TransparentPanel();
private final Hashtable<CallPeer, CallPeerPanel>
peersPanels = new Hashtable<CallPeer, CallPeerPanel>();
private String title;
private Call call;
private final CallDialog callDialog;
/**
* Creates a call panel for the corresponding call, by specifying the
* call type (incoming or outgoing) and the parent dialog.
*
* @param callDialog the dialog containing this panel
* @param call the call corresponding to this panel
* @param callType the type of the call
*/
public CallPanel(CallDialog callDialog, Call call, String callType)
{
super(new BorderLayout());
this.callDialog = callDialog;
this.mainPanel.setBorder(BorderFactory
.createEmptyBorder(5, 5, 5, 5));
int contactsCount = call.getCallPeerCount();
mainPanel.setLayout(new GridLayout(0, (contactsCount < 2) ? 1 : 2));
if (contactsCount > 0)
{
CallPeer peer = call.getCallPeers().next();
this.title = peer.getDisplayName();
}
this.setCall(call, callType);
}
/**
* Creates and adds a panel for a call peer.
*
* @param peer the call peer
* @param callType the type of call - INCOMING of OUTGOING
*/
private CallPeerPanel addCallPeer(
CallPeer peer, String callType)
{
CallPeerPanel peerPanel = getPeerPanel(peer);
if (peerPanel == null)
{
peerPanel
= new CallPeerPanel(callDialog, peer);
this.mainPanel.add(peerPanel);
peerPanel.setCallType(callType);
this.peersPanels.put(peer, peerPanel);
}
if (peersPanels.size() > 1)
{
SCScrollPane scrollPane = new SCScrollPane();
scrollPane.setViewportView(mainPanel);
this.add(scrollPane);
}
else
{
this.add(mainPanel);
}
return peerPanel;
}
/**
* Returns the title of this call panel. The title is now the name of the
* first peer in the list of the call peers. Should be
* improved in the future.
*
* @return the title of this call panel
*/
public String getTitle()
{
return title;
}
/**
* Implements the CallChangeListener.callPeerAdded method. When a new
* peer is added to our call add it to the call panel.
*/
public void callPeerAdded(CallPeerEvent evt)
{
if (evt.getSourceCall() == call)
{
this.addCallPeer(evt.getSourceCallPeer(), null);
this.revalidate();
this.repaint();
}
}
/**
* Implements the CallChangeListener.callPeerRemoved method. When a
* call peer is removed from our call remove it from the call panel.
*/
public void callPeerRemoved(CallPeerEvent evt)
{
if (evt.getSourceCall() == call)
{
CallPeer peer = evt.getSourceCallPeer();
CallPeerPanel peerPanel =
getPeerPanel(peer);
if (peerPanel != null)
{
CallPeerState state = peer.getState();
peerPanel.setState(state.getStateString(), null);
peerPanel.stopCallTimer();
if (peersPanels.size() != 0)
{
Timer timer =
new Timer(5000, new RemovePeerPanelListener(
peer));
timer.setRepeats(false);
timer.start();
}
this.revalidate();
this.repaint();
}
}
}
public void callStateChanged(CallChangeEvent evt)
{
}
/**
* Implements the CallParicipantChangeListener.peerStateChanged
* method.
*/
public void peerStateChanged(CallPeerChangeEvent evt)
{
CallPeer sourcePeer = evt.getSourceCallPeer();
if (sourcePeer.getCall() != call)
return;
CallPeerPanel peerPanel =
getPeerPanel(sourcePeer);
Object newState = evt.getNewValue();
String newStateString = sourcePeer.getState().getStateString();
Icon newStateIcon = null;
if (newState == CallPeerState.ALERTING_REMOTE_SIDE)
{
NotificationManager
.fireNotification(NotificationManager.OUTGOING_CALL);
}
else if (newState == CallPeerState.BUSY)
{
NotificationManager.stopSound(NotificationManager.OUTGOING_CALL);
NotificationManager.fireNotification(NotificationManager.BUSY_CALL);
}
else if (newState == CallPeerState.CONNECTED)
{
if (!CallPeerState.isOnHold((CallPeerState) evt
.getOldValue()))
{
// start the timer that takes care of refreshing the time label
NotificationManager
.stopSound(NotificationManager.OUTGOING_CALL);
NotificationManager
.stopSound(NotificationManager.INCOMING_CALL);
peerPanel.startCallTimer();
}
}
else if (newState == CallPeerState.DISCONNECTED)
{
// The call peer should be already removed from the call
// see callPeerRemoved
}
else if (newState == CallPeerState.FAILED)
{
// The call peer should be already removed from the call
// see callPeerRemoved
}
else if (CallPeerState.isOnHold((CallPeerState) newState))
{
newStateIcon = new ImageIcon(
ImageLoader.getImage(ImageLoader.HOLD_STATUS_ICON));
// If we have clicked the hold button in a full screen mode
// we need to update the state of the call dialog hold button.
if ((newState.equals(CallPeerState.ON_HOLD_LOCALLY)
|| newState.equals(CallPeerState.ON_HOLD_MUTUALLY))
&& !callDialog.isHoldButtonSelected())
{
callDialog.setHoldButtonSelected(true);
}
}
peerPanel.setState(newStateString, newStateIcon);
}
public void peerDisplayNameChanged(CallPeerChangeEvent evt)
{
}
public void peerAddressChanged(CallPeerChangeEvent evt)
{
}
public void peerImageChanged(CallPeerChangeEvent evt)
{
}
public void securityOn(CallPeerSecurityOnEvent securityEvent)
{
CallPeer peer = (CallPeer) securityEvent.getSource();
CallPeerPanel peerPanel = getPeerPanel(peer);
peerPanel.setSecured(true);
peerPanel.setEncryptionCipher(securityEvent.getCipher());
switch (securityEvent.getSessionType()) {
case CallPeerSecurityOnEvent.AUDIO_SESSION:
peerPanel.setAudioSecurityOn(true);
break;
case CallPeerSecurityOnEvent.VIDEO_SESSION:
peerPanel.setVideoSecurityOn(true);
break;
}
peerPanel.createSecurityPanel(securityEvent);
NotificationManager.fireNotification(
NotificationManager.CALL_SECURITY_ON);
}
public void securityOff(CallPeerSecurityOffEvent securityEvent)
{
CallPeer peer = (CallPeer) securityEvent.getSource();
CallPeerPanel peerPanel = getPeerPanel(peer);
peerPanel.setSecured(false);
switch (securityEvent.getSessionType())
{
case CallPeerSecurityOnEvent.AUDIO_SESSION:
peerPanel.setAudioSecurityOn(false);
break;
case CallPeerSecurityOnEvent.VIDEO_SESSION:
peerPanel.setVideoSecurityOn(false);
break;
}
}
/**
* Returns the call for this call panel.
*
* @return the call for this call panel
*/
public Call getCall()
{
return call;
}
/**
* Sets the <tt>Call</tt> corresponding to this <tt>CallPanel</tt>.
*
* @param call the <tt>Call</tt> corresponding to this <tt>CallPanel</tt>
* @param callType the call type - INCOMING or OUTGOING
*/
private void setCall(Call call, String callType)
{
this.call = call;
this.call.addCallChangeListener(this);
// Remove all previously added peer panels, because they do not
// correspond to real peers.
this.mainPanel.removeAll();
this.peersPanels.clear();
Iterator<CallPeer> peers = call.getCallPeers();
while (peers.hasNext())
{
CallPeer peer = peers.next();
peer.addCallPeerListener(this);
peer.addCallPeerSecurityListener(this);
peer.addPropertyChangeListener(this);
this.addCallPeer(peer, callType);
}
}
/**
* Indicates that a change has occurred in the transport address that we use
* to communicate with the peer.
*
* @param evt The <tt>CallPeerChangeEvent</tt> instance containing
* the source event as well as its previous and its new transport
* address.
*/
public void peerTransportAddressChanged(
CallPeerChangeEvent evt)
{
/** @todo implement peerTransportAddressChanged() */
}
/**
* Removes the given CallPeer panel from this CallPanel.
*/
private class RemovePeerPanelListener
implements ActionListener
{
private CallPeer peer;
public RemovePeerPanelListener(CallPeer peer)
{
this.peer = peer;
}
public void actionPerformed(ActionEvent e)
{
CallPeerPanel peerPanel =
peersPanels.get(peer);
mainPanel.remove(peerPanel);
// remove the peer panel from the list of panels
peersPanels.remove(peer);
}
}
/**
* Returns all peer panels contained in this call panel.
*
* @return an <tt>Iterator</tt> over a list of all peer panels
* contained in this call panel
*/
public Iterator<CallPeerPanel> getPeerPanels()
{
return peersPanels.values().iterator();
}
/**
* Returns the number of peers for this call.
*
* @return the number of peers for this call.
*/
public int getPeerCount()
{
return peersPanels.size();
}
/**
* Returns the <tt>CallPeerPanel</tt>, which correspond to the given
* peer.
*
* @param peer the <tt>CallPeer</tt> we're looking for
* @return the <tt>CallPeerPanel</tt>, which correspond to the given
* peer
*/
public CallPeerPanel getPeerPanel(CallPeer peer)
{
for (Map.Entry<CallPeer, CallPeerPanel> peerEntry :
peersPanels.entrySet())
{
CallPeer entryPeer = peerEntry.getKey();
if ((entryPeer != null)
&& entryPeer.equals(peer))
{
return peerEntry.getValue();
}
}
return null;
}
public void securityMessageRecieved(
CallPeerSecurityMessageEvent event)
{
int severity = event.getEventSeverity();
String messageTitle = null;
switch (severity)
{
// Don't play alert sound for Info or warning.
case CallPeerSecurityMessageEvent.INFORMATION:
{
messageTitle = GuiActivator.getResources().getI18NString(
"service.gui.SECURITY_INFO");
break;
}
case CallPeerSecurityMessageEvent.WARNING:
{
messageTitle = GuiActivator.getResources().getI18NString(
"service.gui.SECURITY_WARNING");
break;
}
// Alert sound indicates: security cannot established
case CallPeerSecurityMessageEvent.SEVERE:
case CallPeerSecurityMessageEvent.ERROR:
{
messageTitle = GuiActivator.getResources().getI18NString(
"service.gui.SECURITY_ERROR");
NotificationManager.fireNotification(
NotificationManager.CALL_SECURITY_ERROR);
}
}
NotificationManager.fireNotification(
NotificationManager.SECURITY_MESSAGE,
messageTitle,
event.getI18nMessage());
}
public void propertyChange(PropertyChangeEvent evt)
{
String propertyName = evt.getPropertyName();
if (propertyName.equals(CallPeer.MUTE_PROPERTY_NAME))
{
boolean isMute = (Boolean) evt.getNewValue();
CallPeer sourcePeer
= (CallPeer) evt.getSource();
if (sourcePeer.getCall() != call)
return;
CallPeerPanel peerPanel = getPeerPanel(sourcePeer);
if (isMute)
{
// If we have clicked the mute button in a full screen mode
// we need to update the state of the call dialog mute button.
if (!callDialog.isMuteButtonSelected())
{
callDialog.setMuteButtonSelected(true);
}
}
peerPanel.setMute(isMute);
}
}
}

@ -0,0 +1,46 @@
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import javax.swing.*;
import net.java.sip.communicator.util.swing.*;
/**
* Represents the background status panel of a peer
*/
public class CallStatusPanel
extends TransparentPanel
{
/*
* Silence the serial warning. Though there isn't a plan to serialize
* the instances of the class, there're no fields so the default
* serialization routine will work.
*/
private static final long serialVersionUID = 0L;
public CallStatusPanel(LayoutManager layout)
{
super(layout);
this.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
this.setBackground(Color.WHITE);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g = g.create();
try
{
AntialiasingManager.activateAntialiasing(g);
g.setColor(Color.DARK_GRAY);
g.fillRoundRect(0, 0, this.getWidth(), this.getHeight(), 20, 20);
}
finally
{
g.dispose();
}
}
}

@ -0,0 +1,56 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import net.java.sip.communicator.util.swing.*;
/**
* The panel, containing the title name of the call peer or member. It defines
* its background color depending on the specified in initialization background
* color.
*
* @author Yana Stamcheva
*/
public class CallTitlePanel
extends TransparentPanel
{
private static final long serialVersionUID = 0L;
private final Color backgroundColor;
/**
* Creates a <tt>CallTitlePanel</tt> by specifying the background color to
* be used.
*
* @param backgroundColor indicates the color to be used to paint the
* background of this title panel.
*/
public CallTitlePanel(Color backgroundColor)
{
this.backgroundColor = backgroundColor;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g = g.create();
try
{
AntialiasingManager.activateAntialiasing(g);
g.setColor(backgroundColor);
g.fillRoundRect(0, 0, this.getWidth(), this.getHeight(), 20, 20);
}
finally
{
g.dispose();
}
}
}

@ -12,6 +12,7 @@
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
/**
@ -25,6 +26,8 @@ public class HoldButton
{
private static final long serialVersionUID = 0L;
private static final Logger logger = Logger.getLogger(HoldButton.class);
/**
* Initializes a new <tt>HoldButton</tt> instance which is to put a specific
* <tt>CallPeer</tt> on/off hold.
@ -137,7 +140,10 @@ public void actionPerformed(ActionEvent evt)
}
catch (OperationFailedException ex)
{
// TODO Auto-generated method stub
if (isSelected())
logger.error("Failed to put on hold.", ex);
else
logger.error("Failed to put off hold.", ex);
}
}
}

@ -25,6 +25,11 @@ public class LocalVideoButton
private static final long serialVersionUID = 0L;
/**
* Creates a <tt>LocalVideoButton</tt> by specifying the corresponding
* <tt>call</tt>.
* @param call the corresponding to this button call
*/
public LocalVideoButton(Call call)
{
setBgImage(ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG));

@ -175,8 +175,8 @@ public void actionPerformed(ActionEvent evt)
Object[] selectedContacts = mainFrame.getContactListPanel()
.getContactList().getSelectedValues();
java.util.List<Contact> telephonyContacts =
new Vector<Contact>();
java.util.List<String> telephonyContacts =
new Vector<String>();
for (Object o : selectedContacts)
{
@ -187,7 +187,7 @@ public void actionPerformed(ActionEvent evt)
OperationSetBasicTelephony.class);
if (contact != null)
telephonyContacts.add(contact);
telephonyContacts.add(contact.getAddress());
else
{
new ErrorDialog(
@ -204,7 +204,15 @@ public void actionPerformed(ActionEvent evt)
}
if (telephonyContacts.size() > 0)
CallManager.createCall(protocolProvider, telephonyContacts);
{
String[] contactAddressStrings
= new String[telephonyContacts.size()];
contactAddressStrings
= telephonyContacts.toArray(contactAddressStrings);
CallManager.createConferenceCall(
protocolProvider, contactAddressStrings);
}
}
else if (!phoneNumberCombo.isComboFieldEmpty())
{

@ -0,0 +1,66 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license. See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import javax.swing.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.swing.*;
/**
* The <tt>CallPanel</tt> is the panel containing call information. It's created
* and added to the main tabbed pane when user makes or receives calls. It shows
* information about call peers, call duration, etc.
*
* @author Yana Stamcheva
* @author Lubomir Marinov
*/
public class OneToOneCallPanel
extends TransparentPanel
{
private OneToOneCallPeerPanel peerPanel;
private final CallDialog callDialog;
/**
* Creates a call panel for the corresponding call, by specifying the
* call type (incoming or outgoing) and the parent dialog.
*
* @param callDialog the dialog containing this panel
* @param call the call corresponding to this panel
* @param callPeer the remote participant in the call
*/
public OneToOneCallPanel( CallDialog callDialog,
Call call,
CallPeer callPeer)
{
super(new BorderLayout());
this.callDialog = callDialog;
this.setBorder(BorderFactory
.createEmptyBorder(5, 5, 5, 5));
this.createCallPeerPanel(callPeer);
}
/**
* Creates and adds a panel for a call peer.
*
* @param peer the call peer
*/
public void createCallPeerPanel(CallPeer peer)
{
if (peerPanel == null)
{
peerPanel = new OneToOneCallPeerPanel(callDialog, peer);
this.add(peerPanel);
}
}
}

@ -11,7 +11,6 @@
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
@ -28,32 +27,18 @@
* @author Yana Stamcheva
* @author Lubomir Marinov
*/
public class CallPeerPanel
extends TransparentPanel
public class OneToOneCallPeerPanel
extends ParentCallPeerPanel
{
private static final Logger logger =
Logger.getLogger(CallPeerPanel.class);
private static final Logger logger
= Logger.getLogger(OneToOneCallPeerPanel.class);
private final JLabel callStatusLabel = new JLabel();
private final SecurityStatusLabel securityStatusLabel;
private final JLabel muteStatusLabel = new JLabel();
private final JLabel photoLabel
= new JLabel(new ImageIcon(ImageLoader
.getImage(ImageLoader.DEFAULT_USER_PHOTO)));
private final JLabel timeLabel = new JLabel("00:00:00", JLabel.CENTER);
/**
* This date is meant to be used in the GuiCallPeerRecord, which is
* added to the CallList after a call.
*/
private final Date callStartTime = new Date(System.currentTimeMillis());
private Date callDuration;
private Timer timer;
private String callType;
private final String peerName;
private final CallPeer callPeer;
@ -65,12 +50,6 @@ public class CallPeerPanel
private Component localVideo;
private boolean isAudioSecurityOn = false;
private boolean isVideoSecurityOn = false;
private String encryptionCipher;
/**
* The current <code>Window</code> being displayed in full-screen. Because
* the AWT API with respect to the full-screen support doesn't seem
@ -79,36 +58,29 @@ public class CallPeerPanel
*/
private Window fullScreenWindow;
private SecurityPanel securityPanel = null;
private final CallDialog callDialog;
/**
* Creates a <tt>CallPeerPanel</tt> for the given call peer.
*
* @param callDialog the parent dialog containing this call peer panel
* @param callPeer a call peer
*/
public CallPeerPanel(CallDialog callDialog,
CallPeer callPeer)
public OneToOneCallPeerPanel( CallDialog callDialog,
CallPeer callPeer)
{
this.callDialog = callDialog;
super(callDialog, callPeer);
this.callPeer = callPeer;
this.peerName = callPeer.getDisplayName();
this.securityStatusLabel = new SecurityStatusLabel(
this,
new ImageIcon(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF)),
JLabel.CENTER);
// Initialize the date to 0
// Need to use Calendar because new Date(0) returns a date where the
// hour is initialized to 1.
Calendar c = Calendar.getInstance();
c.set(0, 0, 0, 0, 0, 0);
this.callDuration = c.getTime();
// Add all CallPeer related listeners.
callPeer.addCallPeerListener(this);
callPeer.addPropertyChangeListener(this);
callPeer.addCallPeerSecurityListener(this);
/* Create the main Components of the UI. */
Component nameBar = createNameBar();
nameLabel.setText(peerName);
nameLabel.setAlignmentX(JLabel.CENTER);
Component center = createCenter();
Component statusBar = createStatusBar();
@ -116,14 +88,14 @@ public CallPeerPanel(CallDialog callDialog,
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
if (nameBar != null)
if (nameLabel != null)
{
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 0;
add(nameBar, constraints);
add(nameLabel, constraints);
}
if (center != null)
{
@ -155,9 +127,6 @@ public CallPeerPanel(CallDialog callDialog,
add(statusBar, constraints);
}
this.timer = new Timer(1000, new CallTimerListener());
this.timer.setRepeats(true);
addVideoListener();
}
@ -188,10 +157,6 @@ private Component createButtonBar( boolean heavyweight,
*/
private Component createCenter()
{
final JLabel photoLabel =
new JLabel(new ImageIcon(ImageLoader
.getImage(ImageLoader.DEFAULT_USER_PHOTO)));
photoLabel.setPreferredSize(new Dimension(90, 90));
final Container videoContainer = createVideoContainer(photoLabel);
@ -245,16 +210,6 @@ private Container createVideoContainer(Component noVideoComponent)
return new VideoContainer(noVideoComponent);
}
private Component createNameBar()
{
// nameLabel
JLabel nameLabel = new JLabel("", JLabel.CENTER);
nameLabel.setText(peerName);
nameLabel.setAlignmentX(JLabel.CENTER);
return nameLabel;
}
/**
* Creates the <code>Component</code> hierarchy of the area of
* status-related information such as <code>CallPeer</code> display
@ -300,68 +255,6 @@ private Component createStatusBar()
return statusPanel;
}
/**
* Creates a new <code>Component</code> representing a UI means to transfer
* the <code>Call</code> of the associated <code>callPeer</code> or
* <tt>null</tt> if call-transfer is unsupported.
*
* @return a new <code>Component</code> representing the UI means to
* transfer the <code>Call</code> of <code>callPeer</code> or
* <tt>null</tt> if call-transfer is unsupported
*/
private Component createTransferCallButton()
{
Call call = callPeer.getCall();
if (call != null)
{
OperationSetAdvancedTelephony telephony =
(OperationSetAdvancedTelephony) call.getProtocolProvider()
.getOperationSet(OperationSetAdvancedTelephony.class);
if (telephony != null)
return new TransferCallButton(callPeer);
}
return null;
}
public void createSecurityPanel(
CallPeerSecurityOnEvent event)
{
Call call = callPeer.getCall();
if (call != null)
{
OperationSetSecureTelephony secure
= (OperationSetSecureTelephony) call
.getProtocolProvider().getOperationSet(
OperationSetSecureTelephony.class);
if (secure != null)
{
if (securityPanel == null)
{
securityPanel = new SecurityPanel(callPeer);
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
constraints.gridy = 2;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.insets = new Insets(5, 0, 0, 0);
this.add(securityPanel, constraints);
}
securityPanel.refreshStates(event);
this.revalidate();
}
}
}
private class VideoTelephonyListener
implements PropertyChangeListener,
VideoListener
@ -663,201 +556,6 @@ else if (localVideo != null)
}
}
/**
* Sets the state of the contained call peer by specifying the
* state name and icon.
*
* @param state the state of the contained call peer
* @param icon the icon of the state
*/
public void setState(String state, Icon icon)
{
this.callStatusLabel.setText(state);
this.callStatusLabel.setIcon(icon);
}
/**
* Sets the secured status icon to the status panel.
*
* @param isSecured indicates if the call with this peer is
* secured
*/
public void setSecured(boolean isSecured)
{
if (isSecured)
securityStatusLabel.setIcon(new ImageIcon(ImageLoader
.getImage(ImageLoader.SECURE_BUTTON_ON)));
else
securityStatusLabel.setIcon(new ImageIcon(ImageLoader
.getImage(ImageLoader.SECURE_BUTTON_OFF)));
}
/**
* Sets the mute status icon to the status panel.
*
* @param isMute indicates if the call with this peer is
* muted
*/
public void setMute(boolean isMute)
{
if(isMute)
muteStatusLabel.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.MUTE_STATUS_ICON)));
else
muteStatusLabel.setIcon(null);
}
/**
* Sets the audio security on or off.
*
* @param isAudioSecurityOn indicates if the audio security is turned on or
* off.
*/
public void setAudioSecurityOn(boolean isAudioSecurityOn)
{
this.isAudioSecurityOn = isAudioSecurityOn;
}
/**
* Sets the video security on or off.
*
* @param isVideoSecurityOn indicates if the video security is turned on or
* off.
*/
public void setVideoSecurityOn(boolean isVideoSecurityOn)
{
this.isVideoSecurityOn = isVideoSecurityOn;
}
/**
* Indicates if the audio security is turned on or off.
*
* @return <code>true</code> if the audio security is on, otherwise -
* <code>false</code>.
*/
public boolean isAudioSecurityOn()
{
return isAudioSecurityOn;
}
/**
* Indicates if the video security is turned on or off.
*
* @return <code>true</code> if the video security is on, otherwise -
* <code>false</code>.
*/
public boolean isVideoSecurityOn()
{
return isVideoSecurityOn;
}
/**
* Returns the cipher used for the encryption of the current call.
*
* @return the cipher used for the encryption of the current call.
*/
public String getEncryptionCipher()
{
return encryptionCipher;
}
/**
* Sets the cipher used for the encryption of the current call.
*
* @param encryptionCipher the cipher used for the encryption of the
* current call.
*/
public void setEncryptionCipher(String encryptionCipher)
{
this.encryptionCipher = encryptionCipher;
}
/**
* Starts the timer that counts call duration.
*/
public void startCallTimer()
{
this.timer.start();
}
/**
* Stops the timer that counts call duration.
*/
public void stopCallTimer()
{
this.timer.stop();
}
/**
* Each second refreshes the time label to show to the user the exact
* duration of the call.
*/
private class CallTimerListener
implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Date time =
GuiUtils.substractDates(new Date(System.currentTimeMillis()),
new Date(callPeer.getCallDurationStartTime()));
callDuration.setTime(time.getTime());
timeLabel.setText(GuiUtils.formatTime(time));
}
}
/**
* Returns the start time of the contained peer call. Note that the
* start time of the call is different from the conversation start time. For
* example if we receive a call, the call start time is when the call is
* received and the conversation start time would be when we accept the
* call.
*
* @return the start time of the contained peer call
*/
public Date getCallStartTime()
{
return callStartTime;
}
/**
* Returns the duration of the contained peer call.
*
* @return the duration of the contained peer call
*/
public Date getCallDuration()
{
return callDuration;
}
/**
* Returns this call type - GuiCallPeerRecord: INCOMING_CALL or
* OUTGOING_CALL
*
* @return Returns this call type : INCOMING_CALL or OUTGOING_CALL
*/
public String getCallType()
{
if (callDuration != null)
return callType;
else
return GuiCallPeerRecord.INCOMING_CALL;
}
/**
* Sets the type of the call. Call type could be
* <tt>GuiCallPeerRecord.INCOMING_CALL</tt> or
* <tt>GuiCallPeerRecord.INCOMING_CALL</tt>.
*
* @param callType the type of call to set
*/
public void setCallType(String callType)
{
this.callType = callType;
}
/**
* Returns the name of the peer, contained in this panel.
*
@ -1058,7 +756,6 @@ private void addKeyListener(Component component, KeyListener l)
private static class PeerStatusPanel
extends TransparentPanel
{
/*
* Silence the serial warning. Though there isn't a plan to serialize
* the instances of the class, there're no fields so the default

@ -0,0 +1,559 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
/**
* The parent component for all <tt>CallPeer</tt> panels.
* @author Yana Stamcheva
*/
public abstract class ParentCallPeerPanel
extends TransparentPanel
implements CallPeerListener,
PropertyChangeListener,
CallPeerSecurityListener
{
/**
* The parent dialog containing this panel.
*/
protected final CallDialog callDialog;
/**
* The peer who own this UI
*/
protected final CallPeer callPeer;
/**
* The component showing the name of the underlying call peer.
*/
protected final JLabel nameLabel = new JLabel("", JLabel.CENTER);
/**
* The component showing the status of the underlying call peer.
*/
protected final JLabel callStatusLabel = new JLabel();
/**
* Indicates the state of the audio security (on or off).
*/
private boolean isAudioSecurityOn = false;
/**
* Indicates the state of the video security (on or off).
*/
private boolean isVideoSecurityOn = false;
/**
* The label showing whether the voice has been set to mute
*/
protected final JLabel muteStatusLabel = new JLabel();
/**
* The security status of the peer
*/
protected SecurityStatusLabel securityStatusLabel;
/**
* The encryption cipher.
*/
private String encryptionCipher;
/**
* Panel showing information about security
*/
private SecurityPanel securityPanel = null;
/**
* The image of the peer
*/
protected ImageIcon peerImage;
/**
* Creates a <tt>DefaultCallPeerRenderer</tt> by specifying the
* corresponding <tt>callPeer</tt>.
* @param callPeer the peer that would be rendered
*/
public ParentCallPeerPanel(CallDialog callDialog, CallPeer callPeer)
{
this.callDialog = callDialog;
this.callPeer = callPeer;
this.peerImage = new ImageIcon
(ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO)
.getScaledInstance(50, 50, Image.SCALE_SMOOTH));
this.securityStatusLabel = new SecurityStatusLabel(
this,
new ImageIcon(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF)),
JLabel.CENTER);
}
/**
* Sets the audio security on or off.
*
* @param isAudioSecurityOn indicates if the audio security is turned on or
* off.
*/
public void setAudioSecurityOn(boolean isAudioSecurityOn)
{
this.isAudioSecurityOn = isAudioSecurityOn;
}
/**
* Sets the video security on or off.
*
* @param isVideoSecurityOn indicates if the video security is turned on or
* off.
*/
public void setVideoSecurityOn(boolean isVideoSecurityOn)
{
this.isVideoSecurityOn = isVideoSecurityOn;
}
/**
* Indicates if the audio security is turned on or off.
*
* @return <code>true</code> if the audio security is on, otherwise -
* <code>false</code>.
*/
public boolean isAudioSecurityOn()
{
return isAudioSecurityOn;
}
/**
* Indicates if the video security is turned on or off.
*
* @return <code>true</code> if the video security is on, otherwise -
* <code>false</code>.
*/
public boolean isVideoSecurityOn()
{
return isVideoSecurityOn;
}
/**
* Returns the cipher used for the encryption of the current call.
*
* @return the cipher used for the encryption of the current call.
*/
public String getEncryptionCipher()
{
return encryptionCipher;
}
/**
* Sets the cipher used for the encryption of the current call.
*
* @param encryptionCipher the cipher used for the encryption of the
* current call.
*/
public void setEncryptionCipher(String encryptionCipher)
{
this.encryptionCipher = encryptionCipher;
}
/**
* Notifies this listener about a change in the characteristic of being a
* conference focus of a specific <code>CallPeer</code>.
*
* @param conferenceEvent
* a <code>CallPeerConferenceEvent</code> with ID
* <code>CallPeerConferenceEvent#CONFERENCE_FOCUS_CHANGED</code>
* and no associated <code>ConferenceMember</code>
*/
public void conferenceFocusChanged(
CallPeerConferenceEvent conferenceEvent)
{
CallPeer sourcePeer = conferenceEvent.getSourceCallPeer();
if (!sourcePeer.equals(callPeer))
return;
this.setBackground(Color.LIGHT_GRAY);
}
/**
* Fired when peer's state is changed
*
* @param evt fired CallPeerEvent
*/
public void peerStateChanged(CallPeerChangeEvent evt)
{
CallPeer sourcePeer = evt.getSourceCallPeer();
if (!sourcePeer.equals(callPeer))
return;
Object newState = evt.getNewValue();
String newStateString = sourcePeer.getState().getStateString();
Icon newStateIcon = null;
if (newState == CallPeerState.ALERTING_REMOTE_SIDE)
{
NotificationManager
.fireNotification(NotificationManager.OUTGOING_CALL);
}
else if (newState == CallPeerState.BUSY)
{
NotificationManager.stopSound(NotificationManager.OUTGOING_CALL);
NotificationManager.fireNotification(NotificationManager.BUSY_CALL);
}
else if (newState == CallPeerState.CONNECTED)
{
if (!CallPeerState.isOnHold((CallPeerState) evt
.getOldValue()))
{
NotificationManager
.stopSound(NotificationManager.OUTGOING_CALL);
NotificationManager
.stopSound(NotificationManager.INCOMING_CALL);
if (!callDialog.isCallTimerStarted())
callDialog.startCallTimer();
}
}
else if (newState == CallPeerState.DISCONNECTED)
{
// The call peer should be already removed from the call
// see CallPeerRemoved
}
else if (newState == CallPeerState.FAILED)
{
// The call peer should be already removed from the call
// see CallPeerRemoved
}
else if (CallPeerState.isOnHold((CallPeerState) newState))
{
newStateIcon = new ImageIcon(
ImageLoader.getImage(ImageLoader.HOLD_STATUS_ICON));
// If we have clicked the hold button in a full screen mode
// we need to update the state of the call dialog hold button.
if ((newState.equals(CallPeerState.ON_HOLD_LOCALLY)
|| newState.equals(CallPeerState.ON_HOLD_MUTUALLY))
&& !callDialog.isHoldButtonSelected())
{
callDialog.setHoldButtonSelected(true);
}
}
this.setState(newStateString, newStateIcon);
}
/**
* Fired when peer's adress is changed
*
* @param evt fired CallPeerEvent
*/
public void peerAddressChanged(CallPeerChangeEvent evt)
{
}
/**
* Fired when peer's display name is changed
*
* @param evt fired CallPeerEvent
*/
public void peerDisplayNameChanged(CallPeerChangeEvent evt)
{
CallPeer sourcePeer = evt.getSourceCallPeer();
if (sourcePeer.equals(callPeer))
{
nameLabel.setText((String) evt.getNewValue());
}
}
/**
* Fired when peer's image is changed
*
* @param evt fired CallPeerEvent
*/
public void peerImageChanged(CallPeerChangeEvent evt)
{
CallPeer sourcePeer = evt.getSourceCallPeer();
if (!sourcePeer.equals(callPeer))
return;
this.setPeerImage(new ImageIcon( (byte[]) evt.getNewValue()));
}
/**
* Fired when peer's transport address is changed
*
* @param evt fired CallPeerEvent
*/
public void peerTransportAddressChanged(CallPeerChangeEvent evt)
{
}
/**
* Set the image of the peer
*
* @param peerImage new image
*/
public void setPeerImage(ImageIcon peerImage)
{
this.peerImage = peerImage;
}
/**
* Sets the state of the contained call peer by specifying the
* state name and icon.
*
* @param state the state of the contained call peer
* @param icon the icon of the state
*/
public void setState(String state, Icon icon)
{
this.callStatusLabel.setText(state);
this.callStatusLabel.setIcon(icon);
}
/**
* Sets the mute status icon to the status panel.
*
* @param isMute indicates if the call with this peer is
* muted
*/
public void setMute(boolean isMute)
{
if(isMute)
muteStatusLabel.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.MUTE_STATUS_ICON)));
else
muteStatusLabel.setIcon(null);
}
/**
* Sets the secured status icon to the status panel.
*
* @param isSecured indicates if the call with this peer is
* secured
*/
public void setSecured(boolean isSecured)
{
if (isSecured)
securityStatusLabel.setIcon(new ImageIcon(ImageLoader
.getImage(ImageLoader.SECURE_BUTTON_ON)));
else
securityStatusLabel.setIcon(new ImageIcon(ImageLoader
.getImage(ImageLoader.SECURE_BUTTON_OFF)));
}
/**
* Fired when a change in property happened.
*
* @param evt fired PropertyChangeEvent
*/
public void propertyChange(PropertyChangeEvent evt)
{
String propertyName = evt.getPropertyName();
if (propertyName.equals(CallPeer.MUTE_PROPERTY_NAME))
{
boolean isMute = (Boolean) evt.getNewValue();
if (isMute)
{
// If we have clicked the mute button in a full screen mode
// we need to update the state of the call dialog mute button.
if (!callDialog.isMuteButtonSelected())
{
callDialog.setMuteButtonSelected(true);
}
}
this.setMute(isMute);
}
}
/**
* Processes the received security message and passes it to the
* <tt>NotificationManager</tt> responsible for popup notifications.
* @param event the event we received
*/
public void securityMessageRecieved(CallPeerSecurityMessageEvent event)
{
int severity = event.getEventSeverity();
String messageTitle = null;
switch (severity)
{
// Don't play alert sound for Info or warning.
case CallPeerSecurityMessageEvent.INFORMATION:
{
messageTitle = GuiActivator.getResources().getI18NString(
"service.gui.SECURITY_INFO");
break;
}
case CallPeerSecurityMessageEvent.WARNING:
{
messageTitle = GuiActivator.getResources().getI18NString(
"service.gui.SECURITY_WARNING");
break;
}
// Alert sound indicates: security cannot established
case CallPeerSecurityMessageEvent.SEVERE:
case CallPeerSecurityMessageEvent.ERROR:
{
messageTitle = GuiActivator.getResources().getI18NString(
"service.gui.SECURITY_ERROR");
NotificationManager.fireNotification(
NotificationManager.CALL_SECURITY_ERROR);
}
}
NotificationManager.fireNotification(
NotificationManager.SECURITY_MESSAGE,
messageTitle,
event.getI18nMessage());
}
/**
* Creates the security panel, when a <tt>securityOnEvent</tt> is received.
* @param securityOnEvent the event we received
*/
public void securityOn(CallPeerSecurityOnEvent securityOnEvent)
{
CallPeer peer = (CallPeer) securityOnEvent.getSource();
if (!peer.equals(callPeer))
return;
this.setSecured(true);
this.setEncryptionCipher(securityOnEvent.getCipher());
switch (securityOnEvent.getSessionType()) {
case CallPeerSecurityOnEvent.AUDIO_SESSION:
this.setAudioSecurityOn(true);
break;
case CallPeerSecurityOnEvent.VIDEO_SESSION:
this.setVideoSecurityOn(true);
break;
}
this.createSecurityPanel(securityOnEvent);
NotificationManager.fireNotification(
NotificationManager.CALL_SECURITY_ON);
}
/**
* Indicates the new state through the security indicator components.
* @param securityOffEvent the event we received
*/
public void securityOff(CallPeerSecurityOffEvent securityOffEvent)
{
CallPeer peer = (CallPeer) securityOffEvent.getSource();
if (!peer.equals(callPeer))
return;
this.setSecured(false);
switch (securityOffEvent.getSessionType())
{
case CallPeerSecurityOnEvent.AUDIO_SESSION:
this.setAudioSecurityOn(false);
break;
case CallPeerSecurityOnEvent.VIDEO_SESSION:
this.setVideoSecurityOn(false);
break;
}
}
/**
* Returns the underlying call peer.
*
* @return the underlying call peer
*/
public CallPeer getCallPeer()
{
return callPeer;
}
/**
* Create a security panel
*
* @param event fired CallPeerSecurityOnEvent
*/
private void createSecurityPanel(CallPeerSecurityOnEvent event)
{
if (callPeer != null)
{
OperationSetSecureTelephony secure
= (OperationSetSecureTelephony) callPeer
.getProtocolProvider().getOperationSet(
OperationSetSecureTelephony.class);
if (secure != null)
{
if (securityPanel == null)
{
securityPanel = new SecurityPanel(callPeer);
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
constraints.gridy = 2;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.insets = new Insets(5, 0, 0, 0);
this.add(securityPanel, constraints);
}
securityPanel.refreshStates(event);
this.revalidate();
}
}
}
/**
* Creates a new <code>Component</code> representing a UI means to transfer
* the <code>Call</code> of the associated <code>callPeer</code> or
* <tt>null</tt> if call-transfer is unsupported.
*
* @return a new <code>Component</code> representing the UI means to
* transfer the <code>Call</code> of <code>callPeer</code> or
* <tt>null</tt> if call-transfer is unsupported
*/
protected Component createTransferCallButton()
{
if (callPeer != null)
{
OperationSetAdvancedTelephony telephony =
(OperationSetAdvancedTelephony) callPeer.getProtocolProvider()
.getOperationSet(OperationSetAdvancedTelephony.class);
if (telephony != null)
return new TransferCallButton(callPeer);
}
return null;
}
}

@ -16,15 +16,15 @@
public class SecurityStatusLabel
extends JLabel
{
private final CallPeerPanel callPeerPanel;
private final ParentCallPeerPanel callPeerRenderer;
public SecurityStatusLabel( CallPeerPanel callPeerPanel,
public SecurityStatusLabel( ParentCallPeerPanel callPeerRenderer,
Icon icon,
int alignment)
{
super(icon, alignment);
this.callPeerPanel = callPeerPanel;
this.callPeerRenderer = callPeerRenderer;
this.setToolTipText("Security status");
}
@ -40,7 +40,7 @@ public JToolTip createToolTip()
ImageIcon audioStatusIcon;
String audioStatusString;
if (callPeerPanel.isAudioSecurityOn())
if (callPeerRenderer.isAudioSecurityOn())
{
audioStatusIcon = new ImageIcon(
ImageLoader.getImage(ImageLoader.SECURE_AUDIO_ON));
@ -55,7 +55,7 @@ public JToolTip createToolTip()
ImageIcon videoStatusIcon;
String videoStatusString;
if (callPeerPanel.isVideoSecurityOn())
if (callPeerRenderer.isVideoSecurityOn())
{
videoStatusIcon = new ImageIcon(
ImageLoader.getImage(ImageLoader.SECURE_VIDEO_ON));
@ -68,7 +68,7 @@ public JToolTip createToolTip()
videoStatusString = "Video security off.";
}
String cipher = "Cipher: " + callPeerPanel.getEncryptionCipher();
String cipher = "Cipher: " + callPeerRenderer.getEncryptionCipher();
tip.addLine(audioStatusIcon,
audioStatusString);

@ -0,0 +1,22 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call.conference;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.service.protocol.*;
/**
* @author Yana Stamcheva
*/
public class ConferenceCallDialog
extends CallDialog
{
public ConferenceCallDialog(Call call, String callType)
{
super(call, callType);
}
}

@ -0,0 +1,180 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call.conference;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.swing.*;
/**
* The UI for a conference
*
* @author Dilshan Amadoru
*/
public class ConferenceCallPanel
extends JScrollPane
{
/**
* The conference call
*/
private final Call call;
/**
* The panel which contains ConferencePeerPanels
*/
private final TransparentPanel mainPanel;
/**
* The constraints to create the GridBagLayout
*/
private final GridBagConstraints constraints = new GridBagConstraints();
/**
* The CallDialog which contains this panel
*/
private final CallDialog callDialog;
/**
* Constructor
*
* @param callDialog The dialog which contains this panel
* @param c The conference call object
*/
public ConferenceCallPanel(CallDialog callDialog, Call c)
{
this.callDialog = callDialog;
this.call = c;
mainPanel = new TransparentPanel();
mainPanel.setLayout(new GridBagLayout());
this.addLocalCallPeer();
Iterator<CallPeer> iterator = this.call.getCallPeers();
while (iterator.hasNext())
{
this.addCallPeerPanel(iterator.next());
}
this.setBorder(BorderFactory
.createEmptyBorder(10, 10, 10, 10));
this.setOpaque(false);
this.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
this.getViewport().setOpaque(false);
this.getViewport().add(mainPanel);
}
/**
* Adds the local call peer panel to this conference call.
*/
private void addLocalCallPeer()
{
ConferenceCallPeerPanel localPeerPanel
= new ConferenceCallPeerPanel(
callDialog, call.getProtocolProvider());
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(0, 0, 10, 10);
mainPanel.add(localPeerPanel, constraints);
}
/**
* Add a ConferencePeerPanel for a given Peer
*
* @param peer New Peer
*/
public void addCallPeerPanel(CallPeer peer)
{
ConferenceCallPeerPanel remotePeerPanel =
new ConferenceCallPeerPanel(callDialog, peer);
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = mainPanel.getComponentCount() + 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(0, 0, 10, 10);
mainPanel.add(remotePeerPanel, constraints);
for (ConferenceMember member : peer.getConferenceMembers())
{
remotePeerPanel.addConferenceMemberPanel(member);
}
this.revalidate();
this.repaint();
peer.addCallPeerListener(remotePeerPanel);
peer.addPropertyChangeListener(remotePeerPanel);
peer.addCallPeerSecurityListener(remotePeerPanel);
}
/**
* Removes the <tt>ConferenceCallPeerPanel</tt> corresponding to the given
* <tt>peer</tt>.
* @param peer the <tt>CallPeer</tt>, which panel to remove
*/
public void removeCallPeerPanel(CallPeer peer)
{
ConferenceCallPeerPanel callPeerPanel = null;
for (int i=0; i<mainPanel.getComponentCount(); i++)
{
Component c = mainPanel.getComponent(i);
if (c instanceof ConferenceCallPeerPanel
&& ((ConferenceCallPeerPanel) c)
.getPeerId().equals(peer.getPeerID()))
{
callPeerPanel = (ConferenceCallPeerPanel) c;
mainPanel.remove(callPeerPanel);
peer.removeCallPeerListener(callPeerPanel);
peer.removePropertyChangeListener(callPeerPanel);
peer.removeCallPeerSecurityListener(callPeerPanel);
break;
}
}
if (callPeerPanel != null)
{
for (ConferenceMember member : peer.getConferenceMembers())
{
callPeerPanel.addConferenceMemberPanel(member);
}
}
this.revalidate();
this.repaint();
}
/**
* Returns the call for this call panel.
*
* @return the call for this call panel
*/
public Call getCall()
{
return call;
}
}

@ -0,0 +1,400 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call.conference;
import java.awt.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.swing.*;
/**
* The UI showing the information of a peer in the conference
*
* @author Lubomir Marinov
* @author Yana Stamcheva
* @author Dilshan Amadoru
*/
public class ConferenceCallPeerPanel
extends ParentCallPeerPanel
implements CallPeerConferenceListener
{
/**
* The name of the peer
*/
private String peerName;
/**
* The unique id of the peer
*/
private String peerId;
/**
* The title panel.
*/
private final CallTitlePanel callTitlePanel;
/**
* The sound level indicator component.
*/
private SoundLevelIndicator soundLevelsIndicator = null;
/**
* The bar showing call information of a peer
*/
Component statusBar = null;
/**
* The constraints to create the GridBagLayout
*/
private final GridBagConstraints constraints = new GridBagConstraints();
/**
* Creates a <tt>ConferenceCallPeerPanel</tt> by specifying the parent
* <tt>callDialog</tt>, containing it and the corresponding
* <tt>protocolProvider</tt>.
*
* @param callDialog
* @param protocolProvider
*/
public ConferenceCallPeerPanel( CallDialog callDialog,
ProtocolProviderService protocolProvider)
{
super(callDialog, null);
this.peerName
= protocolProvider.getAccountID().getDisplayName();
this.peerId
= protocolProvider.getAccountID().getUserID();
soundLevelsIndicator = createSoundLevelIndicator(protocolProvider);
callTitlePanel = new CallTitlePanel(
new Color(GuiActivator.getResources().getColor(
"service.gui.CALL_LOCAL_USER_BACKGROUND")));
this.init();
}
/**
* Creates a <tt>ConferenceCallPeerPanel</tt>, that would be contained in
* the given <tt>callDialog</tt> and would correspond to the given
* <tt>callPeer</tt>.
*
* @param callDialog the dialog, in which this panel is shown
* @param callPeer The peer who own this UI
*/
public ConferenceCallPeerPanel(CallDialog callDialog, CallPeer callPeer)
{
super(callDialog, callPeer);
this.peerName = callPeer.getDisplayName();
this.peerId = callPeer.getPeerID();
soundLevelsIndicator = createSoundLevelIndicator(callPeer);
statusBar = createStatusBar();
callTitlePanel = new CallTitlePanel(
new Color(GuiActivator.getResources().getColor(
"service.gui.CALL_PEER_NAME_BACKGROUND")));
this.init();
}
private void init()
{
Component nameBar = createNameBar();
callTitlePanel.setLayout(new GridBagLayout());
this.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
TransparentPanel detailPanel = new TransparentPanel();
detailPanel.setLayout(new GridBagLayout());
detailPanel.setBackground(new Color(255, 255, 255));
this.setLayout(new GridBagLayout());
// Add the name bar
if (nameBar != null)
{
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(2, 0, 2, 0);
callTitlePanel.add(nameBar, constraints);
}
// Add the image
if (peerImage != null)
{
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.insets = new Insets(5, 22, 5, 0);
detailPanel.add(new JLabel(peerImage), constraints);
}
if (soundLevelsIndicator != null)
{
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridx = 1;
constraints.gridy = 0;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(2, 20, 2, 20);
detailPanel.add(soundLevelsIndicator, constraints);
}
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(0, 0, 0, 0);
this.add(callTitlePanel, constraints);
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(0, 0, 5, 0);
this.add(detailPanel, constraints);
}
/**
* Create the sound level indicator of the peer
*
* @return The sound level indicator component
*/
private SoundLevelIndicator createSoundLevelIndicator(CallPeer callPeer)
{
SoundLevelIndicator indicator
= new SoundLevelIndicator();
callPeer.addCallPeerSoundLevelListener(indicator);
return indicator;
}
/**
* Create the sound level indicator of the given <tt>protocolProvider</tt>.
*
* @return The sound level indicator component
*/
private SoundLevelIndicator createSoundLevelIndicator(
ProtocolProviderService protocolProvider)
{
SoundLevelIndicator indicator
= new SoundLevelIndicator();
// TODO: Add a listener for the local user sound level indicator.
return indicator;
}
/**
* Creates a buttons bar from the given list of button components.
*
* @param buttons the list of buttons to add in the created button bar
* @return the created button bar
*/
private Component createButtonBar(Component[] buttons)
{
Container buttonBar = new TransparentPanel();
buttonBar.setLayout(new FlowLayout(FlowLayout.CENTER, 3, 3));
for (Component button : buttons)
{
if (button != null)
buttonBar.add(button);
}
return buttonBar;
}
/**
* Create the name bar of the peer
*
* @return The name bar component
*/
private Component createNameBar()
{
TransparentPanel namePanel = new TransparentPanel(new BorderLayout());
namePanel.setBorder(BorderFactory.createEmptyBorder(0,22,0,22));
namePanel.add(nameLabel, BorderLayout.WEST);
nameLabel.setText(peerName);
if (statusBar != null)
namePanel.add(statusBar, BorderLayout.EAST);
return namePanel;
}
/**
* Create the status bar of the peer
*
* @return The status bar component
*/
private Component createStatusBar()
{
if (callPeer != null)
callStatusLabel.setText(callPeer.getState().getStateString());
TransparentPanel statusPanel
= new TransparentPanel(
new FlowLayout(FlowLayout.RIGHT, 0, 0));
statusPanel.add(securityStatusLabel);
statusPanel.add(muteStatusLabel);
statusPanel.add(callStatusLabel);
Component[] buttons = new Component[]
{
createTransferCallButton()
};
Component buttonBar = createButtonBar(buttons);
statusPanel.add(buttonBar);
return statusPanel;
}
/**
* Get id of the peer
*
* @return peer id
*/
public String getPeerId()
{
return peerId;
}
/**
* Paints the background of this panel.
*/
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g = g.create();
try
{
AntialiasingManager.activateAntialiasing(g);
g.setColor(Color.WHITE);
g.fillRoundRect(0, 0, this.getWidth(), this.getHeight(), 20, 20);
}
finally
{
g.dispose();
}
}
public void conferenceFocusChanged(CallPeerConferenceEvent conferenceEvent)
{
// We're adding the up-coming members on conferenceMemberAdded, so for
// now we have nothing to do here.
}
/**
* Adds a <tt>ConferenceMemberPanel</tt> to this container when a
* <tt>ConferenceMember</tt> has been added to the corresponding conference.
* @param conferenceEvent the <tt>CallPeerConferenceEvent</tt> that has been
* triggered
*/
public void conferenceMemberAdded(CallPeerConferenceEvent conferenceEvent)
{
ConferenceMember member = conferenceEvent.getConferenceMember();
this.addConferenceMemberPanel(member);
}
/**
* Removes the corresponding <tt>ConferenceMemberPanel</tt> from this
* container when a <tt>ConferenceMember</tt> has been removed from the
* corresponding conference.
* @param conferenceEvent the <tt>CallPeerConferenceEvent</tt> that has been
* triggered
*/
public void conferenceMemberRemoved(CallPeerConferenceEvent conferenceEvent)
{
ConferenceMember member = conferenceEvent.getConferenceMember();
this.removeConferenceMemberPanel(member);
}
/**
* Adds a <tt>ConferenceMemberPanel</tt> for a given
* <tt>ConferenceMember</tt>.
*
* @param member the <tt>ConferenceMember</tt> that will correspond to the
* panel to add.
*/
public void addConferenceMemberPanel(ConferenceMember member)
{
ConferenceMemberPanel memberPanel
= new ConferenceMemberPanel(member);
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = getComponentCount();
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(5, 10, 5, 10);
this.add(memberPanel, constraints);
this.revalidate();
this.repaint();
member.addPropertyChangeListener(memberPanel);
}
/**
* Removes the <tt>ConferenceMemberPanel</tt> corresponding to the given
* <tt>member</tt>.
*
* @param member the <tt>ConferenceMember</tt>, which panel to remove
*/
public void removeConferenceMemberPanel(ConferenceMember member)
{
for (int i=0; i < getComponentCount(); i++)
{
Component c = getComponent(i);
if (c instanceof ConferenceMemberPanel
&& ((ConferenceMemberPanel) c)
.getConferenceMember().equals(member))
{
this.remove(c);
member.removePropertyChangeListener((ConferenceMemberPanel) c);
break;
}
}
this.revalidate();
this.repaint();
}
}

@ -0,0 +1,221 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call.conference;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.swing.*;
/**
* The invite dialog is the one shown when the user clicks on the conference
* button in the chat toolbar.
*
* @author Yana Stamcheva
*/
public class ConferenceInviteDialog
extends InviteDialog
{
private final JComboBox accountSelectorBox = new JComboBox();
private Object lastSelectedAccount;
/**
* Constructs the <tt>ChatInviteDialog</tt>.
*
* <tt>ChatRoom</tt>, where the contact is invited.
*/
public ConferenceInviteDialog ()
{
super(GuiActivator.getResources()
.getI18NString("service.gui.INVITE_CONTACT_TO_CALL"));
JLabel accountSelectorLabel = new JLabel(
GuiActivator.getResources().getI18NString("service.gui.CALL_VIA"));
TransparentPanel accountSelectorPanel
= new TransparentPanel(new BorderLayout());
accountSelectorPanel.setBorder(
BorderFactory.createEmptyBorder(5, 5, 5, 5));
accountSelectorPanel.add(accountSelectorLabel, BorderLayout.WEST);
accountSelectorPanel.add(accountSelectorBox, BorderLayout.CENTER);
this.getContentPane().add(accountSelectorPanel, BorderLayout.NORTH);
this.accountSelectorBox.setRenderer(new DefaultListCellRenderer()
{
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected,
boolean cellHasFocus)
{
ProtocolProviderService protocolProvider
= (ProtocolProviderService) value;
if (protocolProvider != null)
{
this.setText(
protocolProvider.getAccountID().getDisplayName());
this.setIcon(
ImageLoader.getAccountStatusImage(protocolProvider));
}
return this;
}
});
this.accountSelectorBox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (lastSelectedAccount == null
|| !lastSelectedAccount
.equals(accountSelectorBox.getSelectedItem()))
{
lastSelectedAccount = accountSelectorBox.getSelectedItem();
initContactListData(
(ProtocolProviderService) accountSelectorBox
.getSelectedItem());
}
}
});
// Initialize the account selector box.
this.initAccountListData();
// Initialize the list of contacts to select from.
this.initContactListData(
(ProtocolProviderService) accountSelectorBox
.getSelectedItem());
this.addInviteButtonListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (getSelectedMetaContacts().hasMoreElements())
{
inviteContacts();
dispose();
}
else
{
// TODO: The underlying invite dialog should show a message
// to the user that she should select at least two contacts
// in order to create a conference.
}
}
});
this.addCancelButtonListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
dispose();
}
});
}
/**
* Initializes the account list.
*/
private void initAccountListData()
{
Iterator<ProtocolProviderService> protocolProviders
= GuiActivator.getUIService()
.getMainFrame().getProtocolProviders();
while(protocolProviders.hasNext())
{
ProtocolProviderService protocolProvider = protocolProviders.next();
OperationSet opSet = protocolProvider
.getOperationSet(OperationSetTelephonyConferencing.class);
if (opSet != null && protocolProvider.isRegistered())
accountSelectorBox.addItem(protocolProvider);
}
// Select the first possible account.
if (accountSelectorBox.getItemCount() > 0)
accountSelectorBox.setSelectedIndex(0);
}
/**
* Initializes the left contact list with the contacts that could be added
* to the current chat session.
*/
private void initContactListData(ProtocolProviderService protocolProvider)
{
// re-init list.
this.removeAllMetaContacts();
MetaContactListService metaContactListService
= GuiActivator.getMetaContactListService();
Iterator<MetaContact> contactListIter = metaContactListService
.findAllMetaContactsForProvider(protocolProvider);
while (contactListIter.hasNext())
{
MetaContact metaContact = contactListIter.next();
this.addMetaContact(metaContact);
}
}
/**
* Invites the contacts to the chat conference.
*/
private void inviteContacts()
{
ProtocolProviderService selectedProvider
= (ProtocolProviderService) accountSelectorBox.getSelectedItem();
java.util.List<String> selectedContactAddresses =
new ArrayList<String>();
Enumeration<MetaContact> selectedContacts
= getSelectedMetaContacts();
while (selectedContacts.hasMoreElements())
{
MetaContact metaContact
= selectedContacts.nextElement();
Iterator<Contact> contactsIter = metaContact
.getContactsForProvider(selectedProvider);
// We invite the first protocol contact that corresponds to the
// invite provider.
if (contactsIter.hasNext())
{
Contact inviteContact = contactsIter.next();
selectedContactAddresses.add(inviteContact.getAddress());
}
}
String[] contactAddressStrings = null;
if (selectedContactAddresses.size() > 0)
{
contactAddressStrings = new String[selectedContactAddresses.size()];
contactAddressStrings
= selectedContactAddresses.toArray(contactAddressStrings);
}
CallManager.createConferenceCall(
selectedProvider, contactAddressStrings);
}
}

@ -0,0 +1,230 @@
package net.java.sip.communicator.impl.gui.main.call.conference;
import java.awt.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
public class ConferenceMemberPanel
extends TransparentPanel
implements PropertyChangeListener
{
private final JLabel nameLabel = new JLabel();
/**
* The image of the member.
*/
private ImageIcon memberImage;
/**
* The status of the peer
*/
private final JLabel callStatusLabel = new JLabel();
private final ConferenceMember member;
private final Color bgColor = new Color(222, 222, 222);
/**
* Creates a <tt><ConferenceMemberPanel</tt> by specifying the corresponding
* <tt>member</tt> that it represents.
* @param member the <tt>ConferenceMember</tt> shown in this panel
*/
public ConferenceMemberPanel(ConferenceMember member)
{
this.member = member;
this.memberImage = new ImageIcon
(ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO)
.getScaledInstance(50, 50, Image.SCALE_SMOOTH));
Component nameBar = createNameBar(member.getDisplayName());
Component soundLevelsIndicator = createSoundLevelIndicator();
JPanel titlePanel = new CallTitlePanel(
new Color(GuiActivator.getResources().getColor(
"service.gui.CALL_MEMBER_NAME_BACKGROUND")));
titlePanel.setLayout(new GridBagLayout());
this.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
TransparentPanel detailPanel = new TransparentPanel();
detailPanel.setLayout(new GridBagLayout());
detailPanel.setBackground(new Color(255, 255, 255));
this.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
if (nameBar != null)
{
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(2, 0, 2, 0);
titlePanel.add(nameBar, constraints);
}
// Add the image
if (memberImage != null)
{
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.insets = new Insets(5, 10, 5, 0);
detailPanel.add(new JLabel(memberImage), constraints);
}
if (soundLevelsIndicator != null)
{
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridx = 1;
constraints.gridy = 0;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(2, 20, 2, 20);
detailPanel.add(soundLevelsIndicator, constraints);
}
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(0, 0, 0, 0);
this.add(titlePanel, constraints);
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.insets = new Insets(0, 0, 0, 0);
this.add(detailPanel, constraints);
}
/**
* Create the name bar of the peer
*
* @return The name bar component
*/
private Component createNameBar(String memberName)
{
TransparentPanel namePanel = new TransparentPanel(new BorderLayout());
namePanel.setBorder(BorderFactory.createEmptyBorder(0,10,0,10));
nameLabel.setText(memberName);
namePanel.add(nameLabel, BorderLayout.WEST);
Component statusBar = createStatusBar();
namePanel.add(statusBar, BorderLayout.EAST);
return namePanel;
}
/**
* Create the sound level indicator of the peer
*
* @return The sound level indicator component
*/
private Component createSoundLevelIndicator()
{
SoundLevelIndicator indicator
= new SoundLevelIndicator();
member.addCallPeerSoundLevelListener(indicator);
return indicator;
}
/**
* Create the status bar of the peer
*
* @return The status bar component
*/
private Component createStatusBar()
{
callStatusLabel.setText(member.getState().toString());
TransparentPanel statusPanel
= new TransparentPanel(
new FlowLayout(FlowLayout.RIGHT, 0, 0));
statusPanel.add(callStatusLabel);
return statusPanel;
}
/**
* Fired when a change in property happened
*
* @param evt fired PropertyChangeEvent
*/
public void propertyChange(PropertyChangeEvent evt)
{
String propertyName = evt.getPropertyName();
if (propertyName.equals(ConferenceMember.DISPLAY_NAME_PROPERTY_NAME))
{
String displayName = (String) evt.getNewValue();
nameLabel.setText(displayName);
this.revalidate();
this.repaint();
}
else if (propertyName.equals(ConferenceMember.STATE_PROPERTY_NAME))
{
ConferenceMemberState state
= (ConferenceMemberState) evt.getNewValue();
callStatusLabel.setText(state.toString());
this.revalidate();
this.repaint();
}
}
/**
* Returns the contained in this panel <tt>ConferenceMember</tt>.
*
* @return the contained in this panel <tt>ConferenceMember</tt>.
*/
public ConferenceMember getConferenceMember()
{
return member;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g = g.create();
try
{
AntialiasingManager.activateAntialiasing(g);
g.setColor(bgColor);
g.fillRoundRect(0, 0, this.getWidth(), this.getHeight(), 20, 20);
}
finally
{
g.dispose();
}
}
}

@ -0,0 +1,181 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call.conference;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.swing.*;
/**
*Represents the sound level indicator for a particular peer
*
* @author Dilshan Amadoru
* @author Yana Stamcheva
*/
public class SoundLevelIndicator
extends TransparentPanel
implements CallPeerSoundLevelListener,
ComponentListener
{
/**
* Image when a sound level block is active
*/
private final ImageIcon soundLevelActiveImage;
/**
* Image when a sound level block is not active
*/
private final ImageIcon soundLevelInactiveImage;
/**
* Current number of distinct sound levels displayed in the UI.
*/
private int soundBarNumber = 8;
private boolean isComponentListenerAdded = false;
/**
* Constructor
*/
public SoundLevelIndicator()
{
soundLevelActiveImage = new ImageIcon(
ImageLoader.getImage(ImageLoader.SOUND_LEVEL_ACTIVE));
soundLevelInactiveImage = new ImageIcon(
ImageLoader.getImage(ImageLoader.SOUND_LEVEL_INACTIVE));
this.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 0));
this.initSoundBars();
this.addComponentListener(new ComponentAdapter()
{
public void componentResized(ComponentEvent e)
{
if (!isComponentListenerAdded)
{
Window parentWindow
= SwingUtilities.getWindowAncestor(
SoundLevelIndicator.this);
if (parentWindow != null)
{
parentWindow.addComponentListener(
SoundLevelIndicator.this);
isComponentListenerAdded = true;
}
}
}
});
}
private void initSoundBars()
{
for (int i = 0; i < soundBarNumber; i++)
{
JLabel block = new JLabel(soundLevelInactiveImage);
this.add(block);
}
}
/**
* TODO: Integrate sound level interfaces and listeners.
*
* Implemented method of PeerSoundLevelListener
*
* @param evt The event fired
*/
public void peerSoundLevelChanged(CallPeerSoundLevelEvent evt)
{
this.updateSoundLevel(evt.getSoundLevel());
}
/**
* Update the UI when received a sound level
*
* @param soundLevel The sound level received
*/
private void updateSoundLevel(int soundLevel)
{
for (int i = 0; i < getComponentCount(); i++)
{
Component c = getComponent(i);
if (c instanceof JLabel)
{
if (i <= (soundLevel))
((JLabel) c).setIcon(soundLevelActiveImage);
else
((JLabel) c).setIcon(soundLevelInactiveImage);
}
}
this.repaint();
}
public void componentHidden(ComponentEvent e) {}
public void componentMoved(ComponentEvent e) {}
public void componentShown(ComponentEvent e) {}
/**
* Adds/removes sound level bars to this component when it's resized.
* @param e the <tt>ComponentEvent</tt> which was triggered
*/
public void componentResized(ComponentEvent e)
{
int windowWidth = e.getComponent().getWidth();
int currentNumber = getSoundBarNumber(windowWidth);
while (currentNumber > 0 && currentNumber < soundBarNumber)
{
for (int i = getComponentCount() - 1; i >= 0; i--)
{
if (getComponent(i) instanceof JLabel)
{
this.remove(getComponent(i));
soundBarNumber--;
}
}
}
while (currentNumber > 0 && soundBarNumber < currentNumber)
{
JLabel block = new JLabel(soundLevelInactiveImage);
this.add(block);
soundBarNumber++;
}
this.revalidate();
this.repaint();
}
/**
* Returns the number of sound level bars that we could currently show in
* this panel.
*
* @param windowWidth the current width of the call window
* @return the number of sound level bars that we could currently show in
* this panel
*/
private int getSoundBarNumber(int windowWidth)
{
int barWidth = soundLevelActiveImage.getIconWidth();
// We deduct 150px from the given windowWidth because this is not the
// only component positioned on the horizontal axe.
return (windowWidth - 150)/barWidth;
}
}

@ -336,6 +336,7 @@ else if (chatPanel.getChatSession() instanceof
/**
* Closes the chat window. Removes all contained chats and invokes
* setVisible(false) to the window.
* @param chatWindow the chat window
*/
public void closeWindow(ChatWindow chatWindow)
{

@ -6,20 +6,14 @@
*/
package net.java.sip.communicator.impl.gui.main.chat.conference;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.lookandfeel.*;
import net.java.sip.communicator.impl.gui.main.chat.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.swing.*;
/**
* The invite dialog is the one shown when the user clicks on the conference
@ -28,22 +22,8 @@
* @author Yana Stamcheva
*/
public class ChatInviteDialog
extends SIPCommDialog
implements ActionListener
extends InviteDialog
{
private final JTextArea reasonArea = new JTextArea();
private final JButton inviteButton = new JButton(
GuiActivator.getResources().getI18NString("service.gui.INVITE"));
private final JButton cancelButton = new JButton(
GuiActivator.getResources().getI18NString("service.gui.CANCEL"));
private final DefaultListModel contactListModel = new DefaultListModel();
private final DefaultListModel selectedContactListModel
= new DefaultListModel();
private final ChatPanel chatPanel;
private ChatTransport inviteChatTransport;
@ -56,177 +36,29 @@ public class ChatInviteDialog
*/
public ChatInviteDialog (ChatPanel chatPanel)
{
this.chatPanel = chatPanel;
this.setModal(false);
String title = GuiActivator.getResources()
.getI18NString("service.gui.INVITE_CONTACT_TO_CHAT");
this.setTitle(title);
TransparentPanel mainPanel
= new TransparentPanel(new BorderLayout(5, 5));
TransparentPanel northPanel
= new TransparentPanel(new BorderLayout(10, 10));
mainPanel.setPreferredSize(new Dimension(450, 350));
mainPanel.setBorder(
BorderFactory.createEmptyBorder(15, 15, 15, 15));
this.reasonArea.setBorder(BorderFactory.createTitledBorder(
GuiActivator.getResources()
.getI18NString("service.gui.INVITE_REASON")));
JTextArea infoTextArea = new JTextArea();
infoTextArea.setText(GuiActivator.getResources()
.getI18NString("service.gui.INVITE_CONTACT_MSG"));
infoTextArea.setFont(infoTextArea.getFont().deriveFont(Font.BOLD));
infoTextArea.setLineWrap(true);
infoTextArea.setOpaque(false);
infoTextArea.setWrapStyleWord(true);
infoTextArea.setEditable(false);
JLabel iconLabel = new JLabel(new ImageIcon(
ImageLoader.getImage(ImageLoader.INVITE_DIALOG_ICON)));
northPanel.add(iconLabel, BorderLayout.WEST);
northPanel.add(infoTextArea, BorderLayout.CENTER);
TransparentPanel buttonsPanel
= new TransparentPanel(new FlowLayout(FlowLayout.RIGHT));
inviteButton.addActionListener(this);
cancelButton.addActionListener(this);
buttonsPanel.add(inviteButton);
buttonsPanel.add(cancelButton);
this.getRootPane().setDefaultButton(inviteButton);
inviteButton.setMnemonic(
GuiActivator.getResources().getI18nMnemonic("service.gui.INVITE"));
cancelButton.setMnemonic(
GuiActivator.getResources().getI18nMnemonic("service.gui.CANCEL"));
final DefaultContactList contactList = new DefaultContactList();
final DefaultContactList selectedContactList = new DefaultContactList();
contactList.setModel(contactListModel);
selectedContactList.setModel(selectedContactListModel);
contactList.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() > 1)
{
MetaContact metaContact
= (MetaContact) contactList.getSelectedValue();
moveContactFromLeftToRight(metaContact);
}
}
});
selectedContactList.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() > 1)
{
MetaContact metaContact
= (MetaContact) selectedContactList.getSelectedValue();
moveContactFromRightToLeft(metaContact);
}
}
});
super(GuiActivator.getResources()
.getI18NString("service.gui.INVITE_CONTACT_TO_CHAT"));
JScrollPane contactListScrollPane = new JScrollPane();
contactListScrollPane.setOpaque(false);
contactListScrollPane.getViewport().setOpaque(false);
contactListScrollPane.getViewport().add(contactList);
contactListScrollPane.getViewport().setBorder(null);
contactListScrollPane.setViewportBorder(null);
contactListScrollPane.setBorder(
SIPCommBorders.getRoundBorder());
JScrollPane selectedListScrollPane = new JScrollPane();
selectedListScrollPane.setOpaque(false);
selectedListScrollPane.getViewport().setOpaque(false);
selectedListScrollPane.getViewport().add(selectedContactList);
selectedListScrollPane.getViewport().setBorder(null);
selectedListScrollPane.setViewportBorder(null);
selectedListScrollPane.setBorder(
SIPCommBorders.getRoundBorder());
JPanel listPanel = new JPanel(new GridLayout(0, 2, 5, 5));
listPanel.setPreferredSize(new Dimension(400, 200));
listPanel.add(contactListScrollPane);
listPanel.add(selectedListScrollPane);
listPanel.setOpaque(false);
this.chatPanel = chatPanel;
this.initContactListData();
// Add remove buttons panel.
JPanel addRemoveButtonsPanel = new JPanel(new GridLayout(0, 2, 5, 5));
addRemoveButtonsPanel.setOpaque(false);
JButton addContactButton = new JButton(
GuiActivator.getResources().getI18NString("service.gui.ADD"));
JButton removeContactButton = new JButton(
GuiActivator.getResources().getI18NString("service.gui.REMOVE"));
addRemoveButtonsPanel.add(addContactButton);
addRemoveButtonsPanel.add(removeContactButton);
addContactButton.addActionListener(new ActionListener()
this.addInviteButtonListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
MetaContact metaContact
= (MetaContact) contactList.getSelectedValue();
if (metaContact != null)
moveContactFromLeftToRight(metaContact);
inviteContacts();
dispose();
}
});
removeContactButton.addActionListener(new ActionListener()
this.addCancelButtonListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
MetaContact metaContact
= (MetaContact) selectedContactList.getSelectedValue();
if (metaContact != null)
moveContactFromRightToLeft(metaContact);
dispose();
}
});
TransparentPanel centerPanel = new TransparentPanel(new BorderLayout());
centerPanel.add(listPanel, BorderLayout.CENTER);
centerPanel.add(addRemoveButtonsPanel, BorderLayout.SOUTH);
TransparentPanel southPanel = new TransparentPanel(new BorderLayout());
southPanel.add(reasonArea, BorderLayout.CENTER);
southPanel.add(buttonsPanel, BorderLayout.SOUTH);
mainPanel.add(northPanel, BorderLayout.NORTH);
mainPanel.add(centerPanel, BorderLayout.CENTER);
mainPanel.add(southPanel, BorderLayout.SOUTH);
this.getContentPane().add(mainPanel);
}
/**
@ -248,80 +80,42 @@ private void initContactListData()
{
MetaContact metaContact = contactListIter.next();
contactListModel.addElement(metaContact);
this.addMetaContact(metaContact);
}
}
/**
* Handles the <tt>ActionEvent</tt> triggered when user clicks
* on one of the buttons.
* Invites the contacts to the chat conference.
*/
@SuppressWarnings("unchecked") //legacy DefaultListModel code.
public void actionPerformed(ActionEvent e)
private void inviteContacts()
{
JButton button = (JButton)e.getSource();
java.util.List<String> selectedContactAddresses =
new ArrayList<String>();
if(button.equals(inviteButton))
Enumeration<MetaContact> selectedContacts
= getSelectedMetaContacts();
while (selectedContacts.hasMoreElements())
{
java.util.List<String> selectedContactAddresses =
new ArrayList<String>();
MetaContact metaContact
= selectedContacts.nextElement();
Enumeration<MetaContact> selectedContacts
= (Enumeration<MetaContact>) selectedContactListModel.elements();
Iterator<Contact> contactsIter = metaContact
.getContactsForProvider(
inviteChatTransport.getProtocolProvider());
while (selectedContacts.hasMoreElements())
// We invite the first protocol contact that corresponds to the
// invite provider.
if (contactsIter.hasNext())
{
MetaContact metaContact
= selectedContacts.nextElement();
Iterator<Contact> contactsIter = metaContact
.getContactsForProvider(
inviteChatTransport.getProtocolProvider());
Contact inviteContact = contactsIter.next();
// We invite the first protocol contact that corresponds to the
// invite provider.
if (contactsIter.hasNext())
{
Contact inviteContact = contactsIter.next();
selectedContactAddresses.add(inviteContact.getAddress());
}
selectedContactAddresses.add(inviteContact.getAddress());
}
chatPanel.inviteContacts( inviteChatTransport,
selectedContactAddresses,
reasonArea.getText());
}
this.dispose();
}
protected void close(boolean isEscaped)
{
this.cancelButton.doClick();
}
/**
* Moves a contact from the left list to the right.
*
* @param metaContact the contact to move.
*/
private void moveContactFromLeftToRight(MetaContact metaContact)
{
contactListModel.removeElement(metaContact);
selectedContactListModel.addElement(metaContact);
}
/**
* Moves a contact from the right list to the left.
*
* @param metaContact the contact to move.
*/
private void moveContactFromRightToLeft(MetaContact metaContact)
{
selectedContactListModel.removeElement(metaContact);
contactListModel.addElement(metaContact);
chatPanel.inviteContacts( inviteChatTransport,
selectedContactAddresses,
this.getReason());
}
}

@ -51,18 +51,17 @@ public FileMenu(MainFrame parentWindow)
ResourceManagementService resources = GuiActivator.getResources();
JMenuItem newAccountMenuItem = new JMenuItem(
resources.getI18NString("service.gui.NEW_ACCOUNT"));
JMenuItem addContactItem
= new JMenuItem(
resources.getI18NString("service.gui.ADD_CONTACT"),
new ImageIcon(ImageLoader.getImage(
ImageLoader.ADD_CONTACT_16x16_ICON)));
JMenuItem createGroupItem
= new JMenuItem(
resources.getI18NString("service.gui.CREATE_GROUP"),
new ImageIcon(ImageLoader.getImage(ImageLoader.GROUPS_16x16_ICON)));
JMenuItem addContactItem = new JMenuItem(
resources.getI18NString("service.gui.ADD_CONTACT"),
new ImageIcon(ImageLoader.getImage(
ImageLoader.ADD_CONTACT_16x16_ICON)));
JMenuItem createGroupItem = new JMenuItem(
resources.getI18NString("service.gui.CREATE_GROUP"),
new ImageIcon(ImageLoader.getImage(ImageLoader.GROUPS_16x16_ICON)));
JMenuItem myChatRoomsItem = new JMenuItem(
resources.getI18NString("service.gui.MY_CHAT_ROOMS"),
new ImageIcon(ImageLoader.getImage(ImageLoader.CHAT_ROOM_16x16_ICON)));
new ImageIcon(ImageLoader.getImage(
ImageLoader.CHAT_ROOM_16x16_ICON)));
this.setOpaque(false);
@ -169,10 +168,9 @@ static boolean registerMenuItemMacOSX(String menuItemText, Object userData)
Exception exception = null;
try
{
Class<?> clazz =
Class
.forName("net.java.sip.communicator.impl.gui.main.menus.MacOSX"
+ menuItemText + "Registration");
Class<?> clazz = Class.forName(
"net.java.sip.communicator.impl.gui.main.menus.MacOSX"
+ menuItemText + "Registration");
Method method = clazz.getMethod("run", new Class[]
{ Object.class });
Object result = method.invoke(null, new Object[]

@ -15,6 +15,7 @@
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.event.*;
import net.java.sip.communicator.impl.gui.main.*;
import net.java.sip.communicator.impl.gui.main.call.conference.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.gui.Container;
import net.java.sip.communicator.util.*;
@ -51,7 +52,7 @@ public ToolsMenu(MainFrame parentWindow) {
this.setOpaque(false);
registerConfigMenuItem();
this.registerMenuItems();
this.initPluginComponents();
}
@ -106,8 +107,18 @@ public void actionPerformed(ActionEvent e)
{
configActionPerformed();
}
else if (itemText.equals("conference"))
{
ConferenceInviteDialog confInviteDialog
= new ConferenceInviteDialog();
confInviteDialog.setVisible(true);
}
}
/**
* Shows the configuration window.
*/
void configActionPerformed()
{
GuiActivator.getUIService().setConfigurationWindowVisible(true);
@ -136,7 +147,7 @@ public void pluginComponentRemoved(PluginComponentEvent event)
}
}
private void registerConfigMenuItem()
private void registerMenuItems()
{
UIService uiService = GuiActivator.getUIService();
if ((uiService == null) || !uiService.useMacOSXScreenMenuBar()
@ -144,6 +155,16 @@ private void registerConfigMenuItem()
{
registerConfigMenuItemNonMacOSX();
}
JMenuItem conferenceMenuItem = new JMenuItem(
GuiActivator.getResources().getI18NString(
"service.gui.CREATE_CONFERENCE_CALL"));
this.add(conferenceMenuItem);
conferenceMenuItem.setMnemonic(GuiActivator.getResources()
.getI18nMnemonic("service.gui.CREATE_CONFERENCE_CALL"));
conferenceMenuItem.setName("conference");
conferenceMenuItem.addActionListener(this);
}
private boolean registerConfigMenuItemMacOSX()

@ -1048,6 +1048,24 @@ public class ImageLoader
public static final ImageID USER_OCCUPIED_ICON
= new ImageID("service.gui.statusicons.USER_OCCUPIED_ICON");
/*
* =====================================================================
* ---------------------------- SOUND LEVEL ICONS ----------------------
* =====================================================================
*/
public static final ImageID SOUND_LEVEL_ACTIVE
= new ImageID("service.gui.soundlevel.SOUND_LEVEL_ACTIVE");
public static final ImageID SOUND_LEVEL_INACTIVE
= new ImageID("service.gui.soundlevel.SOUND_LEVEL_INACTIVE");
public static final ImageID MICROPHONE
= new ImageID("service.gui.soundlevel.MICROPHONE");
public static final ImageID HEADPHONE
= new ImageID("service.gui.soundlevel.HEADPHONE");
/*
* =====================================================================
* ---------------------------- SMILIES --------------------------------

@ -0,0 +1,332 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.utils;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.lookandfeel.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.util.swing.*;
/**
* The invite dialog is a widget that shows a list of contacts, from which the
* user could pick in order to create a conference chat or call.
*
* @author Yana Stamcheva
*/
public class InviteDialog
extends SIPCommDialog
{
private final JTextArea reasonArea = new JTextArea();
private final JButton inviteButton = new JButton(
GuiActivator.getResources().getI18NString("service.gui.INVITE"));
private final JButton cancelButton = new JButton(
GuiActivator.getResources().getI18NString("service.gui.CANCEL"));
private final DefaultListModel contactListModel = new DefaultListModel();
private final DefaultListModel selectedContactListModel
= new DefaultListModel();
/**
* Constructs an <tt>InviteDialog</tt>, by specifying the initial list of
* contacts available for invite.
*
* @param title the title to show on the top of this dialog
* @param metaContacts the list of contacts available for invite
*/
public InviteDialog(String title, java.util.List<MetaContact> metaContacts)
{
this(title);
// Initialize contacts list.
for(MetaContact metaContact : metaContacts)
{
this.addMetaContact(metaContact);
}
}
/**
* Constructs an <tt>InviteDialog</tt>.
* @param title the title to show on the top of this dialog
*/
public InviteDialog (String title)
{
this.setModal(false);
this.setTitle(title);
TransparentPanel mainPanel
= new TransparentPanel(new BorderLayout(5, 5));
TransparentPanel northPanel
= new TransparentPanel(new BorderLayout(10, 10));
mainPanel.setPreferredSize(new Dimension(450, 350));
mainPanel.setBorder(
BorderFactory.createEmptyBorder(15, 15, 15, 15));
this.reasonArea.setBorder(BorderFactory.createTitledBorder(
GuiActivator.getResources()
.getI18NString("service.gui.INVITE_REASON")));
JTextArea infoTextArea = new JTextArea();
infoTextArea.setText(GuiActivator.getResources()
.getI18NString("service.gui.INVITE_CONTACT_MSG"));
infoTextArea.setFont(infoTextArea.getFont().deriveFont(Font.BOLD));
infoTextArea.setLineWrap(true);
infoTextArea.setOpaque(false);
infoTextArea.setWrapStyleWord(true);
infoTextArea.setEditable(false);
JLabel iconLabel = new JLabel(new ImageIcon(
ImageLoader.getImage(ImageLoader.INVITE_DIALOG_ICON)));
northPanel.add(iconLabel, BorderLayout.WEST);
northPanel.add(infoTextArea, BorderLayout.CENTER);
TransparentPanel buttonsPanel
= new TransparentPanel(new FlowLayout(FlowLayout.RIGHT));
buttonsPanel.add(inviteButton);
buttonsPanel.add(cancelButton);
this.getRootPane().setDefaultButton(inviteButton);
inviteButton.setMnemonic(
GuiActivator.getResources().getI18nMnemonic("service.gui.INVITE"));
cancelButton.setMnemonic(
GuiActivator.getResources().getI18nMnemonic("service.gui.CANCEL"));
final DefaultContactList contactList = new DefaultContactList();
final DefaultContactList selectedContactList = new DefaultContactList();
contactList.setModel(contactListModel);
selectedContactList.setModel(selectedContactListModel);
contactList.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() > 1)
{
Object[] metaContacts
= (Object[]) contactList.getSelectedValues();
moveContactFromLeftToRight(metaContacts);
}
}
});
selectedContactList.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() > 1)
{
Object[] metaContacts
= (Object[]) selectedContactList.getSelectedValues();
moveContactFromRightToLeft(metaContacts);
}
}
});
JScrollPane contactListScrollPane = new JScrollPane();
contactListScrollPane.setOpaque(false);
contactListScrollPane.getViewport().setOpaque(false);
contactListScrollPane.getViewport().add(contactList);
contactListScrollPane.getViewport().setBorder(null);
contactListScrollPane.setViewportBorder(null);
contactListScrollPane.setBorder(
SIPCommBorders.getRoundBorder());
JScrollPane selectedListScrollPane = new JScrollPane();
selectedListScrollPane.setOpaque(false);
selectedListScrollPane.getViewport().setOpaque(false);
selectedListScrollPane.getViewport().add(selectedContactList);
selectedListScrollPane.getViewport().setBorder(null);
selectedListScrollPane.setViewportBorder(null);
selectedListScrollPane.setBorder(
SIPCommBorders.getRoundBorder());
JPanel listPanel = new JPanel(new GridLayout(0, 2, 5, 5));
listPanel.setPreferredSize(new Dimension(400, 200));
listPanel.add(contactListScrollPane);
listPanel.add(selectedListScrollPane);
listPanel.setOpaque(false);
// Add remove buttons panel.
JPanel addRemoveButtonsPanel = new JPanel(new GridLayout(0, 2, 5, 5));
addRemoveButtonsPanel.setOpaque(false);
JButton addContactButton = new JButton(
GuiActivator.getResources().getI18NString("service.gui.ADD"));
JButton removeContactButton = new JButton(
GuiActivator.getResources().getI18NString("service.gui.REMOVE"));
addRemoveButtonsPanel.add(addContactButton);
addRemoveButtonsPanel.add(removeContactButton);
addContactButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Object[] metaContacts
= (Object[]) contactList.getSelectedValues();
if (metaContacts != null && metaContacts.length > 0)
moveContactFromLeftToRight(metaContacts);
}
});
removeContactButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Object[] metaContacts
= (Object[]) selectedContactList.getSelectedValues();
if (metaContacts != null && metaContacts.length > 0)
moveContactFromRightToLeft(metaContacts);
}
});
TransparentPanel centerPanel = new TransparentPanel(new BorderLayout());
centerPanel.add(listPanel, BorderLayout.CENTER);
centerPanel.add(addRemoveButtonsPanel, BorderLayout.SOUTH);
TransparentPanel southPanel = new TransparentPanel(new BorderLayout());
southPanel.add(reasonArea, BorderLayout.CENTER);
southPanel.add(buttonsPanel, BorderLayout.SOUTH);
mainPanel.add(northPanel, BorderLayout.NORTH);
mainPanel.add(centerPanel, BorderLayout.CENTER);
mainPanel.add(southPanel, BorderLayout.SOUTH);
this.getContentPane().add(mainPanel);
}
/**
* Adds the given <tt>metaContact</tt> to the left list of contacts
* available for invite.
* @param metaContact the <tt>MetaContact</tt> to add
*/
public void addMetaContact(MetaContact metaContact)
{
contactListModel.addElement(metaContact);
}
/**
* Removes the given <tt>metaContact</tt> from the left list of contacts
* available for invite.
* @param metaContact the <tt>MetaContact</tt> to add
*/
public void removeMetaContact(MetaContact metaContact)
{
contactListModel.removeElement(metaContact);
}
/**
* Removes all <tt>MetaContact</tt>-s from the left list of contacts
* available for invite.
*/
public void removeAllMetaContacts()
{
contactListModel.removeAllElements();
}
/**
* Returns an enumeration of the list of selected contacts.
* @return an enumeration of the list of selected contacts.
*/
public Enumeration<MetaContact> getSelectedMetaContacts()
{
return (Enumeration<MetaContact>) selectedContactListModel.elements();
}
/**
* Returns the reason of this invite, if the user has specified one.
* @return the reason of this invite
*/
public String getReason()
{
return reasonArea.getText();
}
/**
* Adds an <tt>ActionListener</tt> to the contained "Invite" button.
* @param l the <tt>ActionListener</tt> to add
*/
public void addInviteButtonListener(ActionListener l)
{
this.inviteButton.addActionListener(l);
}
/**
* Adds an <tt>ActionListener</tt> to the contained "Cancel" button.
* @param l the <tt>ActionListener</tt> to add
*/
public void addCancelButtonListener(ActionListener l)
{
this.cancelButton.addActionListener(l);
}
/**
* Closes this dialog by clicking on the "Cancel" button.
*/
protected void close(boolean isEscaped)
{
this.cancelButton.doClick();
}
/**
* Moves a contact from the left list to the right.
*
* @param metaContact the contact to move.
*/
private void moveContactFromLeftToRight(Object[] metaContacts)
{
for (Object metaContact : metaContacts)
{
contactListModel.removeElement(metaContact);
selectedContactListModel.addElement(metaContact);
}
}
/**
* Moves a contact from the right list to the left.
*
* @param metaContact the contact to move.
*/
private void moveContactFromRightToLeft(Object[] metaContacts)
{
for (Object metaContact : metaContacts)
{
selectedContactListModel.removeElement(metaContact);
contactListModel.addElement(metaContact);
}
}
}

@ -0,0 +1,26 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.gibberish;
import net.java.sip.communicator.service.protocol.*;
/**
* A default, Gibberish implementation of the account id.
* @author Yana Stamcheva
*/
public class AccountIDGibberishImpl
extends AccountID
{
public static final String GIBBERISH_SERVICE_NAME = "Gibberish";
protected AccountIDGibberishImpl(String userName)
{
super( userName,
new java.util.Hashtable<String, String>(),
ProtocolNames.GIBBERISH,
GIBBERISH_SERVICE_NAME);
}
}

@ -0,0 +1,139 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.gibberish;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* A Gibberish implementation of the <tt>Call</tt> interface.
* @author Yana Stamcheva
* @author Damian Minkov
*/
public class CallGibberishImpl
extends Call
implements CallPeerListener
{
private static final Logger logger
= Logger.getLogger(CallGibberishImpl.class);
/**
* A list containing all <tt>CallPeer</tt>s of this call.
*/
private Vector<CallPeer> callPeers = new Vector<CallPeer>();
public CallGibberishImpl(
ProtocolProviderServiceGibberishImpl sourceProvider)
{
super(sourceProvider);
}
/**
* Returns an iterator over all call peers.
*
* @return an Iterator over all peers currently involved in the
* call.
*/
public Iterator<CallPeer> getCallPeers()
{
return callPeers.iterator();
}
/**
* Returns the number of peers currently associated with this call.
*
* @return an <tt>int</tt> indicating the number of peers
* currently associated with this call.
*/
public int getCallPeerCount()
{
return callPeers.size();
}
/**
* Adds <tt>callPeer</tt> to the list of peers in this call.
* If the call peer is already included in the call, the method has
* no effect.
*
* @param callPeer the new <tt>CallPeer</tt>
*/
public void addCallPeer(CallPeerGibberishImpl callPeer)
{
if(callPeers.contains(callPeer))
return;
callPeer.addCallPeerListener(this);
this.callPeers.add(callPeer);
logger.info("Will fire peer added");
fireCallPeerEvent(
callPeer, CallPeerEvent.CALL_PEER_ADDED);
}
/**
* Removes <tt>callPeer</tt> from the list of peers in this
* call. The method has no effect if there was no such peer in the
* call.
*
* @param callPeer the <tt>CallPeer</tt> leaving the call;
*/
public void removeCallPeer(CallPeerGibberishImpl callPeer)
{
if(!callPeers.contains(callPeer))
return;
this.callPeers.remove(callPeer);
callPeer.removeCallPeerListener(this);
fireCallPeerEvent(
callPeer, CallPeerEvent.CALL_PEER_REMVOVED);
if(callPeers.size() == 0)
setCallState(CallState.CALL_ENDED);
}
public void peerStateChanged(CallPeerChangeEvent evt)
{
if ( ( (CallPeerState) evt.getNewValue())
== CallPeerState.DISCONNECTED
|| ( (CallPeerState) evt.getNewValue())
== CallPeerState.FAILED)
{
removeCallPeer(
(CallPeerGibberishImpl) evt.getSourceCallPeer());
}
else if ( ( (CallPeerState) evt.getNewValue())
== CallPeerState.CONNECTED
&& getCallState().equals(CallState.CALL_INITIALIZATION))
{
setCallState(CallState.CALL_IN_PROGRESS);
}
}
public void peerDisplayNameChanged(CallPeerChangeEvent evt)
{
}
public void peerAddressChanged(CallPeerChangeEvent evt)
{
}
public void peerImageChanged(CallPeerChangeEvent evt)
{
}
public void peerTransportAddressChanged(CallPeerChangeEvent
evt)
{
}
}

@ -0,0 +1,141 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.gibberish;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
/**
* A Gibberish implementation of the <tt>CallPeer</tt> interface.
* @author Yana Stamcheva
*/
public class CallPeerGibberishImpl
extends AbstractCallPeer
{
/**
* The sip address of this peer
*/
private String peerAddress = null;
/**
* The call peer belongs to.
*/
private CallGibberishImpl call;
/**
* A string uniquely identifying the peer.
*/
private String peerID;
public CallPeerGibberishImpl(String address, CallGibberishImpl owningCall)
{
this.peerAddress = address;
this.call = owningCall;
//create the uid
this.peerID = String.valueOf( System.currentTimeMillis())
+ String.valueOf(hashCode());
ConferenceMemberGibberishImpl member1
= new ConferenceMemberGibberishImpl(this);
member1.setDisplayName("conference member1");
member1.setState(ConferenceMemberState.CONNECTED);
ConferenceMemberGibberishImpl member2
= new ConferenceMemberGibberishImpl(this);
member2.setDisplayName("conference member2");
member2.setState(ConferenceMemberState.CONNECTED);
this.addConferenceMember(member1);
this.addConferenceMember(member2);
}
/**
* Returns a String locator for that peer.
*
* @return the peer's address or phone number.
*/
public String getAddress()
{
return peerAddress;
}
/**
* Returns a reference to the call that this peer belongs to.
*
* @return a reference to the call containing this peer.
*/
public Call getCall()
{
return call;
}
/**
* Returns a human readable name representing this peer.
*
* @return a String containing a name for that peer.
*/
public String getDisplayName()
{
return peerAddress;
}
/**
* The method returns an image representation of the call peer
* (e.g.
*
* @return byte[] a byte array containing the image or null if no image
* is available.
*/
public byte[] getImage()
{
return null;
}
/**
* Returns a unique identifier representing this peer.
*
* @return an identifier representing this call peer.
*/
public String getPeerID()
{
return peerID;
}
/**
* Returns the contact corresponding to this peer or null if no
* particular contact has been associated.
* <p>
* @return the <tt>Contact</tt> corresponding to this peer or null
* if no particular contact has been associated.
*/
public Contact getContact()
{
/** @todo implement getContact() */
return null;
}
/**
* Returns the protocol provider that this peer belongs to.
* @return a reference to the ProtocolProviderService that this peer
* belongs to.
*/
public ProtocolProviderService getProtocolProvider()
{
return this.call.getProtocolProvider();
}
public void addCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{
}
public void removeCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{
}
}

@ -0,0 +1,22 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.gibberish;
import net.java.sip.communicator.service.protocol.*;
/**
* A Gibberish implementation of the <tt>ConferenceMember</tt> interface.
* @author Yana Stamcheva
*/
public class ConferenceMemberGibberishImpl
extends AbstractConferenceMember
{
public ConferenceMemberGibberishImpl(CallPeer conferenceFocusCallPeer)
{
super(conferenceFocusCallPeer);
}
}

@ -0,0 +1,245 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.gibberish;
import java.text.*;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* A Gibberish implementation of a basic telephony operation set.
* @author Yana Stamcheva
*/
public class OperationSetBasicTelephonyGibberishImpl
extends AbstractOperationSetBasicTelephony
implements CallChangeListener
{
private static final Logger logger
= Logger.getLogger(OperationSetBasicTelephonyGibberishImpl.class);
/**
* A reference to the <tt>ProtocolProviderServiceSipImpl</tt> instance
* that created us.
*/
private ProtocolProviderServiceGibberishImpl protocolProvider = null;
/**
* A table mapping call ids against call instances.
*/
private Hashtable<String, Call> activeCalls = new Hashtable<String, Call>();
public OperationSetBasicTelephonyGibberishImpl(
ProtocolProviderServiceGibberishImpl protocolProvider)
{
this.protocolProvider = protocolProvider;
}
/**
* Indicates a user request to answer an incoming call from the specified
* CallPeer.
*
* @param peer the call peer that we'd like to answer.
* @throws OperationFailedException with the corresponding code if we
* encounter an error while performing this operation.
*/
public void answerCallPeer(CallPeer peer) throws
OperationFailedException
{
CallPeerGibberishImpl callPeer
= (CallPeerGibberishImpl) peer;
if(peer.getState().equals(CallPeerState.CONNECTED))
{
logger.info("Ignoring user request to answer a CallPeer "
+ "that is already connected. CP:" + peer);
return;
}
callPeer.setState(CallPeerState.CONNECTED, null);
}
/**
* Create a new call and invite the specified CallPeer to it.
*
* @param uri the address of the callee that we should invite to a new
* call.
* @return CallPeer the CallPeer that will represented by
* the specified uri. All following state change events will be
* delivered through that call peer. The Call that this
* peer is a member of could be retrieved from the
* CallParticipatn instance with the use of the corresponding method.
* @throws OperationFailedException with the corresponding code if we
* fail to create the call.
* @throws ParseException if <tt>callee</tt> is not a valid sip address
* string.
*/
public Call createCall(String uri) throws OperationFailedException,
ParseException
{
return createNewCall(uri);
}
/**
* Create a new call and invite the specified CallPeer to it.
*
* @param callee the address of the callee that we should invite to a
* new call.
* @return CallPeer the CallPeer that will represented by
* the specified uri. All following state change events will be
* delivered through that call peer. The Call that this
* peer is a member of could be retrieved from the
* CallParticipatn instance with the use of the corresponding method.
* @throws OperationFailedException with the corresponding code if we
* fail to create the call.
*/
public Call createCall(Contact callee) throws OperationFailedException
{
return createNewCall(callee.getAddress());
}
private Call createNewCall(String address)
{
CallGibberishImpl newCall = new CallGibberishImpl(protocolProvider);
newCall.addCallChangeListener(this);
activeCalls.put(newCall.getCallID(), newCall);
CallPeerGibberishImpl callPeer
= new CallPeerGibberishImpl(address, newCall);
newCall.addCallPeer(callPeer);
this.fireCallEvent(CallEvent.CALL_INITIATED, newCall);
return newCall;
}
/**
* Returns an iterator over all currently active calls.
*
* @return Iterator
*/
public Iterator<Call> getActiveCalls()
{
return activeCalls.values().iterator();
}
/**
* Indicates a user request to end a call with the specified call
* particiapnt.
*
* @param peer the peer that we'd like to hang up on.
* @throws OperationFailedException with the corresponding code if we
* encounter an error while performing this operation.
*/
public void hangupCallPeer(CallPeer peer) throws
OperationFailedException
{
//do nothing if the call is already ended
if (peer.getState().equals(CallPeerState.DISCONNECTED))
{
logger.debug("Ignoring a request to hangup a call peer "
+"that is already DISCONNECTED");
return;
}
CallPeerGibberishImpl callPeer
= (CallPeerGibberishImpl) peer;
logger.info("hangupCallPeer");
callPeer.setState(CallPeerState.DISCONNECTED, null);
}
/**
* Resumes communication with a call peer previously put on hold.
*
* @param peer the call peer to put on hold.
* @todo Implement this
* net.java.sip.communicator.service.protocol.OperationSetBasicTelephony
* method
*/
public void putOffHold(CallPeer peer)
{
}
/**
* Puts the specified CallPeer "on hold".
*
* @param peer the peer that we'd like to put on hold.
* @throws OperationFailedException with the corresponding code if we
* encounter an error while performing this operation.
* @todo Implement this
* net.java.sip.communicator.service.protocol.OperationSetBasicTelephony
* method
*/
public void putOnHold(CallPeer peer) throws
OperationFailedException
{
}
public Call receiveCall(String fromAddress)
throws Exception
{
Call newCall = createCall(fromAddress);
fireCallEvent(CallEvent.CALL_RECEIVED, newCall);
return newCall;
}
public Call placeCall(String toAddress)
throws Exception
{
Call newCall = createCall(toAddress);
fireCallEvent(CallEvent.CALL_INITIATED, newCall);
// must have one peer
CallPeerGibberishImpl callPArt =
(CallPeerGibberishImpl) newCall.getCallPeers().next();
callPArt.setState(CallPeerState.ALERTING_REMOTE_SIDE, "no reason");
callPArt.setState(CallPeerState.CONNECTED, "no reason");
return newCall;
}
public CallPeer addNewCallPeer(Call call, String address)
{
CallPeerGibberishImpl callPArt
= new CallPeerGibberishImpl(address, (CallGibberishImpl) call);
callPArt.setState(CallPeerState.ALERTING_REMOTE_SIDE, "no reason");
callPArt.setState(CallPeerState.CONNECTED, "no reason");
return callPArt;
}
public void callPeerAdded(CallPeerEvent evt)
{
}
public void callPeerRemoved(CallPeerEvent evt)
{
}
public void callStateChanged(CallChangeEvent evt)
{
if(evt.getEventType().equals(CallChangeEvent.CALL_STATE_CHANGE)
&& ((CallState)evt.getNewValue()).equals(CallState.CALL_ENDED))
{
CallGibberishImpl sourceCall = (CallGibberishImpl) this.activeCalls
.remove(evt.getSourceCall().getCallID());
logger.trace( "Removing call " + sourceCall + " from the list of "
+ "active calls because it entered an ENDED state");
fireCallEvent(CallEvent.CALL_ENDED, sourceCall);
}
}
}

@ -0,0 +1,102 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.gibberish;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* A basic implementation of the <tt>OperationSetTelephonyConferencing</tt> for
* the Gibberish protocol (used for test purposes).
*
* @author Yana Stamcheva
*/
public class OperationSetTelephonyConferencingGibberishImpl
implements OperationSetTelephonyConferencing,
CallChangeListener
{
private static final Logger logger
= Logger.getLogger(OperationSetTelephonyConferencingGibberishImpl.class);
/**
* A reference to the <tt>ProtocolProviderServiceGibberishImpl</tt> instance
* that created us.
*/
private final ProtocolProviderServiceGibberishImpl protocolProvider;
/**
* A reference to the <tt>OperationSetBasicTelephonyGibberishImpl<tt> used
* to manage calls.
*/
private final OperationSetBasicTelephonyGibberishImpl telephonyOpSet;
/**
* A table mapping call ids against call instances.
*/
private Hashtable<String, Call> activeCalls = new Hashtable<String, Call>();
public OperationSetTelephonyConferencingGibberishImpl(
ProtocolProviderServiceGibberishImpl provider,
OperationSetBasicTelephonyGibberishImpl telephonyOpSet)
{
this.protocolProvider = provider;
this.telephonyOpSet = telephonyOpSet;
}
public Call createConfCall(String[] callees)
throws OperationNotSupportedException
{
CallGibberishImpl newCall = new CallGibberishImpl(protocolProvider);
newCall.addCallChangeListener(this);
activeCalls.put(newCall.getCallID(), newCall);
for (String callee : callees)
{
CallPeerGibberishImpl callPeer
= new CallPeerGibberishImpl(callee, newCall);
newCall.addCallPeer(callPeer);
}
telephonyOpSet.fireCallEvent(CallEvent.CALL_INITIATED, newCall);
return newCall;
}
public CallPeer inviteCalleeToCall(String uri, Call existingCall)
throws OperationNotSupportedException
{
return null;
}
public void callPeerAdded(CallPeerEvent evt)
{
}
public void callPeerRemoved(CallPeerEvent evt)
{
}
public void callStateChanged(CallChangeEvent evt)
{
if(evt.getEventType().equals(CallChangeEvent.CALL_STATE_CHANGE)
&& ((CallState)evt.getNewValue()).equals(CallState.CALL_ENDED))
{
CallGibberishImpl sourceCall = (CallGibberishImpl) this.activeCalls
.remove(evt.getSourceCall().getCallID());
logger.trace( "Removing call " + sourceCall + " from the list of "
+ "active calls because it entered an ENDED state");
telephonyOpSet.fireCallEvent(CallEvent.CALL_ENDED, sourceCall);
}
}
}

@ -14,6 +14,7 @@
* A Gibberish implementation of the ProtocolProviderService.
*
* @author Emil Ivov
* @author Yana Stamcheva
*/
public class ProtocolProviderServiceGibberishImpl
extends AbstractProtocolProviderService
@ -83,7 +84,7 @@ protected void initialize(String userID,
{
this.accountID = accountID;
//initialize the presence operationset
//initialize the presence operation set
OperationSetPersistentPresenceGibberishImpl persistentPresence =
new OperationSetPersistentPresenceGibberishImpl(this);
@ -116,6 +117,23 @@ protected void initialize(String userID,
OperationSetTypingNotifications.class.getName(),
typingNotifications);
//initialize the basic telephony operation set
OperationSetBasicTelephonyGibberishImpl telphonyOpSet =
new OperationSetBasicTelephonyGibberishImpl(this);
this.supportedOperationSets.put(
OperationSetBasicTelephony.class.getName(),
telphonyOpSet);
//initialize the telephony conferencing operation set
OperationSetTelephonyConferencing conferenceOpSet
= new OperationSetTelephonyConferencingGibberishImpl(
this, telphonyOpSet);
this.supportedOperationSets.put(
OperationSetTelephonyConferencing.class.getName(),
conferenceOpSet);
isInitialized = true;
}
}

@ -8,6 +8,7 @@
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import org.jivesoftware.smackx.jingle.*;
/**
@ -247,4 +248,12 @@ public Contact getContact()
return opSetPresence.findContactByID(getAddress());
}
public void addCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{}
public void removeCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{}
}

@ -7,6 +7,7 @@
package net.java.sip.communicator.impl.protocol.mock;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
/**
* @author Damian Minkov
@ -116,4 +117,11 @@ public ProtocolProviderService getProtocolProvider()
return this.call.getProtocolProvider();
}
public void addCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{}
public void removeCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{}
}

@ -8,6 +8,8 @@
import java.net.*;
import java.text.*;
import java.util.*;
import javax.sip.*;
import javax.sip.address.*;
@ -87,6 +89,13 @@ public class CallPeerSipImpl
*/
private URL callControlURL = null;
/**
* The <tt>CallPeerSoundLevelListener</tt>-s registered to get
* <tt>CallPeerSoundLevelEvent</tt>-s
*/
private final List<CallPeerSoundLevelListener> soundLevelListeners
= new ArrayList<CallPeerSoundLevelListener>();
/**
* Creates a new call peer with address <tt>peerAddress</tt>.
*
@ -485,4 +494,62 @@ public void securityMessage( String messageType,
i18nMessage,
severity);
}
/**
* Adds a specific <tt>CallPeerSoundLevelListener</tt> to the list of
* listeners interested in and notified about changes in sound level related
* information.
*
* @param listener the <tt>CallPeerSoundLevelListener</tt> to add
*/
public void addCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{
synchronized (soundLevelListeners)
{
soundLevelListeners.add(listener);
}
}
/**
* Removes a specific <tt>CallPeerSoundLevelListener</tt> of the list of
* listeners interested in and notified about changes in sound level related
* information.
*
* @param listener the <tt>CallPeerSoundLevelListener</tt> to remove
*/
public void removeCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{
synchronized (soundLevelListeners)
{
soundLevelListeners.remove(listener);
}
}
/**
* Fires a <tt>CallPeerSoundLevelEvent</tt> and notifies all registered
* listeners.
*
* @param level The new sound level
*/
public void fireCallPeerSoundLevelEvent(int level)
{
CallPeerSoundLevelEvent event
= new CallPeerSoundLevelEvent(this, level);
CallPeerSoundLevelListener[] listeners;
synchronized(soundLevelListeners)
{
listeners =
soundLevelListeners.toArray(
new CallPeerSoundLevelListener[soundLevelListeners.size()]);
}
for (CallPeerSoundLevelListener listener : listeners)
{
listener.peerSoundLevelChanged(event);
}
}
}

@ -6,6 +6,9 @@
*/
package net.java.sip.communicator.service.protocol;
import java.util.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
@ -13,6 +16,7 @@
* interface.
*
* @author Lubomir Marinov
* @author Yana Stamcheva
*/
public class AbstractConferenceMember
extends PropertyChangeNotifier
@ -37,6 +41,13 @@ public class AbstractConferenceMember
*/
private ConferenceMemberState state = ConferenceMemberState.UNKNOWN;
/**
* The <tt>CallPeerSoundLevelListener</tt>-s registered to get
* <tt>CallPeerSoundLevelEvent</tt>-s
*/
private final List<CallPeerSoundLevelListener> soundLevelListeners
= new ArrayList<CallPeerSoundLevelListener>();
public AbstractConferenceMember(
CallPeer conferenceFocusCallPeer)
{
@ -114,4 +125,62 @@ public void setState(ConferenceMemberState state)
firePropertyChange(STATE_PROPERTY_NAME, oldValue, this.state);
}
}
/**
* Adds a specific <tt>CallPeerSoundLevelListener</tt> to the list of
* listeners interested in and notified about changes in sound level related
* information.
*
* @param listener the <tt>CallPeerSoundLevelListener</tt> to add
*/
public void addCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{
synchronized (soundLevelListeners)
{
soundLevelListeners.add(listener);
}
}
/**
* Removes a specific <tt>CallPeerSoundLevelListener</tt> of the list of
* listeners interested in and notified about changes in sound level related
* information.
*
* @param listener the <tt>CallPeerSoundLevelListener</tt> to remove
*/
public void removeCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener)
{
synchronized (soundLevelListeners)
{
soundLevelListeners.remove(listener);
}
}
/**
* Fires a <tt>CallPeerSoundLevelEvent</tt> and notifies all registered
* listeners.
*
* @param level The new sound level
*/
public void fireCallPeerSoundLevelEvent(int level)
{
CallPeerSoundLevelEvent event
= new CallPeerSoundLevelEvent(this, level);
CallPeerSoundLevelListener[] listeners;
synchronized(soundLevelListeners)
{
listeners =
soundLevelListeners.toArray(
new CallPeerSoundLevelListener[soundLevelListeners.size()]);
}
for (CallPeerSoundLevelListener listener : listeners)
{
listener.peerSoundLevelChanged(event);
}
}
}

@ -254,4 +254,24 @@ public void addCallPeerConferenceListener(
*/
public void removeCallPeerConferenceListener(
CallPeerConferenceListener listener);
/**
* Adds a specific <tt>CallPeerSoundLevelListener</tt> to the list of
* listeners interested in and notified about changes in sound level related
* information.
*
* @param listener the <tt>CallPeerSoundLevelListener</tt> to add
*/
public void addCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener);
/**
* Removes a specific <tt>CallPeerSoundLevelListener</tt> of the list of
* listeners interested in and notified about changes in sound level related
* information.
*
* @param listener the <tt>CallPeerSoundLevelListener</tt> to remove
*/
public void removeCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener);
}

@ -6,6 +6,7 @@
*/
package net.java.sip.communicator.service.protocol;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
@ -89,4 +90,24 @@ public interface ConferenceMember
* <code>ConferenceMember</code>
*/
public void removePropertyChangeListener(PropertyChangeListener listener);
/**
* Adds a specific <tt>CallPeerSoundLevelListener</tt> to the list of
* listeners interested in and notified about changes in sound level related
* information.
*
* @param listener the <tt>CallPeerSoundLevelListener</tt> to add
*/
public void addCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener);
/**
* Removes a specific <tt>CallPeerSoundLevelListener</tt> of the list of
* listeners interested in and notified about changes in sound level related
* information.
*
* @param listener the <tt>CallPeerSoundLevelListener</tt> to remove
*/
public void removeCallPeerSoundLevelListener(
CallPeerSoundLevelListener listener);
}

@ -0,0 +1,45 @@
/*
* SIP Communicator, 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.*;
/**
* The event triggered when the sound level of a call peer has changed.
*
* @author Dilshan Amadoru
*/
public class CallPeerSoundLevelEvent
extends EventObject
{
/**
* The new sound level indicator.
*/
private int soundLevel;
/**
* Create an event instance.
*
* @param source The object that triggered this event
* @param level The new sound level
*/
public CallPeerSoundLevelEvent(Object source, int level)
{
super(source);
this.soundLevel = level;
}
/**
* Returns the new sound level.
* @return the new sound level
*/
public int getSoundLevel()
{
return soundLevel;
}
}

@ -0,0 +1,23 @@
/*
* SIP Communicator, 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;
/**
* The <tt>CallPeerSoundLevelListener</tt> notifies all interested parties when
* a sound level change has appeared for a certain call peer.
*
* @author Dilshan Amadoru
*/
public interface CallPeerSoundLevelListener
{
/**
* Notifies all interested parties when a peer changes its sound level.
*
* @param evt the <tt>PeerSoundLevelEvent</tt> triggered
*/
public void peerSoundLevelChanged(CallPeerSoundLevelEvent evt);
}
Loading…
Cancel
Save