diff --git a/src/libtomahawk/EchonestCatalogSynchronizer.cpp b/src/libtomahawk/EchonestCatalogSynchronizer.cpp index ba8c6dabe..e8d001d3f 100644 --- a/src/libtomahawk/EchonestCatalogSynchronizer.cpp +++ b/src/libtomahawk/EchonestCatalogSynchronizer.cpp @@ -118,6 +118,9 @@ EchonestCatalogSynchronizer::artistCreateFinished() QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() ); Q_ASSERT( r ); + // We don't support artist catalogs at the moment + return; + /* try { m_artistCatalog = Echonest::Catalog::parseCreate( r ); @@ -131,39 +134,73 @@ EchonestCatalogSynchronizer::artistCreateFinished() { tLog() << "Echonest threw an exception parsing artist catalog create:" << e.what(); return; - } + }*/ } void EchonestCatalogSynchronizer::rawTracks( const QList< QStringList >& tracks ) { tDebug() << "Got raw tracks, num:" << tracks.size(); - Echonest::CatalogUpdateEntries entries( tracks.size() ); - for ( int i = 0; i < tracks.size(); i++ ) + +// int limit = ( tracks.size() < 1000 ) ? tracks.size() : 1000; + + int cur = 0; + while ( cur < tracks.size() ) { - if ( tracks[ i ][ 0 ].isEmpty() || tracks[ i ][ 1 ].isEmpty() ) - continue; + int prev = cur; + cur = ( cur + 2000 > tracks.size() ) ? tracks.size() : cur + 2000; - Echonest::CatalogUpdateEntry entry; - entry.setAction( Echonest::CatalogTypes::Update ); - entry.setSongName( tracks[ i ][ 0 ] ); - entry.setArtistName( tracks[ i ][ 1 ] ); - entry.setRelease( tracks[ i ][ 2 ] ); - entry.setItemId( uuid().toUtf8() ); - - entries.append( entry ); + tDebug() << "Enqueueing a batch of tracks to upload to echonest catalog:" << cur - prev; + Echonest::CatalogUpdateEntries entries( cur - prev ); + for ( int i = prev; i < cur; i++ ) + { + if ( tracks[i][0].isEmpty() || tracks[i][1].isEmpty() ) + continue; + entries.append( entryFromTrack( tracks[i] ) ); + } + m_queuedUpdates.enqueue( entries ); } + doUploadJob(); + +} + +void +EchonestCatalogSynchronizer::doUploadJob() +{ + if ( m_queuedUpdates.isEmpty() ) + return; + + Echonest::CatalogUpdateEntries entries = m_queuedUpdates.dequeue(); + QNetworkReply* updateJob = m_songCatalog.update( entries ); connect( updateJob, SIGNAL( finished() ), this, SLOT( songUpdateFinished() ) ); } + +Echonest::CatalogUpdateEntry +EchonestCatalogSynchronizer::entryFromTrack( const QStringList& track ) const +{ + //qDebug() << "UPLOADING:" << track[0] << track[1] << track[2]; + Echonest::CatalogUpdateEntry entry; + entry.setAction( Echonest::CatalogTypes::Update ); + entry.setSongName( escape( track[ 0 ] ) ); + entry.setArtistName( escape( track[ 1 ] ) ); + entry.setRelease( escape( track[ 2 ] ) ); + entry.setItemId( uuid().toUtf8() ); + + return entry; +} + + void EchonestCatalogSynchronizer::songUpdateFinished() { QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() ); Q_ASSERT( r ); + doUploadJob(); + try { QByteArray ticket = m_songCatalog.parseTicket( r ); @@ -193,3 +230,9 @@ EchonestCatalogSynchronizer::checkTicket() return; } } + +QByteArray +EchonestCatalogSynchronizer::escape( const QString &in ) const +{ + return QUrl::toPercentEncoding( in ); +} diff --git a/src/libtomahawk/EchonestCatalogSynchronizer.h b/src/libtomahawk/EchonestCatalogSynchronizer.h index 766b90856..393e3bc86 100644 --- a/src/libtomahawk/EchonestCatalogSynchronizer.h +++ b/src/libtomahawk/EchonestCatalogSynchronizer.h @@ -19,14 +19,17 @@ #ifndef ECHONESTCATALOGSYNCHRONIZER_H #define ECHONESTCATALOGSYNCHRONIZER_H +#include "dllmacro.h" + #include #include +#include namespace Tomahawk { -class EchonestCatalogSynchronizer : public QObject +class DLLEXPORT EchonestCatalogSynchronizer : public QObject { Q_OBJECT public: @@ -58,12 +61,18 @@ private slots: void rawTracks( const QList< QStringList >& tracks ); private: void uploadDb(); + QByteArray escape( const QString& in ) const; + + Echonest::CatalogUpdateEntry entryFromTrack( const QStringList& ) const; + void doUploadJob(); bool m_syncing; Echonest::Catalog m_songCatalog; Echonest::Catalog m_artistCatalog; + QQueue< Echonest::CatalogUpdateEntries > m_queuedUpdates; + static EchonestCatalogSynchronizer* s_instance; }; diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index 1d4ddf66f..ae9102548 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -19,6 +19,7 @@ #include "audioengine.h" #include +#include #include "playlistinterface.h" #include "sourceplaylistinterface.h" @@ -27,6 +28,7 @@ #include "database/database.h" #include "database/databasecommand_logplayback.h" #include "network/servent.h" +#include "utils/qnr_iodevicestream.h" #include "album.h" @@ -424,7 +426,10 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result ) if ( !isHttpResult( m_currentTrack->url() ) && !isLocalResult( m_currentTrack->url() ) ) { - m_mediaObject->setCurrentSource( io.data() ); + if ( QNetworkReply* qnr_io = qobject_cast< QNetworkReply* >( io.data() ) ) + m_mediaObject->setCurrentSource( new QNR_IODeviceStream( qnr_io, this ) ); + else + m_mediaObject->setCurrentSource( io.data() ); m_mediaObject->currentSource().setAutoDelete( false ); m_isPlayingHttp = false; } diff --git a/src/libtomahawk/database/databasecommand.cpp b/src/libtomahawk/database/databasecommand.cpp index efa32f71e..9397ba853 100644 --- a/src/libtomahawk/database/databasecommand.cpp +++ b/src/libtomahawk/database/databasecommand.cpp @@ -31,6 +31,7 @@ #include "databasecommand_socialaction.h" #include "utils/logger.h" +#include "databasecommand_setcollectionattributes.h" DatabaseCommand::DatabaseCommand( QObject* parent ) @@ -166,6 +167,13 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source ) QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd ); return cmd; } + else if( name == "setcollectionattributes" ) + { + DatabaseCommand_SetCollectionAttributes * cmd = new DatabaseCommand_SetCollectionAttributes; + cmd->setSource( source ); + QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd ); + return cmd; + } qDebug() << "ERROR in" << Q_FUNC_INFO << name; // Q_ASSERT( false ); diff --git a/src/libtomahawk/database/databasecommand_collectionattributes.cpp b/src/libtomahawk/database/databasecommand_collectionattributes.cpp index b1f7493ec..9454d5e3d 100644 --- a/src/libtomahawk/database/databasecommand_collectionattributes.cpp +++ b/src/libtomahawk/database/databasecommand_collectionattributes.cpp @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with Tomahawk. If not, see . */ -#include "DatabaseCommand_CollectionAttributes.h" +#include "databasecommand_collectionattributes.h" #include "databaseimpl.h" #include "source.h" @@ -44,7 +44,7 @@ DatabaseCommand_CollectionAttributes::exec( DatabaseImpl *lib ) else if ( m_type == DatabaseCommand_SetCollectionAttributes::EchonestArtistCatalog ) typeStr = "echonest_artist"; - QString queryStr = QString( "SELECT k, v FROM collection_attributes WHERE k = \"%1\"" ).arg( typeStr ); + QString queryStr = QString( "SELECT id, v FROM collection_attributes WHERE k = \"%1\"" ).arg( typeStr ); qDebug() << "Doing queryL" << queryStr; query.exec( queryStr ); PairList data; @@ -55,5 +55,5 @@ DatabaseCommand_CollectionAttributes::exec( DatabaseImpl *lib ) part.second = query.value( 1 ).toString(); data << part; } - emit data; + emit collectionAttributes( data ); } diff --git a/src/libtomahawk/database/databasecommand_setcollectionattributes.cpp b/src/libtomahawk/database/databasecommand_setcollectionattributes.cpp index 5b13baf5b..e021cb5a6 100644 --- a/src/libtomahawk/database/databasecommand_setcollectionattributes.cpp +++ b/src/libtomahawk/database/databasecommand_setcollectionattributes.cpp @@ -15,15 +15,16 @@ * You should have received a copy of the GNU General Public License * along with Tomahawk. If not, see . */ -#include "DatabaseCommand_SetCollectionAttributes.h" +#include "databasecommand_setcollectionattributes.h" #include "databaseimpl.h" #include "source.h" +#include "network/servent.h" DatabaseCommand_SetCollectionAttributes::DatabaseCommand_SetCollectionAttributes( const Tomahawk::source_ptr& source, AttributeType type, const QByteArray& id ) : DatabaseCommandLoggable( source ) - , m_id( id ) , m_type( type ) + , m_id( id ) { } @@ -44,7 +45,16 @@ DatabaseCommand_SetCollectionAttributes::exec( DatabaseImpl *lib ) else if ( m_type == EchonestArtistCatalog ) typeStr = "echonest_artist"; - QString queryStr = QString( "REPLACE INTO collection_attributes ( id, k, v ) VALUES( %1, \"%2\", \"%3\" )" ).arg( sourceStr ).arg( typeStr ).arg( QString::fromUtf8( m_id ) ); + TomahawkSqlQuery delQuery = lib->newquery(); + delQuery.exec( QString( "DELETE FROM collection_attributes WHERE id %1" ).arg( source()->isLocal() ? QString("IS NULL") : QString( "= %1" ).arg( source()->id() ))); + + QString queryStr = QString( "INSERT INTO collection_attributes ( id, k, v ) VALUES( %1, \"%2\", \"%3\" )" ).arg( sourceStr ).arg( typeStr ).arg( QString::fromUtf8( m_id ) ); qDebug() << "Doing query:" << queryStr; query.exec( queryStr ); } + +void +DatabaseCommand_SetCollectionAttributes::postCommitHook() +{ + Servent::instance()->triggerDBSync(); +} diff --git a/src/libtomahawk/database/databasecommand_setcollectionattributes.h b/src/libtomahawk/database/databasecommand_setcollectionattributes.h index 34d3c6016..be07a3672 100644 --- a/src/libtomahawk/database/databasecommand_setcollectionattributes.h +++ b/src/libtomahawk/database/databasecommand_setcollectionattributes.h @@ -25,6 +25,10 @@ class DatabaseCommand_SetCollectionAttributes : public DatabaseCommandLoggable { + Q_OBJECT + Q_PROPERTY( QByteArray id READ id WRITE setId ) + Q_PROPERTY( int type READ type WRITE setType ) + public: enum AttributeType { EchonestSongCatalog = 0, @@ -32,10 +36,18 @@ public: }; DatabaseCommand_SetCollectionAttributes( const Tomahawk::source_ptr& source, AttributeType type, const QByteArray& id ); + DatabaseCommand_SetCollectionAttributes() {} // JSON virtual void exec( DatabaseImpl* lib ); virtual bool doesMutates() const { return true; } + virtual void postCommitHook(); - virtual QString commandname() const { return "saveechonestcatalog"; } + virtual QString commandname() const { return "setcollectionattributes"; } + + void setId( const QByteArray& id ) { m_id = id; } + QByteArray id() const { return m_id; } + + void setType( int type ) { m_type = (AttributeType)type; } + int type() const { return (int)m_type; } private: AttributeType m_type; diff --git a/src/libtomahawk/database/schema.sql.h b/src/libtomahawk/database/schema.sql.h index 5b223db46..709e226cb 100644 --- a/src/libtomahawk/database/schema.sql.h +++ b/src/libtomahawk/database/schema.sql.h @@ -1,5 +1,5 @@ /* - This file was automatically generated from ./schema.sql on Sun Sep 25 10:36:01 EDT 2011. + This file was automatically generated from schema.sql on Thu Sep 29 17:28:17 EDT 2011. */ static const char * tomahawk_schema_sql = @@ -156,7 +156,7 @@ static const char * tomahawk_schema_sql = " id INTEGER REFERENCES source(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, " " k TEXT NOT NULL," " v TEXT NOT NULL" -"};" +");" "CREATE TABLE IF NOT EXISTS social_attributes (" " id INTEGER REFERENCES track(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, " " source INTEGER REFERENCES source(id) ON DELETE CASCADE ON UPDATE CASCADE, " diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp index a6bd7be79..732919005 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp @@ -208,7 +208,6 @@ Tomahawk::EchonestControl::updateWidgets() { combo->addItem( str, EchonestGenerator::catalogId( str ) ); } - combo->addItem( "lfranchi@gmail.com", "CATNEQO132A15A6C7A" ); m_matchString = match->text(); m_matchData = match->text(); diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp index 2a59c439b..24efe9d87 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp @@ -25,6 +25,7 @@ #include "database/databasecommand_collectionattributes.h" #include "database/database.h" #include "utils/logger.h" +#include "sourcelist.h" #include #include @@ -386,7 +387,11 @@ EchonestGenerator::collectionAttributes(PairList data) QPair part; foreach ( part, data ) { - s_catalogs.insert( part.first, part.second ); + if ( SourceList::instance()->get( part.first.toInt() ).isNull() ) + continue; + + const QString name = SourceList::instance()->get( part.first.toInt() )->friendlyName(); + s_catalogs.insert( name, part.second ); } } @@ -441,7 +446,8 @@ EchonestGenerator::appendRadioType( Echonest::DynamicPlaylist::PlaylistParams& p /// 5. song-radio: If all the artist entries are Similar To. If some were but not all, error out. bool someCatalog = false; foreach( const dyncontrol_ptr& control, m_controls ) { - someCatalog = true; + if ( control->selectedType() == "Catalog Radio" ) + someCatalog = true; } if( someCatalog ) params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::CatalogRadioType ) );