File indexing completed on 2024-05-19 04:50:23
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org> * 0003 * Copyright (c) 2007 Adam Pigg <adam@piggz.co.uk> * 0004 * Copyright (c) 2007,2008 Casey Link <unnamedrambler@gmail.com> * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify it under * 0007 * the terms of the GNU General Public License as published by the Free Software * 0008 * Foundation; either version 2 of the License, or (at your option) any later * 0009 * version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0013 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License along with * 0016 * this program. If not, see <http://www.gnu.org/licenses/>. * 0017 ****************************************************************************************/ 0018 0019 #include "Mp3tunesServiceQueryMaker.h" 0020 0021 #include "core/support/Amarok.h" 0022 #include "core/support/Debug.h" 0023 #include "Mp3tunesMeta.h" 0024 #include "Mp3tunesWorkers.h" 0025 #include "core-impl/collections/support/MemoryMatcher.h" 0026 0027 #include <ThreadWeaver/Job> 0028 #include <ThreadWeaver/ThreadWeaver> 0029 #include <ThreadWeaver/Queue> 0030 0031 #include <QList> 0032 0033 using namespace Collections; 0034 0035 class Mp3tunesServiceQueryMaker::Private { 0036 public: 0037 enum QueryType { NONE, TRACK, ARTIST, ALBUM, COMPOSER, YEAR, GENRE, CUSTOM }; 0038 QueryType type; 0039 int maxsize; 0040 }; 0041 0042 0043 Mp3tunesServiceQueryMaker::Mp3tunesServiceQueryMaker( Mp3tunesServiceCollection * collection, const QString &sessionId ) 0044 : DynamicServiceQueryMaker() 0045 , m_storedTransferJob( ) 0046 , d( new Private ) 0047 0048 { 0049 DEBUG_BLOCK 0050 m_collection = collection; 0051 m_sessionId = sessionId; 0052 0053 d->type = Private::NONE; 0054 d->maxsize = -1; 0055 } 0056 0057 Mp3tunesServiceQueryMaker::Mp3tunesServiceQueryMaker( Mp3tunesLocker * locker, const QString &sessionId, Mp3tunesServiceCollection * collection ) 0058 : DynamicServiceQueryMaker() 0059 , m_storedTransferJob( ) 0060 , d( new Private ) 0061 { 0062 DEBUG_BLOCK 0063 m_collection = collection; 0064 m_sessionId = sessionId; 0065 m_locker = locker; 0066 0067 d->type = Private::NONE; 0068 d->maxsize = -1; 0069 } 0070 0071 Mp3tunesServiceQueryMaker::~Mp3tunesServiceQueryMaker() 0072 { 0073 delete d; 0074 } 0075 0076 void Mp3tunesServiceQueryMaker::run() 0077 { 0078 DEBUG_BLOCK 0079 if ( m_storedTransferJob != 0 ) 0080 return; 0081 0082 m_collection->acquireReadLock(); 0083 //naive implementation, fix this 0084 //note: we are not handling filtering yet 0085 0086 if ( d->type == Private::NONE ) 0087 //TODO error handling 0088 return; 0089 if ( d->type == Private::ARTIST ) 0090 fetchArtists(); 0091 else if ( d->type == Private::ALBUM ) 0092 fetchAlbums(); 0093 else if ( d->type == Private::TRACK ) 0094 fetchTracks(); 0095 0096 m_collection->releaseLock(); 0097 } 0098 0099 0100 void Mp3tunesServiceQueryMaker::abortQuery() 0101 {} 0102 0103 QueryMaker* 0104 Mp3tunesServiceQueryMaker::setQueryType( QueryType type ) 0105 { 0106 switch( type ) { 0107 case QueryMaker::Artist: 0108 case QueryMaker::AlbumArtist: 0109 { 0110 DEBUG_BLOCK 0111 d->type = Private::ARTIST; 0112 return this; 0113 } 0114 0115 case QueryMaker::Album: 0116 { 0117 DEBUG_BLOCK 0118 d->type = Private::ALBUM; 0119 return this; 0120 } 0121 0122 case QueryMaker::Track: 0123 { 0124 DEBUG_BLOCK 0125 d->type = Private::TRACK; 0126 return this; 0127 } 0128 0129 case QueryMaker::Genre: 0130 case QueryMaker::Composer: 0131 case QueryMaker::Year: 0132 case QueryMaker::Custom: 0133 case QueryMaker::None: 0134 default: 0135 //TODO: Implement. 0136 return this; 0137 } 0138 } 0139 0140 0141 0142 QueryMaker * Mp3tunesServiceQueryMaker::addMatch( const Meta::ArtistPtr & artist ) 0143 { 0144 DEBUG_BLOCK 0145 if ( m_parentAlbumId.isEmpty() ) { 0146 const Meta::ServiceArtist * serviceArtist = static_cast< const Meta::ServiceArtist * >( artist.data() ); 0147 m_parentArtistId = QString::number( serviceArtist->id() ); 0148 debug() << "artist parent id set to: " << m_parentArtistId; 0149 } 0150 0151 return this; 0152 } 0153 0154 QueryMaker * Mp3tunesServiceQueryMaker::addMatch(const Meta::AlbumPtr & album) 0155 { 0156 DEBUG_BLOCK 0157 const Meta::ServiceAlbum * serviceAlbum = static_cast< const Meta::ServiceAlbum * >( album.data() ); 0158 m_parentAlbumId = QString::number( serviceAlbum->id() ); 0159 debug() << "album parent id set to: " << m_parentAlbumId; 0160 m_parentArtistId.clear(); 0161 0162 return this; 0163 } 0164 0165 void Mp3tunesServiceQueryMaker::handleResult() 0166 { 0167 DEBUG_BLOCK 0168 } 0169 0170 void Mp3tunesServiceQueryMaker::handleResult( const Meta::ArtistList & artists ) 0171 { 0172 DEBUG_BLOCK 0173 0174 if ( d->maxsize >= 0 && artists.count() > d->maxsize ) { 0175 emit newArtistsReady( artists.mid( 0, d->maxsize ) ); 0176 } else { 0177 emit newArtistsReady( artists ); 0178 } 0179 } 0180 0181 void Mp3tunesServiceQueryMaker::handleResult( const Meta::AlbumList &albums ) 0182 { 0183 DEBUG_BLOCK 0184 0185 if ( d->maxsize >= 0 && albums.count() > d->maxsize ) { 0186 emit newAlbumsReady( albums.mid( 0, d->maxsize ) ); 0187 } else { 0188 emit newAlbumsReady( albums ); 0189 } 0190 } 0191 0192 void Mp3tunesServiceQueryMaker::handleResult(const Meta::TrackList & tracks) 0193 { 0194 DEBUG_BLOCK 0195 0196 if ( d->maxsize >= 0 && tracks.count() > d->maxsize ) { 0197 emit newTracksReady( tracks.mid( 0, d->maxsize ) ); 0198 } else { 0199 emit newTracksReady( tracks ); 0200 } 0201 } 0202 0203 0204 void Mp3tunesServiceQueryMaker::fetchArtists() 0205 { 0206 DEBUG_BLOCK 0207 if ( !m_artistFilter.isEmpty() ) 0208 { 0209 debug() << "Artist Filtering"; 0210 Mp3tunesSearchMonkey * searchMonkey = new Mp3tunesSearchMonkey( m_locker, m_artistFilter, Mp3tunesSearchResult::ArtistQuery ); 0211 connect( searchMonkey, &Mp3tunesSearchMonkey::searchArtistComplete, this, &Mp3tunesServiceQueryMaker::artistDownloadComplete ); 0212 ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(searchMonkey) ); //Go! 0213 } else if( m_locker->sessionValid() ) 0214 { 0215 debug() << "Artist Fetching"; 0216 Mp3tunesArtistFetcher * artistFetcher = new Mp3tunesArtistFetcher( m_locker ); 0217 connect( artistFetcher, &Mp3tunesArtistFetcher::artistsFetched, this, &Mp3tunesServiceQueryMaker::artistDownloadComplete ); 0218 ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(artistFetcher) ); 0219 } 0220 } 0221 0222 void Mp3tunesServiceQueryMaker::fetchAlbums() 0223 { 0224 DEBUG_BLOCK 0225 0226 Meta::AlbumList albums; 0227 0228 debug() << "Fetching Albums for parentArtist id: " << m_parentArtistId; 0229 0230 if ( !m_parentArtistId.isEmpty() ) { 0231 albums = matchAlbums( m_collection, m_collection->artistById( m_parentArtistId.toInt() ) ); 0232 } else { 0233 debug() << "parent id empty"; 0234 return; 0235 } 0236 0237 if ( albums.count() > 0 ) { 0238 handleResult( albums ); 0239 } else if ( m_locker->sessionValid() ) { 0240 Mp3tunesAlbumWithArtistIdFetcher * albumFetcher = new Mp3tunesAlbumWithArtistIdFetcher( m_locker, m_parentArtistId.toInt() ); 0241 connect( albumFetcher, &Mp3tunesAlbumWithArtistIdFetcher::albumsFetched, this, &Mp3tunesServiceQueryMaker::albumDownloadComplete ); 0242 0243 ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(albumFetcher) ); 0244 } else { 0245 debug() << "Session Invalid"; 0246 } 0247 } 0248 0249 void Mp3tunesServiceQueryMaker::fetchTracks() 0250 { 0251 DEBUG_BLOCK 0252 0253 Meta::AlbumList albums; 0254 Meta::TrackList tracks; 0255 0256 debug() << "album parent id: " << m_parentAlbumId; 0257 debug() << "artist parent id: " << m_parentArtistId; 0258 0259 if ( !m_parentArtistId.isEmpty() ) { 0260 ArtistMatcher artistMatcher( m_collection->artistById( m_parentArtistId.toInt() ) ); 0261 tracks = artistMatcher.match( m_collection->trackMap().values() ); 0262 } else if ( !m_parentAlbumId.isEmpty() ) { 0263 AlbumMatcher albumMatcher( m_collection->albumById( m_parentAlbumId.toInt() ) ); 0264 tracks = albumMatcher.match( m_collection->trackMap().values() ); 0265 } else { 0266 debug() << "parent id empty"; 0267 return; 0268 } 0269 0270 if ( tracks.count() > 0 ) { 0271 debug() << tracks.count() << " Tracks selected"; 0272 handleResult( tracks ); 0273 emit queryDone(); 0274 } else if ( m_locker->sessionValid() ) { 0275 if( !m_parentArtistId.isEmpty() ) { 0276 debug() << "Creating track w/ artist id Fetch Worker"; 0277 Mp3tunesTrackWithArtistIdFetcher * trackFetcher = new Mp3tunesTrackWithArtistIdFetcher( m_locker, m_parentArtistId.toInt() ); 0278 connect( trackFetcher, &Mp3tunesTrackWithArtistIdFetcher::tracksFetched, this, &Mp3tunesServiceQueryMaker::trackDownloadComplete ); 0279 ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(trackFetcher) ); //Go! 0280 } else if ( !m_parentAlbumId.isEmpty() ) { 0281 debug() << "Creating track w/ album id Fetch Worker"; 0282 Mp3tunesTrackWithAlbumIdFetcher * trackFetcher = new Mp3tunesTrackWithAlbumIdFetcher( m_locker, m_parentAlbumId.toInt() ); 0283 connect( trackFetcher, &Mp3tunesTrackWithAlbumIdFetcher::tracksFetched, this, &Mp3tunesServiceQueryMaker::trackDownloadComplete ); 0284 ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(trackFetcher) ); //Go! 0285 } 0286 } else { 0287 debug() << "Session Invalid"; 0288 return; 0289 } 0290 } 0291 0292 void Mp3tunesServiceQueryMaker::artistDownloadComplete( QList<Mp3tunesLockerArtist> artistList ) 0293 { 0294 DEBUG_BLOCK 0295 0296 Meta::ArtistList artists; 0297 0298 debug() << "Received artists"; 0299 foreach(const Mp3tunesLockerArtist &artist, artistList) { 0300 Meta::ServiceArtist * serviceArtist = new Meta::ServiceArtist( artist.artistName() ); 0301 0302 //debug() << "Adding artist: " << artist.artistName(); 0303 0304 serviceArtist->setId( artist.artistId() ); 0305 0306 Meta::ArtistPtr artistPtr( serviceArtist ); 0307 0308 artists.push_back( artistPtr ); 0309 0310 m_collection->acquireWriteLock(); 0311 m_collection->addArtist( artistPtr ); 0312 m_collection->releaseLock(); 0313 0314 } 0315 0316 handleResult( artists ); 0317 emit queryDone(); 0318 0319 } 0320 0321 void Mp3tunesServiceQueryMaker::albumDownloadComplete( QList<Mp3tunesLockerAlbum> albumsList ) 0322 { 0323 DEBUG_BLOCK 0324 0325 debug() << "Received albums"; 0326 0327 Meta::AlbumList albums; 0328 foreach(const Mp3tunesLockerAlbum &album, albumsList) { 0329 0330 QString title = album.albumTitle(); 0331 if ( title.contains("* PlayMix") ) continue; 0332 if ( title.isEmpty() ) title = "Unknown"; 0333 0334 QString albumIdStr = QString::number( album.albumId() ); 0335 int albumId = album.albumId(); 0336 0337 bool hasArt = album.hasArt(); 0338 0339 Meta::Mp3TunesAlbum * serviceAlbum = new Meta::Mp3TunesAlbum( title ); 0340 0341 if ( hasArt ) 0342 { 0343 0344 QString coverUrl = "http://content.mp3tunes.com/storage/albumartget/<ALBUM_ID>?alternative=1&partner_token=<PARTNER_TOKEN>&sid=<SESSION_ID>"; 0345 0346 coverUrl.replace( "<SESSION_ID>", m_locker->sessionId() ); 0347 coverUrl.replace( "<PARTNER_TOKEN>", m_locker->partnerToken() ); 0348 coverUrl.replace( "<ALBUM_ID>", albumIdStr ); 0349 0350 serviceAlbum->setCoverUrl(coverUrl); 0351 } 0352 0353 Meta::AlbumPtr albumPtr( serviceAlbum ); 0354 0355 //debug() << "Adding album: " << title; 0356 0357 serviceAlbum->setId( albumId ); 0358 m_collection->acquireWriteLock(); 0359 m_collection->addAlbum( albumPtr ); 0360 m_collection->releaseLock(); 0361 0362 Meta::ArtistPtr artistPtr = m_collection->artistById( album.artistId() ); 0363 if ( artistPtr.data() != 0 ) 0364 { 0365 //debug() << "Found parent artist"; 0366 serviceAlbum->setAlbumArtist( artistPtr ); 0367 } 0368 0369 albums.push_back( albumPtr ); 0370 0371 } 0372 0373 handleResult( albums ); 0374 emit queryDone(); 0375 0376 } 0377 0378 void Mp3tunesServiceQueryMaker::trackDownloadComplete( QList<Mp3tunesLockerTrack> tracksList ) 0379 { 0380 DEBUG_BLOCK 0381 //debug() << "Received Tracks"; 0382 0383 Meta::TrackList tracks; 0384 0385 //so lets figure out what we got here: 0386 0387 foreach(const Mp3tunesLockerTrack &track, tracksList) 0388 { 0389 0390 QString title = track.trackTitle(); 0391 if ( title.isEmpty() ) title = "Unknown"; 0392 0393 Meta::Mp3TunesTrack * serviceTrack = new Meta::Mp3TunesTrack( title ); 0394 Meta::TrackPtr trackPtr( serviceTrack ); 0395 0396 // debug() << "Adding track: " << title; 0397 0398 serviceTrack->setId( track.trackId() ); 0399 0400 serviceTrack->setUidUrl( track.playUrl() ); 0401 serviceTrack->setDownloadableUrl( track.downloadUrl() ); 0402 0403 serviceTrack->setLength( track.trackLength() ); 0404 0405 serviceTrack->setTrackNumber( track.trackNumber() ); 0406 0407 serviceTrack->setYear( track.albumYear() ); 0408 0409 debug() << "setting type: " << Amarok::extension( track.trackFileName() ); 0410 serviceTrack->setType( Amarok::extension( track.trackFileName() ) ); 0411 //debug() << "set type"; 0412 m_collection->acquireWriteLock(); 0413 //debug() << "adding track"; 0414 m_collection->addTrack( trackPtr ); 0415 //debug() << "added tracktrack"; 0416 m_collection->releaseLock(); 0417 QString albumId = QString::number( track.albumId() ); 0418 QString artistId = QString::number( track.artistId() ); 0419 0420 Meta::ArtistPtr artistPtr = m_collection->artistById( artistId.toInt() ); 0421 if ( artistPtr.data() != 0 ) { 0422 debug() << "Found parent artist"; 0423 Meta::ServiceArtist *artist = dynamic_cast< Meta::ServiceArtist * > ( artistPtr.data() ); 0424 serviceTrack->setArtist( artistPtr ); 0425 artist->addTrack( trackPtr ); 0426 } 0427 0428 Meta::AlbumPtr albumPtr = m_collection->albumById( albumId.toInt() ); 0429 if ( albumPtr.data() != 0 ) { 0430 debug() << "Found parent album"; 0431 Meta::ServiceAlbum *album = dynamic_cast< Meta::ServiceAlbum * > ( albumPtr.data() ); 0432 serviceTrack->setAlbumPtr( albumPtr ); 0433 album->addTrack( trackPtr ); 0434 } 0435 0436 tracks.push_back( trackPtr ); 0437 } 0438 0439 //ThreadWeaver::Weaver::instance()->dequeue( job ); 0440 //job->deleteLater(); 0441 0442 handleResult( tracks ); 0443 emit queryDone(); 0444 0445 } 0446 0447 QueryMaker * Mp3tunesServiceQueryMaker::addFilter(qint64 value, const QString & filter, bool /*matchBegin*/, bool /*matchEnd*/) 0448 { 0449 DEBUG_BLOCK 0450 //debug() << "value: " << value; 0451 //for now, only accept artist filters 0452 if ( value == Meta::valArtist ) { 0453 //debug() << "Filter: " << filter; 0454 m_artistFilter = filter; 0455 } 0456 return this; 0457 } 0458 0459 int Mp3tunesServiceQueryMaker::validFilterMask() 0460 { 0461 //we only support artist filters for now... 0462 return ArtistFilter; 0463 } 0464 0465