1 /**************************************************************************************** 2 * Copyright (c) 2007-2008 Maximilian Kossick <maximilian.kossick@googlemail.com> * 3 * Copyright (c) 2008 Mark Kretschmann <kretschmann@kde.org> * 4 * * 5 * This program is free software; you can redistribute it and/or modify it under * 6 * the terms of the GNU General Public License as published by the Free Software * 7 * Foundation; either version 2 of the License, or (at your option) any later * 8 * version. * 9 * * 10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 12 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 13 * * 14 * You should have received a copy of the GNU General Public License along with * 15 * this program. If not, see <http://www.gnu.org/licenses/>. * 16 ****************************************************************************************/ 17 18 #ifndef AMAROK_STREAM_P_H 19 #define AMAROK_STREAM_P_H 20 21 #include "EngineController.h" 22 #include "core/meta/Meta.h" 23 #include "core/meta/support/MetaConstants.h" 24 #include "core/support/Debug.h" 25 #include "core-impl/meta/default/DefaultMetaTypes.h" 26 #include "covermanager/CoverCache.h" 27 28 #include <QObject> 29 30 using namespace MetaStream; 31 32 class MetaStream::Track::Private : public QObject 33 { 34 Q_OBJECT 35 36 public: Private(Track * t)37 Private( Track *t ) 38 : trackNumber( 0 ) 39 , length( 0 ) 40 , track( t ) 41 { 42 EngineController *engine = The::engineController(); 43 if( !engine ) 44 return; // engine might not be available during tests, silence the warning 45 46 // force a direct connection or slot might not be called because of thread 47 // affinity. (see BUG 300334) 48 connect( engine, &EngineController::currentMetadataChanged, 49 this, &Private::currentMetadataChanged, 50 Qt::DirectConnection ); 51 } 52 53 public Q_SLOTS: currentMetadataChanged(const QVariantMap & metaData)54 void currentMetadataChanged( const QVariantMap &metaData ) 55 { 56 const QUrl metaDataUrl = metaData.value( Meta::Field::URL ).toUrl(); 57 if( metaDataUrl == url ) 58 { 59 // keep synchronized to EngineController::slotMetaDataChanged() 60 if( metaData.contains( Meta::Field::ARTIST ) ) 61 artist = metaData.value( Meta::Field::ARTIST ).toString(); 62 if( metaData.contains( Meta::Field::TITLE ) ) 63 title = metaData.value( Meta::Field::TITLE ).toString(); 64 if( metaData.contains( Meta::Field::ALBUM ) ) 65 album = metaData.value( Meta::Field::ALBUM ).toString(); 66 if( metaData.contains( Meta::Field::GENRE ) ) 67 genre = metaData.value( Meta::Field::GENRE ).toString(); 68 if( metaData.contains( Meta::Field::TRACKNUMBER ) ) 69 trackNumber = metaData.value( Meta::Field::TRACKNUMBER ).toInt(); 70 if( metaData.contains( Meta::Field::COMMENT ) ) 71 comment = metaData.value( Meta::Field::COMMENT ).toString(); 72 if( metaData.contains( Meta::Field::LENGTH ) ) 73 length = metaData.value( Meta::Field::LENGTH ).value<qint64>(); 74 75 //TODO: move special handling to subclass or using some configurable XSPF 76 // Special demangling of artist/title for Shoutcast streams, which usually 77 // have "Artist - Title" in the title tag: 78 if( artist.isEmpty() && title.contains( QLatin1String(" - ") ) ) 79 { 80 const QStringList artist_title = title.split( QStringLiteral(" - ") ); 81 if( artist_title.size() >= 2 ) 82 { 83 artist = artist_title[0]; 84 title = title.remove( 0, artist.length() + 3 ); 85 } 86 } 87 88 track->notifyObservers(); 89 } 90 } 91 92 public: 93 QUrl url; 94 QString title; 95 QString artist; 96 QString album; 97 QString genre; 98 int trackNumber; 99 QString comment; 100 qint64 length; 101 102 Meta::ArtistPtr artistPtr; 103 Meta::AlbumPtr albumPtr; 104 Meta::GenrePtr genrePtr; 105 Meta::ComposerPtr composerPtr; 106 Meta::YearPtr yearPtr; 107 108 private: 109 Track *track; 110 }; 111 112 113 // internal helper classes 114 115 class StreamArtist : public Meta::DefaultArtist 116 { 117 public: StreamArtist(MetaStream::Track::Private * dptr)118 explicit StreamArtist( MetaStream::Track::Private *dptr ) 119 : DefaultArtist() 120 , d( dptr ) 121 {} 122 name()123 QString name() const override 124 { 125 if( d && !d->artist.isEmpty() ) 126 return d->artist; 127 return DefaultArtist::name(); 128 } 129 130 MetaStream::Track::Private * const d; 131 }; 132 133 class StreamAlbum : public Meta::DefaultAlbum 134 { 135 public: StreamAlbum(MetaStream::Track::Private * dptr)136 explicit StreamAlbum( MetaStream::Track::Private *dptr ) 137 : DefaultAlbum() 138 , d( dptr ) 139 {} 140 ~StreamAlbum()141 ~StreamAlbum() override 142 { 143 CoverCache::invalidateAlbum( this ); 144 } 145 hasAlbumArtist()146 bool hasAlbumArtist() const override 147 { 148 return false; 149 } 150 name()151 QString name() const override 152 { 153 if( d && !d->album.isEmpty() ) 154 return d->album; 155 return DefaultAlbum::name(); 156 } 157 hasImage(int size)158 bool hasImage( int size ) const override 159 { 160 if( m_cover.isNull() ) 161 return Meta::Album::hasImage( size ); 162 else 163 return true; 164 } 165 image(int size)166 QImage image( int size ) const override 167 { 168 if( m_cover.isNull() ) 169 return Meta::Album::image( size ); 170 else 171 return m_cover.scaled( size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation ); 172 } 173 setImage(const QImage & image)174 void setImage( const QImage &image ) override 175 { 176 m_cover = image; 177 CoverCache::invalidateAlbum( this ); 178 } 179 180 MetaStream::Track::Private * const d; 181 QImage m_cover; 182 }; 183 184 class StreamGenre : public Meta::DefaultGenre 185 { 186 public: StreamGenre(MetaStream::Track::Private * dptr)187 explicit StreamGenre( MetaStream::Track::Private *dptr ) 188 : DefaultGenre() 189 , d( dptr ) 190 {} 191 name()192 QString name() const override 193 { 194 if( d && !d->genre.isEmpty() ) 195 return d->genre; 196 return DefaultGenre::name(); 197 } 198 199 MetaStream::Track::Private * const d; 200 }; 201 202 #endif 203