1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-21 16:29:43 +01: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)
ADD_SUBDIRECTORY( accounts )
ADD_SUBDIRECTORY( infoplugins )
IF(QCA2_FOUND)
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 <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 )

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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