diff --git a/src/libtomahawk/playlist/dynamic/DynamicModel.cpp b/src/libtomahawk/playlist/dynamic/DynamicModel.cpp
index f68766594..b8c660600 100644
--- a/src/libtomahawk/playlist/dynamic/DynamicModel.cpp
+++ b/src/libtomahawk/playlist/dynamic/DynamicModel.cpp
@@ -17,6 +17,7 @@
 #include "playlist/dynamic/DynamicModel.h"
 #include "GeneratorInterface.h"
 #include "audio/audioengine.h"
+#include <pipeline.h>
 
 using namespace Tomahawk;
 
@@ -25,7 +26,7 @@ DynamicModel::DynamicModel( QObject* parent )
     , m_startOnResolved( false )
     , m_onDemandRunning( false )
     , m_changeOnNext( false )
-    , m_firstTrackGenerated( false )
+    , m_filterUnresolvable( true )
     , m_currentAttempts( 0 )
     , m_lastResolvedRow( 0 )
 {
@@ -45,9 +46,11 @@ DynamicModel::loadPlaylist( const Tomahawk::dynplaylist_ptr& playlist )
     }
     m_playlist = playlist;
     
+    if( m_playlist->mode() == OnDemand )
+        setFilterUnresolvable( true );
     
     connect( m_playlist->generator().data(), SIGNAL( nextTrackGenerated( Tomahawk::query_ptr ) ), this, SLOT( newTrackGenerated( Tomahawk::query_ptr ) ) );
-    PlaylistModel::loadPlaylist( m_playlist, !m_onDemandRunning );
+    PlaylistModel::loadPlaylist( m_playlist, m_playlist->mode() == Static );
 }
 
 QString 
@@ -62,25 +65,18 @@ DynamicModel::startOnDemand()
 {
     connect( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ), this, SLOT( newTrackLoading() ) );
     
-    // delete all the tracks
-    clear();
-    
     m_playlist->generator()->startOnDemand();
     
     m_onDemandRunning = true;
-    m_startOnResolved = true;
+    m_startOnResolved = false; // not anymore---user clicks a track to start it
     m_currentAttempts = 0;
-    m_lastResolvedRow = 0;
+    m_lastResolvedRow = rowCount( QModelIndex() );
 }
 
 void 
 DynamicModel::newTrackGenerated( const Tomahawk::query_ptr& query )
 {
     if( m_onDemandRunning ) {
-        if( !m_firstTrackGenerated ) {
-            emit firstTrackGenerated();
-            m_firstTrackGenerated = false;
-        }
         connect( query.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( trackResolveFinished( bool ) ) );
         connect( query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ), this, SLOT( trackResolved() ) );
     
@@ -92,7 +88,6 @@ void
 DynamicModel::stopOnDemand( bool stopPlaying )
 {
     m_onDemandRunning = false;
-    m_firstTrackGenerated = false;
     if( stopPlaying )
         AudioEngine::instance()->stop();
     
@@ -156,6 +151,79 @@ DynamicModel::newTrackLoading()
     }    
 }
 
