diff --git a/livesupport/modules/playlistExecutor/etc/playlist.xml b/livesupport/modules/playlistExecutor/etc/playlist.xml
index 54d6ca9c3..b8b2e217d 100644
--- a/livesupport/modules/playlistExecutor/etc/playlist.xml
+++ b/livesupport/modules/playlistExecutor/etc/playlist.xml
@@ -38,21 +38,21 @@
     <playlistElement id="0000000000000102"    
                      relativeOffset="00:00:06" >
         <audioClip   id="0000000000010002"  
-                     playlength="00:00:12" 
+                     playlength="00:00:12.200000" 
 		     title = "two"
                      uri="file:var/test10002.mp3" /> 
         <fadeInfo    id="0000000000009902"   
                      fadeIn="00:00:05" 
-                     fadeOut="0" />
+                     fadeOut="00:00:04" />
     </playlistElement>
     <playlistElement id="0000000000000103" 
-                     relativeOffset="00:00:18" >
+                     relativeOffset="00:00:18.200000" >
         <audioClip   id="0000000000010003" 
                      playlength="00:00:11.500000" 
-		     title = "three"
+		             title = "three"
                      uri="file:var/test10003.mp3" />
         <fadeInfo    id="0000000000009903"   
-                     fadeIn="0" 
-                     fadeOut="00:00:05" />
+                     fadeIn="00:00:06" 
+                     fadeOut="00:00:04" />
     </playlistElement>
 </playlist>
diff --git a/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h b/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h
index 26aa470c4..a17c8e38f 100644
--- a/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h
+++ b/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.5 $
+    Version  : $Revision: 1.6 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/include/LiveSupport/PlaylistExecutor/AudioPlayerInterface.h,v $
 
 ------------------------------------------------------------------------------*/
@@ -68,7 +68,7 @@ using namespace LiveSupport::Core;
  *  A generic interface for playing audio files.
  *
  *  @author  $Author: fgerlits $
