diff --git a/src/org/jitsi/impl/neomedia/device/AudioSystem.java b/src/org/jitsi/impl/neomedia/device/AudioSystem.java index 687044839df688d701a97c0b0f51635b28e864bf..8a1ac516014f66628752c343e8669f15ff310d5d 100644 --- a/src/org/jitsi/impl/neomedia/device/AudioSystem.java +++ b/src/org/jitsi/impl/neomedia/device/AudioSystem.java @@ -217,7 +217,7 @@ protected void setPlaybackDevices( List<ExtendedCaptureDeviceInfo> activePlaybackDevices) { devices[PLAYBACK_INDEX].setActiveDevices(activePlaybackDevices); - // The active notify device list is a copy of the playback one. + // The notify devices are the same as the playback devices. devices[NOTIFY_INDEX].setActiveDevices(activePlaybackDevices); } @@ -282,7 +282,7 @@ protected void postInitialize() /** * Sets the device lists after the different audio systems (PortAudio, - * PulseAudio, etc) have finished to detects the devices. + * PulseAudio, etc) have finished detecting their devices. * * @param index The index corresponding to a specific device kind: * capture/notify/playback. @@ -357,8 +357,8 @@ public InputStream getAudioInputStream(String uri) url = new URL(uri); } - audioStream = javax.sound.sampled.AudioSystem - .getAudioInputStream(url); + audioStream + = javax.sound.sampled.AudioSystem.getAudioInputStream(url); } catch (MalformedURLException e) { diff --git a/src/org/jitsi/impl/neomedia/device/CaptureDevices.java b/src/org/jitsi/impl/neomedia/device/CaptureDevices.java index 422b1adddc47064f8b7a8b58c43d0327ef61ead3..6e58099edc124bc1340b47782c5e12d7e8bb79ad 100644 --- a/src/org/jitsi/impl/neomedia/device/CaptureDevices.java +++ b/src/org/jitsi/impl/neomedia/device/CaptureDevices.java @@ -51,24 +51,24 @@ public CaptureDevices(AudioSystem audioSystem) */ public List<ExtendedCaptureDeviceInfo> getDevices() { - Format[] formats; - Format format = new AudioFormat(AudioFormat.LINEAR, -1, 16, -1); List<ExtendedCaptureDeviceInfo> devices = null; - if(this.activeCaptureDevices != null) + if(activeCaptureDevices != null) { - devices = new ArrayList<ExtendedCaptureDeviceInfo>( - this.activeCaptureDevices.size()); + devices + = new ArrayList<ExtendedCaptureDeviceInfo>( + activeCaptureDevices.size()); - for(ExtendedCaptureDeviceInfo device: this.activeCaptureDevices) + Format format = new AudioFormat(AudioFormat.LINEAR, -1, 16, -1); + + for(ExtendedCaptureDeviceInfo device: activeCaptureDevices) { - formats = device.getFormats(); - for(int i = 0; i < formats.length; ++i) + for(Format deviceFormat : device.getFormats()) { - if(formats[i].matches(format)) + if(deviceFormat.matches(format)) { devices.add(device); - i = formats.length; + break; } } } @@ -77,6 +77,16 @@ public List<ExtendedCaptureDeviceInfo> getDevices() return devices; } + /** + * Returns the property of the capture devices. + * + * @return The property of the capture devices. + */ + protected String getPropDevice() + { + return PROP_DEVICE; + } + /** * Sets the list of the active devices. * @@ -106,18 +116,8 @@ public void setActiveDevices(List<ExtendedCaptureDeviceInfo> activeDevices) } } - this.activeCaptureDevices = (activeDevices == null) + activeCaptureDevices = (activeDevices == null) ? null : new ArrayList<ExtendedCaptureDeviceInfo>(activeDevices); } - - /** - * Returns the property of the capture devices. - * - * @return The property of the capture devices. - */ - protected String getPropDevice() - { - return PROP_DEVICE; - } } diff --git a/src/org/jitsi/impl/neomedia/device/DeviceSystem.java b/src/org/jitsi/impl/neomedia/device/DeviceSystem.java index 8c957c3f4377844170aed2e286b8e00a9296680e..48f7604811cb19eb2aa6a3673b3cff116de28462 100644 --- a/src/org/jitsi/impl/neomedia/device/DeviceSystem.java +++ b/src/org/jitsi/impl/neomedia/device/DeviceSystem.java @@ -41,6 +41,12 @@ public abstract class DeviceSystem */ private static final Logger logger = Logger.getLogger(DeviceSystem.class); + /** + * The list of <tt>DeviceSystem</tt>s which have been initialized. + */ + private static List<DeviceSystem> deviceSystems + = new LinkedList<DeviceSystem>(); + /** * The constant/flag (to be) returned by {@link #getFeatures()} in order to * indicate that the respective <tt>DeviceSystem</tt> supports invoking its @@ -63,23 +69,30 @@ public abstract class DeviceSystem public static final String PROP_DEVICES = "devices"; /** - * The list of devices connected at the last preInitialize. + * The list of devices connected at the last postInitialize. */ - private static Vector<CaptureDeviceInfo> propertyChangeOldDevices + private static Vector<CaptureDeviceInfo> propertyChangeNewDevices = new Vector<CaptureDeviceInfo>(); /** - * The list of devices connected at the last postInitialize. + * The list of devices connected at the last preInitialize. */ - private static Vector<CaptureDeviceInfo> propertyChangeNewDevices + private static Vector<CaptureDeviceInfo> propertyChangeOldDevices = new Vector<CaptureDeviceInfo>(); /** - * The list of <tt>DeviceSystem</tt>s which have been initialized. + * Returns a <tt>List</tt> of <tt>CaptureDeviceInfo</tt>s which are elements + * of a specific <tt>List</tt> of <tt>CaptureDeviceInfo</tt>s and have a + * specific <tt>MediaLocator</tt> protocol. + * + * @param deviceList the <tt>List</tt> of <tt>CaptureDeviceInfo</tt> which + * are to be filtered based on the specified <tt>MediaLocator</tt> protocol + * @param locatorProtocol the protocol of the <tt>MediaLocator</tt>s of the + * <tt>CaptureDeviceInfo</tt>s which are to be returned + * @return a <tt>List</tt> of <tt>CaptureDeviceInfo</tt>s which are elements + * of the specified <tt>deviceList</tt> and have the specified + * <tt>locatorProtocol</tt> */ - private static List<DeviceSystem> deviceSystems - = new LinkedList<DeviceSystem>(); - protected static List<CaptureDeviceInfo> filterDeviceListByLocatorProtocol( List<CaptureDeviceInfo> deviceList, String locatorProtocol) @@ -388,14 +401,72 @@ public Renderer createRenderer(boolean playback) return null; } + /** + * Invoked by {@link #initialize()} to perform the very logic of the + * initialization of this <tt>DeviceSystem</tt>. This instance has been + * prepared for initialization by an earlier call to + * {@link #preInitialize()} and the initialization will be completed with a + * subsequent call to {@link #postInitialize()}. + * + * @throws Exception if an error occurs during the initialization of this + * instance. The initialization of this instance will be completed with a + * subsequent call to <tt>postInitialize()</tt> regardless of any + * <tt>Exception</tt> thrown by <tt>doInitialize()</tt>. + */ protected abstract void doInitialize() throws Exception; + /** + * Gets the flags indicating the optional features supported by this + * <tt>DeviceSystem</tt>. + * + * @return the flags indicating the optional features supported by this + * <tt>DeviceSystem</tt>. The possible flags are among the + * <tt>FEATURE_XXX</tt> constants defined by the <tt>DeviceSystem</tt> class + * and its extenders. + */ public final int getFeatures() { return features; } + /** + * Returns the format depending on the media type: AudioFormat for AUDIO, + * VideoFormat for VIDEO. Otherwise, returns null. + * + * @return The format depending on the media type: AudioFormat for AUDIO, + * VideoFormat for VIDEO. Otherwise, returns null. + */ + public Format getFormat() + { + Format format = null; + + switch (getMediaType()) + { + case AUDIO: + format = new AudioFormat(null); + break; + case VIDEO: + format = new VideoFormat(null); + break; + default: + format = null; + break; + } + + return format; + } + + /** + * Gets the protocol of the <tt>MediaLocator</tt> of the + * <tt>CaptureDeviceInfo</tt>s (to be) registered (with FMJ) by this + * <tt>DeviceSystem</tt>. The protocol is a unique identifier of a + * <tt>DeviceSystem</tt>. + * + * @return the protocol of the <tt>MediaLocator</tt> of the + * <tt>CaptureDeviceInfo</tt>s (to be) registered (with FMJ) by this + * <tt>DeviceSystem</tt> + */ public final String getLocatorProtocol() { return locatorProtocol; @@ -406,11 +477,32 @@ public final MediaType getMediaType() return mediaType; } + /** + * Gets the name of the class which implements the <tt>Renderer</tt> + * interface to render media on a playback or notification device associated + * with this <tt>DeviceSystem</tt>. Invoked by + * {@link #createRenderer(boolean)}. + * + * @return the name of the class which implements the <tt>Renderer</tt> + * interface to render media on a playback or notification device associated + * with this <tt>DeviceSystem</tt> or <tt>null</tt> if no <tt>Renderer</tt> + * instance is to be created by the <tt>DeviceSystem</tt> implementation or + * <tt>createRenderer(boolean) is overridden. + */ protected String getRendererClassName() { return null; } + /** + * Initializes this <tt>DeviceSystem</tt> i.e. represents the native/system + * devices in the terms of the application so that they may be utilized. For + * example, the capture devices are represented as + * <tt>CaptureDeviceInfo</tt> instances registered with FMJ. + * + * @throws Exception if an error occurs during the initialization of this + * <tt>DeviceSystem</tt> + */ protected final void initialize() throws Exception { @@ -435,7 +527,7 @@ protected final void initialize() */ protected void postInitialize() { - Format format = this.getFormat(); + Format format = getFormat(); if (format != null) { @@ -444,7 +536,7 @@ protected void postInitialize() propertyChangeNewDevices.addAll( CaptureDeviceManager.getDeviceList(format)); - // Compares the previous conencted device list with the current one, + // Compares the previous connected device list with the current one // in order to detect new connected or disconnected devices. for(int i = 0; i < propertyChangeOldDevices.size(); ++i) { @@ -478,7 +570,7 @@ protected void postInitialize() */ protected void preInitialize() { - Format format = this.getFormat(); + Format format = getFormat(); if (format != null) { @@ -535,31 +627,4 @@ public String toString() { return getLocatorProtocol(); } - - /** - * Returns the format depending on the media type: AudioFormat for AUDIO, - * VideoFormat for VIDEO. Otherwise, returns null. - * - * @return The format depending on the media type: AudioFormat for AUDIO, - * VideoFormat for VIDEO. Otherwise, returns null. - */ - public Format getFormat() - { - Format format = null; - - switch (getMediaType()) - { - case AUDIO: - format = new AudioFormat(null); - break; - case VIDEO: - format = new VideoFormat(null); - break; - default: - format = null; - break; - } - - return format; - } } diff --git a/src/org/jitsi/impl/neomedia/device/Devices.java b/src/org/jitsi/impl/neomedia/device/Devices.java index f63cae7e900e285e0818e87efa3e4ee7e29fc70a..56ab17b8bad9a5451c8f9ffa72f16e714b5278da 100644 --- a/src/org/jitsi/impl/neomedia/device/Devices.java +++ b/src/org/jitsi/impl/neomedia/device/Devices.java @@ -75,7 +75,7 @@ public ExtendedCaptureDeviceInfo getDevice( // Adds the device in the preference list (to the end of the // list, but the save device will push it to the top of // active devices). - this.saveDevice( + saveDevice( locator, property, activeDevice, @@ -88,20 +88,20 @@ public ExtendedCaptureDeviceInfo getDevice( // in the preferences. synchronized(devicePreferences) { - for(int i = 0; i < devicePreferences.size(); ++i) + for(String devicePreference : devicePreferences) { for(ExtendedCaptureDeviceInfo activeDevice : activeDevices) { // If we have found the "preferred" device among active // device. - if(devicePreferences.get(i).equals( - activeDevice.getIdentifier())) + if(devicePreference.equals( + activeDevice.getIdentifier())) { return activeDevice; } // If the "none" device is the "preferred" device among // "active" device. - else if(devicePreferences.get(i).equals( + else if(devicePreference.equals( NoneAudioSystem.LOCATOR_PROTOCOL)) { return null; @@ -211,14 +211,14 @@ private void saveDevice( } // Sorts the user preferences to put the selected device on top. - this.addToDevicePreferences( + addToDevicePreferences( locator, activeDevices, selectedDeviceIdentifier, isSelected); // Saves the user preferences. - this.writeDevicePreferences(locator, property); + writeDevicePreferences(locator, property); } /** @@ -253,8 +253,7 @@ public void setDevice( } this.device = device; - this.audioSystem - .propertyChange(getPropDevice(), oldValue, this.device); + audioSystem.propertyChange(getPropDevice(), oldValue, this.device); } } @@ -394,7 +393,8 @@ private void writeDevicePreferences(String locator, String property) + "." + property + "_list"; - StringBuffer value = new StringBuffer("[\""); + StringBuilder value = new StringBuilder("[\""); + synchronized(devicePreferences) { if(devicePreferences.size() > 0) @@ -402,11 +402,12 @@ private void writeDevicePreferences(String locator, String property) value.append(devicePreferences.get(0)); for(int i = 1; i < devicePreferences.size(); ++i) { - value.append("\", \"" + devicePreferences.get(i)); + value.append("\", \"").append(devicePreferences.get(i)); } } } value.append("\"]"); + cfg.setProperty(property, value.toString()); } } diff --git a/src/org/jitsi/impl/neomedia/device/ExtendedCaptureDeviceInfo.java b/src/org/jitsi/impl/neomedia/device/ExtendedCaptureDeviceInfo.java index abad36387492608227cf23d060dd9f308e6359fa..7a3f611045ae7d88f8d4aa8ae920cd057df2f0c7 100644 --- a/src/org/jitsi/impl/neomedia/device/ExtendedCaptureDeviceInfo.java +++ b/src/org/jitsi/impl/neomedia/device/ExtendedCaptureDeviceInfo.java @@ -18,14 +18,14 @@ public class ExtendedCaptureDeviceInfo extends CaptureDeviceInfo { /** - * The device UID (unique identifier). + * The device transport type. */ - private final String UID; + private final String transportType; /** - * The device transport type. + * The device UID (unique identifier). */ - private final String transportType; + private final String uid; /** * Constructs a CaptureDeviceInfo object with the specified name, media @@ -37,14 +37,14 @@ public class ExtendedCaptureDeviceInfo */ public ExtendedCaptureDeviceInfo( CaptureDeviceInfo captureDeviceInfo, - String UID, + String uid, String transportType) { this( captureDeviceInfo.getName(), captureDeviceInfo.getLocator(), captureDeviceInfo.getFormats(), - UID, + uid, transportType); } @@ -59,82 +59,92 @@ public ExtendedCaptureDeviceInfo( * @param transportType The device transport type. */ public ExtendedCaptureDeviceInfo( - String name, - MediaLocator locator, - Format[] formats, - String UID, - String transportType) + String name, MediaLocator locator, Format[] formats, + String uid, String transportType) { super(name, locator, formats); - this.UID = UID; + this.uid = uid; this.transportType = transportType; } /** - * Returns the device UID (unique identifier). + * Determines whether a specific <tt>Object</tt> is equal (by value) to this + * instance. * - * @return The device UID (unique identifier). + * @param obj the <tt>Object</tt> to be determined whether it is equal (by + * value) to this instance + * @return <tt>true</tt> if the specified <tt>obj</tt> is equal (by value) + * to this instance; otherwise, <tt>false</tt> */ - public String getUID() + @Override + public boolean equals(Object obj) { - return this.UID; + return + (obj != null) + && (obj instanceof ExtendedCaptureDeviceInfo) + && getIdentifier().equals( + ((ExtendedCaptureDeviceInfo) obj).getIdentifier()); } /** - * Returns the device transport type. + * Returns the device identifier used to save and load device preferences. + * It is composed by the system UID if not null. Otherwise returns the + * device name and (if not null) the transport type. * - * @return The device transport type. + * @return The device identifier. */ - public String getTransportType() + public String getIdentifier() { - return this.transportType; + return (uid == null) ? name : uid; } /** - * Returns if the transport type matches the one given in parameter. - * - * The transport type to compare with. + * Returns the device transport type of this instance. * - * @return True if the transport type matches the one given in parameter. - * False otherwise. + * @return the device transport type of this instance */ - public boolean isSameTransportType(String transportType) + public String getTransportType() { - if(this.transportType == null) - { - return (transportType == null); - } - return this.transportType.equals(transportType); + return transportType; } - @Override - public boolean equals(Object obj) + /** + * Returns the device UID (unique identifier) of this instance. + * + * @return the device UID (unique identifier) of this instance + */ + public String getUID() { - if(obj != null - && obj instanceof ExtendedCaptureDeviceInfo) - { - return this.getIdentifier().equals( - ((ExtendedCaptureDeviceInfo) obj).getIdentifier()); - } - return false; + return uid; } + /** + * Returns a hash code value for this object for the benefit of hashtables. + * + * @return a hash code value for this object for the benefit of hashtables + */ @Override public int hashCode() { - return this.getIdentifier().hashCode(); + return getIdentifier().hashCode(); } /** - * Returns the device identifier used to save and load device preferences. - * It is composed by the system UID if not null. Otherwise returns the - * device name and (if not null) the transport type. + * Determines whether a specific transport type is equal to/the same as the + * transport type of this instance. * - * @return The device identifier. + * @param transportType the transport type to compare to the transport type + * of this instance + * @return <tt>true</tt> if the specified <tt>transportType</tt> is equal + * to/the same as the transport type of this instance; otherwise, + * <tt>false</tt> */ - public String getIdentifier() + public boolean isSameTransportType(String transportType) { - return (UID == null) ? name : UID; + return + (this.transportType == null) + ? (transportType == null) + : this.transportType.equals(transportType); } } diff --git a/src/org/jitsi/impl/neomedia/device/PlaybackDevices.java b/src/org/jitsi/impl/neomedia/device/PlaybackDevices.java index 8f2715fc837750c442d089675c78a594e642b17b..e7b64895035befc2c6ce63950330a89dc2c19d65 100644 --- a/src/org/jitsi/impl/neomedia/device/PlaybackDevices.java +++ b/src/org/jitsi/impl/neomedia/device/PlaybackDevices.java @@ -45,31 +45,31 @@ public PlaybackDevices(AudioSystem audioSystem) */ public List<ExtendedCaptureDeviceInfo> getDevices() { - return (this.activePlaybackDevices == null) + return (activePlaybackDevices == null) ? null : new ArrayList<ExtendedCaptureDeviceInfo>( - this.activePlaybackDevices); + activePlaybackDevices); } /** - * Sets the list of the active devices. + * Returns the property of the capture devices. * - * @param activeDevices The list of the active devices. + * @return The property of the capture devices. */ - public void setActiveDevices(List<ExtendedCaptureDeviceInfo> activeDevices) + protected String getPropDevice() { - this.activePlaybackDevices = (activeDevices == null) - ? null - : new ArrayList<ExtendedCaptureDeviceInfo>(activeDevices); + return PROP_DEVICE; } /** - * Returns the property of the capture devices. + * Sets the list of the active devices. * - * @return The property of the capture devices. + * @param activeDevices The list of the active devices. */ - protected String getPropDevice() + public void setActiveDevices(List<ExtendedCaptureDeviceInfo> activeDevices) { - return PROP_DEVICE; + activePlaybackDevices = (activeDevices == null) + ? null + : new ArrayList<ExtendedCaptureDeviceInfo>(activeDevices); } } diff --git a/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java b/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java index 41fad820066ff951977841b9a3f847550539a977..2af313dd1526ab37dddc1a1dea6670525adc3bee 100644 --- a/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java +++ b/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java @@ -8,6 +8,7 @@ import java.lang.ref.*; import java.util.*; +import java.util.regex.*; import javax.media.*; import javax.media.format.*; @@ -220,10 +221,13 @@ protected void doInitialize() long sampleFormat = Pa.getPaSampleFormat(sampleSizeInBits); int defaultInputDeviceIndex = Pa.GetDefaultInputDevice(); int defaultOutputDeviceIndex = Pa.GetDefaultOutputDevice(); + List<ExtendedCaptureDeviceInfo> captureAndPlaybackDevices + = new LinkedList<ExtendedCaptureDeviceInfo>(); List<ExtendedCaptureDeviceInfo> captureDevices = new LinkedList<ExtendedCaptureDeviceInfo>(); List<ExtendedCaptureDeviceInfo> playbackDevices = new LinkedList<ExtendedCaptureDeviceInfo>(); + final boolean loggerIsDebugEnabled = logger.isDebugEnabled(); for (int deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) { @@ -242,83 +246,152 @@ protected void doInitialize() String deviceUID = Pa.DeviceInfo_getDeviceUID(deviceInfo); + /* + * TODO The intention of reinitialize() was to perform the + * initialization from scratch. However, AudioSystem was later + * changed to disobey. But we should at least search through both + * CAPTURE_INDEX and PLAYBACK_INDEX. + */ + List<ExtendedCaptureDeviceInfo> existingCdis + = getDevices(CAPTURE_INDEX); ExtendedCaptureDeviceInfo cdi = null; - List<ExtendedCaptureDeviceInfo> devices = getDevices(CAPTURE_INDEX); - boolean found = false; - // Search if the device is already initiated. If yes used it, - // otherwise a call currently using this device will fail. - for(int i = 0; devices !=null && i < devices.size() && !found; ++i) + + if (existingCdis != null) { - // using identifier (name or uid, cause there can be some - // uid that are null) - String id = devices.get(i).getIdentifier(); - if(id.equals(deviceUID) || id.equals(name)) + for (ExtendedCaptureDeviceInfo existingCdi : existingCdis) { - cdi = devices.get(i); - found = true; + /* + * The deviceUID is optional so a device may be identified + * by deviceUID if it is available or by name if the + * deviceUID is not available. + */ + String id = existingCdi.getIdentifier(); + + if (id.equals(deviceUID) || id.equals(name)) + { + cdi = existingCdi; + break; + } } } - // If not found, then we must initialized this new device. - if(!found) + if (cdi == null) { - cdi = new ExtendedCaptureDeviceInfo( - name, - new MediaLocator(LOCATOR_PROTOCOL + ":#" + deviceIndex), - new Format[] - { - new AudioFormat( - AudioFormat.LINEAR, - (maxInputChannels > 0) - ? getSupportedSampleRate( - true, - deviceIndex, - channels, - sampleFormat) - : Pa.DEFAULT_SAMPLE_RATE, - sampleSizeInBits, - channels, - AudioFormat.LITTLE_ENDIAN, - AudioFormat.SIGNED, - Format.NOT_SPECIFIED /* frameSizeInBits */, - Format.NOT_SPECIFIED /* frameRate */, - Format.byteArray) - }, - deviceUID, - transportType); + cdi + = new ExtendedCaptureDeviceInfo( + name, + new MediaLocator( + LOCATOR_PROTOCOL + ":#" + deviceIndex), + new Format[] + { + new AudioFormat( + AudioFormat.LINEAR, + (maxInputChannels > 0) + ? getSupportedSampleRate( + true, + deviceIndex, + channels, + sampleFormat) + : Pa.DEFAULT_SAMPLE_RATE, + sampleSizeInBits, + channels, + AudioFormat.LITTLE_ENDIAN, + AudioFormat.SIGNED, + Format.NOT_SPECIFIED /* frameSizeInBits */, + Format.NOT_SPECIFIED /* frameRate */, + Format.byteArray) + }, + deviceUID, + transportType); } + /* + * When we perform automatic selection of capture and + * playback/notify devices, we would like to pick up devices from + * one and the same hardware because that sound like a natural + * expectation from the point of view of the user. In order to + * achieve that, we will bring the devices which support both + * capture and playback to the top. + */ if (maxInputChannels > 0) { - if (deviceIndex == defaultInputDeviceIndex) + List<ExtendedCaptureDeviceInfo> devices; + + if (maxOutputChannels > 0) + devices = captureAndPlaybackDevices; + else + devices = captureDevices; + + if ((deviceIndex == defaultInputDeviceIndex) + || ((maxOutputChannels > 0) + && (deviceIndex == defaultOutputDeviceIndex))) { - captureDevices.add(0, cdi); - if (logger.isDebugEnabled()) + devices.add(0, cdi); + if (loggerIsDebugEnabled) logger.debug("Added default capture device: " + name); } else { - captureDevices.add(cdi); - if (logger.isDebugEnabled()) + devices.add(cdi); + if (loggerIsDebugEnabled) logger.debug("Added capture device: " + name); } + if (loggerIsDebugEnabled && (maxInputChannels > 0)) + { + if (deviceIndex == defaultOutputDeviceIndex) + logger.debug("Added default playback device: " + name); + else + logger.debug("Added playback device: " + name); + } } - if (maxOutputChannels > 0) + else if (maxOutputChannels > 0) { if (deviceIndex == defaultOutputDeviceIndex) { playbackDevices.add(0, cdi); - if (logger.isDebugEnabled()) + if (loggerIsDebugEnabled) logger.debug("Added default playback device: " + name); } else { playbackDevices.add(cdi); - if (logger.isDebugEnabled()) + if (loggerIsDebugEnabled) logger.debug("Added playback device: " + name); } } } + /* + * Make sure that devices which support both capture and playback are + * reported as such and are preferred over devices which support either + * capture or playback (in order to achieve our goal to have automatic + * selection pick up devices from one and the same hardware). + */ + if (!captureDevices.isEmpty() && !playbackDevices.isEmpty()) + { + /* + * Event if we have not been provided with the information regarding + * the matching of the capture and playback/notify devices from one + * and the same hardware, we may still be able to deduce it by + * examining their names. + */ + matchDevicesByName(captureDevices, playbackDevices); + } + /* + * Of course, of highest reliability is the fact that a specific + * instance supports both capture and playback. + */ + if (!captureAndPlaybackDevices.isEmpty()) + { + for (int i = captureAndPlaybackDevices.size() - 1; i >= 0; i--) + { + ExtendedCaptureDeviceInfo cdi + = captureAndPlaybackDevices.get(i); + + captureDevices.add(0, cdi); + playbackDevices.add(0, cdi); + } + } + setCaptureDevices(captureDevices); setPlaybackDevices(playbackDevices); @@ -488,6 +561,87 @@ private static double getSupportedSampleRate( return supportedSampleRate; } + /** + * Attempts to reorder specific lists of capture and playback/notify + * <tt>ExtendedCaptureDeviceInfo</tt>s so that devices from the same + * hardware appear at the same indices in the respective lists. The judgment + * with respect to the belonging to the same hardware is based on the names + * of the specified <tt>ExtendedCaptureDeviceInfo</tt>s. The implementation + * is provided as a fallback to stand in for scenarios in which more + * accurate relevant information is not available. + * + * @param captureDevices + * @param playbackDevices + */ + private void matchDevicesByName( + List<ExtendedCaptureDeviceInfo> captureDevices, + List<ExtendedCaptureDeviceInfo> playbackDevices) + { + Iterator<ExtendedCaptureDeviceInfo> captureIter + = captureDevices.iterator(); + Pattern pattern + = Pattern.compile( + "microphone|speakers|\\p{Space}|\\(|\\)", + Pattern.CASE_INSENSITIVE); + LinkedList<ExtendedCaptureDeviceInfo> captureDevicesWithPlayback + = new LinkedList<ExtendedCaptureDeviceInfo>(); + LinkedList<ExtendedCaptureDeviceInfo> playbackDevicesWithCapture + = new LinkedList<ExtendedCaptureDeviceInfo>(); + int count = 0; + + while (captureIter.hasNext()) + { + ExtendedCaptureDeviceInfo captureDevice = captureIter.next(); + String captureName = captureDevice.getName(); + + if (captureName != null) + { + captureName = pattern.matcher(captureName).replaceAll(""); + if (captureName.length() != 0) + { + Iterator<ExtendedCaptureDeviceInfo> playbackIter + = playbackDevices.iterator(); + ExtendedCaptureDeviceInfo matchingPlaybackDevice = null; + + while (playbackIter.hasNext()) + { + ExtendedCaptureDeviceInfo playbackDevice + = playbackIter.next(); + String playbackName = playbackDevice.getName(); + + if (playbackName != null) + { + playbackName + = pattern + .matcher(playbackName) + .replaceAll(""); + if (captureName.equals(playbackName)) + { + playbackIter.remove(); + matchingPlaybackDevice = playbackDevice; + break; + } + } + } + if (matchingPlaybackDevice != null) + { + captureIter.remove(); + captureDevicesWithPlayback.add(captureDevice); + playbackDevicesWithCapture.add( + matchingPlaybackDevice); + count++; + } + } + } + } + + for (int i = count - 1; i >= 0; i--) + { + captureDevices.add(0, captureDevicesWithPlayback.get(i)); + playbackDevices.add(0, playbackDevicesWithCapture.get(i)); + } + } + /** * Reinitializes this <tt>PortAudioSystem</tt> in order to bring it up to * date with possible changes in the PortAudio devices. Invokes diff --git a/src/org/jitsi/impl/neomedia/maccoreaudio/CoreAudioVolumeControl.java b/src/org/jitsi/impl/neomedia/maccoreaudio/CoreAudioVolumeControl.java index 217906ba482b31624174b9b074375eade16a3b2d..873653501d3deda9e3556f0cf63e8a5acb4d592f 100644 --- a/src/org/jitsi/impl/neomedia/maccoreaudio/CoreAudioVolumeControl.java +++ b/src/org/jitsi/impl/neomedia/maccoreaudio/CoreAudioVolumeControl.java @@ -7,7 +7,6 @@ package org.jitsi.impl.neomedia.maccoreaudio; import org.jitsi.impl.neomedia.*; -import org.jitsi.impl.neomedia.device.*; import org.jitsi.util.*; /** @@ -56,7 +55,7 @@ protected int setInputDeviceVolume(String deviceUID, float volume) if(CoreAudioDevice.setInputDeviceVolume(deviceUID, volume) != 0) { logger.debug( - "Could not change MacOsX CoreAudio input device level"); + "Could not change Mac OS X CoreAudio input device level"); return -1; } return 0; @@ -68,18 +67,14 @@ protected int setInputDeviceVolume(String deviceUID, float volume) * @param deviceUID The device ID. * * @Return A scalar value between 0 and 1 if everything works fine. -1 if an - * error occured. + * error occurred. */ protected float getInputDeviceVolume(String deviceUID) { - float volume; + float volume = CoreAudioDevice.getInputDeviceVolume(deviceUID); - if((volume = CoreAudioDevice.getInputDeviceVolume(deviceUID)) - != 0) - { - logger.debug( - "Could not get MacOsX CoreAudio input device level"); - } + if(logger.isDebugEnabled() && (volume != 0)) + logger.debug("Could not get Mac OS X CoreAudio input device level"); return volume; } diff --git a/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java b/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java index 574716fbd4b4d33c2496fef721ce2dcab8e61e3f..8e7b81507ef333854623c1e569ca661520717746 100644 --- a/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java +++ b/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java @@ -7,7 +7,6 @@ package org.jitsi.impl.neomedia.notify; import java.beans.*; -import java.net.*; import java.util.*; import java.util.concurrent.*; @@ -16,8 +15,6 @@ import org.jitsi.impl.neomedia.*; import org.jitsi.impl.neomedia.device.*; import org.jitsi.service.audionotifier.*; -import org.jitsi.service.libjitsi.*; -import org.jitsi.service.resources.*; /** * The implementation of <tt>AudioNotifierService</tt>. diff --git a/src/org/jitsi/impl/neomedia/portaudio/Pa.java b/src/org/jitsi/impl/neomedia/portaudio/Pa.java index 49babcdc0ecb0c6bfd4edf817bb332f1e81c3301..072740c77ad319340ecf25e0f8da6a83ddaaf3df 100644 --- a/src/org/jitsi/impl/neomedia/portaudio/Pa.java +++ b/src/org/jitsi/impl/neomedia/portaudio/Pa.java @@ -6,7 +6,6 @@ */ package org.jitsi.impl.neomedia.portaudio; -import java.io.*; import java.lang.reflect.*; import org.jitsi.service.configuration.*; diff --git a/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java b/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java index d05427f2401eedc0f8c691339e7d850892dc339c..d2db8e64dfbd8834dae65ca41878ec57ff665833 100644 --- a/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java +++ b/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java @@ -34,7 +34,7 @@ public class PayloadTypeTransformEngine private Map<Byte, Byte> mappingOverrides = new HashMap<Byte, Byte>(); /** - * This map is a copy of <tt>mappingOverride</tt> that we use durig actual + * This map is a copy of <tt>mappingOverride</tt> that we use during actual * transformation */ private Map<Byte, Byte> mappingOverridesCopy = null; @@ -118,19 +118,16 @@ public PacketTransformer getRTCPTransformer() * thread-safe way without using synchronization. * * @param originalPt the payload type that we are overriding - * @param overloadPt the payload type that we are overriging it with + * @param overridePt the payload type that we are overriding it with */ - - public void addPTMappingOverride(byte originalPt, byte overloadPt) + public void addPTMappingOverride(byte originalPt, byte overridePt) { - if (mappingOverrides.containsKey(originalPt) - && mappingOverrides.get(originalPt) == overloadPt) + Byte existingOverride = mappingOverrides.get(originalPt); + + if ((existingOverride == null) || (existingOverride != overridePt)) { - return; + mappingOverrides.put(originalPt, overridePt); + mappingOverridesCopy = new HashMap<Byte, Byte>(mappingOverrides); } - - mappingOverrides.put(originalPt, overloadPt); - - mappingOverridesCopy = new HashMap(mappingOverrides); } } diff --git a/src/org/jitsi/impl/neomedia/wincoreaudio/CoreAudioVolumeControl.java b/src/org/jitsi/impl/neomedia/wincoreaudio/CoreAudioVolumeControl.java index 188540b445d344c46ad166473531ad3be58b745c..e6052abdacb61c2dd3cae6082db351d74756b2a4 100644 --- a/src/org/jitsi/impl/neomedia/wincoreaudio/CoreAudioVolumeControl.java +++ b/src/org/jitsi/impl/neomedia/wincoreaudio/CoreAudioVolumeControl.java @@ -7,7 +7,6 @@ package org.jitsi.impl.neomedia.wincoreaudio; import org.jitsi.impl.neomedia.*; -import org.jitsi.impl.neomedia.device.*; import org.jitsi.util.*; /** @@ -78,7 +77,7 @@ protected int setInputDeviceVolume(String deviceUID, float volume) * @param deviceUID The device ID. * * @Return A scalar value between 0 and 1 if everything works fine. -1 if an - * error occured. + * error occurred. */ protected float getInputDeviceVolume(String deviceUID) { diff --git a/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java b/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java index 5d484612f621675e119eb35b34fe979bb507ae72..f42fa6b93667d47888f922999fb4975e731e0e0a 100644 --- a/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java +++ b/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java @@ -6,7 +6,6 @@ */ package org.jitsi.service.audionotifier; -import java.net.*; import java.util.concurrent.*; /**