+void 
+DynamicModel::tracksGenerated( const QList< query_ptr > entries, int limitResolvedTo )
+{
+    if( m_filterUnresolvable ) { // wait till we get them resolved
+        m_limitResolvedTo = limitResolvedTo;
+        filterUnresolved( entries );
+    } else {
+        addToPlaylist( entries, m_playlist->mode() == OnDemand ); // if ondemand, we're previewing, so clear old
+    }
+}
+
+void 
+DynamicModel::filterUnresolved( const QList< query_ptr >& entries )
+{
+    m_toResolveList = entries;
+    
+    foreach( const query_ptr& q, entries ) {
+        connect( q.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( filteringTrackResolved( bool ) ) );
+        Pipeline::instance()->resolve( q );
+    }    
+}
+
+void 
+DynamicModel::filteringTrackResolved( bool successful )
+{    
+    // arg, we don't have the query_ptr, just the Query
+    Query* q = qobject_cast< Query* >( sender() );
+    Q_ASSERT( q );
+    
+    query_ptr realptr;
+    foreach( const query_ptr& qptr, m_toResolveList ) {
+        if( qptr.data() == q ) {
+            realptr = qptr;
+            break;
+        }
+    }
+    if( realptr.isNull() ) // we already finished
+        return;
+    
+    m_toResolveList.removeAll( realptr );
+    
+    if( successful )
+        m_resolvedList << realptr;
+    
+    if( m_toResolveList.isEmpty() || m_resolvedList.size() == m_limitResolvedTo ) { // done, add to playlist
+        if( m_limitResolvedTo < m_resolvedList.count() ) // limit to how many we were asked for
+            m_resolvedList = m_resolvedList.mid( 0, m_limitResolvedTo );
+        
+        addToPlaylist( m_resolvedList, true );
+        m_toResolveList.clear();
+        m_resolvedList.clear();
+    }       
+}
+
+
+void 
+DynamicModel::addToPlaylist( const QList< query_ptr >& entries, bool clearFirst )
+{
+    if( clearFirst )
+        clear();
+    
+    if( m_playlist->author()->isLocal() && m_playlist->mode() == Static ) {
+        m_playlist->addEntries( entries, m_playlist->currentrevision() );
+    } else { // read-only, so add tracks only in the GUI, not to the playlist itself
+        foreach( const query_ptr& query, entries ) {
+            append( query );
+        }
+    }    
+    
+    emit tracksAdded();
+}
+
+
 void 
 DynamicModel::removeIndex(const QModelIndex& idx, bool moreToCome)
 {
diff --git a/src/libtomahawk/playlist/dynamic/DynamicModel.h b/src/libtomahawk/playlist/dynamic/DynamicModel.h
index 6748e4c3f..11271aa9e 100644
--- a/src/libtomahawk/playlist/dynamic/DynamicModel.h
+++ b/src/libtomahawk/playlist/dynamic/DynamicModel.h
@@ -47,13 +47,19 @@ public:
     virtual void removeIndex( const QModelIndex& index, bool moreToCome = false );
     
     bool searchingForNext() const { return m_searchingForNext; }
+    
+    void setFilterUnresolvable( bool filter ) { m_filterUnresolvable = filter; }
+    bool filterUnresolvable() const { return m_filterUnresolvable; }
+    
+    // a batchof static tracks wre generated
+    void tracksGenerated( const QList< query_ptr > entries, int limitResolvedTo = -1 );
 signals:
     void collapseFromTo( int startRow, int num );
     void checkForOverflow();
 
-    void firstTrackGenerated();
     void trackGenerationFailure( const QString& msg );
     
+    void tracksAdded();
 private slots:    
     void newTrackGenerated( const Tomahawk::query_ptr& query );
     
@@ -61,13 +67,23 @@ private slots:
     void trackResolved();
     void newTrackLoading();
     
+    void filteringTrackResolved( bool successful );
 private:
+    void filterUnresolved( const QList< query_ptr >& entries );
+    void addToPlaylist( const QList< query_ptr >& entries, bool clearFirst );
+    
     dynplaylist_ptr m_playlist;
+    // for filtering unresolvable
+    int m_limitResolvedTo;
+    QList< query_ptr > m_toResolveList;
+    QList< query_ptr > m_resolvedList;
+    
     bool m_startOnResolved;
     bool m_onDemandRunning;
     bool m_changeOnNext;
     bool m_searchingForNext;
     bool m_firstTrackGenerated;
+    bool m_filterUnresolvable;
     int m_currentAttempts;
     int m_lastResolvedRow;
 };
diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp
index f1036b9c2..787cf3bec 100644
--- a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp
+++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp
@@ -29,10 +29,10 @@ Tomahawk::EchonestControl::EchonestControl( const QString& selectedType, const Q
     : DynamicControl ( selectedType.isEmpty() ? "Artist" : selectedType, typeSelectors, parent )
 {
     setType( "echonest" );
-    m_editingTimer.setInterval( 2000 ); // 2 second timeout to edits
+    m_editingTimer.setInterval( 500 ); //timeout to edits
     m_editingTimer.setSingleShot( true );
     
-    connect( &m_editingTimer, SIGNAL( timeout() ), this, SIGNAL( changed() ) );
+    connect( &m_editingTimer, SIGNAL( timeout() ), this, SLOT( editTimerFired() ) );
     updateWidgets();
 }
 
@@ -340,7 +340,6 @@ Tomahawk::EchonestControl::setupMinMaxWidgets( Echonest::DynamicPlaylist::Playli
     connect( match, SIGNAL( activated( int ) ), this, SLOT( editingFinished() ) );
     connect( input->slider(), SIGNAL( valueChanged( int ) ), this, SLOT( updateData() ) );
     connect( input->slider(), SIGNAL( valueChanged( int ) ), this, SLOT( editingFinished() ) );
-    connect( input->slider(), SIGNAL( sliderMoved( int ) ), &m_editingTimer, SLOT( stop() ) );
     
     match->hide();
     input->hide();
@@ -491,6 +490,18 @@ Tomahawk::EchonestControl::editingFinished()
     m_editingTimer.start();
 }
 
+void 
+Tomahawk::EchonestControl::editTimerFired()
+{
+    // make sure it's really changed
+    if( m_cacheData != m_data.second ) { // new, so emit changed
+        emit changed();
+    }
+    
+    m_cacheData = m_data.second;
+}
+
+
 void 
 Tomahawk::EchonestControl::calculateSummary()
 {
diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.h b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.h
index a5cf6b0d1..357def005 100644
--- a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.h
+++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.h
@@ -52,6 +52,7 @@ public slots:
 private slots:
     void updateData();
     void editingFinished();
+    void editTimerFired();
     
 private:
     void updateWidgets();
@@ -79,6 +80,7 @@ private:
     QTimer m_editingTimer;
     
     Echonest::DynamicPlaylist::PlaylistParamData m_data;
+    QVariant m_cacheData;
     
     friend class EchonestGenerator;
 };
diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicSetupWidget.h b/src/libtomahawk/playlist/dynamic/widgets/DynamicSetupWidget.h
index 4d475f8a8..7bf7cf1c6 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/DynamicSetupWidget.h
+++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicSetupWidget.h
@@ -45,13 +45,15 @@ public:
     
     void setPlaylist( const dynplaylist_ptr& playlist );
     
-    void fadeIn();
-    void fadeOut();
-    
     qreal opacity() const { return m_opacity; }
     void setOpacity( qreal opacity );
     
     virtual void paintEvent( QPaintEvent* );
+    
+public slots:        
+    void fadeIn();
+    void fadeOut();
+    
 signals:
     void generatePressed( int num );
     void typeChanged( const QString& playlistType );
diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
index e7829a6bb..2d87d6ba8 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
+++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
@@ -68,13 +68,15 @@ DynamicWidget::DynamicWidget( const Tomahawk::dynplaylist_ptr& playlist, QWidget
     
     connect( m_model, SIGNAL( collapseFromTo( int, int ) ), m_view, SLOT( collapseEntries( int, int ) ) );
     connect( m_model, SIGNAL( trackGenerationFailure( QString ) ), this, SLOT( stationFailed( QString ) ) );    
-    connect( m_model, SIGNAL( firstTrackGenerated() ), this, SLOT( firstStationTrackGenerated() ) );
     
     m_loading = new LoadingSpinner( m_view ); 
+    connect( m_model, SIGNAL( tracksAdded() ), m_loading, SLOT( fadeOut() ) );
     
     m_setup = new DynamicSetupWidget( playlist, this );
     m_setup->fadeIn();
     
+    connect( m_model, SIGNAL( tracksAdded() ), m_setup, SLOT( fadeOut() ) );
+    
     loadDynamicPlaylist( playlist );
     
     m_layout->setContentsMargins( 0, 0, 0, 0 );
@@ -90,8 +92,7 @@ DynamicWidget::DynamicWidget( const Tomahawk::dynplaylist_ptr& playlist, QWidget
     connect( m_controls, SIGNAL( controlChanged( Tomahawk::dyncontrol_ptr ) ), this, SLOT( controlChanged( Tomahawk::dyncontrol_ptr ) ), Qt::QueuedConnection );
     connect( m_controls, SIGNAL( controlsChanged() ), this, SLOT( controlsChanged() ), Qt::QueuedConnection );
 
-    connect( PlaylistManager::instance(), SIGNAL( playClicked() ), this, SLOT( playPressed() ) );
-    connect( PlaylistManager::instance(), SIGNAL( pauseClicked() ), this, SLOT( pausePressed() ) );
+    connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), this, SLOT( trackStarted() ) );
     connect( AudioEngine::instance(), SIGNAL( playlistChanged( PlaylistInterface* ) ), this, SLOT( playlistStopped( PlaylistInterface* ) ) );
 }
 
