From 4098cc2709ba40bf919f06b33577841965190863 Mon Sep 17 00:00:00 2001
From: Christian Muehlhaeuser <muesli@gmail.com>
Date: Tue, 19 Jul 2011 17:54:10 +0200
Subject: [PATCH] * PlaylistInterface now provides getSharedPointer().
 AudioEngine makes use of it and doesn't crash when encountering a deleted
 playlist.

---
 src/libtomahawk/audio/audioengine.cpp | 59 +++++++++++++--------------
 src/libtomahawk/audio/audioengine.h   | 10 ++---
 src/libtomahawk/playlistinterface.h   | 18 +++++++-
 src/libtomahawk/source.cpp            |  1 +
 4 files changed, 52 insertions(+), 36 deletions(-)

diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp
index a6ec343b0..b3b3ceaa2 100644
--- a/src/libtomahawk/audio/audioengine.cpp
+++ b/src/libtomahawk/audio/audioengine.cpp
@@ -46,8 +46,8 @@ AudioEngine::instance()
 AudioEngine::AudioEngine()
     : QObject()
     , m_isPlayingHttp( false )
-    , m_playlist( 0 )
-    , m_currentTrackPlaylist( 0 )
+//    , m_playlist( 0 )
+//    , m_currentTrackPlaylist( 0 )
     , m_queue( 0 )
     , m_timeElapsed( 0 )
     , m_expectStop( false )
@@ -141,8 +141,8 @@ AudioEngine::stop()
 
     m_mediaObject->stop();
 
-    if ( m_playlist )
-        m_playlist->reset();
+    if ( !m_playlist.isNull() )
+        m_playlist.data()->reset();
 
     setCurrentTrack( Tomahawk::result_ptr() );
     emit stopped();
