1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-11 08:34:34 +02:00

Make infoplugins dynamically loadable, and convert echonest plugin to

this format
This commit is contained in:
Jeff Mitchell
2012-05-13 17:37:25 -04:00
parent 485d076d73
commit 3e781a243e
12 changed files with 217 additions and 38 deletions

View File

@@ -160,6 +160,7 @@ IF(GLOOX_FOUND)
ENDIF(GLOOX_FOUND) ENDIF(GLOOX_FOUND)
ADD_SUBDIRECTORY( accounts ) ADD_SUBDIRECTORY( accounts )
ADD_SUBDIRECTORY( infoplugins )
IF(QCA2_FOUND) IF(QCA2_FOUND)
INCLUDE_DIRECTORIES( ${QCA2_INCLUDE_DIR} ) INCLUDE_DIRECTORIES( ${QCA2_INCLUDE_DIR} )

View File

@@ -0,0 +1 @@
ADD_SUBDIRECTORY( generic )

View File

@@ -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

View File

@@ -0,0 +1 @@
ADD_SUBDIRECTORY( echonest )

View File

@@ -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} )

View File

@@ -18,20 +18,23 @@
*/ */
#include "EchonestPlugin.h" #include "EchonestPlugin.h"
#include <echonest/Artist.h>
#include <echonest/ArtistTypes.h> #include <echonest/ArtistTypes.h>
#include "utils/TomahawkUtils.h" #include "utils/TomahawkUtils.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include <QNetworkConfiguration> #include <QNetworkConfiguration>
#include <QtPlugin>
using namespace Tomahawk::InfoSystem; namespace Tomahawk
using namespace Echonest; {
namespace InfoSystem
{
// for internal neatness // for internal neatness
EchoNestPlugin::EchoNestPlugin() EchonestPlugin::EchonestPlugin()
: InfoPlugin() : InfoPlugin()
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
@@ -40,14 +43,14 @@ EchoNestPlugin::EchoNestPlugin()
} }
EchoNestPlugin::~EchoNestPlugin() EchonestPlugin::~EchonestPlugin()
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
} }
void void
EchoNestPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) EchonestPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{ {
switch ( requestData.type ) switch ( requestData.type )
{ {
@@ -73,7 +76,7 @@ EchoNestPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
void 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 //WARNING: Totally not implemented yet
Q_UNUSED( item ); Q_UNUSED( item );
@@ -91,7 +94,7 @@ EchoNestPlugin::getSongProfile( const Tomahawk::InfoSystem::InfoRequestData &req
void void
EchoNestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData &requestData ) EchonestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData &requestData )
{ {
if( !isValidArtistData( requestData ) ) if( !isValidArtistData( requestData ) )
return; return;
@@ -105,7 +108,7 @@ EchoNestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData
void void
EchoNestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData &requestData ) EchonestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData &requestData )
{ {
if( !isValidArtistData( requestData ) ) if( !isValidArtistData( requestData ) )
return; return;
@@ -120,7 +123,7 @@ EchoNestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestDat
void void
EchoNestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData &requestData ) EchonestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData &requestData )
{ {
if( !isValidArtistData( requestData ) ) if( !isValidArtistData( requestData ) )
return; return;
@@ -134,7 +137,7 @@ EchoNestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData
void void
EchoNestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData ) EchonestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
{ {
if( !isValidArtistData( requestData ) ) if( !isValidArtistData( requestData ) )
return; return;
@@ -148,7 +151,7 @@ EchoNestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &req
void void
EchoNestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData ) EchonestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
{ {
QNetworkReply* reply = Echonest::Artist::topTerms( 20 ); QNetworkReply* reply = Echonest::Artist::topTerms( 20 );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
@@ -157,13 +160,13 @@ EchoNestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &re
void void
EchoNestPlugin::getArtistBiographySlot() EchonestPlugin::getArtistBiographySlot()
{ {
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() ); QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Echonest::Artist artist = artistFromReply( reply ); Echonest::Artist artist = artistFromReply( reply );
BiographyList biographies = artist.biographies(); Echonest::BiographyList biographies = artist.biographies();
QVariantMap biographyMap; QVariantMap biographyMap;
Q_FOREACH( const Biography& biography, biographies ) Q_FOREACH( const Echonest::Biography& biography, biographies )
{ {
QVariantHash siteData; QVariantHash siteData;
siteData[ "site" ] = biography.site(); siteData[ "site" ] = biography.site();
@@ -181,7 +184,7 @@ EchoNestPlugin::getArtistBiographySlot()
void void
EchoNestPlugin::getArtistFamiliaritySlot() EchonestPlugin::getArtistFamiliaritySlot()
{ {
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() ); QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Echonest::Artist artist = artistFromReply( reply ); Echonest::Artist artist = artistFromReply( reply );
@@ -193,7 +196,7 @@ EchoNestPlugin::getArtistFamiliaritySlot()
void void
EchoNestPlugin::getArtistHotttnesssSlot() EchonestPlugin::getArtistHotttnesssSlot()
{ {
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() ); QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Echonest::Artist artist = artistFromReply( reply ); Echonest::Artist artist = artistFromReply( reply );
@@ -205,11 +208,11 @@ EchoNestPlugin::getArtistHotttnesssSlot()
void void
EchoNestPlugin::getArtistTermsSlot() EchonestPlugin::getArtistTermsSlot()
{ {
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() ); QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Echonest::Artist artist = artistFromReply( reply ); Echonest::Artist artist = artistFromReply( reply );
TermList terms = artist.terms(); Echonest::TermList terms = artist.terms();
QVariantMap termsMap; QVariantMap termsMap;
Q_FOREACH( const Echonest::Term& term, terms ) { Q_FOREACH( const Echonest::Term& term, terms ) {
QVariantHash termHash; QVariantHash termHash;
@@ -224,10 +227,10 @@ EchoNestPlugin::getArtistTermsSlot()
void void
EchoNestPlugin::getMiscTopSlot() EchonestPlugin::getMiscTopSlot()
{ {
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() ); QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
TermList terms = Echonest::Artist::parseTopTerms( reply ); Echonest::TermList terms = Echonest::Artist::parseTopTerms( reply );
QVariantMap termsMap; QVariantMap termsMap;
Q_FOREACH( const Echonest::Term& term, terms ) { Q_FOREACH( const Echonest::Term& term, terms ) {
QVariantHash termHash; QVariantHash termHash;
@@ -242,7 +245,7 @@ EchoNestPlugin::getMiscTopSlot()
bool 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 >() ) if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
{ {
@@ -260,7 +263,7 @@ EchoNestPlugin::isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &
bool 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 >() ) if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
{ {
@@ -282,8 +285,8 @@ EchoNestPlugin::isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &r
} }
Artist Echonest::Artist
EchoNestPlugin::artistFromReply( QNetworkReply* reply ) EchonestPlugin::artistFromReply( QNetworkReply* reply )
{ {
Echonest::Artist artist = reply->property("artist").value<Echonest::Artist>(); Echonest::Artist artist = reply->property("artist").value<Echonest::Artist>();
try { try {
@@ -293,4 +296,9 @@ EchoNestPlugin::artistFromReply( QNetworkReply* reply )
} }
return artist; return artist;
} }
//
} //ns InfoSystem
} //ns Tomahawk
Q_EXPORT_PLUGIN2( Tomahawk::InfoSystem::InfoPlugin, Tomahawk::InfoSystem::EchonestPlugin )

View File

@@ -20,31 +20,29 @@
#ifndef ECHONESTPLUGIN_H #ifndef ECHONESTPLUGIN_H
#define ECHONESTPLUGIN_H #define ECHONESTPLUGIN_H
#include "infoplugins/InfoPluginDllMacro.h"
#include "infosystem/InfoSystem.h" #include "infosystem/InfoSystem.h"
#include "infosystem/InfoSystemWorker.h" #include "infosystem/InfoSystemWorker.h"
#include "echonest/Artist.h"
#include <QObject> #include <QObject>
class QNetworkReply; class QNetworkReply;
namespace Echonest
{
class Artist;
}
namespace Tomahawk namespace Tomahawk
{ {
namespace InfoSystem namespace InfoSystem
{ {
class EchoNestPlugin : public InfoPlugin class INFOPLUGINDLLEXPORT EchonestPlugin : public InfoPlugin
{ {
Q_OBJECT Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public: public:
EchoNestPlugin(); EchonestPlugin();
virtual ~EchoNestPlugin(); virtual ~EchonestPlugin();
protected slots: protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ); virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );

View File

@@ -254,7 +254,6 @@ set( libSources
infosystem/InfoSystemCache.cpp infosystem/InfoSystemCache.cpp
infosystem/InfoSystemWorker.cpp infosystem/InfoSystemWorker.cpp
infosystem/infoplugins/generic/EchonestPlugin.cpp
infosystem/infoplugins/generic/ChartsPlugin.cpp infosystem/infoplugins/generic/ChartsPlugin.cpp
infosystem/infoplugins/generic/NewReleasesPlugin.cpp infosystem/infoplugins/generic/NewReleasesPlugin.cpp
infosystem/infoplugins/generic/spotifyPlugin.cpp infosystem/infoplugins/generic/spotifyPlugin.cpp

View File

@@ -336,7 +336,6 @@ inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash )
return returnval; return returnval;
} }
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPushData ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPushData );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoStringHash ); 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::InfoPluginPtr );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPlugin* ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPlugin* );
Q_DECLARE_INTERFACE( Tomahawk::InfoSystem::InfoPlugin, "tomahawk.InfoPluginy/1.0" )
#endif // TOMAHAWK_INFOSYSTEM_H #endif // TOMAHAWK_INFOSYSTEM_H

View File

@@ -21,11 +21,13 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QNetworkConfiguration> #include <QNetworkConfiguration>
#include <QNetworkProxy> #include <QNetworkProxy>
#include <QDir>
#include "config.h" #include "config.h"
#include "HeadlessCheck.h"
#include "InfoSystemWorker.h" #include "InfoSystemWorker.h"
#include "InfoSystemCache.h" #include "InfoSystemCache.h"
#include "infoplugins/generic/EchonestPlugin.h" #include "infoplugins/generic/echonest/EchonestPlugin.h"
#include "infoplugins/generic/MusixMatchPlugin.h" #include "infoplugins/generic/MusixMatchPlugin.h"
#include "infoplugins/generic/ChartsPlugin.h" #include "infoplugins/generic/ChartsPlugin.h"
#include "infoplugins/generic/NewReleasesPlugin.h" #include "infoplugins/generic/NewReleasesPlugin.h"
@@ -82,8 +84,11 @@ InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache )
tDebug() << Q_FUNC_INFO; tDebug() << Q_FUNC_INFO;
m_shortLinksWaiting = 0; m_shortLinksWaiting = 0;
m_cache = cache; m_cache = cache;
loadInfoPlugins( findInfoPlugins() );
#ifndef ENABLE_HEADLESS #ifndef ENABLE_HEADLESS
addInfoPlugin( InfoPluginPtr( new EchoNestPlugin() ) ); //addInfoPlugin( InfoPluginPtr( new EchoNestPlugin() ) );
addInfoPlugin( InfoPluginPtr( new MusixMatchPlugin() ) ); addInfoPlugin( InfoPluginPtr( new MusixMatchPlugin() ) );
addInfoPlugin( InfoPluginPtr( new MusicBrainzPlugin() ) ); addInfoPlugin( InfoPluginPtr( new MusicBrainzPlugin() ) );
addInfoPlugin( InfoPluginPtr( new ChartsPlugin() ) ); 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 void
InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType >& getTypes, const QSet< InfoType >& pushTypes ) InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType >& getTypes, const QSet< InfoType >& pushTypes )
{ {

View File

@@ -64,6 +64,8 @@ public slots:
void addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ); void addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin );
void removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ); void removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin );
QStringList findInfoPlugins();
void loadInfoPlugins( const QStringList &pluginPaths );
void getShortUrl( Tomahawk::InfoSystem::InfoPushData data ); void getShortUrl( Tomahawk::InfoSystem::InfoPushData data );
void shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callbackObj ); void shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callbackObj );

View File

@@ -452,6 +452,14 @@ Servent::socketConnected()
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << thread() << "socket: " << sock << ", hostaddr: " << sock->peerAddress() << ", hostname: " << sock->peerName(); 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(); Connection* conn = sock->_conn.data();
handoverSocket( conn, sock ); handoverSocket( conn, sock );
} }