@@ -153,6 +154,9 @@ DynamicWidget::loadDynamicPlaylist( const Tomahawk::dynplaylist_ptr& playlist )
     if( !m_playlist.isNull() )
         m_controls->setControls( m_playlist, m_playlist->author()->isLocal() );
     
+    if( m_playlist->mode() == OnDemand )
+        showPreview();
+    
     connect( m_playlist->generator().data(), SIGNAL( generated( QList<Tomahawk::query_ptr> ) ), this, SLOT( tracksGenerated( QList<Tomahawk::query_ptr> ) ) );
     connect( m_playlist.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( onRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ) );
     connect( m_playlist->generator().data(), SIGNAL( error( QString, QString ) ), this, SLOT( generatorError( QString, QString ) ) );
@@ -232,15 +236,10 @@ DynamicWidget::showEvent(QShowEvent* )
 void 
 DynamicWidget::generate( int num )
 {
-    if( m_playlist->mode() == Static ) 
-    {
-        // get the items from the generator, and put them in the playlist
-        m_view->setDynamicWorking( true );
-        m_loading->fadeIn();
-        m_playlist->generator()->generate( num );
-    } else if( m_playlist->mode() == OnDemand ) {
-
-    }
+    // get the items from the generator, and put them in the playlist
+    m_view->setDynamicWorking( true );
+    m_loading->fadeIn();
+    m_playlist->generator()->generate( num );
 }
 
 void 
@@ -253,36 +252,16 @@ DynamicWidget::stationFailed( const QString& msg )
     stopStation( false );
 }
 
-
 void 
