From 3e781a243e3972597fc5056d3ec5af8714fbc419 Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeff@tomahawk-player.org>
Date: Sun, 13 May 2012 17:37:25 -0400
Subject: [PATCH] Make infoplugins dynamically loadable, and convert echonest
 plugin to this format

---
 src/CMakeLists.txt                            |  1 +
 src/infoplugins/CMakeLists.txt                |  1 +
 src/infoplugins/InfoPluginDllMacro.h          | 33 +++++++
 src/infoplugins/generic/CMakeLists.txt        |  1 +
 .../generic/echonest/CMakeLists.txt           | 45 ++++++++++
 .../generic/echonest}/EchonestPlugin.cpp      | 60 +++++++------
 .../generic/echonest}/EchonestPlugin.h        | 14 ++-
 src/libtomahawk/CMakeLists.txt                |  1 -
 src/libtomahawk/infosystem/InfoSystem.h       |  3 +-
 .../infosystem/InfoSystemWorker.cpp           | 86 ++++++++++++++++++-
 src/libtomahawk/infosystem/InfoSystemWorker.h |  2 +
 src/libtomahawk/network/Servent.cpp           |  8 ++
 12 files changed, 217 insertions(+), 38 deletions(-)
 create mode 100644 src/infoplugins/CMakeLists.txt
 create mode 100644 src/infoplugins/InfoPluginDllMacro.h
 create mode 100644 src/infoplugins/generic/CMakeLists.txt
 create mode 100644 src/infoplugins/generic/echonest/CMakeLists.txt
 rename src/{libtomahawk/infosystem/infoplugins/generic => infoplugins/generic/echonest}/EchonestPlugin.cpp (87%)
 rename src/{libtomahawk/infosystem/infoplugins/generic => infoplugins/generic/echonest}/EchonestPlugin.h (91%)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6349911ad..78aefef0d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -160,6 +160,7 @@ IF(GLOOX_FOUND)
 ENDIF(GLOOX_FOUND)
 
 ADD_SUBDIRECTORY( accounts )
+ADD_SUBDIRECTORY( infoplugins )
 
 IF(QCA2_FOUND)
     INCLUDE_DIRECTORIES( ${QCA2_INCLUDE_DIR} )
