diff --git a/src/org/jitsi/impl/neomedia/device/AudioSystem.java b/src/org/jitsi/impl/neomedia/device/AudioSystem.java
index 5a8f372839c8270f967b80c8d0bde08091ba1ea5..bc3a9d784a89ce1f0260a04e45d0c3691c4077ae 100644
--- a/src/org/jitsi/impl/neomedia/device/AudioSystem.java
+++ b/src/org/jitsi/impl/neomedia/device/AudioSystem.java
@@ -421,21 +421,20 @@ public List<CaptureDeviceInfo2> getDevices(DataFlow dataFlow)
      * @return the FMJ format of the specified <tt>audioInputStream</tt> or
      * <tt>null</tt> if such an FMJ format could not be determined
      */
-    public Format getFormat(InputStream audioInputStream)
+    public javax.media.format.AudioFormat getFormat(
+            InputStream audioInputStream)
     {
         if ((audioInputStream instanceof AudioInputStream))
         {
-            AudioFormat audioInputStreamFormat
-                = ((AudioInputStream) audioInputStream).getFormat();
+            AudioFormat af = ((AudioInputStream) audioInputStream).getFormat();
 
             return
                 new javax.media.format.AudioFormat(
                         javax.media.format.AudioFormat.LINEAR,
-                        audioInputStreamFormat.getSampleRate(),
-                        audioInputStreamFormat.getSampleSizeInBits(),
-                        audioInputStreamFormat.getChannels());
+                        af.getSampleRate(),
+                        af.getSampleSizeInBits(),
+                        af.getChannels());
         }
-
         return null;
     }
 
diff --git a/src/org/jitsi/impl/neomedia/notify/AudioSystemClipImpl.java b/src/org/jitsi/impl/neomedia/notify/AudioSystemClipImpl.java
index 63a88d6d6e2721f4d8f8dd43971bcc9df647c589..bafd820cc27092b266d046825634274d4ab4c519 100644
--- a/src/org/jitsi/impl/neomedia/notify/AudioSystemClipImpl.java
+++ b/src/org/jitsi/impl/neomedia/notify/AudioSystemClipImpl.java
@@ -37,6 +37,13 @@ public class AudioSystemClipImpl
     private static final Logger logger
         = Logger.getLogger(AudioSystemClipImpl.class);
 
+    /**
+     * The minimum duration in milliseconds to be assumed for the audio streams
+     * played by <tt>AudioSystemClipImpl</tt> in order to ensure that they are
+     * played back long enough to be heard.
+     */
+    private static final long MIN_AUDIO_STREAM_DURATION = 200;
+
     private final AudioSystem audioSystem;
 
     private Buffer buffer;
@@ -109,7 +116,9 @@ protected void exitRunOnceInPlayThread()
         }
     }
 
