1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 19:30:21 +02:00

More work on getting basic uploading to work, and showing in echonest controls

This commit is contained in:
Leo Franchi
2011-09-25 13:45:35 -04:00
parent 13ac8c093a
commit 1e6bbba189
10 changed files with 119 additions and 27 deletions

View File

@@ -118,6 +118,9 @@ EchonestCatalogSynchronizer::artistCreateFinished()
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() ); QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
Q_ASSERT( r ); Q_ASSERT( r );
// We don't support artist catalogs at the moment
return;
/*
try try
{ {
m_artistCatalog = Echonest::Catalog::parseCreate( r ); m_artistCatalog = Echonest::Catalog::parseCreate( r );
@@ -131,39 +134,73 @@ EchonestCatalogSynchronizer::artistCreateFinished()
{ {
tLog() << "Echonest threw an exception parsing artist catalog create:" << e.what(); tLog() << "Echonest threw an exception parsing artist catalog create:" << e.what();
return; return;
} }*/
} }
void void
EchonestCatalogSynchronizer::rawTracks( const QList< QStringList >& tracks ) EchonestCatalogSynchronizer::rawTracks( const QList< QStringList >& tracks )
{ {
tDebug() << "Got raw tracks, num:" << tracks.size(); 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() ) int prev = cur;
continue; cur = ( cur + 2000 > tracks.size() ) ? tracks.size() : cur + 2000;
Echonest::CatalogUpdateEntry entry; tDebug() << "Enqueueing a batch of tracks to upload to echonest catalog:" << cur - prev;
entry.setAction( Echonest::CatalogTypes::Update ); Echonest::CatalogUpdateEntries entries( cur - prev );
entry.setSongName( tracks[ i ][ 0 ] ); for ( int i = prev; i < cur; i++ )
entry.setArtistName( tracks[ i ][ 1 ] ); {
entry.setRelease( tracks[ i ][ 2 ] ); if ( tracks[i][0].isEmpty() || tracks[i][1].isEmpty() )
entry.setItemId( uuid().toUtf8() ); continue;
entries.append( entryFromTrack( tracks[i] ) );
entries.append( entry ); }
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 ); QNetworkReply* updateJob = m_songCatalog.update( entries );
connect( updateJob, SIGNAL( finished() ), this, SLOT( songUpdateFinished() ) ); 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 void
EchonestCatalogSynchronizer::songUpdateFinished() EchonestCatalogSynchronizer::songUpdateFinished()
{ {
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() ); QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
Q_ASSERT( r ); Q_ASSERT( r );
doUploadJob();
try try
{ {
QByteArray ticket = m_songCatalog.parseTicket( r ); QByteArray ticket = m_songCatalog.parseTicket( r );
@@ -193,3 +230,9 @@ EchonestCatalogSynchronizer::checkTicket()
return; return;
} }
} }
QByteArray
EchonestCatalogSynchronizer::escape( const QString &in ) const
{
return QUrl::toPercentEncoding( in );
}

View File

@@ -19,14 +19,17 @@
#ifndef ECHONESTCATALOGSYNCHRONIZER_H #ifndef ECHONESTCATALOGSYNCHRONIZER_H
#define ECHONESTCATALOGSYNCHRONIZER_H #define ECHONESTCATALOGSYNCHRONIZER_H
#include "dllmacro.h"
#include <echonest/Catalog.h> #include <echonest/Catalog.h>
#include <QObject> #include <QObject>
#include <QQueue>
namespace Tomahawk namespace Tomahawk
{ {
class EchonestCatalogSynchronizer : public QObject class DLLEXPORT EchonestCatalogSynchronizer : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
@@ -58,12 +61,18 @@ private slots:
void rawTracks( const QList< QStringList >& tracks ); void rawTracks( const QList< QStringList >& tracks );
private: private:
void uploadDb(); void uploadDb();
QByteArray escape( const QString& in ) const;
Echonest::CatalogUpdateEntry entryFromTrack( const QStringList& ) const;
void doUploadJob();
bool m_syncing; bool m_syncing;
Echonest::Catalog m_songCatalog; Echonest::Catalog m_songCatalog;
Echonest::Catalog m_artistCatalog; Echonest::Catalog m_artistCatalog;
QQueue< Echonest::CatalogUpdateEntries > m_queuedUpdates;
static EchonestCatalogSynchronizer* s_instance; static EchonestCatalogSynchronizer* s_instance;
}; };

View File

@@ -19,6 +19,7 @@
#include "audioengine.h" #include "audioengine.h"
#include <QUrl> #include <QUrl>
#include <QNetworkReply>
#include "playlistinterface.h" #include "playlistinterface.h"
#include "sourceplaylistinterface.h" #include "sourceplaylistinterface.h"
@@ -27,6 +28,7 @@
#include "database/database.h" #include "database/database.h"
#include "database/databasecommand_logplayback.h" #include "database/databasecommand_logplayback.h"
#include "network/servent.h" #include "network/servent.h"
#include "utils/qnr_iodevicestream.h"
#include "album.h" #include "album.h"
@@ -424,7 +426,10 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
if ( !isHttpResult( m_currentTrack->url() ) && !isLocalResult( m_currentTrack->url() ) ) 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_mediaObject->currentSource().setAutoDelete( false );
m_isPlayingHttp = false; m_isPlayingHttp = false;
} }

View File

@@ -31,6 +31,7 @@
#include "databasecommand_socialaction.h" #include "databasecommand_socialaction.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "databasecommand_setcollectionattributes.h"
DatabaseCommand::DatabaseCommand( QObject* parent ) DatabaseCommand::DatabaseCommand( QObject* parent )
@@ -166,6 +167,13 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd ); QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
return 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; qDebug() << "ERROR in" << Q_FUNC_INFO << name;
// Q_ASSERT( false ); // Q_ASSERT( false );