diff --git a/src/infoplugins/CMakeLists.txt b/src/infoplugins/CMakeLists.txt
new file mode 100644
index 000000000..ea6f39bf1
--- /dev/null
+++ b/src/infoplugins/CMakeLists.txt
@@ -0,0 +1 @@
+ADD_SUBDIRECTORY( generic )
diff --git a/src/infoplugins/InfoPluginDllMacro.h b/src/infoplugins/InfoPluginDllMacro.h
new file mode 100644
index 000000000..0ae9b7db6
--- /dev/null
+++ b/src/infoplugins/InfoPluginDllMacro.h
@@ -0,0 +1,33 @@
+/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
+ *
+ *   Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
+ *   Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
+ *
+ *   Tomahawk is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Tomahawk is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INFOPLUGINDLLMACRO_H
+#define INFOPLUGINDLLMACRO_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef INFOPLUGINDLLEXPORT
+# if defined (INFOPLUGINDLLEXPORT_PRO)
+#  define INFOPLUGINDLLEXPORT Q_DECL_EXPORT
+# else
+#  define INFOPLUGINDLLEXPORT Q_DECL_IMPORT
+# endif
+#endif
+
+#endif
diff --git a/src/infoplugins/generic/CMakeLists.txt b/src/infoplugins/generic/CMakeLists.txt
new file mode 100644
index 000000000..0a9ed2c32
--- /dev/null
+++ b/src/infoplugins/generic/CMakeLists.txt
@@ -0,0 +1 @@
+ADD_SUBDIRECTORY( echonest )
diff --git a/src/infoplugins/generic/echonest/CMakeLists.txt b/src/infoplugins/generic/echonest/CMakeLists.txt
new file mode 100644
index 000000000..b956444f2
--- /dev/null
+++ b/src/infoplugins/generic/echonest/CMakeLists.txt
@@ -0,0 +1,45 @@
+project( tomahawk )
+
+include( ${QT_USE_FILE} )
+add_definitions( ${QT_DEFINITIONS} )
+add_definitions( -DQT_PLUGIN )
+add_definitions( -DQT_SHARED )
+add_definitions( -DINFOPLUGINDLLEXPORT_PRO )
+
+set( echonestInfoPluginSources
+    EchonestPlugin.cpp
+)
+
+set( echonestInfoPluginHeaders
+    EchonestPlugin.h
+)
+
+include_directories(
+   ${QT_INCLUDE_DIR}
+   ${LIBECHONEST_INCLUDE_DIR}
+)
+
+qt4_wrap_cpp( echonestInfoPluginMoc ${echonestInfoPluginHeaders} )
+add_library( tomahawk_infoplugin_echonest SHARED ${echonestInfoPluginSources} ${echonestInfoPluginMoc} ${RC_SRCS} )
+
+IF( WIN32 )
+SET( OS_SPECIFIC_LINK_LIBRARIES
+        ${OS_SPECIFIC_LINK_LIBRARIES}
+        "winmm.dll"
+        "iphlpapi.a"
+)
+ENDIF( WIN32 )
+
+target_link_libraries( tomahawk_infoplugin_echonest
+    ${TOMAHAWK_LIBRARIES}
+    ${LIBECHONEST_LIBRARY}
+    ${QT_LIBRARIES}
+    ${OS_SPECIFIC_LINK_LIBRARIES}
+)
+
+IF( APPLE )
+#  SET( CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-undefined dynamic_lookup" )
+ENDIF( APPLE )
+
+install( TARGETS tomahawk_infoplugin_echonest DESTINATION ${CMAKE_INSTALL_LIBDIR} )
+
diff --git a/src/libtomahawk/infosystem/infoplugins/generic/EchonestPlugin.cpp b/src/infoplugins/generic/echonest/EchonestPlugin.cpp
similarity index 87%
rename from src/libtomahawk/infosystem/infoplugins/generic/EchonestPlugin.cpp
rename to src/infoplugins/generic/echonest/EchonestPlugin.cpp
index 128bea70e..f1d28b89a 100644
--- a/src/libtomahawk/infosystem/infoplugins/generic/EchonestPlugin.cpp
+++ b/src/infoplugins/generic/echonest/EchonestPlugin.cpp
@@ -18,20 +18,23 @@
  */
 
 #include "EchonestPlugin.h"
-#include <echonest/Artist.h>
 #include <echonest/ArtistTypes.h>
 
 #include "utils/TomahawkUtils.h"
 #include "utils/Logger.h"
 
 #include <QNetworkConfiguration>
+#include <QtPlugin>
 
