1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-02 20:28:14 +02:00

MusicBrainzPlugin: Make more use of Musicbrainz search api features.

This offloads filtering and sorting of the results to musicbrainz and makes the artistID retrieval step obsolte and should speed things up.
This commit is contained in:
Kilian Lackhove
2012-09-10 02:01:27 +02:00
parent 871cf43b3d
commit e8c044a41c
2 changed files with 118 additions and 156 deletions

View File

@@ -62,7 +62,6 @@ MusicBrainzPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{ {
case InfoArtistReleases: case InfoArtistReleases:
{ {
Tomahawk::InfoSystem::InfoStringHash criteria; Tomahawk::InfoSystem::InfoStringHash criteria;
criteria["artist"] = hash["artist"]; criteria["artist"] = hash["artist"];
@@ -72,7 +71,6 @@ MusicBrainzPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
case InfoAlbumSongs: case InfoAlbumSongs:
{ {
Tomahawk::InfoSystem::InfoStringHash criteria; Tomahawk::InfoSystem::InfoStringHash criteria;
criteria["artist"] = hash["artist"]; criteria["artist"] = hash["artist"];
criteria["album"] = hash["album"]; criteria["album"] = hash["album"];
@@ -94,31 +92,103 @@ MusicBrainzPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
void void
MusicBrainzPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requestData ) MusicBrainzPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requestData )
{ {
QString querySt;
switch ( requestData.type ) switch ( requestData.type )
{ {
case InfoArtistReleases: case InfoArtistReleases:
{ {
QString requestString( "http://musicbrainz.org/ws/2/artist" ); querySt.append( QString( "artist:\"%1\"" ).arg(criteria["artist"]) );
querySt.append( " AND (type:album OR type:ep)" );
querySt.append( " AND status:official" );
querySt.append( " AND NOT secondarytype:live" );
querySt.append( " AND NOT secondarytype:compilation" );
// we dont handle more than 100 results atm, but not even the beatles have more than 100 ep+albums, so its probably safe
QString requestString( "http://musicbrainz.org/ws/2/release-group" );
QUrl url( requestString ); QUrl url( requestString );
url.addQueryItem( "query", criteria["artist"] ); url.addQueryItem( "query", querySt );
url.addQueryItem( "limit", "100" );
tDebug() << Q_FUNC_INFO << url.toString();
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) ); QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( artistSearchSlot() ) ); connect( reply, SIGNAL( finished() ), SLOT( gotReleaseGroupsSlot() ) );
break; break;
} }
case InfoAlbumSongs: case InfoAlbumSongs:
{ {
QString requestString( "http://musicbrainz.org/ws/2/artist" ); querySt.append( QString( "release:\"%1\"" ).arg(criteria["album"]) );
querySt.append( QString( " AND artist:\"%1\"" ).arg(criteria["artist"]) );
// not pre-filtering will yield more than 100 results which we dont handle atm. But since we only take the first result anyway that wont hurt
QString requestString( "http://musicbrainz.org/ws/2/release" );
QUrl url( requestString ); QUrl url( requestString );
url.addQueryItem( "query", criteria["artist"] ); url.addQueryItem( "query", querySt );
url.addQueryItem( "limit", "100" );
tDebug() << Q_FUNC_INFO << url.toString();
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) ); QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( albumSearchSlot() ) ); connect( reply, SIGNAL( finished() ), SLOT( gotReleasesSlot() ) );
break; break;
} }
default:
{
Q_ASSERT( false );
break;
}
}
}
void
MusicBrainzPlugin::gotReleaseGroupsSlot()
{
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
if ( !oldReply )
return; //timeout will handle it
QDomDocument doc;
doc.setContent( oldReply->readAll() );
QDomNodeList releaseGroupsNL = doc.elementsByTagName( "release-group" );
if ( releaseGroupsNL.isEmpty() )
{
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
tDebug() << Q_FUNC_INFO << doc.toString();
return;
}
Tomahawk::InfoSystem::InfoRequestData requestData = oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
switch ( requestData.type )
{
case InfoArtistReleases:
{
QStringList albums;
for ( int i = 0; i < releaseGroupsNL.count(); i++ )
{
QString groupTitle = releaseGroupsNL.at(i).firstChildElement("title").text();
QString a = releaseGroupsNL.at(i).firstChildElement( "artist-credit" ).firstChildElement( "name-credit" ).firstChildElement( "artist" ).firstChildElement( "name" ).text();
if ( !albums.contains( groupTitle ) && hash["artist"] == a )
{
albums << groupTitle;
tDebug() << Q_FUNC_INFO << groupTitle;
}
}
QVariantMap returnedData;
returnedData["albums"] = albums;
emit info( requestData, returnedData );
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria["artist"] = origData["artist"];
emit updateCache( criteria, 0, requestData.type, returnedData );
}
default: default:
{ {
@@ -130,7 +200,7 @@ MusicBrainzPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requ
void void
MusicBrainzPlugin::artistSearchSlot() MusicBrainzPlugin::gotReleasesSlot()
{ {
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() ); QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
if ( !oldReply ) if ( !oldReply )
@@ -138,101 +208,44 @@ MusicBrainzPlugin::artistSearchSlot()
QDomDocument doc; QDomDocument doc;
doc.setContent( oldReply->readAll() ); doc.setContent( oldReply->readAll() );
QDomNodeList domNodeList = doc.elementsByTagName( "artist" ); QDomNodeList releasesNL = doc.elementsByTagName( "release" );
if ( domNodeList.isEmpty() ) if ( releasesNL.isEmpty() )
{ {
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() ); emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
tDebug() << Q_FUNC_INFO << doc.toString(); tDebug() << Q_FUNC_INFO << doc.toString();
return; return;
} }
QString artist_id = domNodeList.at( 0 ).toElement().attribute( "id" );
QString requestString( "http://musicbrainz.org/ws/2/release-group" );
QUrl url( requestString );
url.addQueryItem( "artist", artist_id );
url.addQueryItem( "type", "album|ep" );
url.addQueryItem( "limit", "100" );
QNetworkReply* newReply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
newReply->setProperty( "requestData", oldReply->property( "requestData" ) );
connect( newReply, SIGNAL( finished() ), SLOT( albumFoundSlot() ) );
}
void
MusicBrainzPlugin::albumSearchSlot()
{
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
if ( !oldReply )
return; //timeout will handle it
QDomDocument doc;
doc.setContent( oldReply->readAll() );
QDomNodeList domNodeList = doc.elementsByTagName( "artist" );
if ( domNodeList.isEmpty() )
{
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
QString artist_id = domNodeList.at( 0 ).toElement().attribute( "id" );
QString requestString( "http://musicbrainz.org/ws/2/release-group" );
QUrl url( requestString );
url.addQueryItem( "artist", artist_id );
url.addQueryItem( "type", "album|ep" );
url.addQueryItem( "limit", "100" );
QNetworkReply* newReply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
newReply->setProperty( "requestData", oldReply->property( "requestData" ) );
connect( newReply, SIGNAL( finished() ), SLOT( tracksSearchSlot() ) );
}
void
MusicBrainzPlugin::tracksSearchSlot()
{
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
if ( !oldReply )
return; //timeout will handle it
QDomDocument doc;
doc.setContent( oldReply->readAll() );
QDomNodeList domNodeList = doc.elementsByTagName( "release" );
if ( domNodeList.isEmpty() )
{
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
Tomahawk::InfoSystem::InfoRequestData requestData = oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); Tomahawk::InfoSystem::InfoRequestData requestData = oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >(); switch ( requestData.type )
QDomElement element;
for ( int i = 0; i < domNodeList.count(); i++ )
{ {
QDomNodeList albumNodeList = domNodeList.at( i ).toElement().elementsByTagName( "title" ); case InfoAlbumSongs:
if ( albumNodeList.at( 0 ).toElement().text() == hash["album"] )
element = domNodeList.at( i ).toElement();
}
if ( element.isNull() )
{ {
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() ); // we can simply use the first result as they are sorted by score
return; QString release_id = releasesNL.at(0).toElement().attribute( "id" );
}
QString release_id = element.attribute( "id" ); QString requestString = QString( "http://musicbrainz.org/ws/2/release/%1" ).arg( release_id );
QString requestString = QString( "http://musicbrainz.org/ws/2/release/%1?inc=recordings" ).arg( release_id );
QUrl url( requestString ); QUrl url( requestString );
url.addQueryItem( "inc", "recordings" );
tDebug() << Q_FUNC_INFO << url.toString();
QNetworkReply* newReply = TomahawkUtils::nam()->get( QNetworkRequest( url ) ); QNetworkReply* newReply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
newReply->setProperty( "requestData", oldReply->property( "requestData" ) ); newReply->setProperty( "requestData", oldReply->property( "requestData" ) );
connect( newReply, SIGNAL( finished() ), SLOT( tracksFoundSlot() ) ); connect( newReply, SIGNAL( finished() ), SLOT( gotRecordingsSlot() ) );
}
default:
{
Q_ASSERT( false );
break;
}
}
} }
void void
MusicBrainzPlugin::albumFoundSlot() MusicBrainzPlugin::gotRecordingsSlot()
{ {
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() ); QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
if ( !reply ) if ( !reply )
@@ -240,75 +253,26 @@ MusicBrainzPlugin::albumFoundSlot()
QDomDocument doc; QDomDocument doc;
doc.setContent( reply->readAll() ); doc.setContent( reply->readAll() );
QDomNodeList groups = doc.elementsByTagName( "release-group" ); QDomNodeList mediumList = doc.elementsByTagName( "medium-list" );
if ( groups.isEmpty() ) if ( mediumList.isEmpty() )
{ {
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() ); emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
tDebug() << Q_FUNC_INFO << doc.toString();
return; return;
} }
QStringList albums;
for ( int i = 0; i < groups.count(); i++ ) QDomNodeList tracksNL = mediumList.at(0).toElement().elementsByTagName( "track" );
QStringList tracksSL;
for ( int i = 0; i < tracksNL.count(); i++ )
{ {
QDomElement group = groups.at(i).toElement(); QString track = tracksNL.at(i).firstChildElement( "recording" ).firstChildElement( "title" ).text();
QDomNodeList secTypesDL = group.elementsByTagName("secondary-type"); tracksSL << track;
QStringList secTypesSL;
for ( int i = 0; i < secTypesDL.count(); i++ )
{
secTypesSL.append(secTypesDL.at(i).toElement().text());
}
if ( !secTypesSL.contains("Live") && !secTypesSL.contains("Compilation") )
{
QString album = group.firstChildElement("title").text();
if ( !albums.contains( album ) )
albums << album;
}
} }
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
QVariantMap returnedData; QVariantMap returnedData;
returnedData["albums"] = albums; returnedData["tracks"] = tracksSL;
emit info( requestData, returnedData );
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria["artist"] = origData["artist"];
emit updateCache( criteria, 0, requestData.type, returnedData );
}
void
MusicBrainzPlugin::tracksFoundSlot()
{
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
if ( !reply )
return; //timeout will handle it
QDomDocument doc;
doc.setContent( reply->readAll() );
QDomNodeList domNodeList = doc.elementsByTagName( "recording" );
if ( domNodeList.isEmpty() )
{
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
QStringList tracks;
for ( int i = 0; i < domNodeList.count(); i++ )
{
QDomNodeList trackNodeList = domNodeList.at( i ).toElement().elementsByTagName( "title" );
for ( int j = 0; j < trackNodeList.count(); j++ )
{
QString track = trackNodeList.at( j ).toElement().text();
if ( !tracks.contains( track ) )
tracks << track;
}
}
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
QVariantMap returnedData;
returnedData["tracks"] = tracks;
emit info( requestData, returnedData ); emit info( requestData, returnedData );
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>(); Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
@@ -318,5 +282,5 @@ MusicBrainzPlugin::tracksFoundSlot()
emit updateCache( criteria, 0, requestData.type, returnedData ); emit updateCache( criteria, 0, requestData.type, returnedData );
} }
Q_EXPORT_PLUGIN2( Tomahawk::InfoSystem::InfoPlugin, Tomahawk::InfoSystem::MusicBrainzPlugin ) Q_EXPORT_PLUGIN2( Tomahawk::InfoSystem::InfoPlugin, Tomahawk::InfoSystem::MusicBrainzPlugin )

View File

@@ -53,12 +53,10 @@ protected slots:
private slots: private slots:
void artistSearchSlot();
void albumSearchSlot();
void tracksSearchSlot();
void albumFoundSlot(); void gotReleaseGroupsSlot();
void tracksFoundSlot(); void gotReleasesSlot();
void gotRecordingsSlot();
}; };
} }