@@ -168,11 +168,11 @@ AudioEngine::previous()
 {
     qDebug() << Q_FUNC_INFO;
 
-    if ( !m_playlist )
+    if ( m_playlist.isNull() )
         return;
 
-    if ( m_playlist->skipRestrictions() == PlaylistInterface::NoSkip ||
-         m_playlist->skipRestrictions() == PlaylistInterface::NoSkipBackwards )
+    if ( m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkip ||
+         m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipBackwards )
         return;
 
     loadPreviousTrack();
@@ -184,15 +184,15 @@ AudioEngine::next()
 {
     qDebug() << Q_FUNC_INFO;
 
-    if ( !m_playlist )
+    if ( m_playlist.isNull() )
         return;
 
-    if ( m_playlist->skipRestrictions() == PlaylistInterface::NoSkip ||
-         m_playlist->skipRestrictions() == PlaylistInterface::NoSkipForwards )
+    if ( m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkip ||
+         m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipForwards )
         return;
 
-    if ( !m_currentTrack.isNull() && !m_playlist->hasNextItem() &&
-          m_currentTrack->id() == m_playlist->currentItem()->id() )
+    if ( !m_currentTrack.isNull() && !m_playlist.data()->hasNextItem() &&
+         m_currentTrack->id() == m_playlist.data()->currentItem()->id() )
     {
         //For instance, when doing a catch-up while listening along, but the person
         //you're following hasn't started a new track yet...don't do anything
@@ -206,10 +206,7 @@ AudioEngine::next()
 void
 AudioEngine::seek( int ms )
 {
-    if ( !m_playlist )
-        return;
-
-    if ( m_playlist->seekRestrictions() == PlaylistInterface::NoSeek )
+    if ( !m_playlist.isNull() && m_playlist.data()->seekRestrictions() == PlaylistInterface::NoSeek )
         return;
 
     if ( isPlaying() || isPaused() )
@@ -424,13 +421,13 @@ AudioEngine::loadPreviousTrack()
 {
     qDebug() << Q_FUNC_INFO;
 
-    if ( !m_playlist )
+    if ( m_playlist.isNull() )
     {
         stop();
         return;
     }
 
-    Tomahawk::result_ptr result = m_playlist->previousItem();
+    Tomahawk::result_ptr result = m_playlist.data()->previousItem();
     if ( !result.isNull() )
         loadTrack( result );
     else
@@ -450,16 +447,16 @@ AudioEngine::loadNextTrack()
         result = m_queue->nextItem();
     }
 
-    if ( m_playlist && result.isNull() )
+    if ( !m_playlist.isNull() && result.isNull() )
     {
-        result = m_playlist->nextItem();
+        result = m_playlist.data()->nextItem();
     }
 
     if ( !result.isNull() )
         loadTrack( result );
     else
     {
-        if ( m_playlist && m_playlist->retryMode() == Tomahawk::PlaylistInterface::Retry )
+        if ( !m_playlist.isNull() && m_playlist.data()->retryMode() == Tomahawk::PlaylistInterface::Retry )
             m_waitingOnNewTrack = true;
         stop();
     }
@@ -471,15 +468,15 @@ AudioEngine::playItem( Tomahawk::PlaylistInterface* playlist, const Tomahawk::re
 {
     qDebug() << Q_FUNC_INFO;
 
-    if ( m_playlist )
-        m_playlist->reset();
+    if ( !m_playlist.isNull() )
+        m_playlist.data()->reset();
 
     setPlaylist( playlist );
-    m_currentTrackPlaylist = playlist;
+    m_currentTrackPlaylist = playlist->getSharedPointer();
 
     if ( !result.isNull() )
         loadTrack( result );
-    else if ( m_playlist && m_playlist->retryMode() == PlaylistInterface::Retry )
+    else if ( !m_playlist.isNull() && m_playlist.data()->retryMode() == PlaylistInterface::Retry )
     {
         m_waitingOnNewTrack = true;
         stop();
@@ -557,13 +554,15 @@ AudioEngine::timerTriggered( qint64 time )
 void
 AudioEngine::setPlaylist( PlaylistInterface* playlist )
 {
-    if ( m_playlist )
-        m_playlist->reset();
+    if ( !m_playlist.isNull() )
+        m_playlist.data()->reset();
 
-    m_playlist = playlist;
+    if ( !playlist )
+        return;
+    m_playlist = playlist->getSharedPointer();
 
-    if ( m_playlist && m_playlist->object() && m_playlist->retryMode() == PlaylistInterface::Retry )
-        connect( m_playlist->object(), SIGNAL( nextTrackReady() ), SLOT( playlistNextTrackReady() ) );
+    if ( m_playlist.data()->object() && m_playlist.data()->retryMode() == PlaylistInterface::Retry )
+        connect( m_playlist.data()->object(), SIGNAL( nextTrackReady() ), SLOT( playlistNextTrackReady() ) );
 
     emit playlistChanged( playlist );
 }
diff --git a/src/libtomahawk/audio/audioengine.h b/src/libtomahawk/audio/audioengine.h
index 571215edb..e57685ff5 100644
--- a/src/libtomahawk/audio/audioengine.h
+++ b/src/libtomahawk/audio/audioengine.h
@@ -56,13 +56,13 @@ public:
     bool isPaused() const { return m_mediaObject->state() == Phonon::PausedState; }
 
     /* Returns the PlaylistInterface of the currently playing track. Note: This might be different to the current playlist! */
-    Tomahawk::PlaylistInterface* currentTrackPlaylist() const { return m_currentTrackPlaylist; }
+    Tomahawk::PlaylistInterface* currentTrackPlaylist() const { return m_currentTrackPlaylist.data(); }
 
     /* Returns the PlaylistInterface of the current playlist. Note: The currently playing track might still be from a different playlist! */
-    Tomahawk::PlaylistInterface* playlist() const { return m_playlist; }
+    Tomahawk::PlaylistInterface* playlist() const { return m_playlist.data(); }
 
     Tomahawk::result_ptr currentTrack() const { return m_currentTrack; }
-    
+
 public slots:
     void playPause();
     void play();
@@ -130,8 +130,8 @@ private:
 
     Tomahawk::result_ptr m_currentTrack;
     Tomahawk::result_ptr m_lastTrack;
-    Tomahawk::PlaylistInterface* m_playlist;
-    Tomahawk::PlaylistInterface* m_currentTrackPlaylist;
+    QWeakPointer< Tomahawk::PlaylistInterface > m_playlist;
+    QWeakPointer< Tomahawk::PlaylistInterface > m_currentTrackPlaylist;
     Tomahawk::PlaylistInterface* m_queue;
 
     Phonon::MediaObject* m_mediaObject;
diff --git a/src/libtomahawk/playlistinterface.h b/src/libtomahawk/playlistinterface.h
index 01f9f3126..c84c3b45f 100644
--- a/src/libtomahawk/playlistinterface.h
+++ b/src/libtomahawk/playlistinterface.h
@@ -19,6 +19,7 @@
 #ifndef PLAYLISTINTERFACE_H
 #define PLAYLISTINTERFACE_H
 
+#include <QDebug>
 #include <QModelIndex>
 #include <QWidget>
 
@@ -62,7 +63,7 @@ public:
 
     virtual PlaylistInterface::RetryMode retryMode() const { return NoRetry; }
     virtual quint32 retryInterval() const { return 30000; }
-    
+
     virtual QString filter() const { return m_filter; }
     virtual void setFilter( const QString& pattern ) { m_filter = pattern; }
 
@@ -70,6 +71,20 @@ public:
 
     QObject* object() const { return m_object; }
 
+    static void dontDelete( Tomahawk::PlaylistInterface* obj )
+    {
+        qDebug() << Q_FUNC_INFO << obj;
+    }
+    virtual Tomahawk::playlistinterface_ptr getSharedPointer()
+    {
+        if ( m_sharedPtr.isNull() )
+        {
+            m_sharedPtr = Tomahawk::playlistinterface_ptr( this, dontDelete );
+        }
+
+        return m_sharedPtr;
+    }
+
 public slots:
     virtual void setRepeatMode( RepeatMode mode ) = 0;
     virtual void setShuffled( bool enabled ) = 0;
@@ -83,6 +98,7 @@ signals:
 
 private:
     QObject* m_object;
+    Tomahawk::playlistinterface_ptr m_sharedPtr;
 
     QString m_filter;
 };
diff --git a/src/libtomahawk/source.cpp b/src/libtomahawk/source.cpp
index e0eaddc88..9f35df6ea 100644
--- a/src/libtomahawk/source.cpp
+++ b/src/libtomahawk/source.cpp
@@ -282,6 +282,7 @@ Source::getPlaylistInterface()
     return m_playlistInterface;
 }
 
+
 void
 Source::onPlaybackStarted( const Tomahawk::query_ptr& query )
 {