-DynamicWidget::pausePressed()
-{
-    // we don't handle explicit pausing right now
-    // no more track plays == no more adding. we stop when
-    // the user switches to a different playlist.
-}
-
-void 
-DynamicWidget::playPressed()
-{
-    
+DynamicWidget::trackStarted()
+{    
     if( isVisible() && !m_playlist.isNull() &&
         m_playlist->mode() == OnDemand && !m_runningOnDemand ) {
         
-        m_view->setDynamicWorking( true );
         startStation();
     }
-        
 }
 
-void 
-DynamicWidget::firstStationTrackGenerated()
-{
-    m_view->setDynamicWorking( false );
-    m_loading->fadeOut();
-}
-
-
 void 
 DynamicWidget::stopStation( bool stopPlaying )
 {
@@ -328,17 +307,16 @@ DynamicWidget::playlistTypeChanged( QString )
 
 void 
 DynamicWidget::tracksGenerated( const QList< query_ptr >& queries )
-{
-    m_loading->fadeOut();
-    
-    if( m_playlist->author()->isLocal() ) {
-        m_playlist->addEntries( queries, m_playlist->currentrevision() );
+{   
+    int limit = -1; // only limit the "preview" of a station
+    if( m_playlist->author()->isLocal() && m_playlist->mode() == Static ) {
         m_resolveOnNextLoad = true;
-    } else { // read-only, so add tracks only in the GUI, not to the playlist itself
-        foreach( const query_ptr& query, queries ) {
-            m_model->append( query );
-        }
-    }
+    } else if( m_playlist->mode() == OnDemand )
+        limit = 5;
+    
+    if( m_playlist->mode() != OnDemand )
+        m_loading->fadeOut();
+    m_model->tracksGenerated( queries, limit );
 }
 
 
@@ -348,8 +326,6 @@ DynamicWidget::controlsChanged()
     // controlsChanged() is emitted when a control is added or removed
     // in the case of addition, it's blank by default... so to avoid an error
     // when playing a station just ignore it till we're ready and get a controlChanged()
-/*    if( m_runningOnDemand )
-        m_model->changeStation();*/
     m_controlsChanged = true;
     
     if( !m_playlist->author()->isLocal() )
@@ -365,8 +341,19 @@ DynamicWidget::controlChanged( const Tomahawk::dyncontrol_ptr& control )
         return;       
     m_playlist->createNewRevision();
     m_seqRevLaunched++;
+    
+    showPreview();
 }
 
+void 
+DynamicWidget::showPreview()
+{
+    if( m_playlist->mode() == OnDemand && !m_runningOnDemand ) { // if this is a not running station, preview matching tracks
+        generate( 40 ); // ask for more, we'll filter how many we actually want
+}
+}
+
+
 void 
 DynamicWidget::generatorError( const QString& title, const QString& content )
 {
diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
index 78e133708..1a8e9c496 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
+++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
@@ -85,8 +85,7 @@ public slots:
     void startStation();
     void stopStation( bool stopPlaying = true );
     
-    void playPressed();
-    void pausePressed();
+    void trackStarted();
     void stationFailed( const QString& );
     
     void playlistStopped( PlaylistInterface* );
@@ -95,10 +94,10 @@ private slots:
     void generate( int = -1 );
     void tracksGenerated( const QList< Tomahawk::query_ptr>& queries );
     void generatorError( const QString& title, const QString& content );
-    void firstStationTrackGenerated();
     
     void controlsChanged();
     void controlChanged( const Tomahawk::dyncontrol_ptr& control );
+    void showPreview();
     
     void layoutFloatingWidgets();
 
diff --git a/src/libtomahawk/playlist/dynamic/widgets/LoadingSpinner.cpp b/src/libtomahawk/playlist/dynamic/widgets/LoadingSpinner.cpp
index d216dd233..5610e5106 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/LoadingSpinner.cpp
+++ b/src/libtomahawk/playlist/dynamic/widgets/LoadingSpinner.cpp
@@ -104,7 +104,7 @@ LoadingSpinner::paintEvent( QPaintEvent* ev )
 {
     QPainter p( this );
     
-    qDebug() << "FADING" << ( m_showHide->state() == QTimeLine::Running ) << "at frame:" << m_showHide->currentValue();
+//     qDebug() << "FADING" << ( m_showHide->state() == QTimeLine::Running ) << "at frame:" << m_showHide->currentValue();
     if( m_showHide->state() == QTimeLine::Running ) { // showing or hiding
         p.setOpacity( (qreal)m_showHide->currentValue() );
     }
diff --git a/src/libtomahawk/playlist/dynamic/widgets/LoadingSpinner.h b/src/libtomahawk/playlist/dynamic/widgets/LoadingSpinner.h
index 32994d012..9c4ade008 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/LoadingSpinner.h
+++ b/src/libtomahawk/playlist/dynamic/widgets/LoadingSpinner.h
@@ -34,6 +34,7 @@ public:
     virtual void paintEvent( QPaintEvent* );
     virtual void resizeEvent( QResizeEvent* );
     
+public slots:        
     void fadeIn();
     void fadeOut();