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 #ifndef AMAROK_METAPROXY_P_H
0018 #define AMAROK_METAPROXY_P_H
0019 
0020 #include "core/collections/Collection.h"
0021 #include "core/meta/Meta.h"
0022 #include "core/meta/Observer.h"
0023 #include "core-impl/meta/stream/Stream.h"
0024 
0025 #include <QImage>
0026 #include <QList>
0027 #include <QObject>
0028 #include <QStringList>
0029 
0030 #include <kio/job.h>
0031 #include <kio/jobclasses.h>
0032 
0033 
0034 using namespace MetaProxy;
0035 
0036 class MetaProxy::Track::Private : public QObject, public Meta::Observer
0037 {
0038     Q_OBJECT
0039 
0040     public:
0041         Track *proxy;
0042         QUrl url;
0043 
0044         Meta::TrackPtr realTrack;
0045 
0046         QString cachedArtist;
0047         QString cachedAlbum;
0048         QString cachedName;
0049         QString cachedGenre;
0050         QString cachedComposer;
0051         int cachedYear;
0052         qint64 cachedLength;
0053         qreal  cachedBpm;
0054         int cachedTrackNumber;
0055         int cachedDiscNumber;
0056 
0057         Meta::ArtistPtr artistPtr;
0058         Meta::AlbumPtr albumPtr;
0059         Meta::GenrePtr genrePtr;
0060         Meta::ComposerPtr composerPtr;
0061         Meta::YearPtr yearPtr;
0062 
0063     public:
0064         using Observer::metadataChanged;
0065         void metadataChanged( const Meta::TrackPtr &track ) override
0066         {
0067             Q_UNUSED( track )
0068             proxy->notifyObservers();
0069         }
0070 
0071     public Q_SLOTS:
0072         void slotUpdateTrack( const Meta::TrackPtr &track )
0073         {
0074             if( track )
0075             {
0076                 // special handling for streams that cannot fetch metadata until played, bug 305389
0077                 MetaStream::Track *stream = dynamic_cast<MetaStream::Track *>( track.data() );
0078                 if( stream )
0079                     stream->setInitialInfo( cachedArtist, cachedAlbum, cachedName,
0080                                             cachedLength, cachedTrackNumber );
0081 
0082                 subscribeTo( track );
0083                 realTrack = track;
0084 
0085                 // clear memory of now-unused cached fields:
0086                 url.clear();
0087                 cachedArtist.clear();
0088                 cachedAlbum.clear();
0089                 cachedName.clear();
0090                 cachedGenre.clear();
0091                 cachedComposer.clear();
0092 
0093                 proxy->notifyObservers();
0094             }
0095         }
0096 };
0097 
0098 // internal helper classes
0099 
0100 class ProxyArtist : public Meta::Artist
0101 {
0102 public:
0103     explicit ProxyArtist( MetaProxy::Track::Private *dptr )
0104         : Meta::Artist()
0105         , d( dptr )
0106     {}
0107 
0108     Meta::TrackList tracks() override
0109     {
0110         Meta::TrackPtr realTrack = d ? d->realTrack : Meta::TrackPtr();
0111         Meta::ArtistPtr artist = realTrack ? realTrack->artist() : Meta::ArtistPtr();
0112         return artist ? artist->tracks() : Meta::TrackList();
0113     }
0114 
0115     QString name() const override
0116     {
0117         Meta::TrackPtr realTrack = d ? d->realTrack : Meta::TrackPtr();
0118         if( realTrack )
0119         {
0120             Meta::ArtistPtr artist = realTrack ? realTrack->artist() : Meta::ArtistPtr();
0121             return artist ? artist->name() : QString();
0122         }
0123         return d ? d->cachedArtist : QString();
0124     }
0125 
0126     QString prettyName() const override
0127     {
0128         Meta::TrackPtr realTrack = d ? d->realTrack : Meta::TrackPtr();
0129         if( realTrack )
0130         {
0131             Meta::ArtistPtr artist = realTrack ? realTrack->artist() : Meta::ArtistPtr();
0132             return artist ? artist->prettyName() : QString();
0133         }
0134         return d ? d->cachedArtist : QString();
0135     }
0136 
0137     bool operator==( const Meta::Artist &artist ) const override
0138     {
0139         const ProxyArtist *proxy = dynamic_cast<const ProxyArtist*>( &artist );
0140         if( proxy )
0141         {
0142             return d && proxy->d && d->realTrack && proxy->d->realTrack && d->realTrack->artist() && d->realTrack->artist() == proxy->d->realTrack->artist();
0143         }
0144         else
0145         {
0146             return d && d->realTrack && d->realTrack->artist() && d->realTrack->artist().data() == &artist;
0147         }
0148     }
0149 
0150     MetaProxy::Track::Private * const d;
0151 };
0152 
0153 /** TODO: what about MetaDataChanged? */
0154 class ProxyAlbum : public Meta::Album
0155 {
0156 public:
0157     explicit ProxyAlbum( MetaProxy::Track::Private *dptr )
0158         : Meta::Album()
0159         , d( dptr )
0160     {}
0161 
0162     bool hasCapabilityInterface( Capabilities::Capability::Type type ) const override
0163     {
0164         if( d && d->realTrack && d->realTrack->album() )
0165             return d->realTrack->album()->hasCapabilityInterface( type );
0166         else
0167             return false;
0168     }
0169 
0170     Capabilities::Capability* createCapabilityInterface( Capabilities::Capability::Type type ) override
0171     {
0172         if( d && d->realTrack && d->realTrack->album() )
0173             return d->realTrack->album()->createCapabilityInterface( type );
0174         else
0175             return nullptr;
0176     }
0177 
0178     bool isCompilation() const override
0179     {
0180         if( d && d->realTrack && d->realTrack->album() )
0181             return d->realTrack->album()->isCompilation();
0182         else
0183             return false;
0184     }
0185 
0186     bool canUpdateCompilation() const override
0187     {
0188         if( d && d->realTrack && d->realTrack->album() )
0189             return d->realTrack->album()->canUpdateCompilation();
0190         else
0191             return Meta::Album::canUpdateCompilation();
0192     }
0193 
0194     void setCompilation( bool isCompilation ) override
0195     {
0196         if( d && d->realTrack && d->realTrack->album() )
0197             d->realTrack->album()->setCompilation( isCompilation );
0198     }
0199 
0200     bool hasAlbumArtist() const override
0201     {
0202         if( d && d->realTrack && d->realTrack->album() )
0203             return d->realTrack->album()->hasAlbumArtist();
0204         else
0205             return false;
0206     }
0207 
0208     Meta::ArtistPtr albumArtist() const override
0209     {
0210         if( d && d->realTrack && d->realTrack->album() )
0211             return d->realTrack->album()->albumArtist();
0212         else
0213             return Meta::ArtistPtr();
0214     }
0215 
0216     Meta::TrackList tracks() override
0217     {
0218         if( d && d->realTrack && d->realTrack->album() )
0219             return d->realTrack->album()->tracks();
0220         else
0221             return Meta::TrackList();
0222     }
0223 
0224     QString name() const override
0225     {
0226         if( d && d->realTrack )
0227         {
0228             if ( d->realTrack->album() )
0229                 return d->realTrack->album()->name();
0230             return QString();
0231         }
0232         else if ( d )
0233               return d->cachedAlbum;
0234         else
0235             return QString();
0236     }
0237 
0238     QString prettyName() const override
0239     {
0240         if( d && d->realTrack && d->realTrack->album() )
0241             return d->realTrack->album()->prettyName();
0242         else
0243             return name();
0244     }
0245 
0246     QImage image( int size ) const override
0247     {
0248         if( d && d->realTrack && d->realTrack->album() )
0249             return d->realTrack->album()->image( size );
0250         else
0251             return Meta::Album::image( size );
0252     }
0253 
0254     bool hasImage( int size ) const override
0255     {
0256         if( d && d->realTrack && d->realTrack->album() )
0257             return d->realTrack->album()->hasImage( size );
0258         else
0259             return Meta::Album::hasImage( size );
0260     }
0261 
0262     QUrl imageLocation( int size = 0 ) override
0263     {
0264         if( d && d->realTrack && d->realTrack->album() )
0265             return d->realTrack->album()->imageLocation( size );
0266         else
0267             return Meta::Album::imageLocation( size );
0268     }
0269 
0270     bool canUpdateImage() const override
0271     {
0272         if( d && d->realTrack && d->realTrack->album() )
0273             return d->realTrack->album()->canUpdateImage();
0274         else
0275             return Meta::Album::canUpdateImage();
0276     }
0277 
0278     void setImage( const QImage &image ) override
0279     {
0280         if( d && d->realTrack && d->realTrack->album() )
0281             d->realTrack->album()->setImage( image );
0282     }
0283 
0284     void removeImage() override
0285     {
0286         if( d && d->realTrack && d->realTrack->album() )
0287             d->realTrack->album()->removeImage();
0288     }
0289 
0290     bool operator==( const Meta::Album &album ) const override
0291     {
0292         const ProxyAlbum *proxy = dynamic_cast<const ProxyAlbum*>( &album );
0293         if( proxy )
0294         {
0295             return d && proxy->d && d->realTrack && proxy->d->realTrack && d->realTrack->album() && ( *d->realTrack->album().data() ) == ( *proxy->d->realTrack->album().data() );
0296         }
0297         else
0298         {
0299             return d && d->realTrack && d->realTrack->album() && ( *d->realTrack->album().data() ) == album;
0300         }
0301     }
0302 
0303     MetaProxy::Track::Private * const d;
0304 };
0305 
0306 class ProxyGenre : public Meta::Genre
0307 {
0308 public:
0309     explicit ProxyGenre( MetaProxy::Track::Private *dptr )
0310         : Meta::Genre()
0311         , d( dptr )
0312     {}
0313 
0314     QString name() const override
0315     {
0316         if( d && d->realTrack && d->realTrack->genre() )
0317             return d->realTrack->genre()->name();
0318         else if( d )
0319             return d->cachedGenre;
0320         else
0321             return QString();
0322     }
0323 
0324     QString prettyName() const override
0325     {
0326         if( d && d->realTrack && d->realTrack->genre() )
0327             return d->realTrack->genre()->prettyName();
0328         else
0329             return QString();
0330     }
0331 
0332     Meta::TrackList tracks() override
0333     {
0334         if( d && d->realTrack && d->realTrack->genre() )
0335             return d->realTrack->genre()->tracks();
0336         else
0337             return Meta::TrackList();
0338     }
0339 
0340     bool operator==( const Meta::Genre &genre ) const override
0341     {
0342         const ProxyGenre *proxy = dynamic_cast<const ProxyGenre*>( &genre );
0343         if( proxy )
0344         {
0345             return d && proxy->d && d->realTrack && proxy->d->realTrack && d->realTrack->genre() && d->realTrack->genre() == proxy->d->realTrack->genre();
0346         }
0347         else
0348         {
0349             return d && d->realTrack && d->realTrack->genre() && d->realTrack->genre().data() == &genre;
0350         }
0351     }
0352 
0353     MetaProxy::Track::Private * const d;
0354 };
0355 
0356 class ProxyComposer : public Meta::Composer
0357 {
0358 public:
0359     explicit ProxyComposer( MetaProxy::Track::Private *dptr )
0360         : Meta::Composer()
0361         , d( dptr )
0362     {}
0363 
0364     QString name() const override
0365     {
0366         if( d && d->realTrack && d->realTrack->composer() )
0367             return d->realTrack->composer()->name();
0368         else if ( d )
0369             return d->cachedComposer;
0370         else
0371             return QString();
0372     }
0373 
0374     QString prettyName() const override
0375     {
0376         if( d && d->realTrack && d->realTrack->composer())
0377             return d->realTrack->composer()->prettyName();
0378         else
0379             return name();
0380     }
0381 
0382     Meta::TrackList tracks() override
0383     {
0384         if( d && d->realTrack && d->realTrack->composer() )
0385             return d->realTrack->composer()->tracks();
0386         else
0387             return Meta::TrackList();
0388     }
0389 
0390     bool operator==( const Meta::Composer &composer ) const override
0391     {
0392         const ProxyComposer *proxy = dynamic_cast<const ProxyComposer*>( &composer );
0393         if( proxy )
0394         {
0395             return d && proxy->d && d->realTrack && proxy->d->realTrack && d->realTrack->composer() && d->realTrack->composer() == proxy->d->realTrack->composer();
0396         }
0397         else
0398         {
0399             return d && d->realTrack && d->realTrack->composer() && d->realTrack->composer().data() == &composer;
0400         }
0401     }
0402 
0403     MetaProxy::Track::Private * const d;
0404 };
0405 
0406 class ProxyYear : public Meta::Year
0407 {
0408 public:
0409     explicit ProxyYear( MetaProxy::Track::Private *dptr )
0410         : Meta::Year()
0411         , d( dptr )
0412     {}
0413 
0414     QString name() const override
0415     {
0416         if( d && d->realTrack && d->realTrack->year() )
0417             return d->realTrack->year()->name();
0418         else if( d )
0419             return QString::number(d->cachedYear);
0420         else
0421             return QString();
0422     }
0423 
0424     QString prettyName() const override
0425     {
0426         if( d && d->realTrack && d->realTrack->year() )
0427             return d->realTrack->year()->prettyName();
0428         else
0429             return name();
0430     }
0431 
0432     Meta::TrackList tracks() override
0433     {
0434         if( d && d->realTrack && d->realTrack->year() )
0435             return d->realTrack->year()->tracks();
0436         else
0437             return Meta::TrackList();
0438     }
0439 
0440     bool operator==( const Meta::Year &year ) const override
0441     {
0442         const ProxyYear *proxy = dynamic_cast<const ProxyYear*>( &year );
0443         if( proxy )
0444         {
0445             return d && proxy->d && d->realTrack && proxy->d->realTrack && d->realTrack->year() && d->realTrack->year() == proxy->d->realTrack->year();
0446         }
0447         else
0448         {
0449             return d && d->realTrack && d->realTrack->year() && d->realTrack->year().data() == &year;
0450         }
0451     }
0452 
0453     MetaProxy::Track::Private * const d;
0454 };
0455 
0456 #endif