diff --git a/src/net/java/sip/communicator/impl/neomedia/DeviceConfigurationComboBoxModel.java b/src/net/java/sip/communicator/impl/neomedia/DeviceConfigurationComboBoxModel.java index c3aa54598..f5128da0d 100644 --- a/src/net/java/sip/communicator/impl/neomedia/DeviceConfigurationComboBoxModel.java +++ b/src/net/java/sip/communicator/impl/neomedia/DeviceConfigurationComboBoxModel.java @@ -6,7 +6,11 @@ */ package net.java.sip.communicator.impl.neomedia; +import java.awt.*; +import java.awt.event.*; +import java.beans.*; import java.util.*; +import java.util.List; import javax.media.*; import javax.swing.*; @@ -17,9 +21,12 @@ /** * @author Lubomir Marinov + * @author Damian Minkov */ public class DeviceConfigurationComboBoxModel - implements ComboBoxModel + implements ComboBoxModel, + PropertyChangeListener, + HierarchyListener { /** * Encapsulates CaptureDeviceInfo @@ -117,12 +124,19 @@ public String toString() */ private final int type; + /** + * The parent component. + */ + private Component parent; + /** * Creates device combobox model + * @param parent the parent component * @param deviceConfiguration the current device configuration * @param type the device - audio/video */ public DeviceConfigurationComboBoxModel( + Component parent, DeviceConfiguration deviceConfiguration, int type) { @@ -135,8 +149,19 @@ public DeviceConfigurationComboBoxModel( && (type != VIDEO)) throw new IllegalArgumentException("type"); + this.parent = parent; this.deviceConfiguration = deviceConfiguration; this.type = type; + + if (type == AUDIO + || type == AUDIO_CAPTURE + || type == AUDIO_NOTIFY + || type == AUDIO_PLAYBACK) + { + deviceConfiguration.addPropertyChangeListener(this); + + parent.addHierarchyListener(this); + } } public void addListDataListener(ListDataListener listener) @@ -365,4 +390,46 @@ public void setSelectedItem(Object item) else setSelectedDevice((CaptureDevice) item); } + + /** + * We listen for changes in the devices in order to update the list + * of devices we show. + * @param event the event. + */ + public void propertyChange(final PropertyChangeEvent event) + { + if(DeviceConfiguration.PROP_AUDIO_SYSTEM_DEVICES + .equals(event.getPropertyName())) + { + if(!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater( + new Runnable() + { + public void run() + { + propertyChange(event); + } + }); + return; + } + + devices = null; + fireContentsChanged(0, getSize() - 1); + } + } + + /** + * We listen when the component was hidden in order to release resources, + * remove listener to clean this instance. + * @param e the event. + */ + public void hierarchyChanged(HierarchyEvent e) + { + if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0 + && !parent.isShowing()) + { + deviceConfiguration.removePropertyChangeListener(this); + } + } } diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java b/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java index 30b4cb686..be749ee08 100644 --- a/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java +++ b/src/net/java/sip/communicator/impl/neomedia/MediaConfiguration.java @@ -335,7 +335,7 @@ public void run() * are to control the details of the specified audioSystem are to * be added */ - private static void createAudioSystemControls( + public static void createAudioSystemControls( AudioSystem audioSystem, JComponent container) { @@ -380,6 +380,7 @@ private static void createAudioSystemControls( captureCombo.setEditable(false); captureCombo.setModel( new DeviceConfigurationComboBoxModel( + captureCombo, mediaService.getDeviceConfiguration(), DeviceConfigurationComboBoxModel.AUDIO_CAPTURE)); constraints.gridy = 0; @@ -406,6 +407,7 @@ private static void createAudioSystemControls( playbackCombo.setEditable(false); playbackCombo.setModel( new DeviceConfigurationComboBoxModel( + captureCombo, mediaService.getDeviceConfiguration(), DeviceConfigurationComboBoxModel.AUDIO_PLAYBACK)); container.add(playbackCombo, constraints); @@ -415,6 +417,7 @@ private static void createAudioSystemControls( notifyCombo.setEditable(false); notifyCombo.setModel( new DeviceConfigurationComboBoxModel( + captureCombo, mediaService.getDeviceConfiguration(), DeviceConfigurationComboBoxModel.AUDIO_NOTIFY)); container.add(notifyCombo, constraints); @@ -488,6 +491,7 @@ public static Component createBasicControls(final int type) deviceComboBox.setEditable(false); deviceComboBox.setModel( new DeviceConfigurationComboBoxModel( + deviceComboBox, mediaService.getDeviceConfiguration(), type)); diff --git a/src/net/java/sip/communicator/impl/neomedia/NeomediaActivator.java b/src/net/java/sip/communicator/impl/neomedia/NeomediaActivator.java index 7dc5db014..b1073526d 100644 --- a/src/net/java/sip/communicator/impl/neomedia/NeomediaActivator.java +++ b/src/net/java/sip/communicator/impl/neomedia/NeomediaActivator.java @@ -6,6 +6,8 @@ */ package net.java.sip.communicator.impl.neomedia; +import java.awt.*; +import java.awt.event.*; import java.beans.*; import java.io.*; import java.util.*; @@ -24,6 +26,7 @@ import net.java.sip.communicator.service.packetlogging.*; import net.java.sip.communicator.service.resources.*; import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.swing.*; import org.osgi.framework.*; @@ -153,6 +156,11 @@ public class NeomediaActivator */ private static boolean jmfRegistryDisableLoad; + /** + * Audio configuration dialog. + */ + private static SIPCommDialog audioConfigDialog = null; + /** * Sets up FMJ for execution. For example, sets properties which instruct * FMJ whether it is to create a log, where the log is to be created. @@ -265,39 +273,12 @@ public void start(BundleContext bundleContext) deviceConfigurationPropertyChangeListener = new PropertyChangeListener() { - public void propertyChange( - final PropertyChangeEvent event) + public void propertyChange(PropertyChangeEvent event) { if (DeviceConfiguration.PROP_AUDIO_SYSTEM_DEVICES .equals(event.getPropertyName())) { - if (!SwingUtilities.isEventDispatchThread()) - { - SwingUtilities.invokeLater( - new Runnable() - { - public void run() - { - propertyChange(event); - } - }); - return; - } - - UIService uiService = getUIService(); - - if (uiService == null) - return; - - ConfigurationContainer configurationContainer - = uiService.getConfigurationContainer(); - - if (configurationContainer == null) - return; - - configurationContainer.setSelected( - audioConfigurationForm); - configurationContainer.setVisible(true); + showAudioConfiguration(); } } }; @@ -417,6 +398,118 @@ public void run() } } + /** + * Show audio configuration panel when media devices change. + */ + private void showAudioConfiguration() + { + if(audioConfigDialog != null && audioConfigDialog.isVisible()) + { + // Because toFront() method gives us no guarantee that our dialog + // would go on top we'll try to also first request the focus and + // set our dialog always on top to put all the chances on our side. + audioConfigDialog.requestFocus(); + audioConfigDialog.setAlwaysOnTop(true); + audioConfigDialog.toFront(); + audioConfigDialog.setAlwaysOnTop(false); + return; + } + + if (!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater( + new Runnable() + { + public void run() + { + showAudioConfiguration(); + } + }); + return; + } + + audioConfigDialog = + new SIPCommDialog() + { + /** Serial version UID. */ + private static final long serialVersionUID = 0L; + + /** {@inheritDoc} */ + @Override + protected void close(boolean escaped) + { + setVisible(false); + audioConfigDialog = null; + } + }; + + TransparentPanel mainPanel + = new TransparentPanel(new BorderLayout(20, 5)); + TransparentPanel fieldsPanel + = new TransparentPanel(new BorderLayout(10, 5)); + + mainPanel.setBorder( + BorderFactory.createEmptyBorder(20, 20, 20, 20)); + + TransparentPanel btnPanel + = new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); + ResourceManagementService resources + = NeomediaActivator.getResources(); + JButton btn + = new JButton(resources.getI18NString("service.gui.CLOSE")); + + btn.addActionListener( + new ActionListener() + { + public void actionPerformed(ActionEvent evt) + { + audioConfigDialog.setVisible(false); + } + }); + btnPanel.add(btn); + + JTextArea infoTextArea = new JTextArea(); + + infoTextArea.setOpaque(false); + infoTextArea.setEditable(false); + infoTextArea.setWrapStyleWord(true); + infoTextArea.setLineWrap(true); + infoTextArea.setText( + resources.getI18NString( + "impl.media.configform" + + ".AUDIO_DEVICE_CONNECTED_REMOVED")); + + JPanel preview = new TransparentPanel(new GridBagLayout()); + MediaConfiguration.createAudioSystemControls( + mediaServiceImpl.getDeviceConfiguration().getAudioSystem(), + preview); + + fieldsPanel.add(infoTextArea, BorderLayout.NORTH); + fieldsPanel.add(preview, BorderLayout.CENTER); + fieldsPanel.add(btnPanel, BorderLayout.SOUTH); + + TransparentPanel iconPanel + = new TransparentPanel(new BorderLayout()); + + iconPanel.add( + new JLabel( + resources.getImage( + "plugin.mediaconfig.AUDIO_ICON_64x64")), + BorderLayout.NORTH); + + mainPanel.add(iconPanel, BorderLayout.WEST); + mainPanel.add(fieldsPanel, BorderLayout.CENTER); + + audioConfigDialog.setTitle( + resources.getI18NString( + "impl.media.configform.AUDIO_DEVICE_CONFIG")); + audioConfigDialog.add(mainPanel); + audioConfigDialog.validate(); + audioConfigDialog.pack(); + + audioConfigDialog.setVisible(true); + } + /** * Stops the execution of the neomedia bundle in the specified context. *