- *  @version $Revision: 1.5 $
+ *  @version $Revision: 1.6 $
  */
 class AudioPlayerInterface
 {
@@ -165,12 +165,18 @@ class AudioPlayerInterface
         virtual void
         stop(void)                              throw (std::logic_error)
                                                                       = 0;
+
         /**
          *  Play a playlist, with simulated fading.
          *
          *  This is a stopgap method, and should be replaced as soon as
          *  the SMIL animation issues are fixed in the Helix client.
          *
+         *  The playlist is assumed to contain a URI field, which points
+         *  to a SMIL file containing the same audio clips, with the same
+         *  offsets, as the playlist.  This can be ensured, for example, by 
+         *  calling Storage::WebStorageClient::acquirePlaylist().
+         *
          *  @param playlist the Playlist object to be played.
          *  @exception std::invalid_argument playlist is invalid (e.g.,
          *              does not have a URI field, or there is no valid
@@ -180,7 +186,7 @@ class AudioPlayerInterface
          *  @exception std::runtime_error on errors thrown by the helix player
          */
         virtual void
-        openAndStartPlaylist(Ptr<Playlist>::Ref  playlist)       
+        openAndStart(Ptr<Playlist>::Ref  playlist)       
                                                 throw (std::invalid_argument,
                                                        std::logic_error,
                                                        std::runtime_error)
diff --git a/livesupport/modules/playlistExecutor/src/AdviseSink.cxx b/livesupport/modules/playlistExecutor/src/AdviseSink.cxx
index 257f08b64..17e6fb635 100644
--- a/livesupport/modules/playlistExecutor/src/AdviseSink.cxx
+++ b/livesupport/modules/playlistExecutor/src/AdviseSink.cxx
@@ -21,8 +21,8 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  
-    Author   : $Author: maroy $
-    Version  : $Revision: 1.2 $
+    Author   : $Author: fgerlits $
+    Version  : $Revision: 1.3 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/AdviseSink.cxx,v $
 
 ------------------------------------------------------------------------------*/
@@ -173,6 +173,11 @@ AdviseSink::OnPosLength(UINT32      ulPosition,
                         UINT32      ulLength)               throw ()
 {
     helixPlayer->setPlaylength(ulLength);
+    try {
+        helixPlayer->implementFading(ulPosition);
+    } catch (std::runtime_error) {
+        // TODO: mark error; log it somewhere, maybe?
+    }
     return HXR_OK;
 }
 
diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx b/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx
index 78e405192..31bfab832 100644
--- a/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx
+++ b/livesupport/modules/playlistExecutor/src/HelixPlayer.cxx
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.14 $
+    Version  : $Revision: 1.15 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayer.cxx,v $
 
 ------------------------------------------------------------------------------*/
@@ -85,14 +85,12 @@ static const std::string    clntcoreName = "/clntcore.so";
 /**
  *  Magic number #1: max time to wait for an audio stream, in milliseconds
  */
-static const int            getAudioStreamTimeOut = 10;
+static const int            getAudioStreamTimeOut = 5;
 
 /**
- *  Magic number #2: time to wait after getting crossfade interface, 
- *  and before setting crossfade values, in milliseconds
+ *  Magic number #2: schedule fading this many milliseconds in advance
  */
-static const int            crossFadeWaitingTime = 50;
-
+static const int            lookAheadTime = 2500;
 
 /* ===============================================  local function prototypes */
 
@@ -398,10 +396,10 @@ DLLAccessPath* GetDLLAccessPath(void)
 
 
 /*------------------------------------------------------------------------------
- *  Play a playlist, with simulated fading.
+ *  Open a playlist, with simulated fading.
  *----------------------------------------------------------------------------*/
 void
-HelixPlayer :: openAndStartPlaylist(Ptr<Playlist>::Ref  playlist)       
+HelixPlayer :: openAndStart(Ptr<Playlist>::Ref  playlist)       
                                                 throw (std::invalid_argument,
                                                        std::logic_error,
                                                        std::runtime_error)
@@ -409,96 +407,177 @@ HelixPlayer :: openAndStartPlaylist(Ptr<Playlist>::Ref  playlist)
     if (!playlist || !playlist->getUri()) {
         throw std::invalid_argument("no playlist SMIL file found");
     }
+
     open(*playlist->getUri());      // may throw invalid_argument
 
-    bool    hasFadeInfo = false;
-    int     numberOfPlaylistElements = 0;
-    Playlist::const_iterator    it = playlist->begin();
-    while (it != playlist->end()) {
-        ++numberOfPlaylistElements;
-        if (it->second->getFadeInfo()) {
-            hasFadeInfo = true;
-        }
-        ++it;
-    }
-
     start();                        // may throw logic_error
-    if (!numberOfPlaylistElements || !hasFadeInfo) {
-        return;
-    }
 
     IHXAudioPlayer* audioPlayer = 0;
-    if (player->QueryInterface(IID_IHXAudioPlayer, (void**)&audioPlayer)
-                                                        != HXR_OK
+    if (player->QueryInterface(IID_IHXAudioPlayer, 
+                                (void**)&audioPlayer)    != HXR_OK
             || !audioPlayer) {
         throw std::runtime_error("can't get IHXAudioPlayer interface");
     }
 
-    IHXAudioCrossFade* crossFade = 0;
-    if (audioPlayer->QueryInterface(IID_IHXAudioCrossFade, (void**)&crossFade)
-                                                            != HXR_OK
-            || !crossFade) {
-        throw std::runtime_error("can't get IHXAudioCrossFade interface");
-    }
+    int                 playlistSize = playlist->size();
+    IHXAudioStream*     audioStream[playlistSize];
 
+    unsigned long       playlength[playlistSize];
+    unsigned long       relativeOffset[playlistSize];
+    unsigned long       fadeIn[playlistSize];
+    unsigned long       fadeOut[playlistSize];
+    
     Ptr<time_duration>::Ref sleepT(new time_duration(microseconds(10)));
 
-    IHXAudioStream*     audioStream[numberOfPlaylistElements + 1];
-    for (int i = 0; i < numberOfPlaylistElements; i++) {
-        int j = 0;
-        do {
-            TimeConversion::sleep(sleepT);
-            audioStream[i] = audioPlayer->GetAudioStream(i);
-            ++j;
-            if (j > getAudioStreamTimeOut * 100) {
+    bool                        hasFadeInfo = false;
+    Playlist::const_iterator    it = playlist->begin();
+
+    for (int i = 0; i < playlistSize; ++i) {
+        audioStream[i] = audioPlayer->GetAudioStream(i);
+        int counter = 0;
+        while (!audioStream[i]) {
+            if (counter > getAudioStreamTimeOut * 100) {
                 std::stringstream   eMsg;
                 eMsg << "can't get audio stream number " << i;
                 throw std::runtime_error(eMsg.str());
             }
-        } while (!audioStream[i]);
-    }
-    audioStream[numberOfPlaylistElements] = 0;  // fade out last clip into 0
-
-    it = playlist->begin();
+            TimeConversion::sleep(sleepT);
     
-    sleepT.reset(new time_duration(milliseconds(crossFadeWaitingTime)));
-    TimeConversion::sleep(sleepT);
-
-    for (int i = 0; i < numberOfPlaylistElements; i++) {
-
-        Ptr<PlaylistElement>::Ref   playlistElement = it->second;
-        if (!playlistElement->getFadeInfo()) {
-            ++it;
-            continue;
+            audioStream[i] = audioPlayer->GetAudioStream(i);
+            ++counter;
         }
         
-        // we assume i-th fade out is the same as (i+1)-st fade in
-        unsigned long   crossFadeLength = playlistElement
-                                                ->getFadeInfo()
-                                                ->getFadeOut()
-                                                ->total_milliseconds();
-        unsigned long   fadeOutAt   = playlistElement->getRelativeOffset()
-                                                     ->total_milliseconds()
-                                    + playlistElement->getPlayable()
-                                                     ->getPlaylength()
-                                                     ->total_milliseconds()
-                                    - crossFadeLength;
-
-        if (crossFadeLength) {
-//std::cerr << "fadeOutAt: " << fadeOutAt << "\n"
-//          << "crossFadeLength: " << crossFadeLength << "\n";
-            crossFade->CrossFade(audioStream[i], audioStream[i+1], 
-                                fadeOutAt, fadeOutAt, crossFadeLength);
+        relativeOffset[i]   = it->second->getRelativeOffset()
+                                        ->total_milliseconds();
+        playlength[i]       = it->second->getPlayable()->getPlaylength()
+                                        ->total_milliseconds();
+        
+        if (it->second->getFadeInfo()) {
+            hasFadeInfo = true;
+            fadeIn[i] = it->second->getFadeInfo()
+                                  ->getFadeIn()->total_milliseconds();
+            fadeOut[i] = it->second->getFadeInfo()
+                                   ->getFadeOut()->total_milliseconds();
+        } else {
+            fadeIn[i]  = 0;
+            fadeOut[i] = 0;
         }
-    
+
         ++it;
     }
 
-    for (int i = 0; i < numberOfPlaylistElements; i++) {
+    if (!hasFadeInfo) {
+        return;
+    }
+
+    fadeIn[0] = 0;  // can't do fade-in on the first audio clip, sorry
+    
+    fadeDataList.reset(new std::list<FadeData>);
+    FadeData    fadeData;
+
+    for (int i = 0; i < playlistSize; ++i) {
+        if (fadeIn[i]) {
+            fadeData.audioStreamFrom    = 0;
+            fadeData.audioStreamTo      = audioStream[i];
+            fadeData.fadeAt             = relativeOffset[i];
+            fadeData.fadeLength         = fadeIn[i];
+            fadeDataList->push_back(fadeData);
+        }
+        
+        if (fadeOut[i]) {
+            if (i < playlistSize - 1 
+                    && fadeOut[i] == fadeIn[i+1]
+                    && relativeOffset[i] + playlength[i] 
+                                  == relativeOffset[i+1] + fadeIn[i+1]) {
+                fadeData.audioStreamFrom    = audioStream[i];
+                fadeData.audioStreamTo      = audioStream[i+1];
+                fadeData.fadeAt             = relativeOffset[i+1];
+                fadeData.fadeLength         = fadeIn[i+1];
+                fadeDataList->push_back(fadeData);
+                fadeIn[i+1] = 0;
+            } else {
+                fadeData.audioStreamFrom    = audioStream[i];
+                fadeData.audioStreamTo      = 0;
+                fadeData.fadeAt             = relativeOffset[i] 
+                                              + playlength[i] - fadeOut[i];
+                fadeData.fadeLength         = fadeOut[i];
+                fadeDataList->push_back(fadeData);
+            }
+        }
+        
         HX_RELEASE(audioStream[i]);
     }
-    HX_RELEASE(crossFade);
-    HX_RELEASE(audioPlayer);
+
+//do {
+//    std::cerr << "\n";
+//    std::list<FadeData>::const_iterator it = fadeDataList->begin();
+//    while (it != fadeDataList->end()) {
+//        std::cerr << it->audioStreamFrom << " -> "
+//                  << it->audioStreamTo << " : at "
+//                  << it->fadeAt << ", for "
+//                  << it->fadeLength << "\n";
+//        ++it;
+//    }
+//    std::cerr << "\n";
+//} while (false);
+
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Activate the crossfading of clips in a playlist.
+ *----------------------------------------------------------------------------*/
+void
+HelixPlayer :: implementFading(unsigned long    position)
+                                                throw (std::runtime_error)
+{
+    if (!fadeDataList) {
+        return;
+    }
+
+    std::list<FadeData>::iterator   it = fadeDataList->begin();
+    
+    while (it != fadeDataList->end()) {
+        unsigned long   fadeAt = it->fadeAt;
+
+        if (fadeAt < position) {                            // we missed it
+            it = fadeDataList->erase(it);
+            continue;
+
+        } else if (fadeAt < position + lookAheadTime) {     // we are on time
+
+            IHXAudioPlayer* audioPlayer = 0;
+            if (player->QueryInterface(IID_IHXAudioPlayer, 
+                                       (void**)&audioPlayer)    != HXR_OK
+                    || !audioPlayer) {
+                throw std::runtime_error("can't get IHXAudioPlayer interface");
+            }
+
+            IHXAudioCrossFade* crossFade = 0;
+            if (audioPlayer->QueryInterface(IID_IHXAudioCrossFade,
+                                            (void**)&crossFade) != HXR_OK
+                    || !crossFade) {
+                throw std::runtime_error("can't get IHXAudioCrossFade "
+                                                                "interface");
+            }
+
+//std::cerr << "position:" << position << "\n"
+//          << "fadeAt: " << fadeAt << "\n"
+//          << "fadeLength: " << it->fadeLength << "\n\n";
+          
+            crossFade->CrossFade(it->audioStreamFrom, it->audioStreamTo, 
+                                fadeAt, fadeAt, it->fadeLength);
+
+            HX_RELEASE(crossFade);
+            HX_RELEASE(audioPlayer);
+
+            it = fadeDataList->erase(it);
+            continue;
+
+        } else {
+            ++it;
+        }
+    }
 }
 
 
diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayer.h b/livesupport/modules/playlistExecutor/src/HelixPlayer.h
index cb7503423..2ae0b1d0c 100644
--- a/livesupport/modules/playlistExecutor/src/HelixPlayer.h
+++ b/livesupport/modules/playlistExecutor/src/HelixPlayer.h
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.12 $
+    Version  : $Revision: 1.13 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayer.h,v $
 
 ------------------------------------------------------------------------------*/
@@ -40,6 +40,7 @@
 #include "configure.h"
 #endif
 
+#include <list>
 #include <boost/enable_shared_from_this.hpp>
 
 #include "LiveSupport/Core/Configurable.h"
@@ -54,6 +55,9 @@
 #include "ClientContext.h"
 #include "LiveSupport/Core/Playlist.h"
 
+#include <hxausvc.h>
+
+
 namespace LiveSupport {
 namespace PlaylistExecutor {
 
@@ -94,7 +98,7 @@ using namespace LiveSupport::Core;
  *  </pre></code>
  *
  *  @author  $Author: fgerlits $
- *  @version $Revision: 1.12 $
+ *  @version $Revision: 1.13 $
  */
 class HelixPlayer : virtual public Configurable,
                     virtual public AudioPlayerInterface,
@@ -135,7 +139,7 @@ class HelixPlayer : virtual public Configurable,
          *  The Helix player.
          */
         IHXPlayer             * player;
-
+        
         /**
          *  The example client context.
          */
@@ -171,6 +175,44 @@ class HelixPlayer : virtual public Configurable,
          */
         Ptr<Thread>::Ref        eventHandlerThread;
 
+        /**
+         *  A type to contain the data about a single fade-in or fade-out
+         *  event.
+         */
+        struct FadeData {
+            IHXAudioStream* audioStreamFrom;
+            IHXAudioStream* audioStreamTo;
+            unsigned long   fadeAt;
+            unsigned long   fadeLength;
+        };
+
+        /**
+         *  A list of fade-in/fade-out events.
+         *  This is set by the openAndStartPlaylist() method, and the
+         *  actual fading is done by implementFading(), called from
+         *  AdviseSink::OnPosLength().
+         */
+        Ptr<std::list<FadeData> >::Ref  fadeDataList;
+
+        /**
+         *  Declare AdviseSink::OnPosLength() to be a friend, so it can
+         *  call the private method implementFading().
+         */
+        friend STDMETHODIMP
+        AdviseSink::OnPosLength(UINT32      ulPosition,
+                                UINT32      ulLength)
+                                                throw ();
+
+        /**
+         *  Implement the actual fading scheduled by open(Ptr<Playlist>::Ref).
+         *  This method is called from AdviceSink::OnPosLength().
+         *  DO NOT call this method directly.
+         *
+         *  @param position the clip position
+         */
+        void
+        implementFading(unsigned long position)
+                                                throw(std::runtime_error);
 
     public:
         /**
@@ -336,9 +378,6 @@ class HelixPlayer : virtual public Configurable,
          *  This is a stopgap method, and should be replaced as soon as
          *  the SMIL animation issues are fixed in the Helix client.
          *
-         *  Note: the method only reads the fade out value, and assumes
-         *  that the following fade in value is equal to it.
-         *
          *  The playlist is assumed to contain a URI field, which points
          *  to a SMIL file containing the same audio clips, with the same
          *  offsets, as the playlist.  This can be ensured, for example, by 
@@ -353,7 +392,7 @@ class HelixPlayer : virtual public Configurable,
          *  @exception std::runtime_error on errors thrown by the helix player
          */
         virtual void
-        openAndStartPlaylist(Ptr<Playlist>::Ref  playlist)       
+        openAndStart(Ptr<Playlist>::Ref  playlist)       
                                                 throw (std::invalid_argument,
                                                        std::logic_error,
                                                        std::runtime_error);
diff --git a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx
index 25ab8065d..156e7bc04 100644
--- a/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx
+++ b/livesupport/modules/playlistExecutor/src/HelixPlayerTest.cxx
@@ -22,7 +22,7 @@
  
  
     Author   : $Author: fgerlits $
-    Version  : $Revision: 1.9 $
+    Version  : $Revision: 1.10 $
     Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/playlistExecutor/src/Attic/HelixPlayerTest.cxx,v $
 
 ------------------------------------------------------------------------------*/
@@ -419,7 +419,7 @@ HelixPlayerTest :: animationWorkaroundTest(void)
     playlist->setUri(uri);
     
     CPPUNIT_ASSERT_NO_THROW(helixPlayer->initialize());
-    CPPUNIT_ASSERT_NO_THROW(helixPlayer->openAndStartPlaylist(playlist));
+    CPPUNIT_ASSERT_NO_THROW(helixPlayer->openAndStart(playlist));
     CPPUNIT_ASSERT(helixPlayer->isPlaying());
 
     Ptr<time_duration>::Ref     sleepT(new time_duration(microseconds(10)));
diff --git a/livesupport/modules/playlistExecutor/var/playlist.smil b/livesupport/modules/playlistExecutor/var/playlist.smil
index a44302802..1efdcba60 100644
--- a/livesupport/modules/playlistExecutor/var/playlist.smil
+++ b/livesupport/modules/playlistExecutor/var/playlist.smil
@@ -4,7 +4,7 @@
         <par>
             <audio src="file:var/test10001.mp3" begin="0s"/> 
             <audio src="file:var/test10002.mp3" begin="6s"/> 
-            <audio src="file:var/test10003.mp3" begin="18s"/> 
+            <audio src="file:var/test10003.mp3" begin="18.2s"/> 
         </par>
     </body>
 </smil>