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:
@@ -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 );
|
||||||
|
}
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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 );
|
||||||
|
@@ -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 );
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
|
}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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, "
|
||||||
|
@@ -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();
|
||||||
|
@@ -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 ) );
|
||||||
|
Reference in New Issue
Block a user