/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sip.communicator.impl.gui.main.call.conference; import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.List; 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.main.contactlist.contactsource.*; import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.plugin.desktoputil.*; import net.java.sip.communicator.service.contactsource.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; /** * The invite dialog is the one shown when the user clicks on the conference * button in the chat toolbar. * * @author Yana Stamcheva * @author Lyubomir Marinov */ public class ConferenceInviteDialog extends InviteDialog { /** * Serial version UID. */ private static final long serialVersionUID = 0L; /** * The account selector box. */ private final JComboBox accountSelectorBox = new JComboBox(); /** * The last selected account. */ private Object lastSelectedAccount; /** * The telephony conference into which this instance is to invite * participants. */ private final CallConference conference; /** * The current provider contact source. */ private ContactSourceService currentProviderContactSource; /** * The current string contact source. */ private ContactSourceService currentStringContactSource; /** * The previously selected protocol provider, with which this dialog has * been instantiated. */ private ProtocolProviderService preselectedProtocolProvider; /** * Indicates whether this conference invite dialog is associated with a * Jitsi Videobridge invite. */ private final boolean isJitsiVideobridge; /** * Initializes a new <tt>ConferenceInviteDialog</tt> instance which is to * invite contacts/participants in a specific telephony conference. * * @param conference the telephony conference in which the new instance is * to invite contacts/participants */ public ConferenceInviteDialog( CallConference conference, ProtocolProviderService preselectedProvider, List<ProtocolProviderService> protocolProviders, final boolean isJitsiVideobridge) { // Set the correct dialog title depending if we're going to create a // video bridge conference call super((isJitsiVideobridge ? GuiActivator.getResources() .getI18NString("service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE") : GuiActivator.getResources() .getI18NString("service.gui.INVITE_CONTACT_TO_CALL")), false); this.conference = conference; this.preselectedProtocolProvider = preselectedProvider; this.isJitsiVideobridge = isJitsiVideobridge; if (preselectedProtocolProvider == null) initAccountSelectorPanel(protocolProviders); // init the list, as we check whether features are supported // it may take some time if we have too much contacts SwingUtilities.invokeLater(new Runnable() { public void run() { initContactSources(); // Initialize the list of contacts to select from. if (preselectedProtocolProvider != null) initContactListData(preselectedProtocolProvider); else initContactListData( (ProtocolProviderService) accountSelectorBox .getSelectedItem()); } }); this.addInviteButtonListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Collection<UIContact> selectedContacts = destContactList.getContacts(null); if (selectedContacts != null && selectedContacts.size() > 0) { if (preselectedProtocolProvider == null) preselectedProtocolProvider = (ProtocolProviderService) accountSelectorBox .getSelectedItem(); if (isJitsiVideobridge) inviteJitsiVideobridgeContacts( preselectedProtocolProvider, selectedContacts); else inviteContacts(selectedContacts); // Store the last used account in order to pre-select it // next time. ConfigurationUtils.setLastCallConferenceProvider( preselectedProtocolProvider); 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(); } }); } /** * Constructs the <tt>ConferenceInviteDialog</tt>. */ public ConferenceInviteDialog() { this(null, null, null, false); } /** * Creates an instance of <tt>ConferenceInviteDialog</tt> by specifying an * already created conference. To use when inviting contacts to an existing * conference is needed. * * @param conference the existing <tt>CallConference</tt> */ public ConferenceInviteDialog(CallConference conference) { this(conference, null, null, false); } /** * Creates an instance of <tt>ConferenceInviteDialog</tt> by specifying an * already created conference. To use when inviting contacts to an existing * conference is needed. * * @param conference the existing <tt>CallConference</tt> */ public ConferenceInviteDialog( CallConference conference, ProtocolProviderService preselectedProtocolProvider, boolean isJitsiVideobridge) { this(conference, preselectedProtocolProvider, null, isJitsiVideobridge); } /** * Creates an instance of <tt>ConferenceInviteDialog</tt> by specifying a * preselected protocol provider to be used and if this is an invite for * a video bridge conference. * * @param protocolProviders the protocol providers list * @param isJitsiVideobridge <tt>true</tt> if this dialog should create a * conference through a Jitsi Videobridge; otherwise, <tt>false</tt> */ public ConferenceInviteDialog( List<ProtocolProviderService> protocolProviders, boolean isJitsiVideobridge) { this(null, null, protocolProviders, isJitsiVideobridge); } /** * Creates an instance of <tt>ConferenceInviteDialog</tt> by specifying a * preselected protocol provider to be used and if this is an invite for * a video bridge conference. * * @param selectedConfProvider the preselected protocol provider * @param isJitsiVideobridge <tt>true</tt> if this dialog should create a * conference through a Jitsi Videobridge; otherwise, <tt>false</tt> */ public ConferenceInviteDialog( ProtocolProviderService selectedConfProvider, boolean isJitsiVideobridge) { this(null, selectedConfProvider, null, isJitsiVideobridge); } /** * Initializes the account selector panel. * * @param protocolProviders the list of protocol providers we'd like to * show in the account selector box */ private void initAccountSelectorPanel( List<ProtocolProviderService> protocolProviders) { 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); // Initialize the account selector box. if (protocolProviders != null && protocolProviders.size() > 0) this.initAccountListData(protocolProviders); else this.initAccountListData(); this.accountSelectorBox.setRenderer(new DefaultListCellRenderer() { private static final long serialVersionUID = 0L; @Override 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) { Object accountSelectorBoxSelectedItem = accountSelectorBox.getSelectedItem(); if (lastSelectedAccount == null || !lastSelectedAccount .equals(accountSelectorBoxSelectedItem)) { lastSelectedAccount = accountSelectorBoxSelectedItem; initContactListData( (ProtocolProviderService) accountSelectorBox .getSelectedItem()); if (isJitsiVideobridge) destContactList.removeAll(); } } }); this.getContentPane().add(accountSelectorPanel, BorderLayout.NORTH); } /** * Initializes the account selector box with the given list of * <tt>ProtocolProviderService</tt>-s. * * @param protocolProviders the list of <tt>ProtocolProviderService</tt>-s * we'd like to show in the account selector box */ private void initAccountListData( List<ProtocolProviderService> protocolProviders) { Iterator<ProtocolProviderService> providersIter = protocolProviders.iterator(); while (providersIter.hasNext()) { ProtocolProviderService protocolProvider = providersIter.next(); accountSelectorBox.addItem(protocolProvider); } if (accountSelectorBox.getItemCount() > 0) accountSelectorBox.setSelectedIndex(0); } /** * 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); } // Try to select the last used account if available. ProtocolProviderService pps = ConfigurationUtils.getLastCallConferenceProvider(); if (pps == null && conference != null) { /* * Pick up the first account from the ones participating in the * associated telephony conference which supports * OperationSetTelephonyConferencing. */ for (Call call : conference.getCalls()) { ProtocolProviderService callPps = call.getProtocolProvider(); if (callPps.getOperationSet( OperationSetTelephonyConferencing.class) != null) { pps = callPps; break; } } } if (pps != null) accountSelectorBox.setSelectedItem(pps); else if (accountSelectorBox.getItemCount() > 0) accountSelectorBox.setSelectedIndex(0); } /** * Initializes contact list sources. */ private void initContactSources() { DemuxContactSourceService demuxCSService = GuiActivator.getDemuxContactSourceService(); // If the DemuxContactSourceService isn't registered we use the default // contact source set. if (demuxCSService == null) return; Iterator<UIContactSource> sourcesIter = new ArrayList<UIContactSource>( srcContactList.getContactSources()).iterator(); srcContactList.removeAllContactSources(); while (sourcesIter.hasNext()) { ContactSourceService contactSource = sourcesIter.next().getContactSourceService(); srcContactList.addContactSource( demuxCSService.createDemuxContactSource(contactSource)); } } /** * Initializes the left contact list with the contacts that could be added * to the current chat session. * @param protocolProvider the protocol provider from which to initialize * the contact list data */ private void initContactListData(ProtocolProviderService protocolProvider) { this.setCurrentProvider(protocolProvider); Iterator<UIContactSource> sourcesIter = new ArrayList<UIContactSource>( srcContactList.getContactSources()).iterator(); while (sourcesIter.hasNext()) { ContactSourceService contactSource = sourcesIter.next().getContactSourceService(); if (contactSource instanceof ProtocolAwareContactSourceService) { ((ProtocolAwareContactSourceService) contactSource) .setPreferredProtocolProvider( OperationSetBasicTelephony.class, protocolProvider); } } srcContactList.removeContactSource(currentProviderContactSource); srcContactList.removeContactSource(currentStringContactSource); currentProviderContactSource = new ProtocolContactSourceServiceImpl( protocolProvider, OperationSetBasicTelephony.class); currentStringContactSource = new StringContactSourceServiceImpl( protocolProvider, OperationSetBasicTelephony.class); srcContactList.addContactSource(currentProviderContactSource); srcContactList.addContactSource(currentStringContactSource); srcContactList.applyDefaultFilter(); } /** * Invites the contacts to the chat conference. * * @param contacts the list of contacts to invite */ private void inviteContacts(Collection<UIContact> contacts) { ProtocolProviderService selectedProvider; Map<ProtocolProviderService, List<String>> selectedProviderCallees = new HashMap<ProtocolProviderService, List<String>>(); List<String> callees; Iterator<UIContact> contactsIter = contacts.iterator(); while (contactsIter.hasNext()) { UIContact uiContact = contactsIter.next(); Iterator<UIContactDetail> contactDetailsIter = uiContact .getContactDetailsForOperationSet( OperationSetBasicTelephony.class).iterator(); // We invite the first protocol contact that corresponds to the // invite provider. if (contactDetailsIter.hasNext()) { UIContactDetail inviteDetail = contactDetailsIter.next(); selectedProvider = inviteDetail .getPreferredProtocolProvider( OperationSetBasicTelephony.class); if (selectedProvider == null) { selectedProvider = (ProtocolProviderService) accountSelectorBox.getSelectedItem(); } if(selectedProvider != null && selectedProviderCallees.get(selectedProvider) != null) { callees = selectedProviderCallees.get(selectedProvider); } else { callees = new ArrayList<String>(); } callees.add(inviteDetail.getAddress()); selectedProviderCallees.put(selectedProvider, callees); } } if(conference != null) { CallManager.inviteToConferenceCall( selectedProviderCallees, conference); } else { CallManager.createConferenceCall(selectedProviderCallees); } } /** * Invites the contacts to the chat conference. * * @param contacts the list of contacts to invite */ private void inviteJitsiVideobridgeContacts( ProtocolProviderService preselectedProvider, Collection<UIContact> contacts) { List<String> callees = new ArrayList<String>(); Iterator<UIContact> contactsIter = contacts.iterator(); while (contactsIter.hasNext()) { UIContact uiContact = contactsIter.next(); Iterator<UIContactDetail> contactDetailsIter = uiContact .getContactDetailsForOperationSet( OperationSetBasicTelephony.class).iterator(); // We invite the first protocol contact that corresponds to the // invite provider. if (contactDetailsIter.hasNext()) { UIContactDetail inviteDetail = contactDetailsIter.next(); callees.add(inviteDetail.getAddress()); } } if(conference != null) { CallManager.inviteToJitsiVideobridgeConfCall( callees.toArray(new String[callees.size()]), conference.getCalls().get(0)); } else { CallManager.createJitsiVideobridgeConfCall( preselectedProvider, callees.toArray(new String[callees.size()])); } } }