Merge branch 'master' into accounts
@ -127,8 +127,16 @@ ENDIF()
|
||||
#macro_log_feature(LIBLASTFM_FOUND "LastFm" "Qt library for the Last.fm webservices" "https://github.com/mxcl/liblastfm" FALSE "" "liblastfm is needed for scrobbling tracks to Last.fm and fetching cover artwork")
|
||||
set(LIBLASTFM_FOUND true)
|
||||
|
||||
#### submodules start
|
||||
|
||||
# this installs headers and such and should really be handled in a separate package by packagers
|
||||
IF( INTERNAL_JREEN OR INTERNAL_QTWEETLIB )
|
||||
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.gitmodules)
|
||||
EXECUTE_PROCESS(COMMAND git submodule init WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
EXECUTE_PROCESS(COMMAND git submodule update WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.gitmodules)
|
||||
ENDIF()
|
||||
|
||||
IF( INTERNAL_JREEN )
|
||||
ADD_SUBDIRECTORY( ${THIRDPARTY_DIR}/jreen )
|
||||
SET( LIBJREEN_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/jreen/include )
|
||||
@ -141,7 +149,6 @@ ELSE( INTERNAL_JREEN )
|
||||
ENDIF( INTERNAL_JREEN )
|
||||
macro_log_feature(LIBJREEN_FOUND "Jreen" "Qt XMPP Library" "https://github.com/euroelessar/jreen" FALSE "" "Jreen is needed for the Jabber SIP plugin. \n\n Use -DINTERNAL_JREEN=ON to build the git submodule inside Tomahawk \n Be aware this installs a full jreen with headers and everything!\n")
|
||||
|
||||
# this installs headers and such and should really be handled in a separate package by packagers
|
||||
IF( INTERNAL_QTWEETLIB )
|
||||
ADD_SUBDIRECTORY( ${THIRDPARTY_DIR}/qtweetlib )
|
||||
# copy headers to build/QTweetLib so we can use proper includes inside the code
|
||||
@ -155,6 +162,7 @@ ELSE( INTERNAL_QTWEETLIB )
|
||||
macro_optional_find_package(QTweetLib)
|
||||
ENDIF( INTERNAL_QTWEETLIB )
|
||||
macro_log_feature(QTWEETLIB_FOUND "QTweetLib" "Qt Twitter Library" "https://github.com/minimoog/QTweetLib" FALSE "" "QTweetLib is needed for the Twitter SIP plugin. \n\n Use -DINTERNAL_QTWEETLIB=ON to build the git submodule inside Tomahawk \n")
|
||||
#### submodules end
|
||||
|
||||
### libportfwd
|
||||
SET( LIBPORTFWD_INCLUDE_DIR ${THIRDPARTY_DIR}/libportfwd/include )
|
||||
|
@ -12,7 +12,15 @@
|
||||
INCLUDE(CheckSymbolExists)
|
||||
INCLUDE(FindLibraryWithDebug)
|
||||
|
||||
# try to locate a patched unstable version (for comp's sake *sigh*) first
|
||||
FIND_PACKAGE(CLuceneUnstable)
|
||||
IF(CLUCENEUNSTABLE_FOUND)
|
||||
SET(CLucene_FOUND TRUE)
|
||||
SET(CLUCENE_INCLUDE_DIR ${CLUCENE_UNSTABLE_INCLUDE_DIRS})
|
||||
SET(CLUCENE_LIBRARIES ${CLUCENE_UNSTABLE_LIBS})
|
||||
|
||||
#MESSAGE(FATAL_ERROR NARF)
|
||||
ELSE(CLUCENEUNSTABLE_FOUND)
|
||||
IF(CLucene_FIND_VERSION)
|
||||
SET(CLUCENE_MIN_VERSION ${CLucene_FIND_VERSION})
|
||||
ELSEIF()
|
||||
@ -99,6 +107,7 @@ ENDIF (CLUCENE_LIBRARY_DIR)
|
||||
IF(CLUCENE_INCLUDE_DIR AND CLUCENE_LIBRARIES AND CLUCENE_LIBRARY_DIR AND CLUCENE_GOOD_VERSION)
|
||||
SET(CLucene_FOUND TRUE)
|
||||
ENDIF(CLUCENE_INCLUDE_DIR AND CLUCENE_LIBRARIES AND CLUCENE_LIBRARY_DIR AND CLUCENE_GOOD_VERSION)
|
||||
ENDIF(CLUCENEUNSTABLE_FOUND)
|
||||
|
||||
IF(CLucene_FOUND)
|
||||
IF(NOT CLucene_FIND_QUIETLY)
|
||||
|
37
CMakeModules/FindCLuceneUnstable.cmake
Normal file
@ -0,0 +1,37 @@
|
||||
# - Try to find clucene-unstable
|
||||
# This is a workaround for distros, that want to ship a recent enough clucene but don't want to replace the old version
|
||||
#
|
||||
# CLUCENEUNSTABLE_FOUND - system has clucene-unstable
|
||||
# CLUCENE_UNSTABLE_INCLUDE_DIR - the clucene-unstable include directories
|
||||
# CLUCENE_UNSTABLE_LIBS - link these to use clucene-unstable
|
||||
#
|
||||
# (c) Dominik Schmidt <dev@dominik-schmidt.de>
|
||||
#
|
||||
|
||||
# Include dir
|
||||
find_path(CLUCENE_UNSTABLE_INCLUDE_DIR
|
||||
NAMES CLucene.h
|
||||
PATH_SUFFIXES clucene-unstable
|
||||
PATHS ${KDE4_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
# Finally the library itself
|
||||
find_library(CLUCENE_UNSTABLE_SHARED_LIB
|
||||
NAMES clucene-unstable-shared
|
||||
PATHS ${KDE4_LIB_DIR}
|
||||
)
|
||||
|
||||
find_library(CLUCENE_UNSTABLE_CORE_LIB
|
||||
NAMES clucene-unstable-core
|
||||
PATHS ${KDE4_LIB_DIR}
|
||||
)
|
||||
|
||||
|
||||
SET( CLUCENE_UNSTABLE_LIBS ${CLUCENE_UNSTABLE_SHARED_LIB} ${CLUCENE_UNSTABLE_CORE_LIB} )
|
||||
SET( CLUCENE_UNSTABLE_INCLUDE_DIRS ${CLUCENE_UNSTABLE_INCLUDE_DIR})
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CLuceneUnstable DEFAULT_MSG CLUCENE_UNSTABLE_LIBS CLUCENE_UNSTABLE_INCLUDE_DIRS)
|
||||
|
||||
|
||||
MARK_AS_ADVANCED(CLUCENE_UNSTABLE_LIBS CLUCENE_UNSTABLE_INCLUDE_DIRS)
|
||||
|
60
ChangeLog
@ -1,12 +1,72 @@
|
||||
Version 0.3.0:
|
||||
* Fixed bug where we would download http:// tracks twice.
|
||||
* Make artist names in the album view clickable.
|
||||
* Don't start playing if a tomahawk:// link was clicked while Tomahawk
|
||||
is paused.
|
||||
* Make artist name clickable in header of Album pages.
|
||||
* Fixed adding social actions such as loved tracks from other sources.
|
||||
* Added a drop shadow to cover images, and put CD placeholder in jewel
|
||||
case.
|
||||
* Added shuffle and repeat support to tree view.
|
||||
* Draw a speaker next to the currently playing playlist.
|
||||
* Refresh station previews whenever a filter is changed.
|
||||
* Support and show official releases on album and track pages.
|
||||
* Filter out duplicates from station previews and upcoming tracks.
|
||||
* Resolve lists top-down.
|
||||
* Added YouTube resolver.
|
||||
* Fixed bug where going offline then online would not re-connect to many
|
||||
peers.
|
||||
* Added support for auto-updating live xspf playlists.
|
||||
* Don't show an age of 41 for tracks that have no age information.
|
||||
* Show config UI for resolvers that have them as so on as you add the resolver.
|
||||
* Add support for Echo Nest Personal Catalogs and User Radio. Synchronize
|
||||
your catalog with The Echo Nest and enable personal recommendations
|
||||
from you and your friends.
|
||||
* Added support for Grooveshark resolver (requires Grooveshark Anywhere).
|
||||
* Fixed re-resolving when resolvers or sources go offline.
|
||||
* Correctly sort recently played tracks on the Dashboard.
|
||||
* Show a Lion full-screen toggle button if running on Lion.
|
||||
* Display list of who is currently listening along to you.
|
||||
* Show headphone icon in source item to allow users to listen along; paint
|
||||
headphones red on a source if the user is listening along to it.
|
||||
* Added new job status view in the bottom of the source list that displays
|
||||
current jobs such as resolving, parsing playlists, and loading from
|
||||
database.
|
||||
* Parse and convert a Spotify playlist url when dropped anywhere on the
|
||||
sidebar
|
||||
* Convert resolvers to use asynchronous calls to avoid blocking Tomahawk's
|
||||
UI, greatly increasing responsiveness of Tomahawk while resolving.
|
||||
* Fixed no playlists overlay not disappearing when playlists were added.
|
||||
* Add support for parsing itunes track, artist and album links.
|
||||
* Fixed crash when syncing playlists with peers.
|
||||
* Add support for browsing, downloading and rating resolvers
|
||||
from inside Tomahawk directly.
|
||||
* Support multi-folder selection and scanning.
|
||||
* Actually remove deleted files from the collection.
|
||||
* Fixed handling of special characters in tomahawk:// links
|
||||
* Improve sidebar performance by caching pixmaps and shrinking them.
|
||||
* Send updated playlists to peers when tracks are moved/copied.
|
||||
* Remove splitter handles in sidebar
|
||||
* Fixed Tomahawk preventing system shutdown / logut.
|
||||
* Ignore leading 'The' when sorting artists.
|
||||
* Added Charts page, which shows various sources' top hits & artists.
|
||||
* The Collection tree-views can now be filtered.
|
||||
* Fixed crash when pressing enter in an empty playlist.
|
||||
* Moved the song queue below to the left, below the sidebar.
|
||||
* Added Footnotes, a contextual view that you can slide it.
|
||||
* Show recently added playlists in dashboard rather than recently opened
|
||||
playlists.
|
||||
* Fixed seek slider and give it some smooth animation between ticks.
|
||||
* Fixed Twitter issue where it would repeatedly send DMs to friends.
|
||||
* Add a new drag and drop menu when dropping items onto playlists,
|
||||
allowing users to drop the dragged tracks, the whole album, or
|
||||
the whole artists's tracks.
|
||||
* Bring Tomahawk window to the front when clicking a Tomahawk link.
|
||||
* Fixed crash in source list when initially syncing with remote sources.
|
||||
* Open temporary artist, album, and search playlists as temporary items
|
||||
in the sidebar.
|
||||
* Fixed sorting of playlists and items in the artist view.
|
||||
* Allow dragging and dropping albums and artists to playlists.
|
||||
* Added MPRIS 2.1 support.
|
||||
|
||||
Version 0.2.3:
|
||||
|
2
README
@ -34,7 +34,7 @@ Dependencies
|
||||
TagLib 1.6.2 - http://developer.kde.org/~wheeler/taglib.html
|
||||
Boost 1.3 - http://www.boost.org/
|
||||
CLucene 0.9.23 (0.9.21 will fail) - http://clucene.sourceforge.net/download.shtml
|
||||
libechonest 1.1.9 - http://projects.kde.org/projects/playground/libs/libechonest/
|
||||
libechonest 1.2.0 - http://projects.kde.org/projects/playground/libs/libechonest/
|
||||
|
||||
The following dependencies are optional, but recommended:
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 204 KiB |
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 68 KiB |
BIN
data/images/no-album-no-case.png
Normal file
After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 3.2 KiB |
BIN
data/images/rdio.png
Normal file
After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 563 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@ -4,7 +4,6 @@
|
||||
<file>data/images/avatar-dude.png</file>
|
||||
<file>data/images/back-pressed.png</file>
|
||||
<file>data/images/back-rest.png</file>
|
||||
<file>data/images/cover-shadow.png</file>
|
||||
<file>data/images/filter.png</file>
|
||||
<file>data/images/loved.png</file>
|
||||
<file>data/images/not-loved.png</file>
|
||||
@ -112,7 +111,7 @@
|
||||
<file>data/sql/dbmigrate-23_to_24.sql</file>
|
||||
<file>data/sql/dbmigrate-24_to_25.sql</file>
|
||||
<file>data/sql/dbmigrate-25_to_26.sql</file>
|
||||
<file>data/sql/dbmigrate-26_to_27.sql</file>
|
||||
<file>data/sql/dbmigrate-26_to_27.sql</file>
|
||||
<file>data/js/tomahawk.js</file>
|
||||
<file>data/images/avatar_frame.png</file>
|
||||
<file>data/images/drop-all-songs.png</file>
|
||||
@ -120,7 +119,7 @@
|
||||
<file>data/images/drop-top-songs.png</file>
|
||||
<file>data/images/drop-song.png</file>
|
||||
<file>data/images/drop-album.png</file>
|
||||
<file>data/images/spotify-logo.png</file>
|
||||
<file>data/images/spotify-logo.png</file>
|
||||
<file>data/images/itunes.png</file>
|
||||
<file>data/images/uploading.png</file>
|
||||
<file>data/images/downloading.png</file>
|
||||
@ -128,5 +127,7 @@
|
||||
<file>data/images/headphones-off.png</file>
|
||||
<file>data/images/headphones-sidebar.png</file>
|
||||
<file>data/images/headphones-bigger.png</file>
|
||||
<file>data/images/no-album-no-case.png</file>
|
||||
<file>data/images/rdio.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -5,6 +5,6 @@ FOREACH( _file ${_icons} )
|
||||
INSTALL( FILES ${_file} RENAME tomahawk.png DESTINATION share/icons/hicolor/${_res}/apps )
|
||||
ENDFOREACH( _file )
|
||||
|
||||
INSTALL( FILES ${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon.svg RENAME tomahawk.svg DESTINATION share/icons/hicolor/scalable )
|
||||
INSTALL( FILES ${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon.svg RENAME tomahawk.svg DESTINATION share/icons/hicolor/scalable/apps )
|
||||
|
||||
INSTALL( FILES ${CMAKE_SOURCE_DIR}/admin/unix/tomahawk.desktop DESTINATION share/applications )
|
||||
|
@ -40,6 +40,7 @@
|
||||
GetNewStuffDelegate::GetNewStuffDelegate( QObject* parent )
|
||||
: QStyledItemDelegate ( parent )
|
||||
, m_widestTextWidth( 0 )
|
||||
, m_hoveringOver( -1 )
|
||||
{
|
||||
m_defaultCover.load( RESPATH "images/sipplugin-online.png" );
|
||||
m_ratingStarPositive.load( RESPATH "images/starred.png" );
|
||||
@ -190,8 +191,10 @@ GetNewStuffDelegate::paint( QPainter* painter, const QStyleOptionViewItem& optio
|
||||
if ( i == 1 )
|
||||
m_cachedStarRects[ QPair<int, int>(index.row(), index.column()) ] = r;
|
||||
|
||||
QPixmap pm;
|
||||
if ( m_hoveringOver > -1 )
|
||||
const bool userHasRated = index.data( GetNewStuffModel::UserHasRatedRole ).toBool();
|
||||
if ( !userHasRated && // Show on-hover animation if the user hasn't rated it yet, and is hovering over it
|
||||
m_hoveringOver > -1 &&
|
||||
m_hoveringItem == index )
|
||||
{
|
||||
if ( i <= m_hoveringOver ) // positive star
|
||||
painter->drawPixmap( r, m_onHoverStar );
|
||||
@ -200,8 +203,13 @@ GetNewStuffDelegate::paint( QPainter* painter, const QStyleOptionViewItem& optio
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( i <= rating ) // positive star
|
||||
painter->drawPixmap( r, m_ratingStarPositive );
|
||||
if ( i <= rating ) // positive or rated star
|
||||
{
|
||||
if ( userHasRated )
|
||||
painter->drawPixmap( r, m_onHoverStar );
|
||||
else
|
||||
painter->drawPixmap( r, m_ratingStarPositive );
|
||||
}
|
||||
else
|
||||
painter->drawPixmap( r, m_ratingStarNegative );
|
||||
}
|
||||
@ -258,7 +266,6 @@ bool
|
||||
GetNewStuffDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
|
||||
{
|
||||
Q_UNUSED( option );
|
||||
m_hoveringOver = -1;
|
||||
|
||||
if ( event->type() != QEvent::MouseButtonRelease &&
|
||||
event->type() != QEvent::MouseMove )
|
||||
@ -287,25 +294,30 @@ GetNewStuffDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, cons
|
||||
|
||||
if ( fullStars.contains( me->pos() ) )
|
||||
{
|
||||
tDebug() << "A star was pressed...which one?";
|
||||
|
||||
const int eachStar = starsWidth / 5;
|
||||
const int clickOffset = me->pos().x() - fullStars.x();
|
||||
const int whichStar = (clickOffset / eachStar) + 1;
|
||||
|
||||
if ( event->type() == QEvent::MouseButtonRelease )
|
||||
{
|
||||
tDebug() << "Clicked on:" << whichStar;
|
||||
model->setData( index, whichStar, GetNewStuffModel::RatingRole );
|
||||
}
|
||||
else if ( event->type() == QEvent::MouseMove )
|
||||
{
|
||||
// 0-indexed
|
||||
m_hoveringOver = whichStar;
|
||||
m_hoveringItem = index;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_hoveringOver > -1 )
|
||||
{
|
||||
emit update( m_hoveringItem );
|
||||
m_hoveringOver = -1;
|
||||
m_hoveringItem = QPersistentModelIndex();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -31,6 +31,9 @@ public:
|
||||
virtual void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
|
||||
signals:
|
||||
void update( const QModelIndex& idx );
|
||||
|
||||
protected:
|
||||
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
|
||||
|
||||
@ -39,6 +42,7 @@ private:
|
||||
|
||||
int m_widestTextWidth;
|
||||
int m_hoveringOver;
|
||||
QPersistentModelIndex m_hoveringItem;
|
||||
mutable QHash< QPair<int, int>, QRect > m_cachedButtonRects;
|
||||
mutable QHash< QPair<int, int>, QRect > m_cachedStarRects;
|
||||
};
|
||||
|
@ -30,7 +30,9 @@ GetNewStuffDialog::GetNewStuffDialog( QWidget *parent, Qt::WindowFlags f )
|
||||
ui->setupUi( this );
|
||||
|
||||
ui->listView->setModel( m_model );
|
||||
ui->listView->setItemDelegate( new GetNewStuffDelegate( ui->listView ) );
|
||||
GetNewStuffDelegate* del = new GetNewStuffDelegate( ui->listView );
|
||||
connect( del, SIGNAL( update( QModelIndex ) ), ui->listView, SLOT( update( QModelIndex ) ) );
|
||||
ui->listView->setItemDelegate( del );
|
||||
ui->listView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
|
||||
|
||||
ui->listView->setMouseTracking( true );
|
||||
|
@ -94,6 +94,8 @@ GetNewStuffModel::data( const QModelIndex& index, int role ) const
|
||||
return resolver.author();
|
||||
case StateRole:
|
||||
return (int)AtticaManager::instance()->resolverState( resolver );
|
||||
case UserHasRatedRole:
|
||||
return AtticaManager::instance()->userHasRated( resolver );
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ public:
|
||||
DescriptionRole = Qt::UserRole + 5,
|
||||
TypeRole = Qt::UserRole + 6, // Category in attica-speak. What sort of item this is (resolver, etc).
|
||||
AuthorRole = Qt::UserRole + 7,
|
||||
StateRole = Qt::UserRole + 8
|
||||
StateRole = Qt::UserRole + 8,
|
||||
UserHasRatedRole = Qt::UserRole + 9
|
||||
};
|
||||
|
||||
enum Types {
|
||||
|
@ -128,7 +128,7 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
connect( AudioEngine::instance(), SIGNAL( timerMilliSeconds( qint64 ) ), SLOT( onPlaybackTimer( qint64 ) ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( volumeChanged( int ) ), SLOT( onVolumeChanged( int ) ) );
|
||||
|
||||
m_defaultCover = QPixmap( RESPATH "images/no-album-art-placeholder.png" )
|
||||
m_defaultCover = QPixmap( RESPATH "images/no-album-no-case.png" )
|
||||
.scaled( ui->coverImage->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
|
@ -45,7 +45,6 @@ AtticaManager::AtticaManager( QObject* parent )
|
||||
|
||||
// resolvers
|
||||
m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org:10480/resolvers/providers.xml" ) );
|
||||
QTimer::singleShot( 0, this, SLOT( loadPixmapsFromCache() ) );
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +61,8 @@ AtticaManager::loadPixmapsFromCache()
|
||||
if ( !cacheDir.cd( "atticacache" ) ) // doesn't exist, no cache
|
||||
return;
|
||||
|
||||
qDebug() << "Loading resolvers from cache dir:" << cacheDir.absolutePath();
|
||||
qDebug() << "Currently we know about these resolvers:" << m_resolverStates.keys();
|
||||
foreach ( const QString& file, cacheDir.entryList( QStringList() << "*.png", QDir::Files | QDir::NoSymLinks ) )
|
||||
{
|
||||
// load all the pixmaps
|
||||
@ -204,6 +205,8 @@ AtticaManager::resolversList( BaseJob* j )
|
||||
m_resolverStates = TomahawkSettings::instance()->atticaResolverStates();
|
||||
|
||||
// load icon cache from disk, and fetch any we are missing
|
||||
loadPixmapsFromCache();
|
||||
|
||||
foreach ( Content resolver, m_resolvers )
|
||||
{
|
||||
if ( !m_resolverStates.contains( resolver.id() ) )
|
||||
|
@ -113,8 +113,11 @@ set( libSources
|
||||
infosystem/infoplugins/generic/echonestplugin.cpp
|
||||
infosystem/infoplugins/generic/lastfmplugin.cpp
|
||||
infosystem/infoplugins/generic/chartsplugin.cpp
|
||||
infosystem/infoplugins/generic/spotifyPlugin.cpp
|
||||
infosystem/infoplugins/generic/hypemPlugin.cpp
|
||||
infosystem/infoplugins/generic/musixmatchplugin.cpp
|
||||
infosystem/infoplugins/generic/musicbrainzPlugin.cpp
|
||||
infosystem/infoplugins/generic/RoviPlugin.cpp
|
||||
|
||||
playlist/treemodel.cpp
|
||||
playlist/treeproxymodel.cpp
|
||||
@ -224,11 +227,8 @@ set( libSources
|
||||
widgets/infowidgets/sourceinfowidget.cpp
|
||||
widgets/infowidgets/ArtistInfoWidget.cpp
|
||||
widgets/infowidgets/AlbumInfoWidget.cpp
|
||||
widgets/kbreadcrumbselectionmodel.cpp
|
||||
widgets/breadcrumbbar.cpp
|
||||
widgets/breadcrumbbuttonbase.cpp
|
||||
widgets/headerbreadcrumb.cpp
|
||||
widgets/siblingcrumbbutton.cpp
|
||||
widgets/Breadcrumb.cpp
|
||||
widgets/BreadcrumbButton.cpp
|
||||
|
||||
jobview/JobStatusView.cpp
|
||||
jobview/JobStatusModel.cpp
|
||||
@ -345,8 +345,11 @@ set( libHeaders
|
||||
infosystem/infoplugins/generic/echonestplugin.h
|
||||
infosystem/infoplugins/generic/lastfmplugin.h
|
||||
infosystem/infoplugins/generic/chartsplugin.h
|
||||
infosystem/infoplugins/generic/spotifyPlugin.h
|
||||
infosystem/infoplugins/generic/hypemPlugin.h
|
||||
infosystem/infoplugins/generic/musixmatchplugin.h
|
||||
infosystem/infoplugins/generic/musicbrainzPlugin.h
|
||||
infosystem/infoplugins/generic/RoviPlugin.h
|
||||
|
||||
network/bufferiodevice.h
|
||||
network/msgprocessor.h
|
||||
@ -451,13 +454,10 @@ set( libHeaders
|
||||
widgets/SocialPlaylistWidget.h
|
||||
widgets/infowidgets/sourceinfowidget.h
|
||||
widgets/infowidgets/ArtistInfoWidget.h
|
||||
widgets/infowidgets/ArtistInfoWidget_p.h
|
||||
widgets/infowidgets/AlbumInfoWidget.h
|
||||
widgets/kbreadcrumbselectionmodel.h
|
||||
widgets/kbreadcrumbselectionmodel_p.h
|
||||
widgets/breadcrumbbar.h
|
||||
widgets/breadcrumbbuttonbase.h
|
||||
widgets/headerbreadcrumb.h
|
||||
widgets/siblingcrumbbutton.h
|
||||
widgets/Breadcrumb.h
|
||||
widgets/BreadcrumbButton.h
|
||||
|
||||
jobview/JobStatusView.h
|
||||
jobview/JobStatusModel.h
|
||||
@ -507,7 +507,6 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
|
||||
${LIBECHONEST_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}/..
|
||||
${CLUCENE_INCLUDE_DIR}
|
||||
${CLUCENE_LIBRARY_DIR}
|
||||
${PHONON_INCLUDES}
|
||||
${CMAKE_BINARY_DIR}/thirdparty/liblastfm2/src
|
||||
|
||||
|
@ -424,6 +424,9 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
tLog() << "Starting new song:" << m_currentTrack->url();
|
||||
emit loading( m_currentTrack );
|
||||
|
||||
if ( QNetworkReply* qnr_io = qobject_cast< QNetworkReply* >( io.data() ) )
|
||||
connect( qnr_io, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( ioStreamError( QNetworkReply::NetworkError ) ) );
|
||||
|
||||
if ( !isHttpResult( m_currentTrack->url() ) && !isLocalResult( m_currentTrack->url() ) )
|
||||
{
|
||||
if ( QNetworkReply* qnr_io = qobject_cast< QNetworkReply* >( io.data() ) )
|
||||
@ -573,6 +576,16 @@ AudioEngine::playItem( Tomahawk::PlaylistInterface* playlist, const Tomahawk::re
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioEngine::ioStreamError( QNetworkReply::NetworkError error )
|
||||
{
|
||||
if ( error != QNetworkReply::NoError )
|
||||
{
|
||||
if ( canGoNext() )
|
||||
loadNextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::playlistNextTrackReady()
|
||||
@ -682,7 +695,10 @@ AudioEngine::setPlaylist( PlaylistInterface* playlist )
|
||||
}
|
||||
|
||||
if ( !playlist )
|
||||
{
|
||||
m_playlist.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
m_playlist = playlist->getSharedPointer();
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <phonon/MediaObject>
|
||||
#include <phonon/AudioOutput>
|
||||
@ -134,6 +135,7 @@ private slots:
|
||||
|
||||
void setCurrentTrack( const Tomahawk::result_ptr& result );
|
||||
|
||||
void ioStreamError( QNetworkReply::NetworkError );
|
||||
private:
|
||||
void setState( AudioState state );
|
||||
|
||||
|
@ -276,10 +276,14 @@ ContextWidget::onAnimationFinished()
|
||||
m_scene->setSceneRect( ui->contextView->viewport()->rect() );
|
||||
layoutViews( false );
|
||||
setQuery( m_query, true );
|
||||
|
||||
ui->toggleButton->setText( tr( "Hide Footnotes" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
setFixedHeight( m_minHeight );
|
||||
|
||||
ui->toggleButton->setText( tr( "Show Footnotes" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Footnotes</string>
|
||||
<string>Show Footnotes</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
|
@ -50,7 +50,7 @@ DatabaseCommand_LoadSocialActions::exec( DatabaseImpl* dbi )
|
||||
return;
|
||||
|
||||
QString whereToken;
|
||||
whereToken = QString( "WHERE id IS %1" ).arg( trkid );
|
||||
whereToken = QString( "WHERE id IS %1" ).arg( trkid );
|
||||
|
||||
QString sql = QString(
|
||||
"SELECT k, v, timestamp, source "
|
||||
@ -66,7 +66,7 @@ DatabaseCommand_LoadSocialActions::exec( DatabaseImpl* dbi )
|
||||
Tomahawk::SocialAction action;
|
||||
action.action = query.value( 0 ); // action
|
||||
action.value = query.value( 1 ); // comment
|
||||
action.timestamp = query.value( 2 ); // timestamp
|
||||
action.timestamp = query.value( 2 ); // timestamp
|
||||
action.source = query.value( 3 ); // source
|
||||
|
||||
allSocialActions.append( action );
|
||||
|
@ -49,22 +49,17 @@ DatabaseCommand_SocialAction::exec( DatabaseImpl* dbi )
|
||||
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
|
||||
|
||||
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
|
||||
|
||||
int trkid = -2;
|
||||
if ( !m_result.isNull() && !m_artist.isNull() && !m_track.isEmpty() )
|
||||
{
|
||||
bool autoCreate = true;
|
||||
int artid = dbi->artistId( m_artist, autoCreate );
|
||||
if ( artid < 1 )
|
||||
return;
|
||||
if ( m_artist.isNull() || m_track.isEmpty() )
|
||||
return;
|
||||
|
||||
autoCreate = true; // artistId overwrites autoCreate (reference)
|
||||
trkid = dbi->trackId( artid, m_track, autoCreate );
|
||||
if ( trkid < 1 )
|
||||
return;
|
||||
}
|
||||
int artid = dbi->artistId( m_artist, true );
|
||||
if ( artid < 1 )
|
||||
return;
|
||||
int trkid = dbi->trackId( artid, m_track, true );
|
||||
if ( trkid < 1 )
|
||||
return;
|
||||
|
||||
// update if it already exists
|
||||
TomahawkSqlQuery find = dbi->newquery();
|
||||
@ -80,12 +75,13 @@ DatabaseCommand_SocialAction::exec( DatabaseImpl* dbi )
|
||||
.arg( trkid )
|
||||
.arg( source()->isLocal() ? "IS NULL" : QString( "=%1" ).arg( source()->id() ) )
|
||||
.arg( m_action ) );
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
query.prepare( "INSERT INTO social_attributes(id, source, k, v, timestamp) "
|
||||
query.prepare( "INSERT INTO social_attributes(id, source, k, v, timestamp) "
|
||||
"VALUES (?, ?, ?, ?, ?)" );
|
||||
|
||||
query.bindValue( 0, trkid >= -1 ? trkid : QVariant() );
|
||||
query.bindValue( 0, trkid );
|
||||
query.bindValue( 1, srcid );
|
||||
query.bindValue( 2, m_action );
|
||||
query.bindValue( 3, m_comment );
|
||||
|
@ -112,7 +112,8 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
||||
if ( url.contains( "spotify" ) && url.contains( "track" ) )
|
||||
return true;
|
||||
|
||||
if ( url.contains( "rdio.com" ) && url.contains( "track" ) )
|
||||
if ( url.contains( "rdio.com" ) && ( ( ( url.contains( "track" ) && url.contains( "artist" ) && url.contains( "album" ) )
|
||||
|| url.contains( "playlists" ) ) ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -122,6 +123,8 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
||||
return true;
|
||||
if ( url.contains( "spotify" ) && url.contains( "album" ) )
|
||||
return true;
|
||||
if ( url.contains( "rdio.com" ) && ( url.contains( "artist" ) && url.contains( "album" ) && !url.contains( "track" ) ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( acceptedType.testFlag( Artist ) )
|
||||
@ -130,6 +133,8 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
||||
return true;
|
||||
if ( url.contains( "spotify" ) && url.contains( "artist" ) )
|
||||
return true;
|
||||
if ( url.contains( "rdio.com" ) && ( url.contains( "artist" ) && !url.contains( "album" ) && !url.contains( "track" ) ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
||||
@ -152,6 +157,16 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data )
|
||||
// Not the most elegant
|
||||
if ( url.contains( "spotify" ) && url.contains( "playlist" ) && s_canParseSpotifyPlaylists )
|
||||
return true;
|
||||
|
||||
if ( url.contains( "rdio.com" ) && url.contains( "people" ) && url.contains( "playlist" ) )
|
||||
return true;
|
||||
|
||||
// we don't know about these.. gotta say yes for now
|
||||
if ( url.contains( "bit.ly" ) ||
|
||||
url.contains( "j.mp" ) ||
|
||||
url.contains( "t.co" ) ||
|
||||
url.contains( "rd.io" ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -443,6 +458,25 @@ DropJob::handleSpotifyUrls( const QString& urlsRaw )
|
||||
m_queryCount++;
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::handleRdioUrls( const QString& urlsRaw )
|
||||
{
|
||||
QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
|
||||
qDebug() << "Got Rdio urls!!" << urls;
|
||||
|
||||
if ( dropAction() == Default )
|
||||
setDropAction( Create );
|
||||
|
||||
RdioParser* rdio = new RdioParser( this );
|
||||
connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||
|
||||
rdio->setCreatePlaylist( dropAction() == Create );
|
||||
rdio->parse( urls );
|
||||
|
||||
m_queryCount++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::handleAllUrls( const QString& urls )
|
||||
{
|
||||
@ -452,6 +486,8 @@ DropJob::handleAllUrls( const QString& urls )
|
||||
&& ( urls.contains( "playlist" ) || urls.contains( "artist" ) || urls.contains( "album" ) || urls.contains( "track" ) )
|
||||
&& s_canParseSpotifyPlaylists )
|
||||
handleSpotifyUrls( urls );
|
||||
else if ( urls.contains( "rdio.com" ) )
|
||||
handleRdioUrls( urls );
|
||||
else
|
||||
handleTrackUrls ( urls );
|
||||
}
|
||||
|
@ -102,7 +102,9 @@ public:
|
||||
void setGetWholeAlbums( bool getWholeAlbums );
|
||||
void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false, bool onlyLocal = false, bool top10 = false );
|
||||
void handleXspfs( const QString& files );
|
||||
|
||||
void handleSpotifyUrls( const QString& urls );
|
||||
void handleRdioUrls( const QString& urls );
|
||||
|
||||
static bool canParseSpotifyPlaylists() { return s_canParseSpotifyPlaylists; }
|
||||
static void setCanParseSpotifyPlaylists( bool parseable ) { s_canParseSpotifyPlaylists = parseable; }
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "utils/spotifyparser.h"
|
||||
#include "utils/shortenedlinkparser.h"
|
||||
#include "utils/rdioparser.h"
|
||||
#include "widgets/searchwidget.h"
|
||||
|
||||
GlobalActionManager* GlobalActionManager::s_instance = 0;
|
||||
|
||||
@ -269,6 +270,8 @@ GlobalActionManager::parseTomahawkLink( const QString& urlIn )
|
||||
return handlePlayCommand( u );
|
||||
} else if( cmdType == "open" ) {
|
||||
return handleOpenCommand( u );
|
||||
} else if( cmdType == "view" ) {
|
||||
return handleViewCommand( u );
|
||||
} else {
|
||||
tLog() << "Tomahawk link not supported, command not known!" << cmdType << u.path();
|
||||
return false;
|
||||
@ -357,7 +360,7 @@ GlobalActionManager::handleOpenTrack ( const query_ptr& q )
|
||||
ViewManager::instance()->queue()->model()->append( q );
|
||||
ViewManager::instance()->showQueue();
|
||||
|
||||
if( !AudioEngine::instance()->isPlaying() ) {
|
||||
if( !AudioEngine::instance()->isPlaying() && !AudioEngine::instance()->isPaused() ) {
|
||||
connect( q.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( waitingForResolved( bool ) ) );
|
||||
m_waitingToPlay = q;
|
||||
}
|
||||
@ -498,23 +501,71 @@ bool
|
||||
GlobalActionManager::handleSearchCommand( const QUrl& url )
|
||||
{
|
||||
// open the super collection and set this as the search filter
|
||||
QStringList query;
|
||||
if( url.hasQueryItem( "artist" ) )
|
||||
query << url.queryItemValue( "artist" );
|
||||
if( url.hasQueryItem( "album" ) )
|
||||
query << url.queryItemValue( "album" );
|
||||
if( url.hasQueryItem( "title" ) )
|
||||
query << url.queryItemValue( "title" );
|
||||
QString queryStr = query.join( " " );
|
||||
QString queryStr;
|
||||
if ( url.hasQueryItem( "query" ) )
|
||||
queryStr = url.queryItemValue( "query" );
|
||||
else
|
||||
{
|
||||
QStringList query;
|
||||
if( url.hasQueryItem( "artist" ) )
|
||||
query << url.queryItemValue( "artist" );
|
||||
if( url.hasQueryItem( "album" ) )
|
||||
query << url.queryItemValue( "album" );
|
||||
if( url.hasQueryItem( "title" ) )
|
||||
query << url.queryItemValue( "title" );
|
||||
queryStr = query.join( " " );
|
||||
}
|
||||
|
||||
if( queryStr.isEmpty() )
|
||||
if( queryStr.trimmed().isEmpty() )
|
||||
return false;
|
||||
|
||||
ViewManager::instance()->showSuperCollection();
|
||||
// ViewManager::instance()->topbar()->setFilter( queryStr );
|
||||
ViewManager::instance()->show( new SearchWidget( queryStr.trimmed() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::handleViewCommand( const QUrl& url )
|
||||
{
|
||||
QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command
|
||||
if( parts.isEmpty() ) {
|
||||
tLog() << "No specific view command:" << url.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( parts[ 0 ] == "artist" )
|
||||
{
|
||||
const QString artist = url.queryItemValue( "name" );
|
||||
if ( artist.isEmpty() )
|
||||
{
|
||||
tLog() << "Not artist supplied for view/artist command.";
|
||||
return false;
|
||||
}
|
||||
artist_ptr artistPtr = Artist::get( artist );
|
||||
if ( !artistPtr.isNull() )
|
||||
ViewManager::instance()->show( artistPtr );
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( parts[ 0 ] == "album" )
|
||||
{
|
||||
const QString artist = url.queryItemValue( "artist" );
|
||||
const QString album = url.queryItemValue( "name" );
|
||||
if ( artist.isEmpty() || album.isEmpty() )
|
||||
{
|
||||
tLog() << "Not artist or album supplied for view/artist command:" << url;
|
||||
return false;
|
||||
}
|
||||
album_ptr albumPtr = Album::get( Artist::get( artist, false ), album, false );
|
||||
if ( !albumPtr.isNull() )
|
||||
ViewManager::instance()->show( albumPtr );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GlobalActionManager::handleAutoPlaylistCommand( const QUrl& url )
|
||||
|
@ -95,6 +95,7 @@ private:
|
||||
bool handlePlayCommand(const QUrl& url );
|
||||
bool handleBookmarkCommand(const QUrl& url );
|
||||
bool handleOpenCommand(const QUrl& url );
|
||||
bool handleViewCommand(const QUrl& url );
|
||||
bool doQueueAdd( const QStringList& parts, const QList< QPair< QString, QString > >& queryItems );
|
||||
|
||||
bool playSpotify( const QUrl& url );
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include <QCheckBox>
|
||||
#include <widgets/querylabel.h>
|
||||
|
||||
#define ANIMATION_TIME 400
|
||||
#define IMAGE_HEIGHT 64
|
||||
@ -37,6 +38,7 @@ using namespace Tomahawk;
|
||||
InfoBar::InfoBar( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, ui( new Ui::InfoBar )
|
||||
, m_queryLabel( 0 )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
TomahawkUtils::unmarginLayout( layout() );
|
||||
@ -71,6 +73,14 @@ InfoBar::InfoBar( QWidget* parent )
|
||||
ui->longDescriptionLabel->setText( QString() );
|
||||
ui->imageLabel->setText( QString() );
|
||||
|
||||
m_queryLabel = new QueryLabel( this );
|
||||
m_queryLabel->setType( QueryLabel::Artist );
|
||||
m_queryLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
|
||||
m_queryLabel->setTextPen( palette().brightText().color() );
|
||||
m_queryLabel->setFont( boldFont );
|
||||
m_queryLabel->hide();
|
||||
connect( m_queryLabel, SIGNAL( clickedArtist() ), this, SLOT( artistClicked() ) );
|
||||
|
||||
m_autoUpdate = new QCheckBox( this );
|
||||
m_autoUpdate->setText( tr( "Automatically update" ) );
|
||||
m_autoUpdate->setLayoutDirection( Qt::RightToLeft );
|
||||
@ -95,6 +105,8 @@ InfoBar::InfoBar( QWidget* parent )
|
||||
setPalette( p );
|
||||
setAutoFillBackground( true );
|
||||
|
||||
setMinimumHeight( geometry().height() );
|
||||
setMaximumHeight( geometry().height() );
|
||||
connect( ViewManager::instance(), SIGNAL( filterAvailable( bool ) ), SLOT( setFilterAvailable( bool ) ) );
|
||||
connect( ViewManager::instance(), SIGNAL( autoUpdateAvailable( bool ) ), SLOT( setAutoUpdateAvailable( bool ) ) );
|
||||
}
|
||||
@ -116,9 +128,49 @@ InfoBar::setCaption( const QString& s )
|
||||
void
|
||||
InfoBar::setDescription( const QString& s )
|
||||
{
|
||||
if ( m_queryLabel->isVisible() )
|
||||
{
|
||||
ui->verticalLayout->removeWidget( m_queryLabel );
|
||||
m_queryLabel->hide();
|
||||
|
||||
ui->verticalLayout->addWidget( ui->descriptionLabel );
|
||||
ui->verticalLayout->setContentsMargins( 0, 0, 0, 0 );
|
||||
ui->descriptionLabel->show();
|
||||
}
|
||||
ui->descriptionLabel->setText( s );
|
||||
}
|
||||
|
||||
void
|
||||
InfoBar::setDescription( const artist_ptr& artist )
|
||||
{
|
||||
m_queryLabel->setQuery( Query::get( artist->name(), QString(), QString() ) );
|
||||
m_queryLabel->setExtraContentsMargins( 4, 0, 0, 0 );
|
||||
|
||||
if ( !m_queryLabel->isVisible() )
|
||||
{
|
||||
ui->verticalLayout->removeWidget( ui->descriptionLabel );
|
||||
ui->descriptionLabel->hide();
|
||||
|
||||
m_queryLabel->show();
|
||||
ui->verticalLayout->addWidget( m_queryLabel );
|
||||
ui->verticalLayout->setContentsMargins( 0, 0, 0, 15 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
InfoBar::setDescription( const album_ptr& )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void
|
||||
InfoBar::artistClicked()
|
||||
{
|
||||
if ( m_queryLabel && !m_queryLabel->query().isNull() )
|
||||
ViewManager::instance()->show( Artist::get( m_queryLabel->artist() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::setLongDescription( const QString& s )
|
||||
|
@ -22,7 +22,9 @@
|
||||
#include <QWidget>
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include "artist.h"
|
||||
|
||||
class QueryLabel;
|
||||
class QCheckBox;
|
||||
class QTimeLine;
|
||||
class QSearchField;
|
||||
@ -43,7 +45,12 @@ public:
|
||||
|
||||
public slots:
|
||||
void setCaption( const QString& s );
|
||||
|
||||
void setDescription( const QString& s );
|
||||
// If you want a querylabel instead of an ElidedLabel
|
||||
void setDescription( const Tomahawk::artist_ptr& artist );
|
||||
void setDescription( const Tomahawk::album_ptr& album_ptr );
|
||||
|
||||
void setLongDescription( const QString& s );
|
||||
void setPixmap( const QPixmap& p );
|
||||
|
||||
@ -60,12 +67,14 @@ protected:
|
||||
|
||||
private slots:
|
||||
void onFilterEdited();
|
||||
void artistClicked();
|
||||
|
||||
private:
|
||||
Ui::InfoBar* ui;
|
||||
|
||||
QSearchField* m_searchWidget;
|
||||
QCheckBox* m_autoUpdate;
|
||||
QueryLabel* m_queryLabel;
|
||||
};
|
||||
|
||||
#endif // INFOBAR_H
|
||||
|
@ -65,10 +65,13 @@
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ElidedLabel" name="captionLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
|
207
src/libtomahawk/infosystem/infoplugins/generic/RoviPlugin.cpp
Normal file
@ -0,0 +1,207 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.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/>.
|
||||
*/
|
||||
|
||||
#include "RoviPlugin.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QNetworkReply>
|
||||
#include <parser.h>
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
static QString
|
||||
md5( const QByteArray& src )
|
||||
{
|
||||
QByteArray const digest = QCryptographicHash::hash( src, QCryptographicHash::Md5 );
|
||||
return QString::fromLatin1( digest.toHex() ).rightJustified( 32, '0' );
|
||||
}
|
||||
|
||||
RoviPlugin::RoviPlugin()
|
||||
: InfoPlugin()
|
||||
{
|
||||
m_supportedGetTypes << InfoAlbumSongs;
|
||||
|
||||
/*
|
||||
* Your API Key is 7jxr9zggt45h6rg2n4ss3mrj
|
||||
* Your secret is XUnYutaAW6
|
||||
*/
|
||||
m_apiKey = "7jxr9zggt45h6rg2n4ss3mrj";
|
||||
m_secret = "XUnYutaAW6";
|
||||
}
|
||||
|
||||
RoviPlugin::~RoviPlugin()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
RoviPlugin::namChangedSlot( QNetworkAccessManager* nam )
|
||||
{
|
||||
if ( !nam )
|
||||
return;
|
||||
|
||||
m_nam = nam;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RoviPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "artist" ) || !hash.contains( "album" ) )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = hash["artist"];
|
||||
criteria["album"] = hash["album"];
|
||||
|
||||
emit getCachedInfo( criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
RoviPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoAlbumSongs:
|
||||
{
|
||||
QUrl baseUrl = QUrl( "http://api.rovicorp.com/search/v2/music/search" );
|
||||
baseUrl.addQueryItem( "query", QString( "%1 %2" ).arg( criteria[ "artist" ] ).arg( criteria[ "album" ] ) );
|
||||
baseUrl.addQueryItem( "entitytype", "album" );
|
||||
baseUrl.addQueryItem( "include", "album:tracks" );
|
||||
|
||||
QNetworkReply* reply = makeRequest( baseUrl );
|
||||
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( albumLookupFinished() ) );
|
||||
connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( albumLookupError( QNetworkReply::NetworkError ) ) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Q_ASSERT( false );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RoviPlugin::albumLookupError( QNetworkReply::NetworkError error )
|
||||
{
|
||||
if ( error == QNetworkReply::NoError )
|
||||
return;
|
||||
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
Q_ASSERT( reply );
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info( requestData, QVariant() );
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
RoviPlugin::albumLookupFinished()
|
||||
{
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
Q_ASSERT( reply );
|
||||
|
||||
if ( reply->error() != QNetworkReply::NoError )
|
||||
return;
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
QJson::Parser p;
|
||||
bool ok;
|
||||
QVariantMap response = p.parse( reply, &ok ).toMap();
|
||||
|
||||
if ( !ok || response.isEmpty() || !response.contains( "searchResponse" ) )
|
||||
{
|
||||
tLog() << "Error parsing JSON from Rovi!" << p.errorString() << response;
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantList resultList = response[ "searchResponse" ].toMap().value( "results" ).toList();
|
||||
if ( resultList.size() == 0 )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap results = resultList.first().toMap();
|
||||
QVariantList tracks = results[ "album" ].toMap()[ "tracks" ].toList();
|
||||
|
||||
if ( tracks.isEmpty() )
|
||||
{
|
||||
tLog() << "Error parsing JSON from Rovi!" << p.errorString() << response;
|
||||
emit info( requestData, QVariant() );
|
||||
}
|
||||
|
||||
|
||||
QStringList trackNameList;
|
||||
foreach ( const QVariant& track, tracks )
|
||||
{
|
||||
const QVariantMap trackData = track.toMap();
|
||||
if ( trackData.contains( "title" ) )
|
||||
trackNameList << trackData[ "title" ].toString();
|
||||
}
|
||||
|
||||
QVariantMap returnedData;
|
||||
returnedData["tracks"] = trackNameList;
|
||||
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>()["artist"];
|
||||
criteria["album"] = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>()["album"];
|
||||
|
||||
emit updateCache( criteria, 0, requestData.type, returnedData );
|
||||
}
|
||||
|
||||
|
||||
QNetworkReply*
|
||||
RoviPlugin::makeRequest( QUrl url )
|
||||
{
|
||||
url.addQueryItem( "apikey", m_apiKey );
|
||||
url.addEncodedQueryItem( "sig", generateSig() );
|
||||
|
||||
qDebug() << "Rovi request url:" << url.toString();
|
||||
return m_nam->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
|
||||
QByteArray
|
||||
RoviPlugin::generateSig() const
|
||||
{
|
||||
QByteArray raw = m_apiKey + m_secret + QString::number( QDateTime::currentMSecsSinceEpoch() / 1000 ).toLatin1();
|
||||
return md5( raw ).toLatin1();
|
||||
|
||||
}
|
67
src/libtomahawk/infosystem/infoplugins/generic/RoviPlugin.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.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 ROVIPLUGIN_H
|
||||
#define ROVIPLUGIN_H
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
class RoviPlugin : public InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RoviPlugin();
|
||||
virtual ~RoviPlugin();
|
||||
|
||||
protected:
|
||||
virtual void namChangedSlot( QNetworkAccessManager* nam );
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
virtual void pushInfo( QString, Tomahawk::InfoSystem::InfoType, QVariant )
|
||||
{}
|
||||
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
private slots:
|
||||
void albumLookupFinished();
|
||||
void albumLookupError( QNetworkReply::NetworkError );
|
||||
private:
|
||||
QNetworkReply* makeRequest( QUrl url );
|
||||
QByteArray generateSig() const;
|
||||
|
||||
QNetworkAccessManager* m_nam;
|
||||
|
||||
QByteArray m_apiKey;
|
||||
QByteArray m_secret;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // ROVIPLUGIN_H
|
@ -49,7 +49,7 @@ ChartsPlugin::ChartsPlugin()
|
||||
|
||||
|
||||
/// Add resources here
|
||||
m_chartResources << "billboard" << "itunes";
|
||||
m_chartResources << "billboard" << "itunes" << "rdio" << "wearehunted";
|
||||
m_supportedGetTypes << InfoChart << InfoChartCapabilities;
|
||||
|
||||
}
|
||||
@ -73,9 +73,10 @@ ChartsPlugin::namChangedSlot( QNetworkAccessManager *nam )
|
||||
m_nam = QWeakPointer< QNetworkAccessManager >( nam );
|
||||
|
||||
/// Then get each chart from resource
|
||||
/// We need to fetch them before they are asked for
|
||||
/// We want to prepopulate the breadcrumb to fetch them before they are asked for
|
||||
|
||||
if( !m_chartResources.isEmpty() && m_nam ){
|
||||
if ( !m_chartResources.isEmpty() && m_nam && m_allChartsMap.isEmpty() )
|
||||
{
|
||||
|
||||
tDebug() << "ChartsPlugin: InfoChart fetching possible resources";
|
||||
foreach ( QVariant resource, m_chartResources )
|
||||
@ -93,21 +94,21 @@ ChartsPlugin::namChangedSlot( QNetworkAccessManager *nam )
|
||||
|
||||
|
||||
void
|
||||
ChartsPlugin::dataError( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
ChartsPlugin::dataError( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ChartsPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << requestData.caller;
|
||||
qDebug() << Q_FUNC_INFO << requestData.customData;
|
||||
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
bool foundSource;
|
||||
bool foundSource = false;
|
||||
|
||||
switch ( requestData.type )
|
||||
{
|
||||
@ -116,7 +117,7 @@ ChartsPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData req
|
||||
/// We need something to check if the request is actually ment to go to this plugin
|
||||
if ( !hash.contains( "chart_source" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -131,19 +132,19 @@ ChartsPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData req
|
||||
|
||||
if( !foundSource )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
fetchChart( requestId, requestData );
|
||||
fetchChart( requestData );
|
||||
break;
|
||||
|
||||
case InfoChartCapabilities:
|
||||
fetchChartCapabilities( requestId, requestData );
|
||||
fetchChartCapabilities( requestData );
|
||||
break;
|
||||
default:
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,12 +159,12 @@ ChartsPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoTy
|
||||
|
||||
|
||||
void
|
||||
ChartsPlugin::fetchChart( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -173,7 +174,7 @@ ChartsPlugin::fetchChart( uint requestId, Tomahawk::InfoSystem::InfoRequestData
|
||||
/// Each request needs to contain both a id and source
|
||||
if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
|
||||
}
|
||||
@ -181,29 +182,30 @@ ChartsPlugin::fetchChart( uint requestId, Tomahawk::InfoSystem::InfoRequestData
|
||||
criteria["chart_id"] = hash["chart_id"];
|
||||
criteria["chart_source"] = hash["chart_source"];
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 0, requestData );
|
||||
emit getCachedInfo( criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
ChartsPlugin::fetchChartCapabilities( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
ChartsPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
emit getCachedInfo( requestId, criteria, 0, requestData );
|
||||
|
||||
emit getCachedInfo( criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
ChartsPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
ChartsPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !m_nam.data() )
|
||||
{
|
||||
tLog() << "Have a null QNAM, uh oh";
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -217,7 +219,6 @@ ChartsPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
|
||||
|
||||
QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
|
||||
@ -230,22 +231,18 @@ ChartsPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
if ( m_chartsFetchJobs > 0 )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
|
||||
m_cachedRequests.append( QPair< uint, InfoRequestData >( requestId, requestData ) );
|
||||
m_cachedRequests.append( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
emit info(
|
||||
requestId,
|
||||
requestData,
|
||||
m_allChartsMap
|
||||
);
|
||||
emit info( requestData, m_allChartsMap );
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Couldn't figure out what to do with this type of request after cache miss";
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -279,96 +276,152 @@ ChartsPlugin::chartTypes()
|
||||
// We'll populate charts with the data from the server
|
||||
QVariantMap charts;
|
||||
QString chartName;
|
||||
if ( source == "itunes" )
|
||||
QStringList defaultChain;
|
||||
if ( source == "wearehunted" || source == "itunes" )
|
||||
{
|
||||
// Some charts can have an extra param, itunes has geo, WAH has emerging/mainstream
|
||||
// Itunes has geographic-area based charts. So we build a breadcrumb of
|
||||
// ITunes - Country - Albums - Top Chart Type
|
||||
// - Tracks - Top Chart Type
|
||||
QHash< QString, QVariantMap > countries;
|
||||
// WeAreHunted has Mainstream/Emerging
|
||||
// WeAreHunted - Type - Artists - Chart Type
|
||||
// - Tracks - Chart Type
|
||||
QHash< QString, QVariantMap > extraType;
|
||||
foreach( const QVariant& chartObj, chartObjs.values() )
|
||||
{
|
||||
const QVariantMap chart = chartObj.toMap();
|
||||
const QString id = chart.value( "id" ).toString();
|
||||
const QString geo = chart.value( "geo" ).toString();
|
||||
QString name = chart.value( "name" ).toString();
|
||||
const QString type = chart.value( "type" ).toString();
|
||||
if( !chartObj.toMap().isEmpty() ){
|
||||
const QVariantMap chart = chartObj.toMap();
|
||||
const QString id = chart.value( "id" ).toString();
|
||||
const QString geo = chart.value( "geo" ).toString();
|
||||
QString name = chart.value( "genre" ).toString();
|
||||
const QString type = chart.value( "type" ).toString();
|
||||
const bool isDefault = ( chart.contains( "default" ) && chart[ "default" ].toInt() == 1 );
|
||||
|
||||
QString country;
|
||||
if ( !m_cachedCountries.contains( geo ) )
|
||||
{
|
||||
QLocale l( QString( "en_%1" ).arg( geo ) );
|
||||
country = Tomahawk::CountryUtils::fullCountryFromCode( geo );
|
||||
QString extra;
|
||||
if( !geo.isEmpty() ){
|
||||
|
||||
for ( int i = 1; i < country.size(); i++ )
|
||||
{
|
||||
if ( country.at( i ).isUpper() )
|
||||
if ( !m_cachedCountries.contains( geo ) )
|
||||
{
|
||||
country.insert( i, " " );
|
||||
i++;
|
||||
QLocale l( QString( "en_%1" ).arg( geo ) );
|
||||
extra = Tomahawk::CountryUtils::fullCountryFromCode( geo );
|
||||
|
||||
for ( int i = 1; i < extra.size(); i++ )
|
||||
{
|
||||
if ( extra.at( i ).isUpper() )
|
||||
{
|
||||
extra.insert( i, " " );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
m_cachedCountries[ geo ] = extra;
|
||||
}
|
||||
else
|
||||
{
|
||||
extra = m_cachedCountries[ geo ];
|
||||
}
|
||||
}else extra = chart.value( "extra" ).toString();
|
||||
|
||||
if ( name.isEmpty() ) // not a specific chart, an all chart
|
||||
name = tr( "Top Overall" );
|
||||
|
||||
InfoStringHash c;
|
||||
c[ "id" ] = id;
|
||||
c[ "label" ] = name;
|
||||
c[ "type" ] = "album";
|
||||
if ( isDefault )
|
||||
c[ "default" ] = "true";
|
||||
|
||||
QList<InfoStringHash> extraTypeData = extraType[ extra ][ type ].value< QList< InfoStringHash > >();
|
||||
extraTypeData.append( c );
|
||||
|
||||
extraType[ extra ].insert( type, QVariant::fromValue< QList< InfoStringHash > >( extraTypeData ) );
|
||||
if ( isDefault )
|
||||
{
|
||||
defaultChain.clear();
|
||||
defaultChain.append( extra );
|
||||
defaultChain.append( type );
|
||||
defaultChain.append( name );
|
||||
}
|
||||
m_cachedCountries[ geo ] = country;
|
||||
}
|
||||
else
|
||||
foreach( const QString& c, extraType.keys() )
|
||||
{
|
||||
country = m_cachedCountries[ geo ];
|
||||
charts[ c ] = extraType[ c ];
|
||||
// qDebug() << "extraType has types:" << c;
|
||||
}
|
||||
if( source == "itunes" ){
|
||||
chartName = "iTunes";
|
||||
}
|
||||
if( source == "wearehunted" ){
|
||||
chartName = "WeAreHunted";
|
||||
}
|
||||
|
||||
if ( name.startsWith( "iTunes Store:" ) ) // truncate
|
||||
name = name.mid( 13 );
|
||||
|
||||
InfoStringHash c;
|
||||
c[ "id" ] = id;
|
||||
c[ "label" ] = name;
|
||||
c[ "type" ] = "album";
|
||||
QList<InfoStringHash> countryTypeData = countries[ country ][ type ].value< QList< InfoStringHash > >();
|
||||
countryTypeData.append( c );
|
||||
|
||||
countries[ country ].insert( type, QVariant::fromValue< QList< InfoStringHash > >( countryTypeData ) );
|
||||
}
|
||||
|
||||
foreach( const QString& c, countries.keys() )
|
||||
{
|
||||
charts[ c ] = countries[ c ];
|
||||
// qDebug() << "Country has types:" << countries[ c ];
|
||||
}
|
||||
chartName = "iTunes";
|
||||
} else
|
||||
}else
|
||||
{
|
||||
// We'll just build:
|
||||
// [Source] - Album - Chart Type
|
||||
// [Source] - Track - Chart Type
|
||||
QList< InfoStringHash > albumCharts;
|
||||
QList< InfoStringHash > trackCharts;
|
||||
QList< InfoStringHash > artistCharts;
|
||||
|
||||
foreach( const QVariant& chartObj, chartObjs.values() )
|
||||
{
|
||||
const QVariantMap chart = chartObj.toMap();
|
||||
const QString type = chart.value( "type" ).toString();
|
||||
InfoStringHash c;
|
||||
c[ "id" ] = chart.value( "id" ).toString();
|
||||
c[ "label" ] = chart.value( "name" ).toString();
|
||||
if ( type == "Album" )
|
||||
{
|
||||
c[ "type" ] = "album";
|
||||
albumCharts.append( c );
|
||||
}
|
||||
else if ( type == "Track" )
|
||||
{
|
||||
c[ "type" ] = "tracks";
|
||||
trackCharts.append( c );
|
||||
}
|
||||
}
|
||||
charts.insert( tr( "Albums" ), QVariant::fromValue< QList< InfoStringHash > >( albumCharts ) );
|
||||
charts.insert( tr( "Tracks" ), QVariant::fromValue< QList< InfoStringHash > >( trackCharts ) );
|
||||
if( !chartObj.toMap().isEmpty() ){
|
||||
const QVariantMap chart = chartObj.toMap();
|
||||
const QString type = chart.value( "type" ).toString();
|
||||
const bool isDefault = ( chart.contains( "default" ) && chart[ "default" ].toInt() == 1 );
|
||||
|
||||
/// @note For displaying purposes, upper the first letter
|
||||
/// @note Remeber to lower it when fetching this!
|
||||
chartName = source;
|
||||
chartName[0] = chartName[0].toUpper();
|
||||
InfoStringHash c;
|
||||
c[ "id" ] = chart.value( "id" ).toString();
|
||||
c[ "label" ] = chart.value( "name" ).toString();
|
||||
if ( isDefault )
|
||||
c[ "default" ] = "true";
|
||||
|
||||
if ( type == "Album" )
|
||||
{
|
||||
c[ "type" ] = "album";
|
||||
albumCharts.append( c );
|
||||
}
|
||||
else if ( type == "Track" )
|
||||
{
|
||||
c[ "type" ] = "tracks";
|
||||
trackCharts.append( c );
|
||||
|
||||
}else if ( type == "Artist" )
|
||||
{
|
||||
c[ "type" ] = "artists";
|
||||
artistCharts.append( c );
|
||||
|
||||
}
|
||||
|
||||
if ( isDefault )
|
||||
{
|
||||
defaultChain.clear();
|
||||
defaultChain.append( type + "s" ); //UGLY but it's plural to the user, see below
|
||||
defaultChain.append( c[ "label" ] );
|
||||
}
|
||||
}
|
||||
if( !artistCharts.isEmpty() )
|
||||
charts.insert( tr( "Artists" ), QVariant::fromValue< QList< InfoStringHash > >( artistCharts ) );
|
||||
if( !albumCharts.isEmpty() )
|
||||
charts.insert( tr( "Albums" ), QVariant::fromValue< QList< InfoStringHash > >( albumCharts ) );
|
||||
if( !trackCharts.isEmpty() )
|
||||
charts.insert( tr( "Tracks" ), QVariant::fromValue< QList< InfoStringHash > >( trackCharts ) );
|
||||
|
||||
/// @note For displaying purposes, upper the first letter
|
||||
/// @note Remeber to lower it when fetching this!
|
||||
chartName = source;
|
||||
chartName[0] = chartName[0].toUpper();
|
||||
}
|
||||
}
|
||||
|
||||
/// Add the possible charts and its types to breadcrumb
|
||||
// qDebug() << "ADDING CHART TYPE TO CHARTS:" << chartName;
|
||||
QVariantMap defaultMap = m_allChartsMap.value( "defaults" ).value< QVariantMap >();
|
||||
defaultMap[ source ] = defaultChain;
|
||||
m_allChartsMap[ "defaults" ] = defaultMap;
|
||||
m_allChartsMap[ "defaultSource" ] = "itunes";
|
||||
m_allChartsMap.insert( chartName , QVariant::fromValue< QVariantMap >( charts ) );
|
||||
|
||||
}
|
||||
@ -380,10 +433,9 @@ ChartsPlugin::chartTypes()
|
||||
m_chartsFetchJobs--;
|
||||
if ( !m_cachedRequests.isEmpty() && m_chartsFetchJobs == 0 )
|
||||
{
|
||||
QPair< uint, InfoRequestData > request;
|
||||
foreach ( request, m_cachedRequests )
|
||||
foreach ( InfoRequestData request, m_cachedRequests )
|
||||
{
|
||||
emit info( request.first, request.second, m_allChartsMap );
|
||||
emit info( request, m_allChartsMap );
|
||||
}
|
||||
m_cachedRequests.clear();
|
||||
}
|
||||
@ -414,6 +466,7 @@ ChartsPlugin::chartReturned()
|
||||
QVariantList chartResponse = res.value( "list" ).toList();
|
||||
QList< InfoStringHash > top_tracks;
|
||||
QList< InfoStringHash > top_albums;
|
||||
QStringList top_artists;
|
||||
|
||||
/// Deside what type, we need to handle it differently
|
||||
/// @todo: We allready know the type, append it to breadcrumb hash
|
||||
@ -422,6 +475,8 @@ ChartsPlugin::chartReturned()
|
||||
setChartType( Album );
|
||||
else if( res.value( "type" ).toString() == "Track" )
|
||||
setChartType( Track );
|
||||
else if( res.value( "type" ).toString() == "Artist" )
|
||||
setChartType( Artist );
|
||||
else
|
||||
setChartType( None );
|
||||
|
||||
@ -477,10 +532,29 @@ ChartsPlugin::chartReturned()
|
||||
top_tracks << pair;
|
||||
|
||||
}
|
||||
}else if( chartType() == Artist )
|
||||
{
|
||||
if ( artist.isEmpty() ) // don't have enough...
|
||||
{
|
||||
tLog() << "Didn't get an artist from charts, not enough to build a query on. Aborting" << artist;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
top_artists << artist;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( chartType() == Artist )
|
||||
{
|
||||
tDebug() << "ChartsPlugin:" << "\tgot " << top_artists.size() << " artists";
|
||||
returnedData["artists"] = QVariant::fromValue( top_artists );
|
||||
returnedData["type"] = "artists";
|
||||
}
|
||||
|
||||
if( chartType() == Track )
|
||||
{
|
||||
tDebug() << "ChartsPlugin:" << "\tgot " << top_tracks.size() << " tracks";
|
||||
@ -498,11 +572,7 @@ ChartsPlugin::chartReturned()
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
|
||||
emit info(
|
||||
reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
returnedData
|
||||
);
|
||||
emit info( requestData, returnedData );
|
||||
// TODO update cache
|
||||
}
|
||||
else
|
||||
|
@ -56,15 +56,15 @@ public slots:
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
|
||||
|
||||
private:
|
||||
void fetchChart( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartCapabilities( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void dataError( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
QVariantList m_chartResources;
|
||||
QList<InfoStringHash> m_charts;
|
||||
@ -73,7 +73,7 @@ private:
|
||||
QVariantMap m_allChartsMap;
|
||||
|
||||
uint m_chartsFetchJobs;
|
||||
QList< QPair< uint, InfoRequestData > > m_cachedRequests;
|
||||
QList< InfoRequestData > m_cachedRequests;
|
||||
|
||||
QHash< QString, QString > m_cachedCountries;
|
||||
|
||||
|
@ -68,37 +68,37 @@ EchoNestPlugin::namChangedSlot( QNetworkAccessManager *nam )
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
EchoNestPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case Tomahawk::InfoSystem::InfoArtistBiography:
|
||||
return getArtistBiography( requestId, requestData );
|
||||
return getArtistBiography( requestData );
|
||||
case Tomahawk::InfoSystem::InfoArtistFamiliarity:
|
||||
return getArtistFamiliarity( requestId, requestData );
|
||||
return getArtistFamiliarity( requestData );
|
||||
case Tomahawk::InfoSystem::InfoArtistHotttness:
|
||||
return getArtistHotttnesss( requestId, requestData );
|
||||
return getArtistHotttnesss( requestData );
|
||||
case Tomahawk::InfoSystem::InfoArtistTerms:
|
||||
return getArtistTerms( requestId, requestData );
|
||||
return getArtistTerms( requestData );
|
||||
case Tomahawk::InfoSystem::InfoTrackEnergy:
|
||||
return getSongProfile( requestId, requestData, "energy" );
|
||||
return getSongProfile( requestData, "energy" );
|
||||
case Tomahawk::InfoSystem::InfoMiscTopTerms:
|
||||
return getMiscTopTerms( requestId, requestData );
|
||||
return getMiscTopTerms( requestData );
|
||||
default:
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::getSongProfile( uint requestId, 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 );
|
||||
|
||||
if( !isValidTrackData( requestId, requestData ) )
|
||||
if( !isValidTrackData( requestData ) )
|
||||
return;
|
||||
|
||||
// Track track( input.toString() );
|
||||
@ -110,67 +110,62 @@ EchoNestPlugin::getSongProfile( uint requestId, const Tomahawk::InfoSystem::Info
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::getArtistBiography( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
EchoNestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
{
|
||||
if( !isValidArtistData( requestId, requestData ) )
|
||||
if( !isValidArtistData( requestData ) )
|
||||
return;
|
||||
|
||||
Echonest::Artist artist( requestData.input.toString() );
|
||||
QNetworkReply *reply = artist.fetchBiographies();
|
||||
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
connect( reply, SIGNAL( finished() ), SLOT( getArtistBiographySlot() ) );
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::getArtistFamiliarity( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
EchoNestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
{
|
||||
if( !isValidArtistData( requestId, requestData ) )
|
||||
if( !isValidArtistData( requestData ) )
|
||||
return;
|
||||
|
||||
qDebug() << "Fetching artist familiarity!" << requestData.input;
|
||||
Echonest::Artist artist( requestData.input.toString() );
|
||||
QNetworkReply* reply = artist.fetchFamiliarity();
|
||||
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
connect( reply, SIGNAL( finished() ), SLOT( getArtistFamiliaritySlot() ) );
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::getArtistHotttnesss( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
EchoNestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
{
|
||||
if( !isValidArtistData( requestId, requestData ) )
|
||||
if( !isValidArtistData( requestData ) )
|
||||
return;
|
||||
|
||||
Echonest::Artist artist( requestData.input.toString() );
|
||||
QNetworkReply* reply = artist.fetchHotttnesss();
|
||||
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
connect( reply, SIGNAL( finished() ), SLOT( getArtistHotttnesssSlot() ) );
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::getArtistTerms( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
EchoNestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
{
|
||||
if( !isValidArtistData( requestId, requestData ) )
|
||||
if( !isValidArtistData( requestData ) )
|
||||
return;
|
||||
|
||||
Echonest::Artist artist( requestData.input.toString() );
|
||||
QNetworkReply* reply = artist.fetchTerms( Echonest::Artist::Weight );
|
||||
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
connect( reply, SIGNAL( finished() ), SLOT( getArtistTermsSlot() ) );
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::getMiscTopTerms( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
EchoNestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
{
|
||||
QNetworkReply* reply = Echonest::Artist::topTerms( 20 );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
connect( reply, SIGNAL( finished() ), SLOT( getMiscTopSlot() ) );
|
||||
}
|
||||
@ -195,9 +190,7 @@ EchoNestPlugin::getArtistBiographySlot()
|
||||
biographyMap[ biography.site() ] = siteData;
|
||||
}
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
emit info( reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
biographyMap );
|
||||
emit info( requestData, biographyMap );
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
@ -208,9 +201,7 @@ EchoNestPlugin::getArtistFamiliaritySlot()
|
||||
Echonest::Artist artist = artistFromReply( reply );
|
||||
qreal familiarity = artist.familiarity();
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
emit info( reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
familiarity );
|
||||
emit info( requestData, familiarity );
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
@ -221,9 +212,7 @@ EchoNestPlugin::getArtistHotttnesssSlot()
|
||||
Echonest::Artist artist = artistFromReply( reply );
|
||||
qreal hotttnesss = artist.hotttnesss();
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
emit info( reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
hotttnesss );
|
||||
emit info( requestData, hotttnesss );
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
@ -241,9 +230,7 @@ EchoNestPlugin::getArtistTermsSlot()
|
||||
termsMap[ term.name() ] = termHash;
|
||||
}
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
emit info( reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
termsMap );
|
||||
emit info( requestData, termsMap );
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
@ -260,46 +247,44 @@ EchoNestPlugin::getMiscTopSlot()
|
||||
termsMap[ term.name() ] = termHash;
|
||||
}
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
emit info( reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
termsMap );
|
||||
emit info( requestData, termsMap );
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
bool
|
||||
EchoNestPlugin::isValidArtistData( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
EchoNestPlugin::isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
{
|
||||
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return false;
|
||||
}
|
||||
QString artistName = requestData.input.toString();
|
||||
if ( artistName.isEmpty() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EchoNestPlugin::isValidTrackData( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
EchoNestPlugin::isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
{
|
||||
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return false;
|
||||
}
|
||||
QString trackName = requestData.input.toString();
|
||||
if ( trackName.isEmpty() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return false;
|
||||
}
|
||||
if ( !requestData.customData.contains( "artistName" ) || requestData.customData[ "artistName" ].toString().isEmpty() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
virtual ~EchoNestPlugin();
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data )
|
||||
{
|
||||
@ -55,9 +55,8 @@ protected slots:
|
||||
Q_UNUSED( data );
|
||||
}
|
||||
|
||||
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
@ -66,15 +65,15 @@ public slots:
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
private:
|
||||
void getSongProfile( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData, const QString &item = QString() );
|
||||
void getArtistBiography( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getArtistFamiliarity( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getArtistHotttnesss( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getArtistTerms( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getMiscTopTerms( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getSongProfile( const Tomahawk::InfoSystem::InfoRequestData &requestData, const QString &item = QString() );
|
||||
void getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
void getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
|
||||
bool isValidArtistData( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
bool isValidTrackData( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
bool isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
bool isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &requestData );
|
||||
Echonest::Artist artistFromReply( QNetworkReply* );
|
||||
|
||||
private slots:
|
||||
|
420
src/libtomahawk/infosystem/infoplugins/generic/hypemPlugin.cpp
Normal file
@ -0,0 +1,420 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Hugo Lindström <hugolm84@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "hypemPlugin.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QCryptographicHash>
|
||||
#include <QNetworkConfiguration>
|
||||
#include <QNetworkReply>
|
||||
#include <QDomElement>
|
||||
|
||||
#include "album.h"
|
||||
#include "typedefs.h"
|
||||
#include "audio/audioengine.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
#define HYPEM_URL "http://hypem.com/playlist/"
|
||||
#define HYPEM_END_URL "json/1/data.js"
|
||||
#include <qjson/parser.h>
|
||||
#include <qjson/serializer.h>
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
|
||||
hypemPlugin::hypemPlugin()
|
||||
: InfoPlugin()
|
||||
, m_chartsFetchJobs( 0 )
|
||||
{
|
||||
|
||||
m_supportedGetTypes << InfoChart << InfoChartCapabilities;
|
||||
m_types << "Artists" << "Tracks" << "Recent by Tag";
|
||||
|
||||
m_trackTypes << "Last 3 Days"
|
||||
<< "Last Week"
|
||||
<< "No Remixes"
|
||||
<< "On Twitter";
|
||||
|
||||
m_byTagTypes << "Dance"
|
||||
<< "Experimental"
|
||||
<< "Electronic"
|
||||
<< "Funk"
|
||||
<< "Hip-hop"
|
||||
<< "Indie"
|
||||
<< "Instrumental"
|
||||
<< "Post-punk"
|
||||
<< "Rock"
|
||||
<< "Singer-songwriter"
|
||||
<< "Alternative"
|
||||
<< "Pop"
|
||||
<< "Female"
|
||||
<< "Vocalist"
|
||||
<< "Folk"
|
||||
<< "Electro"
|
||||
<< "Lo-fi"
|
||||
<< "Psychedelic"
|
||||
<< "Rap"
|
||||
<< "British"
|
||||
<< "Ambient"
|
||||
<< "Dubstep"
|
||||
<< "House"
|
||||
<< "Chillwave"
|
||||
<< "Dreampop"
|
||||
<< "Shoegaze"
|
||||
<< "Chillout"
|
||||
<< "Soul"
|
||||
<< "French"
|
||||
<< "Acoustic"
|
||||
<< "Canadian"
|
||||
<< "60s"
|
||||
<< "80s"
|
||||
<< "Techno"
|
||||
<< "Punk"
|
||||
<< "New wave";
|
||||
chartTypes();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
hypemPlugin::~hypemPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hypemPlugin::namChangedSlot( QNetworkAccessManager *nam )
|
||||
{
|
||||
tDebug() << "hypemPlugin: namChangedSLot";
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if( !nam )
|
||||
return;
|
||||
|
||||
m_nam = QWeakPointer< QNetworkAccessManager >( nam );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hypemPlugin::dataError( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hypemPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << requestData.caller;
|
||||
qDebug() << Q_FUNC_INFO << requestData.customData;
|
||||
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
|
||||
|
||||
switch ( requestData.type )
|
||||
{
|
||||
|
||||
case InfoChart:
|
||||
if ( !hash.contains( "chart_source" ) || hash["chart_source"].toLower() != "hype machine" )
|
||||
{
|
||||
dataError( requestData );
|
||||
break;
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << "InfoCHart req for" << hash["chart_source"];
|
||||
fetchChart( requestData );
|
||||
break;
|
||||
|
||||
case InfoChartCapabilities:
|
||||
fetchChartCapabilities( requestData );
|
||||
break;
|
||||
default:
|
||||
dataError( requestData );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hypemPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
|
||||
{
|
||||
Q_UNUSED( caller )
|
||||
Q_UNUSED( type)
|
||||
Q_UNUSED( input )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hypemPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
|
||||
/// Each request needs to contain both a id and source
|
||||
if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
|
||||
}
|
||||
/// Set the criterias for current chart
|
||||
criteria["chart_id"] = hash["chart_id"];
|
||||
criteria["chart_source"] = hash["chart_source"];
|
||||
|
||||
emit getCachedInfo( criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
hypemPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
emit getCachedInfo( criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
hypemPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !m_nam.data() )
|
||||
{
|
||||
tLog() << "Have a null QNAM, uh oh";
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoChart:
|
||||
{
|
||||
/// Fetch the chart, we need source and id
|
||||
|
||||
QUrl url = QUrl( QString( HYPEM_URL "%1/%2" ).arg( criteria["chart_id"].toLower() ).arg(HYPEM_END_URL) );
|
||||
qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
|
||||
|
||||
QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
|
||||
case InfoChartCapabilities:
|
||||
{
|
||||
if ( m_chartsFetchJobs > 0 )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
|
||||
m_cachedRequests.append( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
emit info( requestData, m_allChartsMap );
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Couldn't figure out what to do with this type of request after cache miss";
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hypemPlugin::chartTypes()
|
||||
{
|
||||
/// Get possible chart type for specifichypemPlugin: InfoChart types returned chart source
|
||||
tDebug() << Q_FUNC_INFO << "Got hypem types";
|
||||
|
||||
QVariantMap charts;
|
||||
|
||||
foreach(QVariant types, m_types )
|
||||
{
|
||||
QList< InfoStringHash > chart_types;
|
||||
QList< InfoStringHash > pop_charts;
|
||||
InfoStringHash c;
|
||||
|
||||
if(types.toString() != "Artists")
|
||||
{
|
||||
|
||||
if(types.toString() == "Tracks")
|
||||
{
|
||||
|
||||
foreach(QVariant trackType, m_trackTypes)
|
||||
{
|
||||
QString typeId;
|
||||
if(trackType.toString() == "Last 3 Days")
|
||||
typeId = "popular/3day";
|
||||
|
||||
if(trackType.toString() == "Last Week")
|
||||
typeId = "popular/lastweek";
|
||||
|
||||
if(trackType.toString() == "No Remixes")
|
||||
typeId = "popular/noremix";
|
||||
|
||||
if(trackType.toString() == "On Twitter")
|
||||
typeId = "popular/twitter";
|
||||
|
||||
c[ "id" ] = typeId;
|
||||
c[ "label" ] = trackType.toString();
|
||||
c[ "type" ] = "tracks";
|
||||
pop_charts.append( c );
|
||||
}
|
||||
|
||||
chart_types.append( pop_charts );
|
||||
|
||||
}
|
||||
else if(types.toString() == "Recent by Tag")
|
||||
{
|
||||
foreach(QVariant tagTypes, m_byTagTypes)
|
||||
{
|
||||
|
||||
c[ "id" ] = "tags/" + tagTypes.toString().toLower();
|
||||
c[ "label" ] = tagTypes.toString();
|
||||
c[ "type" ] = tagTypes.toString();
|
||||
chart_types.append( c );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}else
|
||||
{
|
||||
InfoStringHash c;
|
||||
c[ "id" ] = "popular/artists";
|
||||
c[ "label" ] = "Most Recent";
|
||||
c[ "type" ] = "artists";
|
||||
chart_types.append( c );
|
||||
}
|
||||
|
||||
charts.insert( types.toString(), QVariant::fromValue<QList< InfoStringHash > >( chart_types ) );
|
||||
}
|
||||
|
||||
|
||||
m_allChartsMap.insert( "Hype Machine", QVariant::fromValue<QVariantMap>( charts ) );
|
||||
qDebug() << "hypemPlugin:Chartstype: " << m_allChartsMap;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
hypemPlugin::chartReturned()
|
||||
{
|
||||
|
||||
/// Chart request returned something! Woho
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
QString url = reply->url().toString();
|
||||
QVariantMap returnedData;
|
||||
if ( reply->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QJson::Parser p;
|
||||
bool ok;
|
||||
QVariantMap res = p.parse( reply, &ok ).toMap();
|
||||
|
||||
if ( !ok )
|
||||
{
|
||||
tLog() << "Failed to parse json from chart lookup:" << p.errorString() << "On line" << p.errorLine();
|
||||
return;
|
||||
}
|
||||
|
||||
/// SO we have a result, parse it!
|
||||
QList< InfoStringHash > top_tracks;
|
||||
QStringList top_artists;
|
||||
|
||||
if( url.contains( "artists" ) )
|
||||
setChartType( Artist );
|
||||
else
|
||||
setChartType( Track );
|
||||
|
||||
foreach(QVariant result, res )
|
||||
{
|
||||
QString title, artist;
|
||||
QVariantMap chartMap = result.toMap();
|
||||
|
||||
if ( !chartMap.isEmpty() )
|
||||
{
|
||||
|
||||
title = chartMap.value( "title" ).toString();
|
||||
artist = chartMap.value( "artist" ).toString();
|
||||
|
||||
if( chartType() == Track )
|
||||
{
|
||||
InfoStringHash pair;
|
||||
pair["artist"] = artist;
|
||||
pair["track"] = title;
|
||||
top_tracks << pair;
|
||||
|
||||
qDebug() << "HypemChart type is track";
|
||||
}
|
||||
|
||||
|
||||
if( chartType() == Artist )
|
||||
{
|
||||
|
||||
top_artists << artist;
|
||||
qDebug() << "HypemChart type is artist";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( chartType() == Track )
|
||||
{
|
||||
tDebug() << "HypemPlugin:" << "\tgot " << top_tracks.size() << " tracks";
|
||||
returnedData["tracks"] = QVariant::fromValue( top_tracks );
|
||||
returnedData["type"] = "tracks";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( chartType() == Artist )
|
||||
{
|
||||
tDebug() << "HypemPlugin:" << "\tgot " << top_artists.size() << " artists";
|
||||
returnedData["artists"] = top_artists;
|
||||
returnedData["type"] = "artists";
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
|
||||
emit info( requestData, returnedData );
|
||||
// TODO update cache
|
||||
}
|
||||
else
|
||||
qDebug() << "Network error in fetching chart:" << reply->url().toString();
|
||||
|
||||
}
|
93
src/libtomahawk/infosystem/infoplugins/generic/hypemPlugin.h
Normal file
@ -0,0 +1,93 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Hugo Lindström <hugolm84@gmail.com>
|
||||
*
|
||||
* 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 hypemPlugin_H
|
||||
#define hypemPlugin_H
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "infosystem/infosystemworker.h"
|
||||
#include <QNetworkReply>
|
||||
#include <QObject>
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
class hypemPlugin : public InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
hypemPlugin();
|
||||
virtual ~hypemPlugin();
|
||||
|
||||
enum ChartType {
|
||||
None = 0x00,
|
||||
Track = 0x01,
|
||||
Album = 0x02,
|
||||
Artist = 0x04
|
||||
|
||||
};
|
||||
void setChartType( ChartType type ) { m_chartType = type; }
|
||||
ChartType chartType() const { return m_chartType; }
|
||||
|
||||
public slots:
|
||||
void chartReturned();
|
||||
void chartTypes();
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
|
||||
|
||||
private:
|
||||
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
QVariantList m_chartResources;
|
||||
QList<InfoStringHash> m_charts;
|
||||
|
||||
|
||||
ChartType m_chartType;
|
||||
QVariantMap m_allChartsMap;
|
||||
QVariantList m_types;
|
||||
QVariantList m_popularTypes;
|
||||
QVariantList m_trackTypes;
|
||||
QVariantList m_byTagTypes;
|
||||
|
||||
|
||||
uint m_chartsFetchJobs;
|
||||
QList< InfoRequestData > m_cachedRequests;
|
||||
|
||||
QHash< QString, QString > m_cachedCountries;
|
||||
|
||||
QWeakPointer< QNetworkAccessManager > m_nam;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // hypemPlugin_H
|
@ -123,43 +123,43 @@ LastFmPlugin::namChangedSlot( QNetworkAccessManager *nam )
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::dataError( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::dataError( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoArtistImages:
|
||||
fetchArtistImages( requestId, requestData );
|
||||
fetchArtistImages( requestData );
|
||||
break;
|
||||
|
||||
case InfoAlbumCoverArt:
|
||||
fetchCoverArt( requestId, requestData );
|
||||
fetchCoverArt( requestData );
|
||||
break;
|
||||
|
||||
case InfoArtistSimilars:
|
||||
fetchSimilarArtists( requestId, requestData );
|
||||
fetchSimilarArtists( requestData );
|
||||
break;
|
||||
|
||||
case InfoArtistSongs:
|
||||
fetchTopTracks( requestId, requestData );
|
||||
fetchTopTracks( requestData );
|
||||
break;
|
||||
|
||||
case InfoChart:
|
||||
fetchChart( requestId, requestData );
|
||||
fetchChart( requestData );
|
||||
break;
|
||||
|
||||
case InfoChartCapabilities:
|
||||
fetchChartCapabilities( requestId, requestData );
|
||||
fetchChartCapabilities( requestData );
|
||||
break;
|
||||
default:
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,95 +267,95 @@ LastFmPlugin::sendLoveSong( const InfoType type, QVariant input )
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchSimilarArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::fetchSimilarArtists( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "artist" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = hash["artist"];
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
|
||||
emit getCachedInfo( criteria, 2419200000, requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::fetchTopTracks( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "artist" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = hash["artist"];
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
|
||||
emit getCachedInfo( criteria, 2419200000, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchChart( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
if ( !hash.contains( "chart_id" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
} else {
|
||||
criteria["chart_id"] = hash["chart_id"];
|
||||
}
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 0, requestData );
|
||||
emit getCachedInfo( criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchChartCapabilities( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 0, requestData );
|
||||
emit getCachedInfo( criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchCoverArt( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::fetchCoverArt( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "artist" ) || !hash.contains( "album" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -363,39 +363,39 @@ LastFmPlugin::fetchCoverArt( uint requestId, Tomahawk::InfoSystem::InfoRequestDa
|
||||
criteria["artist"] = hash["artist"];
|
||||
criteria["album"] = hash["album"];
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
|
||||
emit getCachedInfo( criteria, 2419200000, requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchArtistImages( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::fetchArtistImages( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "artist" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = hash["artist"];
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
|
||||
emit getCachedInfo( criteria, 2419200000, requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !lastfm::nam() )
|
||||
{
|
||||
tLog() << "Have a null QNAM, uh oh";
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -407,14 +407,14 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
/// We need something to check if the request is actually ment to go to this plugin
|
||||
if ( !hash.contains( "chart_source" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( "last.fm" != hash["chart_source"] )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
dataError( requestData );
|
||||
break;
|
||||
}
|
||||
|
||||
@ -425,7 +425,6 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
args["method"] = criteria["chart_id"];
|
||||
args["limit"] = "100";
|
||||
QNetworkReply* reply = lastfm::ws::get(args);
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
|
||||
@ -466,11 +465,7 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
result.insert( "Last.fm", QVariant::fromValue<QVariantMap>( charts ) );
|
||||
|
||||
tDebug() << "LASTFM RETURNING CHART LIST!";
|
||||
emit info(
|
||||
requestId,
|
||||
requestData,
|
||||
result
|
||||
);
|
||||
emit info( requestData, result );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -478,7 +473,6 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
{
|
||||
lastfm::Artist a( criteria["artist"] );
|
||||
QNetworkReply* reply = a.getSimilar();
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( similarArtistsReturned() ) );
|
||||
@ -489,7 +483,6 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
{
|
||||
lastfm::Artist a( criteria["artist"] );
|
||||
QNetworkReply* reply = a.getTopTracks();
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( topTracksReturned() ) );
|
||||
@ -504,7 +497,6 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=album.imageredirect&artist=%1&album=%2&autocorrect=1&size=large&api_key=7a90f6672a04b809ee309af169f34b8b";
|
||||
QNetworkRequest req( imgurl.arg( artistName ).arg( albumName ) );
|
||||
QNetworkReply* reply = lastfm::nam()->get( req );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( coverArtReturned() ) );
|
||||
@ -518,7 +510,6 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=artist.imageredirect&artist=%1&autocorrect=1&size=large&api_key=7a90f6672a04b809ee309af169f34b8b";
|
||||
QNetworkRequest req( imgurl.arg( artistName ) );
|
||||
QNetworkReply* reply = lastfm::nam()->get( req );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( artistImagesReturned() ) );
|
||||
@ -528,7 +519,7 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
default:
|
||||
{
|
||||
tLog() << "Couldn't figure out what to do with this type of request after cache miss";
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -553,11 +544,7 @@ LastFmPlugin::similarArtistsReturned()
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info(
|
||||
reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
returnedData
|
||||
);
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
@ -609,11 +596,7 @@ LastFmPlugin::chartReturned()
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info(
|
||||
reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
returnedData
|
||||
);
|
||||
emit info( requestData, returnedData );
|
||||
// TODO update cache
|
||||
}
|
||||
|
||||
@ -629,11 +612,7 @@ LastFmPlugin::topTracksReturned()
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info(
|
||||
reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
returnedData
|
||||
);
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
@ -653,7 +632,7 @@ LastFmPlugin::coverArtReturned()
|
||||
if ( ba.isNull() || !ba.length() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Uh oh, null byte array";
|
||||
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
foreach ( const QUrl& url, m_badUrls )
|
||||
@ -668,11 +647,7 @@ LastFmPlugin::coverArtReturned()
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info(
|
||||
reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
returnedData
|
||||
);
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
@ -685,13 +660,12 @@ LastFmPlugin::coverArtReturned()
|
||||
if ( !lastfm::nam() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Uh oh, nam is null";
|
||||
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
// Follow HTTP redirect
|
||||
QNetworkRequest req( redir );
|
||||
QNetworkReply* newReply = lastfm::nam()->get( req );
|
||||
newReply->setProperty( "requestId", reply->property( "requestId" ) );
|
||||
newReply->setProperty( "requestData", reply->property( "requestData" ) );
|
||||
connect( newReply, SIGNAL( finished() ), SLOT( coverArtReturned() ) );
|
||||
}
|
||||
@ -711,7 +685,7 @@ LastFmPlugin::artistImagesReturned()
|
||||
if ( ba.isNull() || !ba.length() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Uh oh, null byte array";
|
||||
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
foreach ( const QUrl& url, m_badUrls )
|
||||
@ -725,7 +699,7 @@ LastFmPlugin::artistImagesReturned()
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info( reply->property( "requestId" ).toUInt(), requestData, returnedData );
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
@ -737,13 +711,12 @@ LastFmPlugin::artistImagesReturned()
|
||||
if ( !lastfm::nam() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Uh oh, nam is null";
|
||||
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
// Follow HTTP redirect
|
||||
QNetworkRequest req( redir );
|
||||
QNetworkReply* newReply = lastfm::nam()->get( req );
|
||||
newReply->setProperty( "requestId", reply->property( "requestId" ) );
|
||||
newReply->setProperty( "requestData", reply->property( "requestData" ) );
|
||||
connect( newReply, SIGNAL( finished() ), SLOT( artistImagesReturned() ) );
|
||||
}
|
||||
|
@ -56,25 +56,25 @@ public slots:
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
|
||||
|
||||
private:
|
||||
void fetchCoverArt( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchArtistImages( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchSimilarArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChart( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartCapabilities( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchCoverArt( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchArtistImages( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchSimilarArtists( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchTopTracks( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
void createScrobbler();
|
||||
void nowPlaying( const QVariant &input );
|
||||
void scrobble();
|
||||
void sendLoveSong( const InfoType type, QVariant input );
|
||||
|
||||
void dataError( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
QList<lastfm::Track> parseTrackList( QNetworkReply * reply );
|
||||
|
||||
|
@ -50,31 +50,64 @@ MusicBrainzPlugin::namChangedSlot( QNetworkAccessManager *nam )
|
||||
m_nam = QWeakPointer< QNetworkAccessManager >( nam );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MusicBrainzPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
MusicBrainzPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "artist" ) )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoArtistReleases:
|
||||
{
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = hash["artist"];
|
||||
|
||||
emit getCachedInfo( criteria, 2419200000, requestData );
|
||||
break;
|
||||
}
|
||||
|
||||
case InfoAlbumSongs:
|
||||
{
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = hash["artist"];
|
||||
criteria["album"] = hash["album"];
|
||||
|
||||
emit getCachedInfo( criteria, 2419200000, requestData );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Q_ASSERT( false );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MusicBrainzPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requestData )
|
||||
{
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoArtistReleases:
|
||||
{
|
||||
QString requestString( "http://musicbrainz.org/ws/2/artist" );
|
||||
QUrl url( requestString );
|
||||
url.addQueryItem( "query", hash["artist"] );
|
||||
url.addQueryItem( "query", criteria["artist"] );
|
||||
QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( artistSearchSlot() ) );
|
||||
@ -85,9 +118,8 @@ MusicBrainzPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestDat
|
||||
{
|
||||
QString requestString( "http://musicbrainz.org/ws/2/artist" );
|
||||
QUrl url( requestString );
|
||||
url.addQueryItem( "query", hash["artist"] );
|
||||
url.addQueryItem( "query", criteria["artist"] );
|
||||
QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( albumSearchSlot() ) );
|
||||
@ -104,24 +136,24 @@ MusicBrainzPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestDat
|
||||
|
||||
|
||||
bool
|
||||
MusicBrainzPlugin::isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
MusicBrainzPlugin::isValidTrackData( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QVariantMap >() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
qDebug() << Q_FUNC_INFO << "Data null, invalid, or can't convert";
|
||||
return false;
|
||||
}
|
||||
QVariantMap hash = requestData.input.value< QVariantMap >();
|
||||
if ( hash[ "trackName" ].toString().isEmpty() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
qDebug() << Q_FUNC_INFO << "Track name is empty";
|
||||
return false;
|
||||
}
|
||||
if ( hash[ "artistName" ].toString().isEmpty() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
qDebug() << Q_FUNC_INFO << "No artist name found";
|
||||
return false;
|
||||
}
|
||||
@ -141,7 +173,7 @@ MusicBrainzPlugin::artistSearchSlot()
|
||||
QDomNodeList domNodeList = doc.elementsByTagName( "artist" );
|
||||
if ( domNodeList.isEmpty() )
|
||||
{
|
||||
emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -151,7 +183,6 @@ MusicBrainzPlugin::artistSearchSlot()
|
||||
url.addQueryItem( "artist", artist_id );
|
||||
|
||||
QNetworkReply* newReply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
newReply->setProperty( "requestId", oldReply->property( "requestId" ) );
|
||||
newReply->setProperty( "requestData", oldReply->property( "requestData" ) );
|
||||
connect( newReply, SIGNAL( finished() ), SLOT( albumFoundSlot() ) );
|
||||
}
|
||||
@ -169,7 +200,7 @@ MusicBrainzPlugin::albumSearchSlot()
|
||||
QDomNodeList domNodeList = doc.elementsByTagName( "artist" );
|
||||
if ( domNodeList.isEmpty() )
|
||||
{
|
||||
emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -179,7 +210,6 @@ MusicBrainzPlugin::albumSearchSlot()
|
||||
url.addQueryItem( "artist", artist_id );
|
||||
|
||||
QNetworkReply* newReply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
newReply->setProperty( "requestId", oldReply->property( "requestId" ) );
|
||||
newReply->setProperty( "requestData", oldReply->property( "requestData" ) );
|
||||
connect( newReply, SIGNAL( finished() ), SLOT( tracksSearchSlot() ) );
|
||||
}
|
||||
@ -197,7 +227,7 @@ MusicBrainzPlugin::tracksSearchSlot()
|
||||
QDomNodeList domNodeList = doc.elementsByTagName( "release" );
|
||||
if ( domNodeList.isEmpty() )
|
||||
{
|
||||
emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -214,7 +244,7 @@ MusicBrainzPlugin::tracksSearchSlot()
|
||||
|
||||
if ( element.isNull() )
|
||||
{
|
||||
emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -223,7 +253,6 @@ MusicBrainzPlugin::tracksSearchSlot()
|
||||
QUrl url( requestString );
|
||||
|
||||
QNetworkReply* newReply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
newReply->setProperty( "requestId", oldReply->property( "requestId" ) );
|
||||
newReply->setProperty( "requestData", oldReply->property( "requestData" ) );
|
||||
connect( newReply, SIGNAL( finished() ), SLOT( tracksFoundSlot() ) );
|
||||
}
|
||||
@ -241,7 +270,7 @@ MusicBrainzPlugin::albumFoundSlot()
|
||||
QDomNodeList domNodeList = doc.elementsByTagName( "title" );
|
||||
if ( domNodeList.isEmpty() )
|
||||
{
|
||||
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -256,7 +285,7 @@ MusicBrainzPlugin::albumFoundSlot()
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
QVariantMap returnedData;
|
||||
returnedData["albums"] = albums;
|
||||
emit info( reply->property( "requestId" ).toUInt(), requestData, returnedData );
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
@ -277,7 +306,7 @@ MusicBrainzPlugin::tracksFoundSlot()
|
||||
QDomNodeList domNodeList = doc.elementsByTagName( "recording" );
|
||||
if ( domNodeList.isEmpty() )
|
||||
{
|
||||
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -297,7 +326,7 @@ MusicBrainzPlugin::tracksFoundSlot()
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
QVariantMap returnedData;
|
||||
returnedData["tracks"] = tracks;
|
||||
emit info( reply->property( "requestId" ).toUInt(), requestData, returnedData );
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
|
@ -42,7 +42,8 @@ public slots:
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( InfoStringHash criteria, InfoRequestData requestData );
|
||||
|
||||
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data )
|
||||
{
|
||||
@ -51,12 +52,6 @@ protected slots:
|
||||
Q_UNUSED( data );
|
||||
}
|
||||
|
||||
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
||||
private slots:
|
||||
void artistSearchSlot();
|
||||
@ -67,7 +62,7 @@ private slots:
|
||||
void tracksFoundSlot();
|
||||
|
||||
private:
|
||||
bool isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
bool isValidTrackData( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
QWeakPointer< QNetworkAccessManager > m_nam;
|
||||
};
|
||||
|
@ -53,17 +53,17 @@ MusixMatchPlugin::namChangedSlot( QNetworkAccessManager *nam )
|
||||
}
|
||||
|
||||
void
|
||||
MusixMatchPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
MusixMatchPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if( !isValidTrackData( requestId, requestData ) || !requestData.input.canConvert< QVariantMap >() || m_nam.isNull() || requestData.type != Tomahawk::InfoSystem::InfoTrackLyrics )
|
||||
if( !isValidTrackData( requestData ) || !requestData.input.canConvert< QVariantMap >() || m_nam.isNull() || requestData.type != Tomahawk::InfoSystem::InfoTrackLyrics )
|
||||
return;
|
||||
QVariantMap hash = requestData.input.value< QVariantMap >();
|
||||
QString artist = hash["artistName"].toString();
|
||||
QString track = hash["trackName"].toString();
|
||||
if( artist.isEmpty() || track.isEmpty() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
qDebug() << "artist is " << artist << ", track is " << track;
|
||||
@ -73,32 +73,31 @@ MusixMatchPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData
|
||||
url.addQueryItem( "q_artist", artist );
|
||||
url.addQueryItem( "q_track", track );
|
||||
QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( trackSearchSlot() ) );
|
||||
}
|
||||
|
||||
bool
|
||||
MusixMatchPlugin::isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
MusixMatchPlugin::isValidTrackData( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QVariantMap >() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
qDebug() << "MusixMatchPlugin::isValidTrackData: Data null, invalid, or can't convert";
|
||||
return false;
|
||||
}
|
||||
QVariantMap hash = requestData.input.value< QVariantMap >();
|
||||
if ( hash[ "trackName" ].toString().isEmpty() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
qDebug() << "MusixMatchPlugin::isValidTrackData: Track name is empty";
|
||||
return false;
|
||||
}
|
||||
if ( hash[ "artistName" ].toString().isEmpty() )
|
||||
{
|
||||
emit info( requestId, requestData, QVariant() );
|
||||
emit info( requestData, QVariant() );
|
||||
qDebug() << "MusixMatchPlugin::isValidTrackData: No artist name found";
|
||||
return false;
|
||||
}
|
||||
@ -119,7 +118,7 @@ MusixMatchPlugin::trackSearchSlot()
|
||||
QDomNodeList domNodeList = doc.elementsByTagName("track_id");
|
||||
if ( domNodeList.isEmpty() )
|
||||
{
|
||||
emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
QString track_id = domNodeList.at(0).toElement().text();
|
||||
@ -128,7 +127,6 @@ MusixMatchPlugin::trackSearchSlot()
|
||||
url.addQueryItem( "apikey", m_apiKey );
|
||||
url.addQueryItem( "track_id", track_id );
|
||||
QNetworkReply* newReply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
newReply->setProperty( "requestId", oldReply->property( "requestId" ) );
|
||||
newReply->setProperty( "requestData", oldReply->property( "requestData" ) );
|
||||
connect( newReply, SIGNAL( finished() ), SLOT( trackLyricsSlot() ) );
|
||||
}
|
||||
@ -146,10 +144,10 @@ MusixMatchPlugin::trackLyricsSlot()
|
||||
QDomNodeList domNodeList = doc.elementsByTagName( "lyrics_body" );
|
||||
if ( domNodeList.isEmpty() )
|
||||
{
|
||||
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
|
||||
return;
|
||||
}
|
||||
QString lyrics = domNodeList.at(0).toElement().text();
|
||||
qDebug() << "Emitting lyrics: " << lyrics;
|
||||
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant( lyrics ) );
|
||||
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant( lyrics ) );
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public slots:
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data )
|
||||
{
|
||||
@ -54,15 +54,14 @@ protected slots:
|
||||
Q_UNUSED( data );
|
||||
}
|
||||
|
||||
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
||||
private:
|
||||
bool isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
bool isValidTrackData( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
QString m_apiKey;
|
||||
|
||||
|
410
src/libtomahawk/infosystem/infoplugins/generic/spotifyPlugin.cpp
Normal file
@ -0,0 +1,410 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Hugo Lindström <hugolm84@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "spotifyPlugin.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QCryptographicHash>
|
||||
#include <QNetworkConfiguration>
|
||||
#include <QNetworkReply>
|
||||
#include <QDomElement>
|
||||
|
||||
#include "album.h"
|
||||
#include "typedefs.h"
|
||||
#include "audio/audioengine.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include "chartsplugin_data_p.h"
|
||||
|
||||
#define SPOTIFY_API_URL "http://spotikea.tomahawk-player.org:10380/"
|
||||
#include <qjson/parser.h>
|
||||
#include <qjson/serializer.h>
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
|
||||
SpotifyPlugin::SpotifyPlugin()
|
||||
: InfoPlugin()
|
||||
, m_chartsFetchJobs( 0 )
|
||||
{
|
||||
|
||||
m_supportedGetTypes << InfoChart << InfoChartCapabilities;
|
||||
|
||||
}
|
||||
|
||||
|
||||
SpotifyPlugin::~SpotifyPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyPlugin::namChangedSlot( QNetworkAccessManager *nam )
|
||||
{
|
||||
tDebug() << "SpotifyPlugin: namChangedSLot";
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if( !nam )
|
||||
return;
|
||||
|
||||
m_nam = QWeakPointer< QNetworkAccessManager >( nam );
|
||||
|
||||
// we never need to re-fetch
|
||||
if ( !m_allChartsMap.isEmpty() )
|
||||
return;
|
||||
|
||||
/// We need to fetch possible types before they are asked for
|
||||
tDebug() << "SpotifyPlugin: InfoChart fetching possible resources";
|
||||
|
||||
QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/charts" ) );
|
||||
QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
tDebug() << Q_FUNC_INFO << "fetching:" << url;
|
||||
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
|
||||
m_chartsFetchJobs++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyPlugin::dataError( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << requestData.caller;
|
||||
qDebug() << Q_FUNC_INFO << requestData.customData;
|
||||
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
|
||||
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoChart:
|
||||
if ( !hash.contains( "chart_source" ) || hash["chart_source"] != "spotify" )
|
||||
{
|
||||
dataError( requestData );
|
||||
break;
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << "InfoCHart req for" << hash["chart_source"];
|
||||
fetchChart( requestData );
|
||||
break;
|
||||
|
||||
case InfoChartCapabilities:
|
||||
fetchChartCapabilities( requestData );
|
||||
break;
|
||||
default:
|
||||
dataError( requestData );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
|
||||
{
|
||||
Q_UNUSED( caller )
|
||||
Q_UNUSED( type)
|
||||
Q_UNUSED( input )
|
||||
}
|
||||
|
||||
void
|
||||
SpotifyPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
if ( !hash.contains( "chart_id" ) )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
} else {
|
||||
criteria["chart_id"] = hash["chart_id"];
|
||||
}
|
||||
|
||||
emit getCachedInfo( criteria, 604800000 /* Expire chart cache in 1 week */, requestData );
|
||||
}
|
||||
void
|
||||
SpotifyPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
emit getCachedInfo( criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
SpotifyPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !m_nam.data() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Have a null QNAM, uh oh";
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch ( requestData.type )
|
||||
{
|
||||
|
||||
case InfoChart:
|
||||
{
|
||||
/// Fetch the chart, we need source and id
|
||||
QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/%1/" ).arg( criteria["chart_id"] ) );
|
||||
qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
|
||||
|
||||
QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
case InfoChartCapabilities:
|
||||
{
|
||||
if ( m_chartsFetchJobs > 0 )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
|
||||
m_cachedRequests.append( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
emit info( requestData, m_allChartsMap );
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Couldn't figure out what to do with this type of request after cache miss";
|
||||
emit info( requestData, QVariant() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyPlugin::chartTypes()
|
||||
{
|
||||
/// Get possible chart type for specificSpotifyPlugin: InfoChart types returned chart source
|
||||
tDebug() << Q_FUNC_INFO << "Got spotifychart type result";
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
|
||||
if ( reply->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QJson::Parser p;
|
||||
bool ok;
|
||||
const QVariantMap res = p.parse( reply, &ok ).toMap();
|
||||
const QVariantMap chartObj = res;
|
||||
|
||||
if ( !ok )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Failed to parse resources" << p.errorString() << "On line" << p.errorLine();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap charts;
|
||||
foreach(QVariant geos, chartObj.value("Charts").toList().takeLast().toMap().value("geo").toList() )
|
||||
{
|
||||
|
||||
const QString geo = geos.toMap().value( "name" ).toString();
|
||||
const QString geoId = geos.toMap().value( "id" ).toString();
|
||||
QString country;
|
||||
|
||||
if( geo == "For me" )
|
||||
continue; /// country = geo; Lets use this later, when we can get the spotify username from tomahawk
|
||||
else if( geo == "Everywhere" )
|
||||
country = geo;
|
||||
else
|
||||
{
|
||||
|
||||
QLocale l( QString( "en_%1" ).arg( geo ) );
|
||||
country = Tomahawk::CountryUtils::fullCountryFromCode( geo );
|
||||
|
||||
for ( int i = 1; i < country.size(); i++ )
|
||||
{
|
||||
if ( country.at( i ).isUpper() )
|
||||
{
|
||||
country.insert( i, " " );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList< InfoStringHash > chart_types;
|
||||
foreach(QVariant types, chartObj.value("Charts").toList().takeFirst().toMap().value("types").toList() )
|
||||
{
|
||||
QString type = types.toMap().value( "id" ).toString();
|
||||
QString label = types.toMap().value( "name" ).toString();
|
||||
|
||||
InfoStringHash c;
|
||||
c[ "id" ] = type + "/" + geoId;
|
||||
c[ "label" ] = label;
|
||||
c[ "type" ] = type;
|
||||
|
||||
chart_types.append( c );
|
||||
|
||||
}
|
||||
|
||||
charts.insert( country.toUtf8(), QVariant::fromValue<QList< InfoStringHash > >( chart_types ) );
|
||||
|
||||
}
|
||||
|
||||
QVariantMap defaultMap;
|
||||
defaultMap[ "spotify" ] = QStringList() << "United States" << "Top Albums";
|
||||
m_allChartsMap[ "defaults" ] = defaultMap;
|
||||
m_allChartsMap.insert( "Spotify", QVariant::fromValue<QVariantMap>( charts ) );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Error fetching charts:" << reply->errorString();
|
||||
}
|
||||
|
||||
m_chartsFetchJobs--;
|
||||
if ( !m_cachedRequests.isEmpty() && m_chartsFetchJobs == 0 )
|
||||
{
|
||||
foreach ( InfoRequestData request, m_cachedRequests )
|
||||
{
|
||||
emit info( request, m_allChartsMap );
|
||||
}
|
||||
m_cachedRequests.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
SpotifyPlugin::chartReturned()
|
||||
{
|
||||
|
||||
/// Chart request returned something! Woho
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
QString url = reply->url().toString();
|
||||
QVariantMap returnedData;
|
||||
if ( reply->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QJson::Parser p;
|
||||
bool ok;
|
||||
QVariantMap res = p.parse( reply, &ok ).toMap();
|
||||
|
||||
if ( !ok )
|
||||
{
|
||||
tLog() << "Failed to parse json from chart lookup:" << p.errorString() << "On line" << p.errorLine();
|
||||
return;
|
||||
}
|
||||
|
||||
/// SO we have a result, parse it!
|
||||
QList< InfoStringHash > top_tracks;
|
||||
QList< InfoStringHash > top_albums;
|
||||
QStringList top_artists;
|
||||
|
||||
if( url.contains( "albums" ) )
|
||||
setChartType( Album );
|
||||
else if( url.contains( "tracks" ) )
|
||||
setChartType( Track );
|
||||
else if( url.contains( "artists" ) )
|
||||
setChartType( Artist );
|
||||
else
|
||||
setChartType( None );
|
||||
|
||||
foreach(QVariant result, res.value("toplist").toMap().value("result").toList() )
|
||||
{
|
||||
QString title, artist;
|
||||
QVariantMap chartMap = result.toMap();
|
||||
|
||||
if ( !chartMap.isEmpty() )
|
||||
{
|
||||
|
||||
title = chartMap.value( "title" ).toString();
|
||||
artist = chartMap.value( "artist" ).toString();
|
||||
|
||||
if( chartType() == Track )
|
||||
{
|
||||
InfoStringHash pair;
|
||||
pair["artist"] = artist;
|
||||
pair["track"] = title;
|
||||
top_tracks << pair;
|
||||
|
||||
qDebug() << "SpotifyChart type is track";
|
||||
}
|
||||
|
||||
if( chartType() == Album )
|
||||
{
|
||||
|
||||
InfoStringHash pair;
|
||||
pair["artist"] = artist;
|
||||
pair["album"] = title;
|
||||
top_albums << pair;
|
||||
qDebug() << "SpotifyChart type is album";
|
||||
}
|
||||
|
||||
if( chartType() == Artist )
|
||||
{
|
||||
|
||||
top_artists << chartMap.value( "name" ).toString();
|
||||
qDebug() << "SpotifyChart type is artist";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( chartType() == Track )
|
||||
{
|
||||
tDebug() << "ChartsPlugin:" << "\tgot " << top_tracks.size() << " tracks";
|
||||
returnedData["tracks"] = QVariant::fromValue( top_tracks );
|
||||
returnedData["type"] = "tracks";
|
||||
}
|
||||
|
||||
if( chartType() == Album )
|
||||
{
|
||||
tDebug() << "ChartsPlugin:" << "\tgot " << top_albums.size() << " albums";
|
||||
returnedData["albums"] = QVariant::fromValue( top_albums );
|
||||
returnedData["type"] = "albums";
|
||||
}
|
||||
|
||||
if( chartType() == Artist )
|
||||
{
|
||||
tDebug() << "ChartsPlugin:" << "\tgot " << top_artists.size() << " artists";
|
||||
returnedData["artists"] = top_artists;
|
||||
returnedData["type"] = "artists";
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
}
|
||||
else
|
||||
qDebug() << "Network error in fetching chart:" << reply->url().toString();
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Hugo Lindström <hugolm84@gmail.com>
|
||||
*
|
||||
* 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 SpotifyPlugin_H
|
||||
#define SpotifyPlugin_H
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "infosystem/infosystemworker.h"
|
||||
#include <QNetworkReply>
|
||||
#include <QObject>
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
class SpotifyPlugin : public InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SpotifyPlugin();
|
||||
virtual ~SpotifyPlugin();
|
||||
|
||||
enum ChartType {
|
||||
None = 0x00,
|
||||
Track = 0x01,
|
||||
Album = 0x02,
|
||||
Artist = 0x04
|
||||
|
||||
};
|
||||
void setChartType( ChartType type ) { m_chartType = type; }
|
||||
ChartType chartType() const { return m_chartType; }
|
||||
|
||||
public slots:
|
||||
void chartReturned();
|
||||
void chartTypes();
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
|
||||
|
||||
private:
|
||||
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
|
||||
ChartType m_chartType;
|
||||
QVariantMap m_allChartsMap;
|
||||
uint m_chartsFetchJobs;
|
||||
QList< InfoRequestData > m_cachedRequests;
|
||||
QWeakPointer< QNetworkAccessManager > m_nam;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // SpotifyPlugin_H
|
@ -41,9 +41,8 @@ public:
|
||||
virtual ~AdiumPlugin();
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
||||
@ -52,9 +51,8 @@ protected slots:
|
||||
public slots:
|
||||
void namChangedSlot( QNetworkAccessManager* nam );
|
||||
|
||||
virtual void notInCacheSlot( uint requestId, const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
@ -38,17 +38,15 @@ public:
|
||||
virtual void namChangedSlot( QNetworkAccessManager* ) {}
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
||||
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant pushData );
|
||||
|
||||
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
@ -432,9 +432,8 @@ MprisPlugin::Stop()
|
||||
// InfoPlugin Methods
|
||||
|
||||
void
|
||||
MprisPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
MprisPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( requestData );
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
|
@ -119,9 +119,8 @@ public:
|
||||
public slots:
|
||||
void namChangedSlot( QNetworkAccessManager* /*nam*/ ) {} // unused
|
||||
|
||||
virtual void notInCacheSlot( uint requestId, const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
@ -143,7 +142,7 @@ public slots:
|
||||
|
||||
|
||||
protected slots:
|
||||
void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );
|
||||
|
||||
private slots:
|
||||
|
@ -74,12 +74,16 @@ InfoSystem::InfoSystem( QObject *parent )
|
||||
|
||||
connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( newNam() ) );
|
||||
|
||||
connect( m_cache.data(), SIGNAL( info( uint, Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
m_worker.data(), SLOT( infoSlot( uint, Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
connect( m_cache.data(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
m_worker.data(), SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
|
||||
connect( m_worker.data(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
this, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
|
||||
connect( m_worker.data(), SIGNAL( finished( QString ) ), this, SIGNAL( finished( QString ) ), Qt::UniqueConnection );
|
||||
|
||||
connect( m_worker.data(), SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ),
|
||||
this, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ), Qt::UniqueConnection );
|
||||
}
|
||||
|
||||
InfoSystem::~InfoSystem()
|
||||
@ -120,10 +124,10 @@ InfoSystem::newNam() const
|
||||
|
||||
|
||||
void
|
||||
InfoSystem::getInfo( const InfoRequestData &requestData, uint timeoutMillis, bool allSources )
|
||||
InfoSystem::getInfo( const InfoRequestData &requestData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ), Q_ARG( uint, timeoutMillis ), Q_ARG( bool, allSources ) );
|
||||
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
|
||||
}
|
||||
|
||||
|
||||
@ -133,11 +137,13 @@ InfoSystem::getInfo( const QString &caller, const QVariantMap &customData, const
|
||||
InfoRequestData requestData;
|
||||
requestData.caller = caller;
|
||||
requestData.customData = customData;
|
||||
requestData.allSources = allSources;
|
||||
Q_FOREACH( InfoType type, inputMap.keys() )
|
||||
{
|
||||
requestData.type = type;
|
||||
requestData.input = inputMap[ type ];
|
||||
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ), Q_ARG( uint, ( timeoutMap.contains( type ) ? timeoutMap[ type ] : 0 ) ), Q_ARG( bool, allSources ) );
|
||||
requestData.timeoutMillis = timeoutMap.contains( type ) ? timeoutMap[ type ] : 10000;
|
||||
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
@ -43,28 +44,29 @@ class InfoSystemCache;
|
||||
class InfoSystemWorker;
|
||||
|
||||
enum InfoType { // as items are saved in cache, mark them here to not change them
|
||||
InfoTrackID = 0,
|
||||
InfoTrackArtist = 1,
|
||||
InfoTrackAlbum = 2,
|
||||
InfoTrackGenre = 3,
|
||||
InfoTrackComposer = 4,
|
||||
InfoTrackDate = 5,
|
||||
InfoTrackNumber = 6,
|
||||
InfoTrackDiscNumber = 7,
|
||||
InfoTrackBitRate = 8,
|
||||
InfoTrackLength = 9,
|
||||
InfoTrackSampleRate = 10,
|
||||
InfoTrackFileSize = 11,
|
||||
InfoTrackBPM = 12,
|
||||
InfoTrackReplayGain = 13,
|
||||
InfoTrackReplayPeakGain = 14,
|
||||
InfoTrackLyrics = 15,
|
||||
InfoTrackLocation = 16,
|
||||
InfoTrackProfile = 17,
|
||||
InfoTrackEnergy = 18,
|
||||
InfoTrackDanceability = 19,
|
||||
InfoTrackTempo = 20,
|
||||
InfoTrackLoudness = 21,
|
||||
InfoNoInfo = 0, //WARNING: *ALWAYS* keep this first!
|
||||
InfoTrackID = 1,
|
||||
InfoTrackArtist = 2,
|
||||
InfoTrackAlbum = 3,
|
||||
InfoTrackGenre = 4,
|
||||
InfoTrackComposer = 5,
|
||||
InfoTrackDate = 6,
|
||||
InfoTrackNumber = 7,
|
||||
InfoTrackDiscNumber = 8,
|
||||
InfoTrackBitRate = 9,
|
||||
InfoTrackLength = 10,
|
||||
InfoTrackSampleRate = 11,
|
||||
InfoTrackFileSize = 12,
|
||||
InfoTrackBPM = 13,
|
||||
InfoTrackReplayGain = 14,
|
||||
InfoTrackReplayPeakGain = 15,
|
||||
InfoTrackLyrics = 16,
|
||||
InfoTrackLocation = 17,
|
||||
InfoTrackProfile = 18,
|
||||
InfoTrackEnergy = 19,
|
||||
InfoTrackDanceability = 20,
|
||||
InfoTrackTempo = 21,
|
||||
InfoTrackLoudness = 22,
|
||||
|
||||
InfoArtistID = 25,
|
||||
InfoArtistName = 26,
|
||||
@ -120,14 +122,40 @@ enum InfoType { // as items are saved in cache, mark them here to not change the
|
||||
|
||||
InfoNotifyUser = 100,
|
||||
|
||||
InfoNoInfo = 101 //WARNING: *ALWAYS* keep this last!
|
||||
InfoLastInfo = 101 //WARNING: *ALWAYS* keep this last!
|
||||
};
|
||||
|
||||
struct InfoRequestData {
|
||||
quint64 requestId;
|
||||
quint64 internalId; //do not assign to this; it may get overwritten by the InfoSystem
|
||||
QString caller;
|
||||
Tomahawk::InfoSystem::InfoType type;
|
||||
QVariant input;
|
||||
QVariantMap customData;
|
||||
uint timeoutMillis;
|
||||
bool allSources;
|
||||
|
||||
InfoRequestData()
|
||||
: requestId( TomahawkUtils::infosystemRequestId() )
|
||||
, internalId( TomahawkUtils::infosystemRequestId() )
|
||||
, caller( QString() )
|
||||
, type( Tomahawk::InfoSystem::InfoNoInfo )
|
||||
, input( QVariant() )
|
||||
, customData( QVariantMap() )
|
||||
, timeoutMillis( 10000 )
|
||||
, allSources( false )
|
||||
{}
|
||||
|
||||
InfoRequestData( const quint64 rId, const QString &callr, const Tomahawk::InfoSystem::InfoType typ, const QVariant &inputvar, const QVariantMap &custom )
|
||||
: requestId( rId )
|
||||
, internalId( TomahawkUtils::infosystemRequestId() )
|
||||
, caller( callr )
|
||||
, type( typ )
|
||||
, input( inputvar )
|
||||
, customData( custom )
|
||||
, timeoutMillis( 10000 )
|
||||
, allSources( false )
|
||||
{}
|
||||
};
|
||||
|
||||
typedef QMap< InfoType, QVariant > InfoTypeMap;
|
||||
@ -147,15 +175,15 @@ public:
|
||||
QSet< InfoType > supportedPushTypes() const { return m_supportedPushTypes; }
|
||||
|
||||
signals:
|
||||
void getCachedInfo( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void info( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void getCachedInfo( Tomahawk::InfoSystem::InfoStringHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
|
||||
void updateCache( Tomahawk::InfoSystem::InfoStringHash criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output );
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) = 0;
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) = 0;
|
||||
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data ) = 0;
|
||||
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) = 0;
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) = 0;
|
||||
|
||||
virtual void namChangedSlot( QNetworkAccessManager *nam ) = 0;
|
||||
|
||||
@ -212,7 +240,7 @@ public:
|
||||
InfoSystem( QObject *parent );
|
||||
~InfoSystem();
|
||||
|
||||
void getInfo( const InfoRequestData &requestData, uint timeoutMillis = 0, bool allSources = false );
|
||||
void getInfo( const InfoRequestData &requestData );
|
||||
//WARNING: if changing timeoutMillis above, also change in below function in .cpp file
|
||||
void getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap = InfoTimeoutMap(), bool allSources = false );
|
||||
void pushInfo( const QString &caller, const InfoType type, const QVariant &input );
|
||||
@ -221,6 +249,7 @@ public:
|
||||
signals:
|
||||
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void finished( QString target );
|
||||
void finished( QString target, Tomahawk::InfoSystem::InfoType type );
|
||||
|
||||
public slots:
|
||||
void newNam() const;
|
||||
|
@ -75,7 +75,7 @@ InfoSystemCache::doUpgrade( uint oldVersion, uint newVersion )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Wiping cache";
|
||||
|
||||
for ( int i = 0; i <= InfoNoInfo; i++ )
|
||||
for ( int i = InfoNoInfo; i <= InfoLastInfo; i++ )
|
||||
{
|
||||
InfoType type = (InfoType)(i);
|
||||
const QString cacheDirName = m_cacheBaseDir + QString::number( (int)type );
|
||||
@ -96,7 +96,7 @@ InfoSystemCache::pruneTimerFired()
|
||||
qDebug() << Q_FUNC_INFO << "Pruning infosystemcache";
|
||||
qlonglong currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
for ( int i = 0; i <= InfoNoInfo; i++ )
|
||||
for ( int i = InfoNoInfo; i <= InfoLastInfo; i++ )
|
||||
{
|
||||
InfoType type = (InfoType)(i);
|
||||
QHash< QString, QString > fileLocationHash = m_fileLocationCache[type];
|
||||
@ -121,7 +121,7 @@ InfoSystemCache::pruneTimerFired()
|
||||
|
||||
|
||||
void
|
||||
InfoSystemCache::getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
QObject* sendingObj = sender();
|
||||
const QString criteriaHashVal = criteriaMd5( criteria );
|
||||
@ -133,7 +133,7 @@ InfoSystemCache::getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoSt
|
||||
{
|
||||
//We already know of some values, so no need to re-read the directory again as it's already happened
|
||||
qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash empty";
|
||||
notInCache( sendingObj, requestId, criteria, requestData );
|
||||
notInCache( sendingObj, criteria, requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ InfoSystemCache::getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoSt
|
||||
{
|
||||
//Dir doesn't exist so clearly not in cache
|
||||
qDebug() << Q_FUNC_INFO << "notInCache -- dir doesn't exist";
|
||||
notInCache( sendingObj, requestId, criteria, requestData );
|
||||
notInCache( sendingObj, criteria, requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ InfoSystemCache::getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoSt
|
||||
{
|
||||
//Still didn't find it? It's really not in the cache then
|
||||
qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash doesn't contain criteria val";
|
||||
notInCache( sendingObj, requestId, criteria, requestData );
|
||||
notInCache( sendingObj, criteria, requestData );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -180,7 +180,7 @@ InfoSystemCache::getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoSt
|
||||
m_dataCache.remove( criteriaHashValWithType );
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "notInCache -- file was stale";
|
||||
notInCache( sendingObj, requestId, criteria, requestData );
|
||||
notInCache( sendingObj, criteria, requestData );
|
||||
return;
|
||||
}
|
||||
else if ( newMaxAge > 0 )
|
||||
@ -190,7 +190,7 @@ InfoSystemCache::getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoSt
|
||||
if ( !QFile::rename( file.canonicalFilePath(), newFilePath ) )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "notInCache -- failed to move old cache file to new location";
|
||||
notInCache( sendingObj, requestId, criteria, requestData );
|
||||
notInCache( sendingObj, criteria, requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -204,25 +204,26 @@ InfoSystemCache::getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoSt
|
||||
QVariant output = cachedSettings.value( "data" );
|
||||
m_dataCache.insert( criteriaHashValWithType, new QVariant( output ) );
|
||||
|
||||
emit info( requestId, requestData, output );
|
||||
emit info( requestData, output );
|
||||
}
|
||||
else
|
||||
{
|
||||
emit info( requestId, requestData, QVariant( *( m_dataCache[ criteriaHashValWithType ] ) ) );
|
||||
emit info( requestData, QVariant( *( m_dataCache[ criteriaHashValWithType ] ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemCache::notInCache( QObject *receiver, uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
InfoSystemCache::notInCache( QObject *receiver, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
QMetaObject::invokeMethod( receiver, "notInCacheSlot", Q_ARG( uint, requestId ), Q_ARG( Tomahawk::InfoSystem::InfoStringHash, criteria ), Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
|
||||
QMetaObject::invokeMethod( receiver, "notInCacheSlot", Q_ARG( Tomahawk::InfoSystem::InfoStringHash, criteria ), Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemCache::updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
const QString criteriaHashVal = criteriaMd5( criteria );
|
||||
const QString criteriaHashValWithType = criteriaMd5( criteria, type );
|
||||
const QString cacheDir = m_cacheBaseDir + QString::number( (int)type );
|
||||
@ -283,7 +284,7 @@ InfoSystemCache::criteriaMd5( const Tomahawk::InfoSystem::InfoStringHash &criter
|
||||
md5.addData( key.toUtf8() );
|
||||
md5.addData( criteria[key].toUtf8() );
|
||||
}
|
||||
if ( type != Tomahawk::InfoSystem::InfoNoInfo )
|
||||
if ( type != Tomahawk::InfoSystem::InfoNoInfo && type != Tomahawk::InfoSystem::InfoLastInfo )
|
||||
md5.addData( QString::number( (int)type ).toUtf8() );
|
||||
return md5.result().toHex();
|
||||
}
|
||||
|
@ -43,17 +43,17 @@ public:
|
||||
virtual ~InfoSystemCache();
|
||||
|
||||
signals:
|
||||
void info( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
|
||||
public slots:
|
||||
void getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output );
|
||||
|
||||
private slots:
|
||||
void pruneTimerFired();
|
||||
|
||||
private:
|
||||
void notInCache( QObject *receiver, uint requestId, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void notInCache( QObject *receiver, Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void doUpgrade( uint oldVersion, uint newVersion );
|
||||
const QString criteriaMd5( const Tomahawk::InfoSystem::InfoStringHash &criteria, Tomahawk::InfoSystem::InfoType type = Tomahawk::InfoSystem::InfoNoInfo ) const;
|
||||
|
||||
|
@ -26,8 +26,10 @@
|
||||
#include "infoplugins/generic/echonestplugin.h"
|
||||
#include "infoplugins/generic/musixmatchplugin.h"
|
||||
#include "infoplugins/generic/chartsplugin.h"
|
||||
#include "infoplugins/generic/spotifyPlugin.h"
|
||||
#include "infoplugins/generic/lastfmplugin.h"
|
||||
#include "infoplugins/generic/musicbrainzPlugin.h"
|
||||
#include "infoplugins/generic/hypemPlugin.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
@ -40,6 +42,7 @@
|
||||
#endif
|
||||
|
||||
#include "lastfm/NetworkAccessManager"
|
||||
#include "infoplugins/generic/RoviPlugin.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
@ -49,7 +52,6 @@ namespace InfoSystem
|
||||
|
||||
InfoSystemWorker::InfoSystemWorker()
|
||||
: QObject()
|
||||
, m_nextRequest( 0 )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO;
|
||||
|
||||
@ -92,6 +94,15 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac
|
||||
InfoPluginPtr sptr( new ChartsPlugin() );
|
||||
m_plugins.append( sptr );
|
||||
registerInfoTypes( sptr, sptr.data()->supportedGetTypes(), sptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr roviptr( new RoviPlugin() );
|
||||
m_plugins.append( roviptr );
|
||||
registerInfoTypes( roviptr, roviptr.data()->supportedGetTypes(), roviptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr spotptr( new SpotifyPlugin() );
|
||||
m_plugins.append( spotptr );
|
||||
registerInfoTypes( spotptr, spotptr.data()->supportedGetTypes(), spotptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr hypeptr( new hypemPlugin() );
|
||||
m_plugins.append( hypeptr );
|
||||
registerInfoTypes( hypeptr, hypeptr.data()->supportedGetTypes(), hypeptr.data()->supportedPushTypes() );
|
||||
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
@ -105,24 +116,24 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac
|
||||
registerInfoTypes( fdonotifyptr, fdonotifyptr.data()->supportedGetTypes(), fdonotifyptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr mprisptr( new MprisPlugin() );
|
||||
m_plugins.append( mprisptr );
|
||||
registerInfoTypes( mprisptr, mprisptr.data()->supportedGetTypes(), mprisptr.data()->supportedPushTypes() );
|
||||
registerInfoTypes( mprisptr, mprisptr.data()->supportedGetTypes(), mprisptr.data()->supportedPushTypes() );
|
||||
#endif
|
||||
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( info( uint, Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
this,
|
||||
SLOT( infoSlot( uint, Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
Qt::UniqueConnection
|
||||
);
|
||||
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( getCachedInfo( uint, Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
|
||||
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
|
||||
cache.data(),
|
||||
SLOT( getCachedInfoSlot( uint, Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) )
|
||||
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) )
|
||||
);
|
||||
connect(
|
||||
plugin.data(),
|
||||
@ -165,19 +176,19 @@ InfoSystemWorker::determineOrderedMatches( const InfoType type ) const
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, uint timeoutMillis, bool allSources )
|
||||
InfoSystemWorker::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO;
|
||||
//qDebug() << Q_FUNC_INFO << "type is " << requestData.type << " and allSources = " << (allSources ? "true" : "false" );
|
||||
|
||||
QList< InfoPluginPtr > providers = determineOrderedMatches( requestData.type );
|
||||
if ( providers.isEmpty() )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
checkFinished( requestData.caller );
|
||||
checkFinished( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !allSources )
|
||||
if ( !requestData.allSources )
|
||||
providers = QList< InfoPluginPtr >( providers.mid( 0, 1 ) );
|
||||
|
||||
bool foundOne = false;
|
||||
@ -187,12 +198,22 @@ InfoSystemWorker::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, ui
|
||||
continue;
|
||||
|
||||
foundOne = true;
|
||||
uint requestId = ++m_nextRequest;
|
||||
|
||||
if ( requestData.allSources || m_savedRequestMap.contains( requestData.requestId ) )
|
||||
{
|
||||
if ( m_savedRequestMap.contains( requestData.requestId ) )
|
||||
tDebug() << Q_FUNC_INFO << "Warning: reassigning requestId because it already exists";
|
||||
requestData.internalId = TomahawkUtils::infosystemRequestId();
|
||||
}
|
||||
else
|
||||
requestData.internalId = requestData.requestId;
|
||||
|
||||
quint64 requestId = requestData.internalId;
|
||||
m_requestSatisfiedMap[ requestId ] = false;
|
||||
if ( timeoutMillis != 0 )
|
||||
if ( requestData.timeoutMillis != 0 )
|
||||
{
|
||||
qint64 currMs = QDateTime::currentMSecsSinceEpoch();
|
||||
m_timeRequestMapper.insert( currMs + timeoutMillis, requestId );
|
||||
m_timeRequestMapper.insert( currMs + requestData.timeoutMillis, requestId );
|
||||
}
|
||||
// qDebug() << "Assigning request with requestId" << requestId << "and type" << requestData.type;
|
||||
m_dataTracker[ requestData.caller ][ requestData.type ] = m_dataTracker[ requestData.caller ][ requestData.type ] + 1;
|
||||
@ -205,19 +226,19 @@ InfoSystemWorker::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, ui
|
||||
data->customData = requestData.customData;
|
||||
m_savedRequestMap[ requestId ] = data;
|
||||
|
||||
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( uint, requestId ), Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
|
||||
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
|
||||
}
|
||||
|
||||
if ( !foundOne )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
checkFinished( requestData.caller );
|
||||
checkFinished( requestData );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::pushInfo( QString caller, InfoType type, QVariant input )
|
||||
InfoSystemWorker::pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO;
|
||||
|
||||
@ -230,10 +251,12 @@ InfoSystemWorker::pushInfo( QString caller, InfoType type, QVariant input )
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::infoSlot( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
|
||||
InfoSystemWorker::infoSlot( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << "with requestId" << requestId;
|
||||
|
||||
quint64 requestId = requestData.internalId;
|
||||
|
||||
if ( m_dataTracker[ requestData.caller ][ requestData.type ] == 0 )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << "Caller was not waiting for that type of data!";
|
||||
@ -252,23 +275,23 @@ InfoSystemWorker::infoSlot( uint requestId, Tomahawk::InfoSystem::InfoRequestDat
|
||||
// qDebug() << "Current count in dataTracker for target" << requestData.caller << "and type" << requestData.type << "is" << m_dataTracker[ requestData.caller ][ requestData.type ];
|
||||
delete m_savedRequestMap[ requestId ];
|
||||
m_savedRequestMap.remove( requestId );
|
||||
checkFinished( requestData.caller );
|
||||
checkFinished( requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::checkFinished( const QString &target )
|
||||
InfoSystemWorker::checkFinished( const Tomahawk::InfoSystem::InfoRequestData &requestData )
|
||||
{
|
||||
Q_FOREACH( InfoType testtype, m_dataTracker[ target ].keys() )
|
||||
if ( m_dataTracker[ requestData.caller ][ requestData.type ] == 0 )
|
||||
emit finished( requestData.caller, requestData.type );
|
||||
|
||||
Q_FOREACH( InfoType testtype, m_dataTracker[ requestData.caller ].keys() )
|
||||
{
|
||||
if ( m_dataTracker[ target ][ testtype ] != 0)
|
||||
{
|
||||
// qDebug() << "Found outstanding request of type" << testtype;
|
||||
if ( m_dataTracker[ requestData.caller ][ testtype ] != 0 )
|
||||
return;
|
||||
}
|
||||
}
|
||||
// qDebug() << "Emitting finished with target" << target;
|
||||
emit finished( target );
|
||||
emit finished( requestData.caller );
|
||||
}
|
||||
|
||||
|
||||
@ -278,7 +301,7 @@ InfoSystemWorker::checkTimeoutsTimerFired()
|
||||
qint64 currTime = QDateTime::currentMSecsSinceEpoch();
|
||||
Q_FOREACH( qint64 time, m_timeRequestMapper.keys() )
|
||||
{
|
||||
Q_FOREACH( uint requestId, m_timeRequestMapper.values( time ) )
|
||||
Q_FOREACH( quint64 requestId, m_timeRequestMapper.values( time ) )
|
||||
{
|
||||
if ( time < currTime )
|
||||
{
|
||||
@ -313,7 +336,7 @@ InfoSystemWorker::checkTimeoutsTimerFired()
|
||||
if ( !m_timeRequestMapper.count( time ) )
|
||||
m_timeRequestMapper.remove( time );
|
||||
|
||||
checkFinished( returnData.caller );
|
||||
checkFinished( returnData );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -338,18 +361,31 @@ InfoSystemWorker::nam() const
|
||||
void
|
||||
InfoSystemWorker::newNam()
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << " begin";
|
||||
|
||||
QNetworkAccessManager *oldNam = TomahawkUtils::nam();
|
||||
if ( oldNam && oldNam->thread() == thread() )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << "Using old nam as it's the same thread (GUI) as me";
|
||||
m_nam = QWeakPointer< QNetworkAccessManager >( oldNam );
|
||||
emit namChanged( m_nam.data() );
|
||||
if ( m_nam.data() != oldNam )
|
||||
{
|
||||
m_nam = QWeakPointer< QNetworkAccessManager >( oldNam );
|
||||
emit namChanged( m_nam.data() );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// qDebug() << Q_FUNC_INFO << "No nam exists, or it's a different thread, creating a new one";
|
||||
if
|
||||
(
|
||||
oldNam &&
|
||||
!m_nam.isNull() &&
|
||||
oldNam->configuration() == m_nam.data()->configuration() &&
|
||||
oldNam->networkAccessible() == m_nam.data()->networkAccessible()
|
||||
)
|
||||
{
|
||||
TomahawkUtils::NetworkProxyFactory fac1 = *( dynamic_cast< TomahawkUtils::NetworkProxyFactory * >( oldNam->proxyFactory() ) );
|
||||
TomahawkUtils::NetworkProxyFactory fac2 = *( dynamic_cast< TomahawkUtils::NetworkProxyFactory * >( m_nam.data()->proxyFactory() ) );
|
||||
if ( fac1 == fac2 )
|
||||
return;
|
||||
}
|
||||
|
||||
QNetworkAccessManager* newNam;
|
||||
#ifdef LIBLASTFM_FOUND
|
||||
newNam = new lastfm::NetworkAccessManager( this );
|
||||
|
@ -52,15 +52,16 @@ public:
|
||||
signals:
|
||||
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void finished( QString target );
|
||||
void finished( QString target, Tomahawk::InfoSystem::InfoType type );
|
||||
|
||||
void namChanged( QNetworkAccessManager* );
|
||||
|
||||
public slots:
|
||||
void init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > cache );
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, uint timeoutMillis, bool allSources );
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );
|
||||
|
||||
void infoSlot( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void infoSlot( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
|
||||
void newNam();
|
||||
|
||||
@ -69,11 +70,11 @@ private slots:
|
||||
|
||||
private:
|
||||
|
||||
void checkFinished( const QString &target );
|
||||
void checkFinished( const Tomahawk::InfoSystem::InfoRequestData &target );
|
||||
QList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
|
||||
|
||||
QHash< QString, QHash< InfoType, int > > m_dataTracker;
|
||||
QMultiMap< qint64, uint > m_timeRequestMapper;
|
||||
QMultiMap< qint64, quint64 > m_timeRequestMapper;
|
||||
QHash< uint, bool > m_requestSatisfiedMap;
|
||||
QHash< uint, InfoRequestData* > m_savedRequestMap;
|
||||
|
||||
@ -85,8 +86,6 @@ private:
|
||||
|
||||
QWeakPointer< QNetworkAccessManager> m_nam;
|
||||
|
||||
uint m_nextRequest;
|
||||
|
||||
QTimer m_checkTimeoutsTimer;
|
||||
};
|
||||
|
||||
|
@ -81,7 +81,7 @@ PortFwdThread::work()
|
||||
qDebug() << "Trying to setup portfwd on" << tryport;
|
||||
if ( m_portfwd->add( tryport, m_port ) )
|
||||
{
|
||||
QString pubip = QString( m_portfwd->external_ip().c_str() );
|
||||
QString pubip = QString( m_portfwd->external_ip().c_str() ).trimmed();
|
||||
m_externalAddress = QHostAddress( pubip );
|
||||
m_externalPort = tryport;
|
||||
tDebug() << "External servent address detected as" << pubip << ":" << m_externalPort;
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include "playlist/albumitem.h"
|
||||
#include "playlist/albumproxymodel.h"
|
||||
#include <QMouseEvent>
|
||||
#include <viewmanager.h>
|
||||
|
||||
|
||||
AlbumItemDelegate::AlbumItemDelegate( QAbstractItemView* parent, AlbumProxyModel* proxy )
|
||||
@ -38,7 +40,6 @@ AlbumItemDelegate::AlbumItemDelegate( QAbstractItemView* parent, AlbumProxyModel
|
||||
, m_view( parent )
|
||||
, m_model( proxy )
|
||||
{
|
||||
m_shadowPixmap = QPixmap( RESPATH "images/cover-shadow.png" );
|
||||
m_defaultCover = QPixmap( RESPATH "images/no-album-art-placeholder.png" );
|
||||
}
|
||||
|
||||
@ -63,9 +64,30 @@ AlbumItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
// painter->setRenderHint( QPainter::Antialiasing );
|
||||
// painter->drawPixmap( option.rect.adjusted( 4, 4, -4, -38 ), m_shadowPixmap );
|
||||
if ( !( option.state & QStyle::State_Selected ) )
|
||||
{
|
||||
QRect shadowRect = option.rect.adjusted( 5, 4, -5, -40 );
|
||||
painter->setPen( QColor( 90, 90, 90 ) );
|
||||
painter->drawRoundedRect( shadowRect, 0.5, 0.5 );
|
||||
|
||||
QPen shadowPen( QColor( 30, 30, 30 ) );
|
||||
shadowPen.setWidth( 0.4 );
|
||||
painter->drawLine( shadowRect.bottomLeft() + QPoint( -1, 2 ), shadowRect.bottomRight() + QPoint( 1, 2 ) );
|
||||
|
||||
shadowPen.setColor( QColor( 160, 160, 160 ) );
|
||||
painter->setPen( shadowPen );
|
||||
painter->drawLine( shadowRect.topLeft() + QPoint( -1, 2 ), shadowRect.bottomLeft() + QPoint( -1, 2 ) );
|
||||
painter->drawLine( shadowRect.topRight() + QPoint( 2, 2 ), shadowRect.bottomRight() + QPoint( 2, 2 ) );
|
||||
painter->drawLine( shadowRect.bottomLeft() + QPoint( 0, 3 ), shadowRect.bottomRight() + QPoint( 0, 3 ) );
|
||||
|
||||
shadowPen.setColor( QColor( 180, 180, 180 ) );
|
||||
painter->setPen( shadowPen );
|
||||
painter->drawLine( shadowRect.topLeft() + QPoint( -2, 3 ), shadowRect.bottomLeft() + QPoint( -2, 1 ) );
|
||||
painter->drawLine( shadowRect.topRight() + QPoint( 3, 3 ), shadowRect.bottomRight() + QPoint( 3, 1 ) );
|
||||
painter->drawLine( shadowRect.bottomLeft() + QPoint( 0, 4 ), shadowRect.bottomRight() + QPoint( 0, 4 ) );
|
||||
}
|
||||
|
||||
QPixmap cover = item->cover.isNull() ? m_defaultCover : item->cover;
|
||||
QRect r = option.rect.adjusted( 6, 5, -6, -41 );
|
||||
@ -117,7 +139,7 @@ AlbumItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
oneLiner = true;
|
||||
else
|
||||
oneLiner = ( textRect.height() / 2 < painter->fontMetrics().boundingRect( item->album()->name() ).height() ||
|
||||
textRect.height() / 2 < painter->fontMetrics().boundingRect( item->album()->artist()->name() ).height() );
|
||||
textRect.height() / 2 < painter->fontMetrics().boundingRect( item->album()->artist()->name() ).height() );
|
||||
|
||||
if ( oneLiner )
|
||||
{
|
||||
@ -127,15 +149,95 @@ AlbumItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setFont( boldFont );
|
||||
to.setAlignment( Qt::AlignHCenter | Qt::AlignTop );
|
||||
text = painter->fontMetrics().elidedText( item->album()->name(), Qt::ElideRight, textRect.width() - 3 );
|
||||
painter->drawText( textRect, text, to );
|
||||
|
||||
painter->setFont( boldFont );
|
||||
// If the user is hovering over an artist rect, draw a background so she knows it's clickable
|
||||
QRect r = textRect;
|
||||
r.setTop( r.bottom() - painter->fontMetrics().height() );
|
||||
r.adjust( 4, 0, -4, -1 );
|
||||
if ( m_hoveringOver == index )
|
||||
TomahawkUtils::drawQueryBackground( painter, opt.palette, r, 1.5 );
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
painter->setPen( opt.palette.color( QPalette::Dark ).darker( 200 ) );
|
||||
#else
|
||||
painter->setPen( opt.palette.color( QPalette::Dark ) );
|
||||
#endif
|
||||
to.setAlignment( Qt::AlignHCenter | Qt::AlignBottom );
|
||||
text = painter->fontMetrics().elidedText( item->album()->artist()->name(), Qt::ElideRight, textRect.width() - 3 );
|
||||
painter->drawText( textRect, text, to );
|
||||
// Calculate rect of artist on-hover button click area
|
||||
|
||||
m_artistNameRects[ index ] = r;
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
bool
|
||||
AlbumItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
|
||||
{
|
||||
Q_UNUSED( option );
|
||||
|
||||
if ( event->type() != QEvent::MouseButtonRelease &&
|
||||
event->type() != QEvent::MouseMove &&
|
||||
event->type() != QEvent::MouseButtonPress &&
|
||||
event->type() != QEvent::Leave )
|
||||
return false;
|
||||
|
||||
if ( m_artistNameRects.contains( index ) )
|
||||
{
|
||||
QMouseEvent* ev = static_cast< QMouseEvent* >( event );
|
||||
QRect artistNameRect = m_artistNameRects[ index ];
|
||||
if ( artistNameRect.contains( ev->pos() ) )
|
||||
{
|
||||
if ( event->type() == QEvent::MouseMove )
|
||||
{
|
||||
if ( m_hoveringOver != index )
|
||||
{
|
||||
QModelIndex old = m_hoveringOver;
|
||||
m_hoveringOver = index;
|
||||
emit updateIndex( old );
|
||||
emit updateIndex( index );
|
||||
}
|
||||
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
else if ( event->type() == QEvent::MouseButtonRelease )
|
||||
{
|
||||
AlbumItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
|
||||
if ( !item || item->album().isNull() || item->album()->artist().isNull() )
|
||||
return false;
|
||||
|
||||
ViewManager::instance()->show( item->album()->artist() );
|
||||
|
||||
event->accept();
|
||||
return true;
|
||||
} else if ( event->type() == QEvent::MouseButtonPress )
|
||||
{
|
||||
// Stop the whole album from having a down click action as we just want the artist name to be clicked
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
whitespaceMouseEvent();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
AlbumItemDelegate::whitespaceMouseEvent()
|
||||
{
|
||||
if ( m_hoveringOver.isValid() )
|
||||
{
|
||||
QModelIndex old = m_hoveringOver;
|
||||
m_hoveringOver = QPersistentModelIndex();
|
||||
emit updateIndex( old );
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class QEvent;
|
||||
class AlbumProxyModel;
|
||||
|
||||
class DLLEXPORT AlbumItemDelegate : public QStyledItemDelegate
|
||||
@ -32,17 +33,26 @@ Q_OBJECT
|
||||
public:
|
||||
AlbumItemDelegate( QAbstractItemView* parent = 0, AlbumProxyModel* proxy = 0 );
|
||||
|
||||
void whitespaceMouseEvent();
|
||||
|
||||
protected:
|
||||
void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
|
||||
bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
|
||||
// QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
|
||||
signals:
|
||||
void updateIndex( const QModelIndex& idx );
|
||||
|
||||
private:
|
||||
QAbstractItemView* m_view;
|
||||
AlbumProxyModel* m_model;
|
||||
|
||||
mutable QHash< qint64, QPixmap > m_cache;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_artistNameRects;
|
||||
QPersistentModelIndex m_hoveringOver;
|
||||
|
||||
QPixmap m_shadowPixmap;
|
||||
QPixmap m_defaultCover;
|
||||
};
|
||||
|
@ -254,6 +254,8 @@ AlbumModel::addCollection( const collection_ptr& collection, bool overwrite )
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
|
||||
m_title = tr( "All albums from %1" ).arg( collection->source()->friendlyName() );
|
||||
|
||||
emit loadingStarted();
|
||||
}
|
||||
|
||||
|
||||
@ -280,6 +282,8 @@ AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned in
|
||||
m_title = tr( "All albums from %1" ).arg( collection->source()->friendlyName() );
|
||||
else
|
||||
m_title = tr( "All albums" );
|
||||
|
||||
emit loadingStarted();
|
||||
}
|
||||
|
||||
|
||||
@ -292,6 +296,8 @@ AlbumModel::addAlbums( const QList<Tomahawk::album_ptr>& albums )
|
||||
if ( m_overwriteOnAdd )
|
||||
clear();
|
||||
|
||||
emit loadingFinished();
|
||||
|
||||
int c = rowCount( QModelIndex() );
|
||||
QPair< int, int > crows;
|
||||
crows.first = c;
|
||||
|
@ -94,6 +94,8 @@ signals:
|
||||
|
||||
void trackCountChanged( unsigned int tracks );
|
||||
|
||||
void loadingStarted();
|
||||
void loadingFinished();
|
||||
private slots:
|
||||
void onDataChanged();
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <QKeyEvent>
|
||||
#include <QPainter>
|
||||
#include <QScrollBar>
|
||||
#include <qmath.h>
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
#include "tomahawksettings.h"
|
||||
@ -31,6 +32,7 @@
|
||||
#include "albummodel.h"
|
||||
#include "viewmanager.h"
|
||||
#include "utils/logger.h"
|
||||
#include "dynamic/widgets/LoadingSpinner.h"
|
||||
|
||||
#define SCROLL_TIMEOUT 280
|
||||
|
||||
@ -41,13 +43,16 @@ AlbumView::AlbumView( QWidget* parent )
|
||||
: QListView( parent )
|
||||
, m_model( 0 )
|
||||
, m_proxyModel( 0 )
|
||||
// , m_delegate( 0 )
|
||||
, m_delegate( 0 )
|
||||
, m_loadingSpinner( new LoadingSpinner( this ) )
|
||||
{
|
||||
setDragEnabled( true );
|
||||
setDropIndicatorShown( false );
|
||||
setDragDropOverwriteMode( false );
|
||||
setUniformItemSizes( true );
|
||||
setSpacing( 20 );
|
||||
setSpacing( 16 );
|
||||
setContentsMargins( 0, 0, 0, 0 );
|
||||
setMouseTracking( true );
|
||||
|
||||
setResizeMode( Adjust );
|
||||
setViewMode( IconMode );
|
||||
@ -75,7 +80,9 @@ void
|
||||
AlbumView::setProxyModel( AlbumProxyModel* model )
|
||||
{
|
||||
m_proxyModel = model;
|
||||
setItemDelegate( new AlbumItemDelegate( this, m_proxyModel ) );
|
||||
m_delegate = new AlbumItemDelegate( this, m_proxyModel );
|
||||
connect( m_delegate, SIGNAL( updateIndex( QModelIndex ) ), this, SLOT( update( QModelIndex ) ) );
|
||||
setItemDelegate( m_delegate );
|
||||
|
||||
QListView::setModel( m_proxyModel );
|
||||
}
|
||||
@ -104,6 +111,9 @@ AlbumView::setAlbumModel( AlbumModel* model )
|
||||
connect( m_proxyModel, SIGNAL( filterChanged( QString ) ), SLOT( onFilterChanged( QString ) ) );
|
||||
connect( m_proxyModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), SLOT( onViewChanged() ) );
|
||||
|
||||
connect( m_model, SIGNAL( loadingStarted() ), m_loadingSpinner, SLOT( fadeIn() ) );
|
||||
connect( m_model, SIGNAL( loadingFinished() ), m_loadingSpinner, SLOT( fadeOut() ) );
|
||||
|
||||
setAcceptDrops( false );
|
||||
onViewChanged(); // Fetch covers if albums were added to model before model was attached to view
|
||||
}
|
||||
@ -179,6 +189,30 @@ AlbumView::paintEvent( QPaintEvent* event )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::resizeEvent( QResizeEvent* event )
|
||||
{
|
||||
QListView::resizeEvent( event );
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
int scrollbar = !verticalScrollBar()->isVisible() ? verticalScrollBar()->rect().width() : 0;
|
||||
#else
|
||||
int scrollbar = verticalScrollBar()->rect().width();
|
||||
#endif
|
||||
int rectWidth = contentsRect().width() - scrollbar - 16 - 3;
|
||||
QSize itemSize = m_proxyModel->data( QModelIndex(), Qt::SizeHintRole ).toSize();
|
||||
|
||||
int itemsPerRow = qFloor( rectWidth / ( itemSize.width() + 16 ) );
|
||||
int rightSpacing = rectWidth - ( itemsPerRow * ( itemSize.width() + 16 ) );
|
||||
int newSpacing = 16 + floor( rightSpacing / ( itemsPerRow + 1 ) );
|
||||
|
||||
if ( itemsPerRow < 1 )
|
||||
setSpacing( 16 );
|
||||
else
|
||||
setSpacing( newSpacing );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::onFilterChanged( const QString& )
|
||||
{
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "albumproxymodel.h"
|
||||
|
||||
class AlbumModel;
|
||||
class LoadingSpinner;
|
||||
class AlbumItemDelegate;
|
||||
|
||||
class DLLEXPORT AlbumView : public QListView, public Tomahawk::ViewPage
|
||||
{
|
||||
@ -63,6 +65,7 @@ protected:
|
||||
virtual void startDrag( Qt::DropActions supportedActions );
|
||||
|
||||
void paintEvent( QPaintEvent* event );
|
||||
void resizeEvent( QResizeEvent* event );
|
||||
|
||||
private slots:
|
||||
void onFilterChanged( const QString& filter );
|
||||
@ -73,7 +76,8 @@ private slots:
|
||||
private:
|
||||
AlbumModel* m_model;
|
||||
AlbumProxyModel* m_proxyModel;
|
||||
// PlaylistItemDelegate* m_delegate;
|
||||
AlbumItemDelegate* m_delegate;
|
||||
LoadingSpinner* m_loadingSpinner;
|
||||
|
||||
QTimer m_timer;
|
||||
};
|
||||
|
@ -158,7 +158,7 @@ ArtistView::onItemActivated( const QModelIndex& index )
|
||||
if ( !item->artist().isNull() )
|
||||
ViewManager::instance()->show( item->artist() );
|
||||
else if ( !item->album().isNull() )
|
||||
ViewManager::instance()->show( item->album() );
|
||||
ViewManager::instance()->show( item->album(), m_model->mode() );
|
||||
else if ( !item->result().isNull() && item->result()->isOnline() )
|
||||
{
|
||||
m_model->setCurrentItem( item->index );
|
||||
|
@ -52,8 +52,11 @@ CustomPlaylistView::CustomPlaylistView( CustomPlaylistView::PlaylistType type, c
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CustomPlaylistView::~CustomPlaylistView()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CustomPlaylistView::isBeingPlayed() const
|
||||
@ -61,6 +64,7 @@ CustomPlaylistView::isBeingPlayed() const
|
||||
return AudioEngine::instance()->currentTrackPlaylist() == playlistInterface();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CustomPlaylistView::jumpToCurrentTrack()
|
||||
{
|
||||
@ -80,7 +84,7 @@ CustomPlaylistView::generateTracks()
|
||||
"FROM social_attributes, track, artist "
|
||||
"WHERE social_attributes.id = track.id AND artist.id = track.artist AND social_attributes.k = 'Love' AND social_attributes.v = 'true' AND social_attributes.source %1 "
|
||||
"GROUP BY track.id "
|
||||
"ORDER BY counter DESC, social_attributes.timestamp DESC " ).arg( m_source->isLocal() ? "IS NULL" : QString( "=%1" ).arg( m_source->id() ) );
|
||||
"ORDER BY counter DESC, social_attributes.timestamp DESC " ).arg( m_source->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_source->id() ) );
|
||||
break;
|
||||
case AllLovedTracks:
|
||||
sql = QString( "SELECT track.name, artist.name, source, COUNT(*) as counter "
|
||||
@ -96,6 +100,7 @@ CustomPlaylistView::generateTracks()
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CustomPlaylistView::tracksGenerated( QList< query_ptr > tracks )
|
||||
{
|
||||
@ -103,6 +108,7 @@ CustomPlaylistView::tracksGenerated( QList< query_ptr > tracks )
|
||||
m_model->append( q );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
CustomPlaylistView::title() const
|
||||
{
|
||||
@ -132,18 +138,21 @@ CustomPlaylistView::description() const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
CustomPlaylistView::longDescription() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
CustomPlaylistView::pixmap() const
|
||||
{
|
||||
return QPixmap( RESPATH "images/loved_playlist.png" );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CustomPlaylistView::reload()
|
||||
{
|
||||
@ -153,7 +162,7 @@ CustomPlaylistView::reload()
|
||||
|
||||
|
||||
void
|
||||
CustomPlaylistView::sourceAdded( const source_ptr& s)
|
||||
CustomPlaylistView::sourceAdded( const source_ptr& s )
|
||||
{
|
||||
connect( s.data(), SIGNAL( socialAttributesChanged() ), this, SLOT( reload() ) );
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010 Leo Franchi <lfranchi@kde.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
|
||||
@ -58,6 +58,9 @@ LoadingSpinner::~LoadingSpinner()
|
||||
void
|
||||
LoadingSpinner::fadeIn()
|
||||
{
|
||||
if ( isVisible() )
|
||||
return;
|
||||
|
||||
show();
|
||||
|
||||
m_anim->start();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010 Leo Franchi <lfranchi@kde.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
|
||||
@ -54,4 +54,4 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
class QPaintEvent;
|
||||
class QPaintEvent;
|
||||
|
@ -384,7 +384,7 @@ PlaylistModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int r
|
||||
// so check if the drag originated in this playlist to determine whether or not to copy
|
||||
#ifdef Q_WS_MAC
|
||||
if ( !data->hasFormat( "application/tomahawk.playlist.id" ) ||
|
||||
data->data( "application/tomahawk.playlist.id" ) != m_playlist->guid() )
|
||||
( !m_playlist.isNull() && data->data( "application/tomahawk.playlist.id" ) != m_playlist->guid() ) )
|
||||
dj->setDropAction( DropJob::Append );
|
||||
#else
|
||||
if ( action & Qt::CopyAction )
|
||||
|
@ -556,7 +556,8 @@ TrackView::mousePressEvent( QMouseEvent* event )
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO
|
||||
artist_ptr artist = Artist::get( item->query()->artist() );
|
||||
ViewManager::instance()->show( Album::get( artist, item->query()->album() ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ TreeItemDelegate::TreeItemDelegate( ArtistView* parent, TreeProxyModel* proxy )
|
||||
, m_model( proxy )
|
||||
{
|
||||
m_nowPlayingIcon = QPixmap( RESPATH "images/now-playing-speaker.png" );
|
||||
m_defaultAlbumCover = QPixmap( RESPATH "images/no-album-art-placeholder.png" );
|
||||
m_defaultAlbumCover = QPixmap( RESPATH "images/no-album-no-case.png" );
|
||||
m_defaultArtistImage = QPixmap( RESPATH "images/no-artist-image-placeholder.png" );
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ TreeModel::TreeModel( QObject* parent )
|
||||
, m_rootItem( new TreeModelItem( 0, this ) )
|
||||
, m_infoId( uuid() )
|
||||
, m_columnStyle( AllColumns )
|
||||
, m_mode( Database )
|
||||
, m_mode( DatabaseMode )
|
||||
{
|
||||
setIcon( QPixmap( RESPATH "images/music-icon.png" ) );
|
||||
|
||||
@ -576,7 +576,7 @@ TreeModel::addAlbums( const artist_ptr& artist, const QModelIndex& parent )
|
||||
{
|
||||
emit loadingStarted();
|
||||
|
||||
if ( m_mode == Database )
|
||||
if ( m_mode == DatabaseMode )
|
||||
{
|
||||
DatabaseCommand_AllAlbums* cmd = new DatabaseCommand_AllAlbums( m_collection, artist );
|
||||
cmd->setData( parent.row() );
|
||||
@ -586,7 +586,7 @@ TreeModel::addAlbums( const artist_ptr& artist, const QModelIndex& parent )
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
else if ( m_mode == InfoSystem )
|
||||
else if ( m_mode == InfoSystemMode )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoStringHash artistInfo;
|
||||
artistInfo["artist"] = artist->name();
|
||||
@ -612,7 +612,7 @@ TreeModel::addTracks( const album_ptr& album, const QModelIndex& parent )
|
||||
rows << parent.row();
|
||||
rows << parent.parent().row();
|
||||
|
||||
if ( m_mode == Database )
|
||||
if ( m_mode == DatabaseMode )
|
||||
{
|
||||
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_collection );
|
||||
cmd->setAlbum( album.data() );
|
||||
@ -623,17 +623,20 @@ TreeModel::addTracks( const album_ptr& album, const QModelIndex& parent )
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
else if ( m_mode == InfoSystem )
|
||||
else if ( m_mode == InfoSystemMode )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoStringHash artistInfo;
|
||||
artistInfo["artist"] = album->artist()->name();
|
||||
artistInfo["album"] = album->name();
|
||||
|
||||
m_receivedInfoData.remove( artistInfo );
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = m_infoId;
|
||||
requestData.customData["rows"] = QVariant( rows );
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( artistInfo );
|
||||
requestData.type = Tomahawk::InfoSystem::InfoAlbumSongs;
|
||||
requestData.timeoutMillis = 0;
|
||||
requestData.allSources = true;
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
}
|
||||
else
|
||||
@ -826,7 +829,7 @@ TreeModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QV
|
||||
QStringList albums = returnedData[ "albums" ].toStringList();
|
||||
QList<album_ptr> al;
|
||||
|
||||
InfoSystem::InfoStringHash inputInfo;
|
||||
Tomahawk::InfoSystem::InfoStringHash inputInfo;
|
||||
inputInfo = requestData.input.value< InfoSystem::InfoStringHash >();
|
||||
artist_ptr artist = Artist::get( inputInfo[ "artist" ], false );
|
||||
|
||||
@ -845,12 +848,23 @@ TreeModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QV
|
||||
|
||||
case Tomahawk::InfoSystem::InfoAlbumSongs:
|
||||
{
|
||||
if ( m_receivedInfoData.contains( requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >() ) )
|
||||
break;
|
||||
|
||||
emit loadingFinished();
|
||||
|
||||
QVariantMap returnedData = output.value< QVariantMap >();
|
||||
if ( returnedData.isEmpty() )
|
||||
break;
|
||||
|
||||
m_receivedInfoData.insert( requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >() );
|
||||
|
||||
|
||||
QStringList tracks = returnedData[ "tracks" ].toStringList();
|
||||
QList<query_ptr> ql;
|
||||
|
||||
InfoSystem::InfoStringHash inputInfo;
|
||||
inputInfo = requestData.input.value< InfoSystem::InfoStringHash >();
|
||||
Tomahawk::InfoSystem::InfoStringHash inputInfo;
|
||||
inputInfo = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
|
||||
foreach ( const QString& trackName, tracks )
|
||||
{
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
class QMetaData;
|
||||
|
||||
@ -55,9 +56,6 @@ public:
|
||||
enum ColumnStyle
|
||||
{ AllColumns = 0, TrackOnly };
|
||||
|
||||
enum ModelMode
|
||||
{ Database = 0, InfoSystem };
|
||||
|
||||
explicit TreeModel( QObject* parent = 0 );
|
||||
virtual ~TreeModel();
|
||||
|
||||
@ -73,8 +71,8 @@ public:
|
||||
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;
|
||||
virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const;
|
||||
|
||||
virtual ModelMode mode() const { return m_mode; }
|
||||
virtual void setMode( ModelMode mode ) { m_mode = mode; }
|
||||
virtual Tomahawk::ModelMode mode() const { return m_mode; }
|
||||
virtual void setMode( Tomahawk::ModelMode mode ) { m_mode = mode; }
|
||||
|
||||
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
|
||||
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
|
||||
@ -165,12 +163,13 @@ private:
|
||||
QString m_description;
|
||||
QPixmap m_icon;
|
||||
ColumnStyle m_columnStyle;
|
||||
ModelMode m_mode;
|
||||
Tomahawk::ModelMode m_mode;
|
||||
|
||||
QList<Tomahawk::artist_ptr> m_artistsFilter;
|
||||
|
||||
Tomahawk::collection_ptr m_collection;
|
||||
QHash<qlonglong, QPersistentModelIndex> m_coverHash;
|
||||
QSet<Tomahawk::InfoSystem::InfoStringHash> m_receivedInfoData;
|
||||
};
|
||||
|
||||
#endif // ALBUMMODEL_H
|
||||
|
@ -195,7 +195,7 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
|
||||
TreeModelItem* pi = sourceModel()->itemFromIndex( sourceModel()->index( sourceRow, 0, sourceParent ) );
|
||||
Q_ASSERT( pi );
|
||||
|
||||
if ( m_model->mode() == TreeModel::Database && !pi->result().isNull() )
|
||||
if ( m_model->mode() == Tomahawk::DatabaseMode && !pi->result().isNull() )
|
||||
{
|
||||
QList< Tomahawk::result_ptr > rl = m_cache.values( sourceParent );
|
||||
foreach ( const Tomahawk::result_ptr& result, rl )
|
||||
@ -329,14 +329,34 @@ TreeProxyModel::siblingItem( int itemsAway )
|
||||
Tomahawk::result_ptr
|
||||
TreeProxyModel::siblingItem( int itemsAway, bool readOnly )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
QModelIndex idx = currentIndex();
|
||||
if ( !idx.isValid() )
|
||||
return Tomahawk::result_ptr();
|
||||
|
||||
if ( m_shuffled )
|
||||
idx = index( qrand() % rowCount( idx.parent() ), 0, idx.parent() );
|
||||
else if ( m_repeatMode == PlaylistInterface::RepeatOne )
|
||||
idx = index( idx.row(), 0, idx.parent() );
|
||||
else
|
||||
idx = index( idx.row() + ( itemsAway > 0 ? 1 : -1 ), 0, idx.parent() );
|
||||
|
||||
if ( !idx.isValid() && m_repeatMode == PlaylistInterface::RepeatAll )
|
||||
{
|
||||
if ( itemsAway > 0 )
|
||||
{
|
||||
// reset to first item
|
||||
idx = index( 0, 0, currentIndex().parent() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset to last item
|
||||
idx = index( rowCount( currentIndex().parent() ) - 1, 0, currentIndex().parent() );
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find the next available PlaylistItem (with results)
|
||||
if ( idx.isValid() ) do
|
||||
{
|
||||
idx = index( idx.row() + ( itemsAway > 0 ? 1 : -1 ), 0, idx.parent() );
|
||||
if ( !idx.isValid() )
|
||||
break;
|
||||
|
||||
|