Make plasma libs build.
[amarok.git] / src / collection / CollectionManager.cpp
blobeb49ad2716da9e690d962da881aa844165d27a78
1 /*
2 * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #define DEBUG_PREFIX "CollectionManager"
20 #include "CollectionManager.h"
22 #include "debug.h"
24 #include "BlockingQuery.h"
25 #include "Collection.h"
26 #include "MetaQueryBuilder.h"
27 #include "meta/file/File.h"
28 #include "meta/stream/Stream.h"
29 #include "meta/lastfm/LastFmMeta.h"
30 #include "pluginmanager.h"
31 #include "scrobbler.h"
32 #include "SqlStorage.h"
34 #include <QtAlgorithms>
35 #include <QtGlobal>
36 #include <QList>
37 #include <QTimer>
39 #include <kservice.h>
41 struct CollectionManager::Private
43 QList<Collection*> collections;
44 QList<CollectionFactory*> factories;
45 SqlStorage *sqlDatabase;
46 QList<Collection*> unmanagedCollections;
47 QList<Collection*> managedCollections;
50 class CollectionManagerSingleton
52 public:
53 CollectionManager instance;
56 K_GLOBAL_STATIC( CollectionManagerSingleton, privateInstance )
59 CollectionManager *
60 CollectionManager::instance( )
62 return &privateInstance->instance;
65 CollectionManager::CollectionManager()
66 : QObject()
67 , d( new Private )
69 init();
72 CollectionManager::~CollectionManager()
74 d->collections.clear();
75 d->unmanagedCollections.clear();
76 qDeleteAll( d->managedCollections );
78 foreach( CollectionFactory *fac, d->factories )
79 PluginManager::unload( fac );
81 delete d;
84 void
85 CollectionManager::init()
87 DEBUG_BLOCK
89 d->sqlDatabase = 0;
90 KService::List plugins = PluginManager::query( "[X-KDE-Amarok-plugintype] == 'collection'" );
91 debug() << "Received [" << QString::number( plugins.count() ) << "] collection plugin offers";
92 foreach( KService::Ptr service, plugins )
94 Amarok::Plugin *plugin = PluginManager::createFromService( service );
95 if ( plugin )
97 CollectionFactory* factory = dynamic_cast<CollectionFactory*>( plugin );
98 if ( factory )
100 connect( factory, SIGNAL( newCollection( Collection* ) ), this, SLOT( slotNewCollection( Collection* ) ) );
101 d->factories.append( factory );
102 factory->init();
104 else
106 debug() << "Plugin has wrong factory class";
107 continue;
113 void
114 CollectionManager::startFullScan()
116 foreach( Collection *coll, d->collections )
118 coll->startFullScan();
122 void
123 CollectionManager::checkCollectionChanges()
125 foreach( Collection *coll, d->collections )
127 coll->startIncrementalScan();
131 QueryMaker*
132 CollectionManager::queryMaker()
134 return new MetaQueryBuilder( d->collections );
137 void
138 CollectionManager::slotNewCollection( Collection* newCollection )
140 if( !newCollection )
142 debug() << "Warning, newCollection in slotNewCollection is 0";
143 return;
145 debug() << "New collection with collectionId: " << newCollection->collectionId();
146 d->collections.append( newCollection );
147 d->managedCollections.append( newCollection );
148 connect( newCollection, SIGNAL( remove() ), SLOT( slotRemoveCollection() ), Qt::QueuedConnection );
149 connect( newCollection, SIGNAL( updated() ), SLOT( slotCollectionChanged() ), Qt::QueuedConnection );
150 SqlStorage *sqlCollection = dynamic_cast<SqlStorage*>( newCollection );
151 if( sqlCollection )
153 if( d->sqlDatabase )
155 if( d->sqlDatabase->sqlDatabasePriority() < sqlCollection->sqlDatabasePriority() )
156 d->sqlDatabase = sqlCollection;
158 else
159 d->sqlDatabase = sqlCollection;
161 emit collectionAdded( newCollection );
164 void
165 CollectionManager::slotRemoveCollection()
167 Collection* collection = dynamic_cast<Collection*>( sender() );
168 if( collection )
170 d->collections.removeAll( collection );
171 d->managedCollections.removeAll( collection );
172 SqlStorage *sqlDb = dynamic_cast<SqlStorage*>( collection );
173 if( sqlDb && sqlDb == d->sqlDatabase )
175 SqlStorage *newSqlDatabase = 0;
176 foreach( Collection* tmp, d->collections )
178 SqlStorage *sqlDb = dynamic_cast<SqlStorage*>( tmp );
179 if( sqlDb )
181 if( newSqlDatabase )
183 if( newSqlDatabase->sqlDatabasePriority() < sqlDb->sqlDatabasePriority() )
184 newSqlDatabase = sqlDb;
186 else
187 newSqlDatabase = sqlDb;
190 d->sqlDatabase = newSqlDatabase;
192 emit collectionRemoved( collection->collectionId() );
193 QTimer::singleShot( 0, collection, SLOT( deleteLater() ) );
197 void
198 CollectionManager::slotCollectionChanged()
200 Collection *collection = dynamic_cast<Collection*>( sender() );
201 if( collection )
203 emit collectionDataChanged( collection );
207 QList<Collection*>
208 CollectionManager::collections()
210 return d->collections;
213 SqlStorage*
214 CollectionManager::sqlStorage() const
216 return d->sqlDatabase;
219 Meta::TrackList
220 CollectionManager::tracksForUrls( const KUrl::List &urls )
222 Meta::TrackList tracks;
223 foreach( KUrl url, urls )
224 tracks.append( trackForUrl( url ) );
225 return tracks;
228 Meta::TrackPtr
229 CollectionManager::trackForUrl( const KUrl &url )
231 //TODO method stub
232 //check all collections
233 //might be a podcast, in that case we'll have additional meta information
234 //might be a lastfm track, another stream
235 //or a file which is not in any collection
236 debug() << "track for url: " << url.url();
237 //check lastfm track
238 if( url.protocol() == "lastfm" )
239 return Meta::TrackPtr( new LastFm::Track( url.url() ) );
241 foreach( Collection *coll, d->collections )
243 if( coll->possiblyContainsTrack( url ) )
245 Meta::TrackPtr track = coll->trackForUrl( url );
246 if( track )
247 return track;
251 if( url.protocol() == "http" || url.protocol() == "mms" )
252 return Meta::TrackPtr( new MetaStream::Track( url ) );
254 if( url.protocol() == "file" )
255 return Meta::TrackPtr( new MetaFile::Track( url ) );
257 return Meta::TrackPtr( 0 );
260 Meta::ArtistList
261 CollectionManager::relatedArtists( Meta::ArtistPtr artist, int maxArtists )
263 SqlStorage *sql = sqlStorage();
264 QString query = QString( "SELECT suggestion FROM related_artists WHERE artist = '%1' ORDER BY %2 LIMIT %3 OFFSET 0;" )
265 .arg( sql->escape( artist->name() ), sql->randomFunc(), QString::number( maxArtists ) );
267 QStringList artistNames = sql->query( query );
268 //TODO: figure out a way to retrieve similar artists from last.fm here
269 /*if( artistNames.isEmpty() )
271 artistNames = Scrobbler::instance()->similarArtists( artist->name() );
273 QueryMaker *qm = queryMaker();
274 foreach( QString artist, artistNames )
276 qm->addFilter( QueryMaker::valArtist, artist, true, true );
278 qm->startArtistQuery();
279 qm->limitMaxResultSize( maxArtists );
280 BlockingQuery bq( qm );
281 bq.startQuery();
283 QStringList ids = bq.collectionIds();
284 Meta::ArtistList result;
285 QSet<QString> artistNameSet;
286 foreach( QString collectionId, ids )
288 Meta::ArtistList artists = bq.artists( collectionId );
289 foreach( Meta::ArtistPtr artist, artists )
291 if( !artistNameSet.contains( artist->name() ) )
293 result.append( artist );
294 artistNameSet.insert( artist->name() );
295 if( result.size() == maxArtists )
296 break;
299 if( result.size() == maxArtists )
300 break;
302 return result;
305 void
306 CollectionManager::addUnmanagedCollection( Collection *newCollection )
308 if( newCollection && d->collections.indexOf( newCollection ) == -1 )
310 d->unmanagedCollections.append( newCollection );
311 d->collections.append( newCollection );
312 emit collectionAdded( newCollection );
316 void
317 CollectionManager::removeUnmanagedCollection( Collection *collection )
319 //do not remove it from collection if it is not in unmanagedCollections
320 if( collection && d->unmanagedCollections.removeAll( collection ) )
322 d->collections.removeAll( collection );
323 emit collectionRemoved( collection->collectionId() );
327 #include "CollectionManager.moc"