File indexing completed on 2025-01-05 04:26:11
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #include "MetaProxy.h" 0018 0019 #include "core/meta/Statistics.h" 0020 #include "core-impl/collections/support/CollectionManager.h" 0021 #include "core-impl/meta/proxy/MetaProxy_p.h" 0022 #include "core-impl/meta/proxy/MetaProxyWorker.h" 0023 0024 #include "AmarokSharedPointer.h" 0025 #include <ThreadWeaver/Queue> 0026 #include <ThreadWeaver/Job> 0027 #include <KLocalizedString> 0028 0029 #include <QCoreApplication> 0030 #include <QThread> 0031 #include <QTimer> 0032 #include <QWeakPointer> 0033 0034 using namespace MetaProxy; 0035 0036 class ProxyArtist; 0037 class ProxyFmAlbum; 0038 class ProxyGenre; 0039 class ProxyComposer; 0040 class ProxyYear; 0041 0042 MetaProxy::Track::Track( const QUrl &url, LookupType lookupType ) 0043 : Meta::Track() 0044 , d( new Private() ) 0045 { 0046 d->url = url; 0047 d->proxy = this; 0048 d->cachedLength = 0; 0049 d->albumPtr = Meta::AlbumPtr( new ProxyAlbum( d ) ); 0050 d->artistPtr = Meta::ArtistPtr( new ProxyArtist( d ) ); 0051 d->genrePtr = Meta::GenrePtr( new ProxyGenre( d ) ); 0052 d->composerPtr = Meta::ComposerPtr( new ProxyComposer( d ) ); 0053 d->yearPtr = Meta::YearPtr( new ProxyYear( d ) ); 0054 0055 QThread *mainThread = QCoreApplication::instance()->thread(); 0056 bool foreignThread = QThread::currentThread() != mainThread; 0057 if( foreignThread ) 0058 d->moveToThread( mainThread ); 0059 0060 if( lookupType == AutomaticLookup ) 0061 { 0062 Worker *worker = new Worker( d->url ); 0063 if( foreignThread ) 0064 worker->moveToThread( mainThread ); 0065 0066 QObject::connect( worker, &Worker::finishedLookup, 0067 d, &Track::Private::slotUpdateTrack ); 0068 ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(worker) ); 0069 } 0070 } 0071 0072 MetaProxy::Track::~Track() 0073 { 0074 delete d; 0075 } 0076 0077 void 0078 MetaProxy::Track::lookupTrack( Collections::TrackProvider *provider ) 0079 { 0080 Worker *worker = new Worker( d->url, provider ); 0081 QThread *mainThread = QCoreApplication::instance()->thread(); 0082 if( QThread::currentThread() != mainThread ) 0083 worker->moveToThread( mainThread ); 0084 0085 QObject::connect( worker, &MetaProxy::Worker::finishedLookup, 0086 d, &Private::slotUpdateTrack ); 0087 ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(worker) ); 0088 } 0089 0090 QString 0091 MetaProxy::Track::name() const 0092 { 0093 if( d->realTrack ) 0094 return d->realTrack->name(); 0095 else 0096 return d->cachedName; 0097 } 0098 0099 void 0100 MetaProxy::Track::setTitle( const QString &name ) 0101 { 0102 d->cachedName = name; 0103 } 0104 0105 QString 0106 MetaProxy::Track::prettyName() const 0107 { 0108 if( d->realTrack ) 0109 return d->realTrack->prettyName(); 0110 else 0111 return Meta::Track::prettyName(); 0112 } 0113 0114 QString 0115 MetaProxy::Track::sortableName() const 0116 { 0117 if( d->realTrack ) 0118 return d->realTrack->sortableName(); 0119 else 0120 return Meta::Track::sortableName(); 0121 } 0122 0123 QUrl 0124 MetaProxy::Track::playableUrl() const 0125 { 0126 if( d->realTrack ) 0127 return d->realTrack->playableUrl(); 0128 else 0129 /* don't return d->url here, it may be something like 0130 * amarok-sqltrackuid://2f9277bb7e49962c1c4c5612811807a1 and Phonon may choke 0131 * on such urls trying to find a codec and causing hang (bug 308371) */ 0132 return QUrl(); 0133 } 0134 0135 QString 0136 MetaProxy::Track::prettyUrl() const 0137 { 0138 if( d->realTrack ) 0139 return d->realTrack->prettyUrl(); 0140 else 0141 return d->url.toDisplayString(); 0142 } 0143 0144 QString 0145 MetaProxy::Track::uidUrl() const 0146 { 0147 if( d->realTrack ) 0148 return d->realTrack->uidUrl(); 0149 else 0150 return d->url.url(); 0151 } 0152 0153 QString 0154 MetaProxy::Track::notPlayableReason() const 0155 { 0156 if( !d->realTrack ) 0157 return i18n( "When Amarok was last closed, this track was at %1, but Amarok " 0158 "cannot find this track on the filesystem or in any of your collections " 0159 "anymore. You may try plugging in the device this track might be on.", 0160 prettyUrl() ); 0161 return d->realTrack->notPlayableReason(); 0162 } 0163 0164 Meta::AlbumPtr 0165 MetaProxy::Track::album() const 0166 { 0167 return d->albumPtr; 0168 } 0169 0170 void 0171 MetaProxy::Track::setAlbum( const QString &album ) 0172 { 0173 d->cachedAlbum = album; 0174 } 0175 0176 void 0177 Track::setAlbumArtist( const QString &artist ) 0178 { 0179 Q_UNUSED( artist ); 0180 } 0181 0182 Meta::ArtistPtr 0183 MetaProxy::Track::artist() const 0184 { 0185 return d->artistPtr; 0186 } 0187 0188 void 0189 MetaProxy::Track::setArtist( const QString &artist ) 0190 { 0191 d->cachedArtist = artist; 0192 } 0193 0194 Meta::GenrePtr 0195 MetaProxy::Track::genre() const 0196 { 0197 return d->genrePtr; 0198 } 0199 0200 void 0201 MetaProxy::Track::setGenre( const QString &genre ) 0202 { 0203 d->cachedGenre = genre; 0204 } 0205 0206 Meta::ComposerPtr 0207 MetaProxy::Track::composer() const 0208 { 0209 return d->composerPtr; 0210 } 0211 0212 void 0213 MetaProxy::Track::setComposer( const QString &composer ) 0214 { 0215 d->cachedComposer = composer; 0216 } 0217 0218 Meta::YearPtr 0219 MetaProxy::Track::year() const 0220 { 0221 return d->yearPtr; 0222 } 0223 0224 void 0225 MetaProxy::Track::setYear( int year ) 0226 { 0227 d->cachedYear = year; 0228 } 0229 0230 Meta::LabelList 0231 Track::labels() const 0232 { 0233 if( d->realTrack ) 0234 return d->realTrack->labels(); 0235 else 0236 return Meta::Track::labels(); 0237 } 0238 0239 qreal 0240 MetaProxy::Track::bpm() const 0241 { 0242 if( d->realTrack ) 0243 return d->realTrack->bpm(); 0244 else 0245 return d->cachedBpm; 0246 } 0247 0248 void 0249 MetaProxy::Track::setBpm( const qreal bpm ) 0250 { 0251 d->cachedBpm = bpm; 0252 } 0253 0254 QString 0255 MetaProxy::Track::comment() const 0256 { 0257 if( d->realTrack ) 0258 return d->realTrack->comment(); 0259 else 0260 return QString(); // we don't cache comment 0261 } 0262 0263 void 0264 Track::setComment( const QString & ) 0265 { 0266 // we don't cache comment 0267 } 0268 0269 int 0270 MetaProxy::Track::trackNumber() const 0271 { 0272 if( d->realTrack ) 0273 return d->realTrack->trackNumber(); 0274 else 0275 return d->cachedTrackNumber; 0276 } 0277 0278 void 0279 MetaProxy::Track::setTrackNumber( int number ) 0280 { 0281 d->cachedTrackNumber = number; 0282 } 0283 0284 int 0285 MetaProxy::Track::discNumber() const 0286 { 0287 if( d->realTrack ) 0288 return d->realTrack->discNumber(); 0289 else 0290 return d->cachedDiscNumber; 0291 } 0292 0293 void 0294 MetaProxy::Track::setDiscNumber( int discNumber ) 0295 { 0296 d->cachedDiscNumber = discNumber; 0297 } 0298 0299 qint64 0300 MetaProxy::Track::length() const 0301 { 0302 if( d->realTrack ) 0303 return d->realTrack->length(); 0304 else 0305 return d->cachedLength; 0306 } 0307 0308 void 0309 MetaProxy::Track::setLength( qint64 length ) 0310 { 0311 d->cachedLength = length; 0312 } 0313 0314 int 0315 MetaProxy::Track::filesize() const 0316 { 0317 if( d->realTrack ) 0318 return d->realTrack->filesize(); 0319 else 0320 return 0; 0321 } 0322 0323 int 0324 MetaProxy::Track::sampleRate() const 0325 { 0326 if( d->realTrack ) 0327 return d->realTrack->sampleRate(); 0328 else 0329 return 0; 0330 } 0331 0332 int 0333 MetaProxy::Track::bitrate() const 0334 { 0335 if( d->realTrack ) 0336 return d->realTrack->bitrate(); 0337 else 0338 return 0; 0339 } 0340 0341 QDateTime 0342 MetaProxy::Track::createDate() const 0343 { 0344 if( d->realTrack ) 0345 return d->realTrack->createDate(); 0346 else 0347 return Meta::Track::createDate(); 0348 } 0349 0350 QDateTime 0351 Track::modifyDate() const 0352 { 0353 if( d->realTrack ) 0354 return d->realTrack->modifyDate(); 0355 else 0356 return Meta::Track::modifyDate(); 0357 } 0358 0359 qreal 0360 Track::replayGain( Meta::ReplayGainTag mode ) const 0361 { 0362 if( d->realTrack ) 0363 return d->realTrack->replayGain( mode ); 0364 else 0365 return Meta::Track::replayGain( mode ); 0366 } 0367 0368 QString 0369 MetaProxy::Track::type() const 0370 { 0371 if( d->realTrack ) 0372 return d->realTrack->type(); 0373 else 0374 // just debugging, normal users shouldn't hit this 0375 return QStringLiteral( "MetaProxy::Track" ); 0376 } 0377 0378 void 0379 Track::prepareToPlay() 0380 { 0381 if( d->realTrack ) 0382 d->realTrack->prepareToPlay(); 0383 } 0384 0385 void 0386 MetaProxy::Track::finishedPlaying( double playedFraction ) 0387 { 0388 if( d->realTrack ) 0389 d->realTrack->finishedPlaying( playedFraction ); 0390 } 0391 0392 bool 0393 MetaProxy::Track::inCollection() const 0394 { 0395 if( d->realTrack ) 0396 return d->realTrack->inCollection(); 0397 else 0398 return false; 0399 } 0400 0401 Collections::Collection * 0402 MetaProxy::Track::collection() const 0403 { 0404 if( d->realTrack ) 0405 return d->realTrack->collection(); 0406 else 0407 return nullptr; 0408 } 0409 0410 QString 0411 Track::cachedLyrics() const 0412 { 0413 if( d->realTrack ) 0414 return d->realTrack->cachedLyrics(); 0415 else 0416 return Meta::Track::cachedLyrics(); 0417 } 0418 0419 void 0420 Track::setCachedLyrics(const QString& lyrics) 0421 { 0422 if( d->realTrack ) 0423 d->realTrack->setCachedLyrics( lyrics ); 0424 else 0425 Meta::Track::setCachedLyrics( lyrics ); 0426 } 0427 0428 void 0429 Track::addLabel( const QString &label ) 0430 { 0431 if( d->realTrack ) 0432 d->realTrack->addLabel( label ); 0433 else 0434 Meta::Track::addLabel( label ); 0435 } 0436 0437 void 0438 Track::addLabel( const Meta::LabelPtr &label ) 0439 { 0440 if( d->realTrack ) 0441 d->realTrack->addLabel( label ); 0442 else 0443 Meta::Track::addLabel( label ); 0444 } 0445 0446 void 0447 Track::removeLabel( const Meta::LabelPtr &label ) 0448 { 0449 if( d->realTrack ) 0450 d->realTrack->removeLabel( label ); 0451 else 0452 Meta::Track::removeLabel( label ); 0453 } 0454 0455 void 0456 MetaProxy::Track::updateTrack( const Meta::TrackPtr &track ) 0457 { 0458 d->slotUpdateTrack( track ); 0459 } 0460 0461 bool 0462 MetaProxy::Track::hasCapabilityInterface( Capabilities::Capability::Type type ) const 0463 { 0464 if( d->realTrack ) 0465 return d->realTrack->hasCapabilityInterface( type ); 0466 else 0467 return false; 0468 } 0469 0470 Capabilities::Capability * 0471 MetaProxy::Track::createCapabilityInterface( Capabilities::Capability::Type type ) 0472 { 0473 if( d->realTrack ) 0474 return d->realTrack->createCapabilityInterface( type ); 0475 else 0476 return nullptr; 0477 } 0478 0479 bool 0480 MetaProxy::Track::operator==( const Meta::Track &track ) const 0481 { 0482 const MetaProxy::Track *proxy = dynamic_cast<const MetaProxy::Track *>( &track ); 0483 if( proxy && d->realTrack ) 0484 return d->realTrack == proxy->d->realTrack; 0485 else if( proxy ) 0486 return d->url == proxy->d->url; 0487 0488 return d->realTrack && d->realTrack.data() == &track; 0489 } 0490 0491 Meta::TrackEditorPtr 0492 Track::editor() 0493 { 0494 if( d->realTrack ) 0495 return d->realTrack->editor(); 0496 else 0497 return Meta::TrackEditorPtr( this ); 0498 } 0499 0500 Meta::StatisticsPtr 0501 Track::statistics() 0502 { 0503 if( d->realTrack ) 0504 return d->realTrack->statistics(); 0505 else 0506 return Meta::Track::statistics(); 0507 } 0508 0509 void 0510 Track::beginUpdate() 0511 { 0512 // nothing to do 0513 } 0514 0515 void 0516 Track::endUpdate() 0517 { 0518 // we intentionally don't call metadataUpdated() so that the first thing that 0519 // triggers metadataUpdated() is when the real track is found. 0520 } 0521 0522 bool 0523 Track::isResolved() const 0524 { 0525 return d->realTrack; 0526 }