View File

@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "DatabaseCommand_CollectionAttributes.h" #include "databasecommand_collectionattributes.h"
#include "databaseimpl.h" #include "databaseimpl.h"
#include "source.h" #include "source.h"
@@ -44,7 +44,7 @@ DatabaseCommand_CollectionAttributes::exec( DatabaseImpl *lib )
else if ( m_type == DatabaseCommand_SetCollectionAttributes::EchonestArtistCatalog ) else if ( m_type == DatabaseCommand_SetCollectionAttributes::EchonestArtistCatalog )
typeStr = "echonest_artist"; 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; qDebug() << "Doing queryL" << queryStr;
query.exec( queryStr ); query.exec( queryStr );
PairList data; PairList data;
@@ -55,5 +55,5 @@ DatabaseCommand_CollectionAttributes::exec( DatabaseImpl *lib )
part.second = query.value( 1 ).toString(); part.second = query.value( 1 ).toString();
data << part; data << part;
} }
emit data; emit collectionAttributes( data );
} }

View File

@@ -15,15 +15,16 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "DatabaseCommand_SetCollectionAttributes.h" #include "databasecommand_setcollectionattributes.h"
#include "databaseimpl.h" #include "databaseimpl.h"
#include "source.h" #include "source.h"
#include "network/servent.h"
DatabaseCommand_SetCollectionAttributes::DatabaseCommand_SetCollectionAttributes( const Tomahawk::source_ptr& source, AttributeType type, const QByteArray& id ) DatabaseCommand_SetCollectionAttributes::DatabaseCommand_SetCollectionAttributes( const Tomahawk::source_ptr& source, AttributeType type, const QByteArray& id )
: DatabaseCommandLoggable( source ) : DatabaseCommandLoggable( source )
, m_id( id )
, m_type( type ) , m_type( type )
, m_id( id )
{ {
} }
@@ -44,7 +45,16 @@ DatabaseCommand_SetCollectionAttributes::exec( DatabaseImpl *lib )
else if ( m_type == EchonestArtistCatalog ) else if ( m_type == EchonestArtistCatalog )
typeStr = "echonest_artist"; 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; qDebug() << "Doing query:" << queryStr;
query.exec( queryStr ); query.exec( queryStr );
} }
void
DatabaseCommand_SetCollectionAttributes::postCommitHook()
{
Servent::instance()->triggerDBSync();
}

View File

@@ -25,6 +25,10 @@
class DatabaseCommand_SetCollectionAttributes : public DatabaseCommandLoggable class DatabaseCommand_SetCollectionAttributes : public DatabaseCommandLoggable
{ {
Q_OBJECT
Q_PROPERTY( QByteArray id READ id WRITE setId )
Q_PROPERTY( int type READ type WRITE setType )
public: public:
enum AttributeType { enum AttributeType {
EchonestSongCatalog = 0, EchonestSongCatalog = 0,
@@ -32,10 +36,18 @@ public:
}; };
DatabaseCommand_SetCollectionAttributes( const Tomahawk::source_ptr& source, AttributeType type, const QByteArray& id ); DatabaseCommand_SetCollectionAttributes( const Tomahawk::source_ptr& source, AttributeType type, const QByteArray& id );
DatabaseCommand_SetCollectionAttributes() {} // JSON
virtual void exec( DatabaseImpl* lib ); virtual void exec( DatabaseImpl* lib );
virtual bool doesMutates() const { return true; } 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: private:
AttributeType m_type; AttributeType m_type;

View File

@@ -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 = 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, " " id INTEGER REFERENCES source(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, "
" k TEXT NOT NULL," " k TEXT NOT NULL,"
" v TEXT NOT NULL" " v TEXT NOT NULL"
"};" ");"
"CREATE TABLE IF NOT EXISTS social_attributes (" "CREATE TABLE IF NOT EXISTS social_attributes ("
" id INTEGER REFERENCES track(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, " " 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, " " source INTEGER REFERENCES source(id) ON DELETE CASCADE ON UPDATE CASCADE, "

View File

@@ -208,7 +208,6 @@ Tomahawk::EchonestControl::updateWidgets()
{ {
combo->addItem( str, EchonestGenerator::catalogId( str ) ); combo->addItem( str, EchonestGenerator::catalogId( str ) );
} }
combo->addItem( "lfranchi@gmail.com", "CATNEQO132A15A6C7A" );
m_matchString = match->text(); m_matchString = match->text();
m_matchData = match->text(); m_matchData = match->text();

View File

@@ -25,6 +25,7 @@
#include "database/databasecommand_collectionattributes.h" #include "database/databasecommand_collectionattributes.h"
#include "database/database.h" #include "database/database.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "sourcelist.h"
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
@@ -386,7 +387,11 @@ EchonestGenerator::collectionAttributes(PairList data)
QPair<QString, QString> part; QPair<QString, QString> part;
foreach ( part, data ) 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. /// 5. song-radio: If all the artist entries are Similar To. If some were but not all, error out.
bool someCatalog = false; bool someCatalog = false;
foreach( const dyncontrol_ptr& control, m_controls ) { foreach( const dyncontrol_ptr& control, m_controls ) {
someCatalog = true; if ( control->selectedType() == "Catalog Radio" )
someCatalog = true;
} }
if( someCatalog ) if( someCatalog )
params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::CatalogRadioType ) ); params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::CatalogRadioType ) );