From ec4e13012fc0d2e39a8c67e153f1a98b91b1fd04 Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov <lyubomir.marinov@jitsi.org> Date: Wed, 2 Apr 2014 23:24:03 +0300 Subject: [PATCH] Removes duplication. --- .../neomedia/device/MacCoreaudioSystem.java | 530 ++---------------- .../impl/neomedia/device/PortAudioSystem.java | 472 +--------------- .../maccoreaudio/MacCoreaudioStream.java | 230 ++++---- .../protocol/portaudio/PortAudioStream.java | 78 ++- .../renderer/audio/MacCoreaudioRenderer.java | 122 ++-- .../renderer/audio/PortAudioRenderer.java | 21 +- .../protocol/PushBufferDataSourceAdapter.java | 12 +- 7 files changed, 309 insertions(+), 1156 deletions(-) diff --git a/src/org/jitsi/impl/neomedia/device/MacCoreaudioSystem.java b/src/org/jitsi/impl/neomedia/device/MacCoreaudioSystem.java index 62aacf4d..204b5f5d 100644 --- a/src/org/jitsi/impl/neomedia/device/MacCoreaudioSystem.java +++ b/src/org/jitsi/impl/neomedia/device/MacCoreaudioSystem.java @@ -6,17 +6,13 @@ */ package org.jitsi.impl.neomedia.device; -import java.lang.ref.*; import java.util.*; -import java.util.regex.*; import javax.media.*; import javax.media.format.*; import org.jitsi.impl.neomedia.*; import org.jitsi.impl.neomedia.jmfext.media.renderer.audio.*; -import org.jitsi.service.configuration.*; -import org.jitsi.service.libjitsi.*; import org.jitsi.util.*; /** @@ -26,42 +22,11 @@ * @author Vincent Lucas */ public class MacCoreaudioSystem - extends AudioSystem + extends AudioSystem2 { - /** - * Represents a listener which is to be notified before and after - * MacCoreaudio's native function <tt>UpdateAvailableDeviceList()</tt> is - * invoked. - */ - public interface UpdateAvailableDeviceListListener - extends EventListener - { - /** - * Notifies this listener that MacCoreaudio's native function - * <tt>UpdateAvailableDeviceList()</tt> was invoked. - * - * @throws Exception if this implementation encounters an error. Any - * <tt>Throwable</tt> apart from <tt>ThreadDeath</tt> will be ignored - * after it is logged for debugging purposes. - */ - void didUpdateAvailableDeviceList() - throws Exception; - - /** - * Notifies this listener that MacCoreaudio's native function - * <tt>UpdateAvailableDeviceList()</tt> will be invoked. - * - * @throws Exception if this implementation encounters an error. Any - * <tt>Throwable</tt> apart from <tt>ThreadDeath</tt> will be ignored - * after it is logged for debugging purposes. - */ - void willUpdateAvailableDeviceList() - throws Exception; - } - /** * The protocol of the <tt>MediaLocator</tt>s identifying MacCoreaudio - * <tt>CaptureDevice</tt>s + * <tt>CaptureDevice</tt>s. */ private static final String LOCATOR_PROTOCOL = LOCATOR_PROTOCOL_MACCOREAUDIO; @@ -73,183 +38,6 @@ void willUpdateAvailableDeviceList() private static final Logger logger = Logger.getLogger(MacCoreaudioSystem.class); - /** - * The number of times that {@link #willPaOpenStream()} has been - * invoked without an intervening {@link #didPaOpenStream()} i.e. the - * number of MacCoreaudio clients which are currently executing - * <tt>Pa_OpenStream</tt> and which are thus inhibiting - * <tt>Pa_UpdateAvailableDeviceList</tt>. - */ - private static int openStream = 0; - - /** - * The <tt>Object</tt> which synchronizes that access to - * {@link #paOpenStream} and {@link #updateAvailableDeviceList}. - */ - private static final Object openStreamSyncRoot = new Object(); - - /** - * The number of times that {@link #willPaUpdateAvailableDeviceList()} - * has been invoked without an intervening - * {@link #didPaUpdateAvailableDeviceList()} i.e. the number of - * MacCoreaudio clients which are currently executing - * <tt>Pa_UpdateAvailableDeviceList</tt> and which are thus inhibiting - * <tt>Pa_OpenStream</tt>. - */ - private static int updateAvailableDeviceList = 0; - - /** - * The list of <tt>PaUpdateAvailableDeviceListListener</tt>s which are to be - * notified before and after MacCoreaudio's native function - * <tt>Pa_UpdateAvailableDeviceList()</tt> is invoked. - */ - private static final List<WeakReference<UpdateAvailableDeviceListListener>> - updateAvailableDeviceListListeners - = new LinkedList<WeakReference<UpdateAvailableDeviceListListener>>(); - - /** - * The <tt>Object</tt> which ensures that MacCoreaudio's native function - * <tt>UpdateAvailableDeviceList()</tt> will not be invoked concurrently. - * The condition should hold true on the native side but, anyway, it shoul - * not hurt (much) to enforce it on the Java side as well. - */ - private static final Object updateAvailableDeviceListSyncRoot - = new Object(); - - /** - * Adds a listener which is to be notified before and after MacCoreaudio's - * native function <tt>UpdateAvailableDeviceList()</tt> is invoked. - * <p> - * <b>Note</b>: The <tt>MacCoreaudioSystem</tt> class keeps a - * <tt>WeakReference</tt> to the specified <tt>listener</tt> in order to - * avoid memory leaks. - * </p> - * - * @param listener the <tt>UpdateAvailableDeviceListListener</tt> to be - * notified before and after MacCoreaudio's native function - * <tt>UpdateAvailableDeviceList()</tt> is invoked - */ - public static void addUpdateAvailableDeviceListListener( - UpdateAvailableDeviceListListener listener) - { - if(listener == null) - throw new NullPointerException("listener"); - - synchronized(updateAvailableDeviceListListeners) - { - Iterator<WeakReference<UpdateAvailableDeviceListListener>> i - = updateAvailableDeviceListListeners.iterator(); - boolean add = true; - - while(i.hasNext()) - { - UpdateAvailableDeviceListListener l = i.next().get(); - - if(l == null) - i.remove(); - else if(l.equals(listener)) - add = false; - } - if(add) - { - updateAvailableDeviceListListeners.add( - new WeakReference<UpdateAvailableDeviceListListener>( - listener)); - } - } - } - - /** - * Notifies <tt>MacCoreaudioSystem</tt> that a MacCoreaudio client finished - * executing <tt>OpenStream</tt>. - */ - public static void didOpenStream() - { - synchronized (openStreamSyncRoot) - { - openStream--; - if (openStream < 0) - openStream = 0; - - openStreamSyncRoot.notifyAll(); - } - } - - /** - * Notifies <tt>MacCoreaudioSystem</tt> that a MacCoreaudio client finished - * executing <tt>UpdateAvailableDeviceList</tt>. - */ - private static void didUpdateAvailableDeviceList() - { - synchronized(openStreamSyncRoot) - { - updateAvailableDeviceList--; - if (updateAvailableDeviceList < 0) - updateAvailableDeviceList = 0; - - openStreamSyncRoot.notifyAll(); - } - - fireUpdateAvailableDeviceListEvent(false); - } - - /** - * Notifies the registered <tt>UpdateAvailableDeviceListListener</tt>s - * that MacCoreaudio's native function - * <tt>UpdateAvailableDeviceList()</tt> will be or was invoked. - * - * @param will <tt>true</tt> if MacCoreaudio's native function - * <tt>UpdateAvailableDeviceList()</tt> will be invoked or <tt>false</tt> - * if it was invoked - */ - private static void fireUpdateAvailableDeviceListEvent(boolean will) - { - try - { - List<WeakReference<UpdateAvailableDeviceListListener>> ls; - - synchronized(updateAvailableDeviceListListeners) - { - ls = new - ArrayList<WeakReference<UpdateAvailableDeviceListListener>>( - updateAvailableDeviceListListeners); - } - - for(WeakReference<UpdateAvailableDeviceListListener> wr : ls) - { - UpdateAvailableDeviceListListener l = wr.get(); - if(l != null) - { - try - { - if(will) - l.willUpdateAvailableDeviceList(); - else - l.didUpdateAvailableDeviceList(); - } - catch (Throwable t) - { - if(t instanceof ThreadDeath) - throw(ThreadDeath) t; - else - { - logger.error( - "UpdateAvailableDeviceListListener." - + (will ? "will" : "did") - + "UpdateAvailableDeviceList failed.", - t); - } - } - } - } - } - catch(Throwable t) - { - if(t instanceof ThreadDeath) - throw(ThreadDeath) t; - } - } - /** * Gets a sample rate supported by a MacCoreaudio device with a specific * device index with which it is to be registered with JMF. @@ -270,97 +58,17 @@ private static double getSupportedSampleRate( String deviceUID, boolean isEchoCancel) { - double supportedSampleRate = MacCoreAudioDevice.getNominalSampleRate( - deviceUID, - false, - isEchoCancel); + double supportedSampleRate + = MacCoreAudioDevice.getNominalSampleRate( + deviceUID, + false, + isEchoCancel); if(supportedSampleRate >= MediaUtils.MAX_AUDIO_SAMPLE_RATE) - { supportedSampleRate = MacCoreAudioDevice.DEFAULT_SAMPLE_RATE; - } - return supportedSampleRate; } - /** - * Waits for all MacCoreaudio clients to finish executing - * <tt>OpenStream</tt>. - */ - private static void waitForOpenStream() - { - boolean interrupted = false; - - while(openStream > 0) - { - try - { - openStreamSyncRoot.wait(); - } - catch(InterruptedException ie) - { - interrupted = true; - } - } - if(interrupted) - Thread.currentThread().interrupt(); - } - - /** - * Waits for all MacCoreaudio clients to finish executing - * <tt>UpdateAvailableDeviceList</tt>. - */ - private static void waitForUpdateAvailableDeviceList() - { - boolean interrupted = false; - - while (updateAvailableDeviceList > 0) - { - try - { - openStreamSyncRoot.wait(); - } - catch (InterruptedException ie) - { - interrupted = true; - } - } - if (interrupted) - Thread.currentThread().interrupt(); - } - - /** - * Notifies <tt>MacCoreaudioSystem</tt> that a MacCoreaudio client will - * start executing <tt>OpenStream</tt>. - */ - public static void willOpenStream() - { - synchronized (openStreamSyncRoot) - { - waitForUpdateAvailableDeviceList(); - - openStream++; - openStreamSyncRoot.notifyAll(); - } - } - - /** - * Notifies <tt>MacCoreaudioSystem</tt> that a MacCoreaudio client will - * start executing <tt>UpdateAvailableDeviceList</tt>. - */ - private static void willUpdateAvailableDeviceList() - { - synchronized(openStreamSyncRoot) - { - waitForOpenStream(); - - updateAvailableDeviceList++; - openStreamSyncRoot.notifyAll(); - } - - fireUpdateAvailableDeviceListEvent(true); - } - private Runnable devicesChangedCallback; /** @@ -381,41 +89,6 @@ private static void willUpdateAvailableDeviceList() | FEATURE_ECHO_CANCELLATION); } - /** - * Sorts a specific list of <tt>CaptureDeviceInfo2</tt>s so that the - * ones representing USB devices appear at the beginning/top of the - * specified list. - * - * @param devices the list of <tt>CaptureDeviceInfo2</tt>s to be - * sorted so that the ones representing USB devices appear at the - * beginning/top of the list - */ - private void bubbleUpUsbDevices(List<CaptureDeviceInfo2> devices) - { - if(!devices.isEmpty()) - { - List<CaptureDeviceInfo2> nonUsbDevices - = new ArrayList<CaptureDeviceInfo2>(devices.size()); - - for(Iterator<CaptureDeviceInfo2> i = devices.iterator(); - i.hasNext();) - { - CaptureDeviceInfo2 d = i.next(); - - if(!d.isSameTransportType("USB")) - { - nonUsbDevices.add(d); - i.remove(); - } - } - if(!nonUsbDevices.isEmpty()) - { - for (CaptureDeviceInfo2 d : nonUsbDevices) - devices.add(d); - } - } - } - /** * {@inheritDoc} */ @@ -426,18 +99,15 @@ protected void doInitialize() if(!CoreAudioDevice.isLoaded) { String message = "MacOSX CoreAudio library is not loaded"; + if (logger.isInfoEnabled()) - { logger.info(message); - } throw new Exception(message); } // Initializes the library only at the first run. if(devicesChangedCallback == null) - { CoreAudioDevice.initDevices(); - } int channels = 1; int sampleSizeInBits = 16; @@ -453,7 +123,6 @@ protected void doInitialize() = new LinkedList<CaptureDeviceInfo2>(); final boolean loggerIsDebugEnabled = logger.isDebugEnabled(); - String[] deviceUIDList = MacCoreAudioDevice.getDeviceUIDList(); for(int i = 0; i < deviceUIDList.length; ++i) { @@ -497,12 +166,15 @@ protected void doInitialize() if (id.equals(deviceUID) || id.equals(name)) { - double rate = ((AudioFormat) existingCdi.getFormats()[0]) - .getSampleRate(); - if(rate == getSupportedSampleRate( - true, - deviceUID, - isEchoCancelActivated())) + double rate + = ((AudioFormat) existingCdi.getFormats()[0]) + .getSampleRate(); + + if(rate + == getSupportedSampleRate( + true, + deviceUID, + isEchoCancel())) { cdi = existingCdi; break; @@ -526,7 +198,7 @@ protected void doInitialize() ? getSupportedSampleRate( true, deviceUID, - isEchoCancelActivated()) + isEchoCancel()) : MacCoreAudioDevice.DEFAULT_SAMPLE_RATE, sampleSizeInBits, channels, @@ -644,6 +316,7 @@ else if(isOutputDevice) devicesChangedCallback = new Runnable() { + @Override public void run() { try @@ -676,114 +349,25 @@ protected String getRendererClassName() } /** - * Attempts to reorder specific lists of capture and playback/notify - * <tt>CaptureDeviceInfo2</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>CaptureDeviceInfo2</tt>s. The implementation - * is provided as a fallback to stand in for scenarios in which more - * accurate relevant information is not available. + * Sets the indicator which determines whether echo cancellation is to be + * performed for captured audio. * - * @param captureDevices - * @param playbackDevices + * @param echoCancel <tt>true</tt> if echo cancellation is to be performed + * for captured audio; otherwise, <tt>false</tt> */ - private void matchDevicesByName( - List<CaptureDeviceInfo2> captureDevices, - List<CaptureDeviceInfo2> playbackDevices) + @Override + public void setEchoCancel(boolean echoCancel) { - Iterator<CaptureDeviceInfo2> captureIter - = captureDevices.iterator(); - Pattern pattern - = Pattern.compile( - "array|headphones|microphone|speakers|\\p{Space}|\\(|\\)", - Pattern.CASE_INSENSITIVE); - LinkedList<CaptureDeviceInfo2> captureDevicesWithPlayback - = new LinkedList<CaptureDeviceInfo2>(); - LinkedList<CaptureDeviceInfo2> playbackDevicesWithCapture - = new LinkedList<CaptureDeviceInfo2>(); - int count = 0; - - while (captureIter.hasNext()) - { - CaptureDeviceInfo2 captureDevice = captureIter.next(); - String captureName = captureDevice.getName(); - - if (captureName != null) - { - captureName = pattern.matcher(captureName).replaceAll(""); - if (captureName.length() != 0) - { - Iterator<CaptureDeviceInfo2> playbackIter - = playbackDevices.iterator(); - CaptureDeviceInfo2 matchingPlaybackDevice = null; - - while (playbackIter.hasNext()) - { - CaptureDeviceInfo2 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++; - } - } - } - } + super.setEchoCancel(echoCancel); - for (int i = count - 1; i >= 0; i--) + try { - captureDevices.add(0, captureDevicesWithPlayback.get(i)); - playbackDevices.add(0, playbackDevicesWithCapture.get(i)); + reinitialize(); } - } - - /** - * Reinitializes this <tt>MacCoreaudioSystem</tt> in order to bring it up to - * date with possible changes in the MacCoreaudio devices. Invokes - * <tt>Pa_UpdateAvailableDeviceList()</tt> to update the devices on the - * native side and then {@link #initialize()} to reflect any changes on the - * Java side. Invoked by MacCoreaudio when it detects that the list of - * devices has changed. - * - * @throws Exception if there was an error during the invocation of - * <tt>Pa_UpdateAvailableDeviceList()</tt> and - * <tt>DeviceSystem.initialize()</tt> - */ - private void reinitialize() - throws Exception - { - synchronized (updateAvailableDeviceListSyncRoot) + catch (Exception e) { - willUpdateAvailableDeviceList(); - didUpdateAvailableDeviceList(); + logger.warn("Failed to reinitialize MacCoreaudio devices", e); } - - /* - * XXX We will likely minimize the risk of crashes on the native side - * even further by invoking initialize() with - * Pa_UpdateAvailableDeviceList locked. Unfortunately, that will likely - * increase the risks of deadlocks on the Java side. - */ - invokeDeviceSystemInitialize(this); } /** @@ -798,57 +382,9 @@ public String toString() return "Core Audio"; } - /** - * Returns if the echo canceller has to be activated. - * - * @return True if the echo canceller has to be activated. False otherwise. - */ - public static boolean isEchoCancelActivated() - { - boolean isEchoCancel = true; - - ConfigurationService cfg = LibJitsi.getConfigurationService(); - if (cfg != null) - isEchoCancel = cfg.getBoolean( - DeviceConfiguration.PROP_AUDIO_SYSTEM - + "." + LOCATOR_PROTOCOL - + "." + PNAME_ECHOCANCEL, - isEchoCancel); - - return isEchoCancel; - } - - /** - * Gets the indicator which determines whether echo cancellation is to be - * performed for captured audio. - * - * @return <tt>true</tt> if echo cancellation is to be performed for - * captured audio; otherwise, <tt>false</tt> - */ - public boolean isEchoCancel() - { - // This function is only implemented to disable by default the AEC for - // CoreAudio. - return isEchoCancelActivated(); - } - - /** - * Sets the indicator which determines whether echo cancellation is to be - * performed for captured audio. - * - * @param echoCancel <tt>true</tt> if echo cancellation is to be performed - * for captured audio; otherwise, <tt>false</tt> - */ - public void setEchoCancel(boolean echoCancel) + @Override + protected void updateAvailableDeviceList() { - super.setEchoCancel(echoCancel); - try - { - reinitialize(); - } - catch(Exception ex) - { - logger.warn("Failed to reinitialize MacCoreaudio devices", ex); - } + // TODO Auto-generated method stub } } diff --git a/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java b/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java index 9b99e2e6..2d1db5b1 100644 --- a/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java +++ b/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java @@ -6,9 +6,7 @@ */ package org.jitsi.impl.neomedia.device; -import java.lang.ref.*; import java.util.*; -import java.util.regex.*; import javax.media.*; import javax.media.format.*; @@ -27,39 +25,8 @@ * @author Lyubomir Marinov */ public class PortAudioSystem - extends AudioSystem + extends AudioSystem2 { - /** - * Represents a listener which is to be notified before and after - * PortAudio's native function <tt>Pa_UpdateAvailableDeviceList()</tt> is - * invoked. - */ - public interface PaUpdateAvailableDeviceListListener - extends EventListener - { - /** - * Notifies this listener that PortAudio's native function - * <tt>Pa_UpdateAvailableDeviceList()</tt> was invoked. - * - * @throws Exception if this implementation encounters an error. Any - * <tt>Throwable</tt> apart from <tt>ThreadDeath</tt> will be ignored - * after it is logged for debugging purposes. - */ - void didPaUpdateAvailableDeviceList() - throws Exception; - - /** - * Notifies this listener that PortAudio's native function - * <tt>Pa_UpdateAvailableDeviceList()</tt> will be invoked. - * - * @throws Exception if this implementation encounters an error. Any - * <tt>Throwable</tt> apart from <tt>ThreadDeath</tt> will be ignored - * after it is logged for debugging purposes. - */ - void willPaUpdateAvailableDeviceList() - throws Exception; - } - /** * The protocol of the <tt>MediaLocator</tt>s identifying PortAudio * <tt>CaptureDevice</tt>s @@ -73,184 +40,6 @@ void willPaUpdateAvailableDeviceList() private static final Logger logger = Logger.getLogger(PortAudioSystem.class); - /** - * The number of times that {@link #willPaOpenStream()} has been - * invoked without an intervening {@link #didPaOpenStream()} i.e. the - * number of PortAudio clients which are currently executing - * <tt>Pa_OpenStream</tt> and which are thus inhibiting - * <tt>Pa_UpdateAvailableDeviceList</tt>. - */ - private static int paOpenStream = 0; - - /** - * The <tt>Object</tt> which synchronizes that access to - * {@link #paOpenStream} and {@link #paUpdateAvailableDeviceList}. - */ - private static final Object paOpenStreamSyncRoot = new Object(); - - /** - * The number of times that {@link #willPaUpdateAvailableDeviceList()} - * has been invoked without an intervening - * {@link #didPaUpdateAvailableDeviceList()} i.e. the number of - * PortAudio clients which are currently executing - * <tt>Pa_UpdateAvailableDeviceList</tt> and which are thus inhibiting - * <tt>Pa_OpenStream</tt>. - */ - private static int paUpdateAvailableDeviceList = 0; - - /** - * The list of <tt>PaUpdateAvailableDeviceListListener</tt>s which are to be - * notified before and after PortAudio's native function - * <tt>Pa_UpdateAvailableDeviceList()</tt> is invoked. - */ - private static final List<WeakReference<PaUpdateAvailableDeviceListListener>> - paUpdateAvailableDeviceListListeners - = new LinkedList<WeakReference<PaUpdateAvailableDeviceListListener>>(); - - /** - * The <tt>Object</tt> which ensures that PortAudio's native function - * <tt>Pa_UpdateAvailableDeviceList()</tt> will not be invoked concurrently. - * The condition should hold true on the native side but, anyway, it shoul - * not hurt (much) to enforce it on the Java side as well. - */ - private static final Object paUpdateAvailableDeviceListSyncRoot - = new Object(); - - /** - * Adds a listener which is to be notified before and after PortAudio's - * native function <tt>Pa_UpdateAvailableDeviceList()</tt> is invoked. - * <p> - * <b>Note</b>: The <tt>PortAudioSystem</tt> class keeps a - * <tt>WeakReference</tt> to the specified <tt>listener</tt> in order to - * avoid memory leaks. - * </p> - * - * @param listener the <tt>PaUpdateAvailableDeviceListListener</tt> to be - * notified before and after PortAudio's native function - * <tt>Pa_UpdateAvailableDeviceList()</tt> is invoked - */ - public static void addPaUpdateAvailableDeviceListListener( - PaUpdateAvailableDeviceListListener listener) - { - if (listener == null) - throw new NullPointerException("listener"); - - synchronized (paUpdateAvailableDeviceListListeners) - { - Iterator<WeakReference<PaUpdateAvailableDeviceListListener>> i - = paUpdateAvailableDeviceListListeners.iterator(); - boolean add = true; - - while (i.hasNext()) - { - PaUpdateAvailableDeviceListListener l = i.next().get(); - - if (l == null) - i.remove(); - else if (l.equals(listener)) - add = false; - } - if (add) - { - paUpdateAvailableDeviceListListeners.add( - new WeakReference<PaUpdateAvailableDeviceListListener>( - listener)); - } - } - } - - /** - * Notifies <tt>PortAudioSystem</tt> that a PortAudio client finished - * executing <tt>Pa_OpenStream</tt>. - */ - public static void didPaOpenStream() - { - synchronized (paOpenStreamSyncRoot) - { - paOpenStream--; - if (paOpenStream < 0) - paOpenStream = 0; - - paOpenStreamSyncRoot.notifyAll(); - } - } - - /** - * Notifies <tt>PortAudioSystem</tt> that a PortAudio client finished - * executing <tt>Pa_UpdateAvailableDeviceList</tt>. - */ - private static void didPaUpdateAvailableDeviceList() - { - synchronized (paOpenStreamSyncRoot) - { - paUpdateAvailableDeviceList--; - if (paUpdateAvailableDeviceList < 0) - paUpdateAvailableDeviceList = 0; - - paOpenStreamSyncRoot.notifyAll(); - } - - firePaUpdateAvailableDeviceListEvent(false); - } - - /** - * Notifies the registered <tt>PaUpdateAvailableDeviceListListener</tt>s - * that PortAudio's native function <tt>Pa_UpdateAvailableDeviceList()</tt> - * will be or was invoked. - * - * @param will <tt>true</tt> if PortAudio's native function - * <tt>Pa_UpdateAvailableDeviceList()</tt> will be invoked or <tt>false</tt> - * if it was invoked - */ - private static void firePaUpdateAvailableDeviceListEvent(boolean will) - { - try - { - List<WeakReference<PaUpdateAvailableDeviceListListener>> ls; - - synchronized (paUpdateAvailableDeviceListListeners) - { - ls - = new ArrayList<WeakReference<PaUpdateAvailableDeviceListListener>>( - paUpdateAvailableDeviceListListeners); - } - - for (WeakReference<PaUpdateAvailableDeviceListListener> wr : ls) - { - PaUpdateAvailableDeviceListListener l = wr.get(); - - if (l != null) - { - try - { - if (will) - l.willPaUpdateAvailableDeviceList(); - else - l.didPaUpdateAvailableDeviceList(); - } - catch (Throwable t) - { - if (t instanceof ThreadDeath) - throw (ThreadDeath) t; - else - { - logger.error( - "PaUpdateAvailableDeviceListListener." - + (will ? "will" : "did") - + "PaUpdateAvailableDeviceList failed.", - t); - } - } - } - } - } - catch (Throwable t) - { - if (t instanceof ThreadDeath) - throw (ThreadDeath) t; - } - } - /** * Gets a sample rate supported by a PortAudio device with a specific device * index with which it is to be registered with JMF. @@ -349,105 +138,6 @@ public static void monitorFunctionalHealth( // TODO Auto-generated method stub } - public static void removePaUpdateAvailableDeviceListListener( - PaUpdateAvailableDeviceListListener listener) - { - if (listener == null) - return; - - synchronized (paUpdateAvailableDeviceListListeners) - { - Iterator<WeakReference<PaUpdateAvailableDeviceListListener>> i - = paUpdateAvailableDeviceListListeners.iterator(); - - while (i.hasNext()) - { - PaUpdateAvailableDeviceListListener l = i.next().get(); - - if ((l == null) || l.equals(listener)) - i.remove(); - } - } - } - - /** - * Waits for all PortAudio clients to finish executing - * <tt>Pa_OpenStream</tt>. - */ - private static void waitForPaOpenStream() - { - boolean interrupted = false; - - while (paOpenStream > 0) - { - try - { - paOpenStreamSyncRoot.wait(); - } - catch (InterruptedException ie) - { - interrupted = true; - } - } - if (interrupted) - Thread.currentThread().interrupt(); - } - - /** - * Waits for all PortAudio clients to finish executing - * <tt>Pa_UpdateAvailableDeviceList</tt>. - */ - private static void waitForPaUpdateAvailableDeviceList() - { - boolean interrupted = false; - - while (paUpdateAvailableDeviceList > 0) - { - try - { - paOpenStreamSyncRoot.wait(); - } - catch (InterruptedException ie) - { - interrupted = true; - } - } - if (interrupted) - Thread.currentThread().interrupt(); - } - - /** - * Notifies <tt>PortAudioSystem</tt> that a PortAudio client will start - * executing <tt>Pa_OpenStream</tt>. - */ - public static void willPaOpenStream() - { - synchronized (paOpenStreamSyncRoot) - { - waitForPaUpdateAvailableDeviceList(); - - paOpenStream++; - paOpenStreamSyncRoot.notifyAll(); - } - } - - /** - * Notifies <tt>PortAudioSystem</tt> that a PortAudio client will start - * executing <tt>Pa_UpdateAvailableDeviceList</tt>. - */ - private static void willPaUpdateAvailableDeviceList() - { - synchronized (paOpenStreamSyncRoot) - { - waitForPaOpenStream(); - - paUpdateAvailableDeviceList++; - paOpenStreamSyncRoot.notifyAll(); - } - - firePaUpdateAvailableDeviceListEvent(true); - } - private Runnable devicesChangedCallback; /** @@ -469,41 +159,6 @@ private static void willPaUpdateAvailableDeviceList() | FEATURE_REINITIALIZE); } - /** - * Sorts a specific list of <tt>CaptureDeviceInfo2</tt>s so that the - * ones representing USB devices appear at the beginning/top of the - * specified list. - * - * @param devices the list of <tt>CaptureDeviceInfo2</tt>s to be - * sorted so that the ones representing USB devices appear at the - * beginning/top of the list - */ - private void bubbleUpUsbDevices(List<CaptureDeviceInfo2> devices) - { - if (!devices.isEmpty()) - { - List<CaptureDeviceInfo2> nonUsbDevices - = new ArrayList<CaptureDeviceInfo2>(devices.size()); - - for (Iterator<CaptureDeviceInfo2> i = devices.iterator(); - i.hasNext();) - { - CaptureDeviceInfo2 d = i.next(); - - if (!d.isSameTransportType("USB")) - { - nonUsbDevices.add(d); - i.remove(); - } - } - if (!nonUsbDevices.isEmpty()) - { - for (CaptureDeviceInfo2 d : nonUsbDevices) - devices.add(d); - } - } - } - /** * {@inheritDoc} */ @@ -725,6 +380,7 @@ else if (maxOutputChannels > 0) devicesChangedCallback = new Runnable() { + @Override public void run() { try @@ -755,124 +411,6 @@ protected String getRendererClassName() return PortAudioRenderer.class.getName(); } - /** - * Attempts to reorder specific lists of capture and playback/notify - * <tt>CaptureDeviceInfo2</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>CaptureDeviceInfo2</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<CaptureDeviceInfo2> captureDevices, - List<CaptureDeviceInfo2> playbackDevices) - { - Iterator<CaptureDeviceInfo2> captureIter - = captureDevices.iterator(); - Pattern pattern - = Pattern.compile( - "array|headphones|microphone|speakers|\\p{Space}|\\(|\\)", - Pattern.CASE_INSENSITIVE); - LinkedList<CaptureDeviceInfo2> captureDevicesWithPlayback - = new LinkedList<CaptureDeviceInfo2>(); - LinkedList<CaptureDeviceInfo2> playbackDevicesWithCapture - = new LinkedList<CaptureDeviceInfo2>(); - int count = 0; - - while (captureIter.hasNext()) - { - CaptureDeviceInfo2 captureDevice = captureIter.next(); - String captureName = captureDevice.getName(); - - if (captureName != null) - { - captureName = pattern.matcher(captureName).replaceAll(""); - if (captureName.length() != 0) - { - Iterator<CaptureDeviceInfo2> playbackIter - = playbackDevices.iterator(); - CaptureDeviceInfo2 matchingPlaybackDevice = null; - - while (playbackIter.hasNext()) - { - CaptureDeviceInfo2 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 - * <tt>Pa_UpdateAvailableDeviceList()</tt> to update the devices on the - * native side and then {@link #initialize()} to reflect any changes on the - * Java side. Invoked by PortAudio when it detects that the list of devices - * has changed. - * - * @throws Exception if there was an error during the invocation of - * <tt>Pa_UpdateAvailableDeviceList()</tt> and - * <tt>DeviceSystem.initialize()</tt> - */ - private void reinitialize() - throws Exception - { - synchronized (paUpdateAvailableDeviceListSyncRoot) - { - willPaUpdateAvailableDeviceList(); - try - { - Pa.UpdateAvailableDeviceList(); - } - finally - { - didPaUpdateAvailableDeviceList(); - } - } - - /* - * XXX We will likely minimize the risk of crashes on the native side - * even further by invoking initialize() with - * Pa_UpdateAvailableDeviceList locked. Unfortunately, that will likely - * increase the risks of deadlocks on the Java side. - */ - invokeDeviceSystemInitialize(this); - } - /** * {@inheritDoc} * @@ -884,4 +422,10 @@ public String toString() { return "PortAudio"; } + + @Override + protected void updateAvailableDeviceList() + { + Pa.UpdateAvailableDeviceList(); + } } diff --git a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/maccoreaudio/MacCoreaudioStream.java b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/maccoreaudio/MacCoreaudioStream.java index 04cef0bf..b372453e 100644 --- a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/maccoreaudio/MacCoreaudioStream.java +++ b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/maccoreaudio/MacCoreaudioStream.java @@ -44,6 +44,12 @@ public class MacCoreaudioStream @SuppressWarnings("unused") // under development private final boolean audioQualityImprovement; + /** + * The buffer which stores the outgoing data before sending them to + * the RTP stack. + */ + private byte[] buffer = null; + /** * The number of bytes to read from a native MacCoreaudio stream in a single * invocation. Based on {@link #framesPerBuffer}. @@ -58,16 +64,10 @@ public class MacCoreaudioStream private String deviceUID; /** - * A mutual eclusion used to avoid conflict when starting / stoping the - * stream for this stream; - */ - private Object startStopMutex = new Object(); - - /** - * The buffer which stores the outgoing data before sending them to - * the RTP stack. + * The last-known <tt>Format</tt> of the media data made available by this + * <tt>PullBufferStream</tt>. */ - private byte[] buffer = null; + private AudioFormat format = null; /** * A list of already allocated buffers, ready to accept new captured data. @@ -80,22 +80,27 @@ public class MacCoreaudioStream */ private Vector<byte[]> fullBufferList = new Vector<byte[]>(); + /** + * The <tt>GainControl</tt> through which the volume/gain of captured media + * is controlled. + */ + private final GainControl gainControl; + /** * The number of data available to feed the RTP stack. */ private int nbBufferData = 0; /** - * The last-known <tt>Format</tt> of the media data made available by this - * <tt>PullBufferStream</tt>. + * Current sequence number. */ - private AudioFormat format = null; + private int sequenceNumber = 0; /** - * The <tt>GainControl</tt> through which the volume/gain of captured media - * is controlled. + * A mutual eclusion used to avoid conflict when starting / stoping the + * stream for this stream; */ - private final GainControl gainControl; + private Object startStopMutex = new Object(); /** * Locked when currently stopping the stream. Prevents deadlock between the @@ -103,9 +108,14 @@ public class MacCoreaudioStream */ private Lock stopLock = new ReentrantLock(); - private final MacCoreaudioSystem.UpdateAvailableDeviceListListener + /** + * The stream structure used by the native maccoreaudio library. + */ + private long stream = 0; + + private final UpdateAvailableDeviceListListener updateAvailableDeviceListListener - = new MacCoreaudioSystem.UpdateAvailableDeviceListListener() + = new UpdateAvailableDeviceListListener() { /** * The device ID (could be deviceUID or name but that is not @@ -116,6 +126,7 @@ public class MacCoreaudioStream private boolean start = false; + @Override public void didUpdateAvailableDeviceList() throws Exception { @@ -131,6 +142,7 @@ public void didUpdateAvailableDeviceList() } } + @Override public void willUpdateAvailableDeviceList() throws Exception { @@ -152,16 +164,6 @@ public void willUpdateAvailableDeviceList() } }; - /** - * Current sequence number. - */ - private int sequenceNumber = 0; - - /** - * The stream structure used by the native maccoreaudio library. - */ - private long stream = 0; - /** * Initializes a new <tt>MacCoreaudioStream</tt> instance which is to have * its <tt>Format</tt>-related information abstracted by a specific @@ -194,8 +196,16 @@ public MacCoreaudioStream( // XXX We will add a UpdateAvailableDeviceListListener and will not // remove it because we will rely on MacCoreaudioSystem's use of // WeakReference. - MacCoreaudioSystem.addUpdateAvailableDeviceListListener( - updateAvailableDeviceListListener); + AudioSystem2 audioSystem + = (AudioSystem2) + AudioSystem.getAudioSystem( + AudioSystem.LOCATOR_PROTOCOL_MACCOREAUDIO); + + if (audioSystem != null) + { + audioSystem.addUpdateAvailableDeviceListListener( + updateAvailableDeviceListListener); + } } private void connect() @@ -306,6 +316,66 @@ public void read(Buffer buffer) buffer.setTimeStamp(bufferTimeStamp); } + /** + * Callback which receives the data from the coreaudio library. + * + * @param buffer The data captured from the input. + * @param bufferLength The length of the data captured. + */ + public void readInput(byte[] buffer, int bufferLength) + { + int nbCopied = 0; + while(bufferLength > 0) + { + int length = this.buffer.length - nbBufferData; + if(bufferLength < length) + { + length = bufferLength; + } + + System.arraycopy( + buffer, + nbCopied, + this.buffer, + nbBufferData, + length); + + nbBufferData += length; + nbCopied += length; + bufferLength -= length; + + if(nbBufferData == this.buffer.length) + { + this.fullBufferList.add(this.buffer); + this.buffer = null; + nbBufferData = 0; + if(stopLock.tryLock()) + { + try + { + synchronized(startStopMutex) + { + startStopMutex.notify(); + if(this.freeBufferList.size() > 0) + { + this.buffer = this.freeBufferList.remove(0); + } + } + } + finally + { + stopLock.unlock(); + } + } + + if(this.buffer == null) + { + this.buffer = new byte[bytesPerBuffer]; + } + } + } + } + /** * Sets the device index of the MacCoreaudio device to be read through this * <tt>PullBufferStream</tt>. @@ -362,19 +432,35 @@ public void start() this.fullBufferList.clear(); this.freeBufferList.clear(); - MacCoreaudioSystem.willOpenStream(); - stream = MacCoreAudioDevice.startStream( - deviceUID, - this, - (float) format.getSampleRate(), - format.getChannels(), - format.getSampleSizeInBits(), - false, - format.getEndian() == AudioFormat.BIG_ENDIAN, - false, - true, - MacCoreaudioSystem.isEchoCancelActivated()); - MacCoreaudioSystem.didOpenStream(); + AudioSystem2 audioSystem + = (AudioSystem2) + AudioSystem.getAudioSystem( + AudioSystem.LOCATOR_PROTOCOL_MACCOREAUDIO); + + if (audioSystem != null) + audioSystem.willOpenStream(); + try + { + stream + = MacCoreAudioDevice.startStream( + deviceUID, + this, + (float) format.getSampleRate(), + format.getChannels(), + format.getSampleSizeInBits(), + false, + format.getEndian() == AudioFormat.BIG_ENDIAN, + false, + true, + (audioSystem == null) + ? true + : audioSystem.isEchoCancel()); + } + finally + { + if (audioSystem != null) + audioSystem.didOpenStream(); + } } } } @@ -407,64 +493,4 @@ public void stop() stopLock.unlock(); } } - - /** - * Callback which receives the data from the coreaudio library. - * - * @param buffer The data captured from the input. - * @param bufferLength The length of the data captured. - */ - public void readInput(byte[] buffer, int bufferLength) - { - int nbCopied = 0; - while(bufferLength > 0) - { - int length = this.buffer.length - nbBufferData; - if(bufferLength < length) - { - length = bufferLength; - } - - System.arraycopy( - buffer, - nbCopied, - this.buffer, - nbBufferData, - length); - - nbBufferData += length; - nbCopied += length; - bufferLength -= length; - - if(nbBufferData == this.buffer.length) - { - this.fullBufferList.add(this.buffer); - this.buffer = null; - nbBufferData = 0; - if(stopLock.tryLock()) - { - try - { - synchronized(startStopMutex) - { - startStopMutex.notify(); - if(this.freeBufferList.size() > 0) - { - this.buffer = this.freeBufferList.remove(0); - } - } - } - finally - { - stopLock.unlock(); - } - } - - if(this.buffer == null) - { - this.buffer = new byte[bytesPerBuffer]; - } - } - } - } } diff --git a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java index 5b7a149a..8c4e1f1c 100644 --- a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java +++ b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/portaudio/PortAudioStream.java @@ -43,6 +43,26 @@ public class PortAudioStream */ private static final long NEVER = DiagnosticsControl.NEVER; + /** + * Causes the currently executing thread to temporarily pause and allow + * other threads to execute. + */ + public static void yield() + { + boolean interrupted = false; + + try + { + Thread.sleep(Pa.DEFAULT_MILLIS_PER_BUFFER); + } + catch (InterruptedException ie) + { + interrupted = true; + } + if (interrupted) + Thread.currentThread().interrupt(); + } + /** * The indicator which determines whether audio quality improvement is * enabled for this <tt>PortAudioStream</tt> in accord with the preferences @@ -145,9 +165,9 @@ public String toString() */ private long inputParameters = 0; - private final PortAudioSystem.PaUpdateAvailableDeviceListListener + private final UpdateAvailableDeviceListListener paUpdateAvailableDeviceListListener - = new PortAudioSystem.PaUpdateAvailableDeviceListListener() + = new UpdateAvailableDeviceListListener() { /** * The device ID (could be deviceUID or name but that is not @@ -158,7 +178,8 @@ public String toString() private boolean start = false; - public void didPaUpdateAvailableDeviceList() + @Override + public void didUpdateAvailableDeviceList() throws Exception { synchronized (PortAudioStream.this) @@ -192,7 +213,8 @@ public void didPaUpdateAvailableDeviceList() } } - public void willPaUpdateAvailableDeviceList() + @Override + public void willUpdateAvailableDeviceList() throws Exception { synchronized (PortAudioStream.this) @@ -290,12 +312,20 @@ public PortAudioStream( : (GainControl) mediaServiceImpl.getInputVolumeControl(); /* - * XXX We will add a PaUpdateAvailableDeviceListListener and will not + * XXX We will add a UpdateAvailableDeviceListListener and will not * remove it because we will rely on PortAudioSystem's use of * WeakReference. */ - PortAudioSystem.addPaUpdateAvailableDeviceListListener( - paUpdateAvailableDeviceListListener); + AudioSystem2 audioSystem + = (AudioSystem2) + AudioSystem.getAudioSystem( + AudioSystem.LOCATOR_PROTOCOL_PORTAUDIO); + + if (audioSystem != null) + { + audioSystem.addUpdateAvailableDeviceListListener( + paUpdateAvailableDeviceListListener); + } } private void connect() @@ -309,8 +339,7 @@ private void connect() if (deviceIndex == Pa.paNoDevice) { throw new IOException( - "The audio device " - + deviceID + "The audio device " + deviceID + " appears to be disconnected."); } @@ -715,14 +744,21 @@ synchronized void setDeviceID(String deviceID) // DataSource#connect if (this.deviceID != null) { - PortAudioSystem.willPaOpenStream(); + AudioSystem2 audioSystem + = (AudioSystem2) + AudioSystem.getAudioSystem( + AudioSystem.LOCATOR_PROTOCOL_PORTAUDIO); + + if (audioSystem != null) + audioSystem.willOpenStream(); try { connect(); } finally { - PortAudioSystem.didPaOpenStream(); + if (audioSystem != null) + audioSystem.didOpenStream(); } } } @@ -839,24 +875,4 @@ private void waitWhileStreamIsBusy() if (interrupted) Thread.currentThread().interrupt(); } - - /** - * Causes the currently executing thread to temporarily pause and allow - * other threads to execute. - */ - public static void yield() - { - boolean interrupted = false; - - try - { - Thread.sleep(Pa.DEFAULT_MILLIS_PER_BUFFER); - } - catch (InterruptedException ie) - { - interrupted = true; - } - if (interrupted) - Thread.currentThread().interrupt(); - } } diff --git a/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/MacCoreaudioRenderer.java b/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/MacCoreaudioRenderer.java index 5edf0d33..f29acf47 100644 --- a/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/MacCoreaudioRenderer.java +++ b/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/MacCoreaudioRenderer.java @@ -117,40 +117,42 @@ public class MacCoreaudioRenderer * corruption afterwards and it will attempt to restore the state of this * <tt>Renderer</tt> after the invocation. */ - private final MacCoreaudioSystem.UpdateAvailableDeviceListListener + private final UpdateAvailableDeviceListListener updateAvailableDeviceListListener - = new MacCoreaudioSystem.UpdateAvailableDeviceListListener() - { - private boolean start = false; - - public void didUpdateAvailableDeviceList() - throws Exception - { - synchronized(startStopMutex) + = new UpdateAvailableDeviceListListener() { - updateDeviceUID(); - if(start) + private boolean start = false; + + @Override + public void didUpdateAvailableDeviceList() + throws Exception { - open(); - start(); + synchronized(startStopMutex) + { + updateDeviceUID(); + if(start) + { + open(); + start(); + } + } } - } - } - public void willUpdateAvailableDeviceList() - throws Exception - { - synchronized(startStopMutex) - { - start = false; - if(stream != 0) + @Override + public void willUpdateAvailableDeviceList() + throws Exception { - start = true; - stop(); + synchronized(startStopMutex) + { + start = false; + if(stream != 0) + { + start = true; + stop(); + } + } } - } - } - }; + }; /** * Array of supported input formats. @@ -180,11 +182,14 @@ public MacCoreaudioRenderer(boolean enableVolumeControl) ? AudioSystem.DataFlow.PLAYBACK : AudioSystem.DataFlow.NOTIFY); - // XXX We will add a PaUpdateAvailableDeviceListListener and will not + // XXX We will add an UpdateAvailableDeviceListListener and will not // remove it because we will rely on MacCoreaudioSystem's use of // WeakReference. - MacCoreaudioSystem.addUpdateAvailableDeviceListListener( - updateAvailableDeviceListListener); + if (audioSystem != null) + { + audioSystem.addUpdateAvailableDeviceListListener( + updateAvailableDeviceListListener); + } } /** @@ -269,14 +274,17 @@ private void getSupportedInputFormats( AudioFormat audioFormat = (AudioFormat) format; int sampleSizeInBits = audioFormat.getSampleSizeInBits(); double sampleRate = audioFormat.getSampleRate(); - float minRate = MacCoreAudioDevice.getMinimalNominalSampleRate( - deviceUID, - true, - MacCoreaudioSystem.isEchoCancelActivated()); - float maxRate = MacCoreAudioDevice.getMaximalNominalSampleRate( - deviceUID, - true, - MacCoreaudioSystem.isEchoCancelActivated()); + boolean isEchoCancel = audioSystem.isEchoCancel(); + float minRate + = MacCoreAudioDevice.getMinimalNominalSampleRate( + deviceUID, + true, + isEchoCancel); + float maxRate + = MacCoreAudioDevice.getMaximalNominalSampleRate( + deviceUID, + true, + isEchoCancel); for(int channels = minOutputChannels; channels <= maxOutputChannels; @@ -314,7 +322,7 @@ public void open() { if(stream == 0) { - MacCoreaudioSystem.willOpenStream(); + audioSystem.willOpenStream(); try { if(!this.updateDeviceUID()) @@ -331,7 +339,7 @@ public void open() } finally { - MacCoreaudioSystem.didOpenStream(); + audioSystem.didOpenStream(); } } @@ -448,19 +456,27 @@ public void start() if (nbChannels == Format.NOT_SPECIFIED) nbChannels = 1; - MacCoreaudioSystem.willOpenStream(); - stream = MacCoreAudioDevice.startStream( - deviceUID, - this, - (float) inputFormat.getSampleRate(), - nbChannels, - inputFormat.getSampleSizeInBits(), - false, - inputFormat.getEndian() == AudioFormat.BIG_ENDIAN, - false, - false, - MacCoreaudioSystem.isEchoCancelActivated()); - MacCoreaudioSystem.didOpenStream(); + audioSystem.willOpenStream(); + try + { + stream + = MacCoreAudioDevice.startStream( + deviceUID, + this, + (float) inputFormat.getSampleRate(), + nbChannels, + inputFormat.getSampleSizeInBits(), + false, + inputFormat.getEndian() + == AudioFormat.BIG_ENDIAN, + false, + false, + audioSystem.isEchoCancel()); + } + finally + { + audioSystem.didOpenStream(); + } } } } diff --git a/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java b/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java index 18f2d08a..a1fb9425 100644 --- a/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java +++ b/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java @@ -210,11 +210,12 @@ public String toString() * corruption afterwards and it will attempt to restore the state of this * <tt>Renderer</tt> after the invocation. */ - private final PortAudioSystem.PaUpdateAvailableDeviceListListener + private final UpdateAvailableDeviceListListener paUpdateAvailableDeviceListListener - = new PortAudioSystem.PaUpdateAvailableDeviceListListener() + = new UpdateAvailableDeviceListListener() { - public void didPaUpdateAvailableDeviceList() + @Override + public void didUpdateAvailableDeviceList() throws Exception { synchronized (PortAudioRenderer.this) @@ -248,7 +249,8 @@ public void didPaUpdateAvailableDeviceList() } } - public void willPaUpdateAvailableDeviceList() + @Override + public void willUpdateAvailableDeviceList() throws Exception { synchronized (PortAudioRenderer.this) @@ -335,8 +337,11 @@ public PortAudioRenderer(boolean enableVolumeControl) * remove it because we will rely on PortAudioSystem's use of * WeakReference. */ - PortAudioSystem.addPaUpdateAvailableDeviceListListener( - paUpdateAvailableDeviceListListener); + if (audioSystem != null) + { + audioSystem.addUpdateAvailableDeviceListListener( + paUpdateAvailableDeviceListListener); + } } /** @@ -520,14 +525,14 @@ public synchronized void open() { try { - PortAudioSystem.willPaOpenStream(); + audioSystem.willOpenStream(); try { doOpen(); } finally { - PortAudioSystem.didPaOpenStream(); + audioSystem.didOpenStream(); } } catch (Throwable t) diff --git a/src/org/jitsi/impl/neomedia/protocol/PushBufferDataSourceAdapter.java b/src/org/jitsi/impl/neomedia/protocol/PushBufferDataSourceAdapter.java index 2efb4c0b..3a428ce4 100644 --- a/src/org/jitsi/impl/neomedia/protocol/PushBufferDataSourceAdapter.java +++ b/src/org/jitsi/impl/neomedia/protocol/PushBufferDataSourceAdapter.java @@ -122,6 +122,7 @@ void close() * @return <tt>true</tt> if the wrapped <tt>PullBufferStream</tt> has * reached the end of the media data; otherwise, <tt>false</tt> */ + @Override public boolean endOfStream() { return stream.endOfStream(); @@ -135,6 +136,7 @@ public boolean endOfStream() * <tt>PullBufferStream</tt> which describes the type of the media data * it gives access to */ + @Override public ContentDescriptor getContentDescriptor() { return stream.getContentDescriptor(); @@ -147,6 +149,7 @@ public ContentDescriptor getContentDescriptor() * @return the length of the content the wrapped * <tt>PullBufferStream</tt> gives access to */ + @Override public long getContentLength() { return stream.getContentLength(); @@ -165,6 +168,7 @@ public long getContentLength() * if the wrapped <tt>PushBufferStream</tt> does not have a control of * the specified type */ + @Override public Object getControl(String controlType) { return stream.getControl(controlType); @@ -177,6 +181,7 @@ public Object getControl(String controlType) * @return an array of <tt>Object</tt>s which represent the controls * available for the wrapped <tt>PushBufferStream</tt> */ + @Override public Object[] getControls() { return stream.getControls(); @@ -188,6 +193,7 @@ public Object[] getControls() * * @return the <tt>Format</tt> of the wrapped <tt>PullBufferStream</tt> */ + @Override public Format getFormat() { return stream.getFormat(); @@ -202,6 +208,7 @@ public Format getFormat() * data from this <tt>PushBufferDataSource</tt> into the specified * <tt>buffer</tt> */ + @Override public void read(Buffer buffer) throws IOException { @@ -284,6 +291,7 @@ else if (yield) * which <tt>PushBufferStream</tt> is to notify its user that media data * is available for reading */ + @Override public void setTransferHandler(BufferTransferHandler transferHandler) { if (this.transferHandler != transferHandler) @@ -562,7 +570,9 @@ else if (format instanceof VideoFormat) } catch (Throwable t) { - if (t instanceof ThreadDeath) + if (t instanceof InterruptedException) + Thread.currentThread().interrupt(); + else if (t instanceof ThreadDeath) throw (ThreadDeath) t; logger.warn("Failed to set the priority of streamReadThread"); -- GitLab