/* * 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.media.device; import java.util.*; import javax.media.*; import javax.media.format.*; import net.java.sip.communicator.impl.media.*; import net.java.sip.communicator.service.configuration.*; import net.java.sip.communicator.util.*; /** * This class aims to provide a simple configuration interface for JMF. It * retrieves stored configuration when started or listens to ConfigurationEvent * for property changes and configures the JMF accordingly. * * @author Martin Andre * @author Emil Ivov * @author Lubomir Marinov */ public class DeviceConfiguration { /** * The name of the <code>DeviceConfiguration</code> property which * represents the device used by <code>DeviceConfiguration</code> for video * capture. */ public static final String AUDIO_CAPTURE_DEVICE = "AUDIO_CAPTURE_DEVICE"; /** * The name of the <code>DeviceConfiguration</code> property which * represents the device used by <code>DeviceConfiguration</code> for video * capture. */ public static final String VIDEO_CAPTURE_DEVICE = "VIDEO_CAPTURE_DEVICE"; private static final String PROP_AUDIO_DEVICE = "net.java.sip.communicator.impl.media.audiodev"; private static final String PROP_AUDIO_DEVICE_IS_DISABLED = "net.java.sip.communicator.impl.media.audiodevIsDisabled"; private static final String PROP_VIDEO_DEVICE = "net.java.sip.communicator.impl.media.videodev"; private static final String PROP_VIDEO_DEVICE_IS_DISABLED = "net.java.sip.communicator.impl.media.videodevIsDisabled"; private static final CaptureDeviceInfo[] NO_CAPTURE_DEVICES = new CaptureDeviceInfo[0]; private Logger logger = Logger.getLogger(DeviceConfiguration.class); /** * The device that we'll be using for audio capture. */ private CaptureDeviceInfo audioCaptureDevice = null; /** * The device that we'll be using for video capture. */ private CaptureDeviceInfo videoCaptureDevice; /** * Listeners that will be notified every time * a device has been changed. */ private final List<PropertyChangeListener> propertyChangeListeners = new Vector<PropertyChangeListener>(); /** * Default constructor. */ public DeviceConfiguration() { } /** * Adds <tt>listener</tt> to the list of listeners registered to receive * events upon modification of chat room properties such as its subject * for example. * * @param listener the <tt>ChatRoomChangeListener</tt> that is to be * registered for <tt>ChatRoomChangeEvent</tt>-s. */ public void addPropertyChangeListener(PropertyChangeListener listener) { synchronized(propertyChangeListeners) { if (!propertyChangeListeners.contains(listener)) propertyChangeListeners.add(listener); } } /** * Removes <tt>listener</tt> from the list of listeneres current * registered for chat room modification events. * * @param listener the <tt>ChatRoomChangeListener</tt> to remove. */ public void removePropertyChangeListener(PropertyChangeListener listener) { synchronized(propertyChangeListeners) { propertyChangeListeners.remove(listener); } } /** * Initializes capture devices. */ public void initialize() { // these seem to be throwing exceptions every now and then so we'll // blindly catch them for now try { JmfDeviceDetector.detectAndConfigureCaptureDevices(); extractConfiguredCaptureDevices(); } catch (Exception ex) { logger.error("Failed to initialize media.", ex); } } /** * Detects capture devices configured through JMF and disable audio and/or * video transmission if none were found. Stores found devices in * audioCaptureDevice and videoCaptureDevice. */ private void extractConfiguredCaptureDevices() { ConfigurationService config = MediaActivator.getConfigurationService(); logger.info("Scanning for configured Audio Devices."); CaptureDeviceInfo[] audioCaptureDevices = getAvailableAudioCaptureDevices(); if (config.getBoolean(PROP_AUDIO_DEVICE_IS_DISABLED, false)) audioCaptureDevice = null; else if (audioCaptureDevices.length < 1) { logger.warn("No Audio Device was found."); audioCaptureDevice = null; } else { logger.debug("Found " + audioCaptureDevices.length + " capture devices: " + audioCaptureDevices); String audioDevName = config.getString(PROP_AUDIO_DEVICE); if(audioDevName == null) audioCaptureDevice = audioCaptureDevices[0]; else { for (CaptureDeviceInfo captureDeviceInfo : audioCaptureDevices) { if (audioDevName.equals(captureDeviceInfo.getName())) { audioCaptureDevice = captureDeviceInfo; break; } } } if (audioCaptureDevice != null) logger.info("Found " + audioCaptureDevice.getName() + " as an audio capture device."); } if (config.getBoolean(PROP_VIDEO_DEVICE_IS_DISABLED, false)) videoCaptureDevice = null; else { logger.info("Scanning for configured Video Devices."); videoCaptureDevice = extractConfiguredVideoCaptureDevice(VideoFormat.RGB); // no RGB camera found. And what about YUV ? if (videoCaptureDevice == null) { videoCaptureDevice = extractConfiguredVideoCaptureDevice(VideoFormat.YUV); if (videoCaptureDevice == null) logger.info("No Video Device was found."); } } } private CaptureDeviceInfo extractConfiguredVideoCaptureDevice(String format) { List<CaptureDeviceInfo> videoCaptureDevices = CaptureDeviceManager.getDeviceList(new VideoFormat(format)); CaptureDeviceInfo videoCaptureDevice = null; if (videoCaptureDevices.size() > 0) { String videoDevName = MediaActivator.getConfigurationService().getString( PROP_VIDEO_DEVICE); if (videoDevName == null) videoCaptureDevice = videoCaptureDevices.get(0); else { for (CaptureDeviceInfo captureDeviceInfo : videoCaptureDevices) { if (videoDevName.equals(captureDeviceInfo.getName())) { videoCaptureDevice = captureDeviceInfo; break; } } } if (videoCaptureDevice != null) logger.info("Found " + videoCaptureDevice.getName() + " as an RGB Video Device."); } return videoCaptureDevice; } /** * Returns a device that we could use for audio capture. * * @return the CaptureDeviceInfo of a device that we could use for audio * capture. */ public CaptureDeviceInfo getAudioCaptureDevice() { return audioCaptureDevice; } /** * Gets the list of audio capture devices which are available through this * <code>DeviceConfiguration</code>, amongst which is * {@link #getAudioCaptureDevice()} and represent acceptable values * for {@link #setAudioCaptureDevice(CaptureDeviceInfo)} * * @return an array of <code>CaptureDeviceInfo</code> describing the audio * capture devices available through this * <code>DeviceConfiguration</code> */ public CaptureDeviceInfo[] getAvailableAudioCaptureDevices() { Vector<CaptureDeviceInfo> audioCaptureDevices = CaptureDeviceManager.getDeviceList(new AudioFormat( AudioFormat.LINEAR, 44100, 16, 1));// 1 means 1 channel for mono return audioCaptureDevices.toArray(NO_CAPTURE_DEVICES); } /** * Gets the list of video capture devices which are available through this * <code>DeviceConfiguration</code>, amongst which is * {@link #getVideoCaptureDevice()} and represent acceptable values * for {@link #setVideoCaptureDevice(CaptureDeviceInfo)} * * @return an array of <code>CaptureDeviceInfo</code> describing the video * capture devices available through this * <code>DeviceConfiguration</code> */ public CaptureDeviceInfo[] getAvailableVideoCaptureDevices() { Set<CaptureDeviceInfo> videoCaptureDevices = new HashSet<CaptureDeviceInfo>(); videoCaptureDevices.addAll(CaptureDeviceManager .getDeviceList(new VideoFormat(VideoFormat.RGB))); videoCaptureDevices.addAll(CaptureDeviceManager .getDeviceList(new VideoFormat(VideoFormat.YUV))); return videoCaptureDevices.toArray(NO_CAPTURE_DEVICES); } /** * Returns a device that we could use for video capture. * * @return the CaptureDeviceInfo of a device that we could use for video * capture. */ public CaptureDeviceInfo getVideoCaptureDevice() { return videoCaptureDevice; } /** * Sets the device which is to be used by this * <code>DeviceConfiguration</code> for video capture. * * @param device a <code>CaptureDeviceInfo</code> describing device to be * used by this <code>DeviceConfiguration</code> for video * capture */ public void setVideoCaptureDevice(CaptureDeviceInfo device) { if (videoCaptureDevice != device) { CaptureDeviceInfo oldDevice = videoCaptureDevice; videoCaptureDevice = device; ConfigurationService config = MediaActivator.getConfigurationService(); config.setProperty(PROP_VIDEO_DEVICE_IS_DISABLED, videoCaptureDevice == null); if (videoCaptureDevice != null) config.setProperty(PROP_VIDEO_DEVICE, videoCaptureDevice .getName()); firePropertyChange(VIDEO_CAPTURE_DEVICE, oldDevice, device); } } /** * Sets the device which is to be used by this * <code>DeviceConfiguration</code> for audio capture. * * @param device a <code>CaptureDeviceInfo</code> describing the device to * be used by this <code>DeviceConfiguration</code> for audio * capture */ public void setAudioCaptureDevice(CaptureDeviceInfo device) { if (audioCaptureDevice != device) { CaptureDeviceInfo oldDevice = audioCaptureDevice; audioCaptureDevice = device; ConfigurationService config = MediaActivator.getConfigurationService(); config.setProperty(PROP_AUDIO_DEVICE_IS_DISABLED, audioCaptureDevice == null); if (audioCaptureDevice != null) config.setProperty(PROP_AUDIO_DEVICE, audioCaptureDevice .getName()); firePropertyChange(AUDIO_CAPTURE_DEVICE, oldDevice, device); } } protected void firePropertyChange(String property, Object oldValue, Object newValue) { PropertyChangeEvent event = new PropertyChangeEvent(this, property, oldValue, newValue); for (PropertyChangeListener listener : propertyChangeListeners) listener.propertyChange(event); } /** * Enable or disable Audio stream transmission. * * @return true if audio capture is supported and false otherwise. */ public boolean isAudioCaptureSupported() { return this.audioCaptureDevice != null; } /** * Enable or disable Video stream transmission. * * @return true if audio capture is supported and false otherwise. */ public boolean isVideoCaptureSupported() { return this.videoCaptureDevice != null; } }