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