-using namespace Tomahawk::InfoSystem;
-using namespace Echonest;
+namespace Tomahawk
+{
+
+namespace InfoSystem
+{
 
 // for internal neatness
 
-EchoNestPlugin::EchoNestPlugin()
+EchonestPlugin::EchonestPlugin()
     : InfoPlugin()
 {
     qDebug() << Q_FUNC_INFO;
@@ -40,14 +43,14 @@ EchoNestPlugin::EchoNestPlugin()
 }
 
 
-EchoNestPlugin::~EchoNestPlugin()
+EchonestPlugin::~EchonestPlugin()
 {
     qDebug() << Q_FUNC_INFO;
 }
 
 
 void
-EchoNestPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
+EchonestPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
 {
     switch ( requestData.type )
     {
@@ -73,7 +76,7 @@ EchoNestPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
 
 
 void
-EchoNestPlugin::getSongProfile( const Tomahawk::InfoSystem::InfoRequestData &requestData, const QString &item )
+EchonestPlugin::getSongProfile( const Tomahawk::InfoSystem::InfoRequestData &requestData, const QString &item )
 {
     //WARNING: Totally not implemented yet
     Q_UNUSED( item );
@@ -91,7 +94,7 @@ EchoNestPlugin::getSongProfile( const Tomahawk::InfoSystem::InfoRequestData &req
 
 
 void
-EchoNestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData &requestData )
+EchonestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData &requestData )
 {
     if( !isValidArtistData( requestData ) )
         return;
@@ -105,7 +108,7 @@ EchoNestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData
 
 
 void
-EchoNestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData &requestData )
+EchonestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData &requestData )
 {
     if( !isValidArtistData( requestData ) )
         return;
@@ -120,7 +123,7 @@ EchoNestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestDat
 
 
 void
-EchoNestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData &requestData )
+EchonestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData &requestData )
 {
     if( !isValidArtistData( requestData ) )
         return;
@@ -134,7 +137,7 @@ EchoNestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData
 
 
 void
-EchoNestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
+EchonestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
 {
     if( !isValidArtistData( requestData ) )
         return;
@@ -148,7 +151,7 @@ EchoNestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &req
 
 
 void
-EchoNestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
+EchonestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
 {
     QNetworkReply* reply = Echonest::Artist::topTerms( 20 );
     reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
@@ -157,13 +160,13 @@ EchoNestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &re
 
 
 void
-EchoNestPlugin::getArtistBiographySlot()
+EchonestPlugin::getArtistBiographySlot()
 {
     QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
     Echonest::Artist artist = artistFromReply( reply );
-    BiographyList biographies = artist.biographies();
+    Echonest::BiographyList biographies = artist.biographies();
     QVariantMap biographyMap;
-    Q_FOREACH( const Biography& biography, biographies )
+    Q_FOREACH( const Echonest::Biography& biography, biographies )
     {
         QVariantHash siteData;
         siteData[ "site" ] = biography.site();
@@ -181,7 +184,7 @@ EchoNestPlugin::getArtistBiographySlot()
 
 
 void
-EchoNestPlugin::getArtistFamiliaritySlot()
+EchonestPlugin::getArtistFamiliaritySlot()
 {
     QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
     Echonest::Artist artist = artistFromReply( reply );
@@ -193,7 +196,7 @@ EchoNestPlugin::getArtistFamiliaritySlot()
 
 
 void
-EchoNestPlugin::getArtistHotttnesssSlot()
+EchonestPlugin::getArtistHotttnesssSlot()
 {
     QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
     Echonest::Artist artist = artistFromReply( reply );
@@ -205,11 +208,11 @@ EchoNestPlugin::getArtistHotttnesssSlot()
 
 
 void
-EchoNestPlugin::getArtistTermsSlot()
+EchonestPlugin::getArtistTermsSlot()
 {
     QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
     Echonest::Artist artist = artistFromReply( reply );
-    TermList terms = artist.terms();
+    Echonest::TermList terms = artist.terms();
     QVariantMap termsMap;
     Q_FOREACH( const Echonest::Term& term, terms ) {
         QVariantHash termHash;
@@ -224,10 +227,10 @@ EchoNestPlugin::getArtistTermsSlot()
 
 
 void
-EchoNestPlugin::getMiscTopSlot()
+EchonestPlugin::getMiscTopSlot()
 {
     QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
-    TermList terms = Echonest::Artist::parseTopTerms( reply );
+    Echonest::TermList terms = Echonest::Artist::parseTopTerms( reply );
     QVariantMap termsMap;
     Q_FOREACH( const Echonest::Term& term, terms ) {
         QVariantHash termHash;
@@ -242,7 +245,7 @@ EchoNestPlugin::getMiscTopSlot()
 
 
 bool
-EchoNestPlugin::isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &requestData )
+EchonestPlugin::isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &requestData )
 {
     if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
     {
@@ -260,7 +263,7 @@ EchoNestPlugin::isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &
 
 
 bool
-EchoNestPlugin::isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &requestData )
+EchonestPlugin::isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &requestData )
 {
     if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
     {
@@ -282,8 +285,8 @@ EchoNestPlugin::isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &r
 }
 
 
-Artist
-EchoNestPlugin::artistFromReply( QNetworkReply* reply )
+Echonest::Artist
+EchonestPlugin::artistFromReply( QNetworkReply* reply )
 {
     Echonest::Artist artist = reply->property("artist").value<Echonest::Artist>();
     try {
@@ -293,4 +296,9 @@ EchoNestPlugin::artistFromReply( QNetworkReply* reply )
     }
     return artist;
 }
-//
+
+} //ns InfoSystem
+
+} //ns Tomahawk
+
+Q_EXPORT_PLUGIN2( Tomahawk::InfoSystem::InfoPlugin, Tomahawk::InfoSystem::EchonestPlugin )
\ No newline at end of file
diff --git a/src/libtomahawk/infosystem/infoplugins/generic/EchonestPlugin.h b/src/infoplugins/generic/echonest/EchonestPlugin.h
similarity index 91%
rename from src/libtomahawk/infosystem/infoplugins/generic/EchonestPlugin.h
rename to src/infoplugins/generic/echonest/EchonestPlugin.h
index 4497af432..4468c375c 100644
--- a/src/libtomahawk/infosystem/infoplugins/generic/EchonestPlugin.h
+++ b/src/infoplugins/generic/echonest/EchonestPlugin.h
@@ -20,31 +20,29 @@
 #ifndef ECHONESTPLUGIN_H
 #define ECHONESTPLUGIN_H
 
+#include "infoplugins/InfoPluginDllMacro.h"
 #include "infosystem/InfoSystem.h"
 #include "infosystem/InfoSystemWorker.h"
+#include "echonest/Artist.h"
 
 #include <QObject>
 
 class QNetworkReply;
 
-namespace Echonest
-{
-    class Artist;
-}
-
 namespace Tomahawk
 {
 
 namespace InfoSystem
 {
 
-class EchoNestPlugin : public InfoPlugin
+class INFOPLUGINDLLEXPORT EchonestPlugin : public InfoPlugin
 {
     Q_OBJECT
+    Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
 
 public:
-    EchoNestPlugin();
-    virtual ~EchoNestPlugin();
+    EchonestPlugin();
+    virtual ~EchonestPlugin();
 
 protected slots:
     virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index afeed00ef..75290e04b 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -254,7 +254,6 @@ set( libSources
     infosystem/InfoSystemCache.cpp
     infosystem/InfoSystemWorker.cpp
 
-    infosystem/infoplugins/generic/EchonestPlugin.cpp
     infosystem/infoplugins/generic/ChartsPlugin.cpp
     infosystem/infoplugins/generic/NewReleasesPlugin.cpp
     infosystem/infoplugins/generic/spotifyPlugin.cpp
diff --git a/src/libtomahawk/infosystem/InfoSystem.h b/src/libtomahawk/infosystem/InfoSystem.h
index 1689e2bbb..2ec1429f4 100644
--- a/src/libtomahawk/infosystem/InfoSystem.h
+++ b/src/libtomahawk/infosystem/InfoSystem.h
@@ -336,7 +336,6 @@ inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash )
     return returnval;
 }
 
-
 Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData );
 Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPushData );
 Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoStringHash );
@@ -348,4 +347,6 @@ Q_DECLARE_METATYPE( QList< Tomahawk::InfoSystem::InfoStringHash > );
 Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPluginPtr );
 Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPlugin* );
 
+Q_DECLARE_INTERFACE( Tomahawk::InfoSystem::InfoPlugin, "tomahawk.InfoPluginy/1.0" )
+
 #endif // TOMAHAWK_INFOSYSTEM_H
diff --git a/src/libtomahawk/infosystem/InfoSystemWorker.cpp b/src/libtomahawk/infosystem/InfoSystemWorker.cpp
index 803c607df..391f33a0a 100644
--- a/src/libtomahawk/infosystem/InfoSystemWorker.cpp
+++ b/src/libtomahawk/infosystem/InfoSystemWorker.cpp
@@ -21,11 +21,13 @@
 #include <QCoreApplication>
 #include <QNetworkConfiguration>
 #include <QNetworkProxy>
+#include <QDir>
 
 #include "config.h"
+#include "HeadlessCheck.h"
 #include "InfoSystemWorker.h"
 #include "InfoSystemCache.h"
-#include "infoplugins/generic/EchonestPlugin.h"
+#include "infoplugins/generic/echonest/EchonestPlugin.h"
 #include "infoplugins/generic/MusixMatchPlugin.h"
 #include "infoplugins/generic/ChartsPlugin.h"
 #include "infoplugins/generic/NewReleasesPlugin.h"
@@ -82,8 +84,11 @@ InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache )
     tDebug() << Q_FUNC_INFO;
     m_shortLinksWaiting = 0;
     m_cache = cache;
+
+    loadInfoPlugins( findInfoPlugins() );
+    
 #ifndef ENABLE_HEADLESS
-    addInfoPlugin( InfoPluginPtr( new EchoNestPlugin() ) );
+    //addInfoPlugin( InfoPluginPtr( new EchoNestPlugin() ) );
     addInfoPlugin( InfoPluginPtr( new MusixMatchPlugin() ) );
     addInfoPlugin( InfoPluginPtr( new MusicBrainzPlugin() ) );
     addInfoPlugin( InfoPluginPtr( new ChartsPlugin() ) );
@@ -178,6 +183,83 @@ InfoSystemWorker::removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
 }
 
 
+QStringList
+InfoSystemWorker::findInfoPlugins()
+{
+    QStringList paths;
+    QList< QDir > pluginDirs;
+
+    QDir appDir( qApp->applicationDirPath() );
+#ifdef Q_WS_MAC
+    if ( appDir.dirName() == "MacOS" )
+    {
+        // Development convenience-hack
+        appDir.cdUp();
+        appDir.cdUp();
+        appDir.cdUp();
+    }
+#endif
+
+    QDir libDir( CMAKE_INSTALL_PREFIX "/lib" );
+
+    QDir lib64Dir( appDir );
+    lib64Dir.cdUp();
+    lib64Dir.cd( "lib64" );
+
+    pluginDirs << appDir << libDir << lib64Dir << QDir( qApp->applicationDirPath() );
+    foreach ( const QDir& pluginDir, pluginDirs )
+    {
+        tDebug() << Q_FUNC_INFO << "Checking directory for plugins:" << pluginDir;
+        foreach ( QString fileName, pluginDir.entryList( QStringList() << "*tomahawk_infoplugin_*.so" << "*tomahawk_infoplugin_*.dylib" << "*tomahawk_infoplugin_*.dll", QDir::Files ) )
+        {
+            if ( fileName.startsWith( "libtomahawk_infoplugin" ) )
+            {
+                const QString path = pluginDir.absoluteFilePath( fileName );
+                if ( !paths.contains( path ) )
+                    paths << path;
+            }
+        }
+    }
+
+    return paths;
+}
+
+
+void
+InfoSystemWorker::loadInfoPlugins( const QStringList& pluginPaths )
+{
+    tDebug() << Q_FUNC_INFO << "Attempting to load the following plugin paths: " << pluginPaths;
+
+    if ( pluginPaths.isEmpty() )
+        return;
+    
+    foreach ( const QString fileName, pluginPaths )
+    {
+        if ( !QLibrary::isLibrary( fileName ) )
+            continue;
+ 
+        tDebug() << Q_FUNC_INFO << "Trying to load plugin:" << fileName;
+
+        QPluginLoader loader( fileName );
+        QObject* plugin = loader.instance();
+        if ( !plugin )
+        {
+            tDebug() << Q_FUNC_INFO << "Error loading plugin:" << loader.errorString();
+            continue;
+        }
+
+        InfoPlugin* infoPlugin = qobject_cast< InfoPlugin* >( plugin );
+        if ( infoPlugin )
+        {
+            tDebug() << Q_FUNC_INFO << "Loaded info plugin:" << loader.fileName();
+            addInfoPlugin( InfoPluginPtr( infoPlugin ) );
+        }
+        else
+            tDebug() << Q_FUNC_INFO << "Loaded invalid plugin: " << loader.fileName();
+    }
+}
+
+
 void
 InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType >& getTypes, const QSet< InfoType >& pushTypes )
 {
diff --git a/src/libtomahawk/infosystem/InfoSystemWorker.h b/src/libtomahawk/infosystem/InfoSystemWorker.h
index f580ffd78..930f0d2e4 100644
--- a/src/libtomahawk/infosystem/InfoSystemWorker.h
+++ b/src/libtomahawk/infosystem/InfoSystemWorker.h
@@ -64,6 +64,8 @@ public slots:
 
     void addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin );
     void removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin );
+    QStringList findInfoPlugins();
+    void loadInfoPlugins( const QStringList &pluginPaths );
     
     void getShortUrl( Tomahawk::InfoSystem::InfoPushData data );
     void shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callbackObj );
diff --git a/src/libtomahawk/network/Servent.cpp b/src/libtomahawk/network/Servent.cpp
index 8643263de..ec409f041 100644
--- a/src/libtomahawk/network/Servent.cpp
+++ b/src/libtomahawk/network/Servent.cpp
@@ -452,6 +452,14 @@ Servent::socketConnected()
 
     tDebug( LOGVERBOSE ) << Q_FUNC_INFO << thread() << "socket: " << sock << ", hostaddr: " << sock->peerAddress() << ", hostname: " << sock->peerName();
 
+    if ( sock->_conn.isNull() )
+    {
+        sock->close();
+        sock->deleteLater();
+        tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Socket's connection was null, could have timed out or been given an invalid address";
+        return;
+    }
+    
     Connection* conn = sock->_conn.data();
     handoverSocket( conn, sock );
 }