-    @Override
+    /**
+     * {@inheritDoc}
+     */
     protected boolean runOnceInPlayThread()
     {
         InputStream audioStream = null;
@@ -126,10 +135,16 @@ protected boolean runOnceInPlayThread()
             return false;
 
         Codec resampler = null;
+        boolean success = true;
+        AudioFormat audioStreamFormat = null;
+        int audioStreamLength = 0;
+        long rendererProcessStartTime = 0;
 
         try
         {
-            Format rendererFormat = audioSystem.getFormat(audioStream);
+            Format rendererFormat
+                = audioStreamFormat
+                    = audioSystem.getFormat(audioStream);
 
             if (rendererFormat == null)
                 return false;
@@ -205,6 +220,8 @@ protected boolean runOnceInPlayThread()
                         && ((bufferLength = audioStream.read(bufferData))
                                 != -1))
                 {
+                    audioStreamLength += bufferLength;
+
                     if (resampler == null)
                     {
                         rendererBuffer.setLength(bufferLength);
@@ -218,7 +235,23 @@ protected boolean runOnceInPlayThread()
                         rendererBuffer.setOffset(0);
                         resampler.process(resamplerBuffer, rendererBuffer);
                     }
-                    while ((renderer.process(rendererBuffer)
+
+                    int rendererProcess;
+
+                    if (rendererProcessStartTime == 0)
+                        rendererProcessStartTime = System.currentTimeMillis();
+                    do
+                    {
+                        rendererProcess = renderer.process(rendererBuffer);
+                        if (rendererProcess == Renderer.BUFFER_PROCESSED_FAILED)
+                        {
+                            logger.error(
+                                    "Failed to render audio stream " + uri);
+                            success = false;
+                            break;
+                        }
+                    }
+                    while ((rendererProcess
                                 & Renderer.INPUT_BUFFER_NOT_CONSUMED)
                             == Renderer.INPUT_BUFFER_NOT_CONSUMED);
                 }
@@ -226,14 +259,14 @@ protected boolean runOnceInPlayThread()
             catch (IOException ioex)
             {
                 logger.error("Failed to read from audio stream " + uri, ioex);
-                return false;
+                success = false;
             }
             catch (ResourceUnavailableException ruex)
             {
                 logger.error(
                         "Failed to open " + renderer.getClass().getName(),
                         ruex);
-                return false;
+                success = false;
             }
         }
         catch (ResourceUnavailableException ruex)
@@ -243,7 +276,7 @@ protected boolean runOnceInPlayThread()
                 logger.error(
                         "Failed to open " + resampler.getClass().getName(),
                         ruex);
-                return false;
+                success = false;
             }
         }
         finally
@@ -262,7 +295,64 @@ protected boolean runOnceInPlayThread()
 
             if (resampler != null)
                 resampler.close();
+
+            /*
+             * XXX We do not know whether the Renderer implementation of the
+             * stop method will wait for the playback to complete.
+             */
+            if (success
+                    && (audioStreamFormat != null)
+                    && (audioStreamLength > 0)
+                    && (rendererProcessStartTime > 0)
+                    && isStarted())
+            {
+                long audioStreamDuration
+                    = (audioStreamFormat.computeDuration(audioStreamLength)
+                            + 999999)
+                        / 1000000;
+
+                if (audioStreamDuration > 0)
+                {
+                    /*
+                     * XXX The estimation is not accurate because we do not
+                     * know, for example, how much the Renderer may be buffering
+                     * before it starts the playback.
+                     */
+                    audioStreamDuration += MIN_AUDIO_STREAM_DURATION;
+
+                    boolean interrupted = false;
+
+                    synchronized (sync)
+                    {
+                        while (isStarted())
+                        {
+                            long timeout
+                                = System.currentTimeMillis()
+                                    - rendererProcessStartTime;
+
+                            if ((timeout >= audioStreamDuration)
+                                    || (timeout <= 0))
+                            {
+                                break;
+                            }
+                            else
+                            {
+                                try
+                                {
+                                    sync.wait(timeout);
+                                }
+                                catch (InterruptedException ie)
+                                {
+                                    interrupted = true;
+                                }
+                            }
+                        }
+                    }
+                    if (interrupted)
+                        Thread.currentThread().interrupt();
+                }
+            }
         }
-        return true;
+        return success;
     }
 }
diff --git a/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java b/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java
index d68272dec9d032bef3b0d3a63a3ebd1da36f4136..249d1532ede6e05e6237758f0dfe06fecb0fd620 100644
--- a/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java
+++ b/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java
@@ -65,8 +65,12 @@ public abstract class AbstractSCAudioClip
      * The <tt>Object</tt> used for internal synchronization purposes which
      * arise because this instance does the actual playback of audio in a
      * separate thread.
+     * <p>
+     * The synchronization root is exposed to extenders in case they would like
+     * to, for example, get notified as soon as possible when this instance gets
+     * stopped.
      */
-    private final Object sync = new Object();
+    protected final Object sync = new Object();
 
     /**
      * The <tt>String</tt> uri of the audio to be played by this instance.