New TrackStatistics object
[amarok:rengelss-amarok.git] / src / core / meta / Meta.h
1 /****************************************************************************************
2  * Copyright (c) 2007 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_META_H
19 #define AMAROK_META_H
20
21 #include "shared/amarok_export.h"
22 #include "shared/MetaReplayGain.h"
23
24 #include "core/capabilities/Capability.h"
25
26 #include <QList>
27 #include <QMetaType>
28 #include <QImage>
29 #include <QDateTime>
30 #include <QSet>
31 #include <QSharedData>
32 #include <QString>
33
34 #include <KSharedPtr>
35 #include <KUrl>
36
37 namespace Statistics
38 {
39     class TrackStatistics;
40 }
41
42 namespace Collections
43 {
44     class Collection;
45     class QueryMaker;
46 }
47
48 namespace Meta
49 {
50     class MetaBase;
51     class Track;
52     class Artist;
53     class Album;
54     class Genre;
55     class Composer;
56     class Year;
57     class Label;
58
59     typedef KSharedPtr<MetaBase> DataPtr;
60     typedef QList<DataPtr> DataList;
61     typedef KSharedPtr<Track> TrackPtr;
62     typedef QList<TrackPtr> TrackList;
63     typedef KSharedPtr<Artist> ArtistPtr;
64     typedef QList<ArtistPtr> ArtistList;
65     typedef KSharedPtr<Album> AlbumPtr;
66     typedef QList<AlbumPtr> AlbumList;
67     typedef KSharedPtr<Composer> ComposerPtr;
68     typedef QList<ComposerPtr> ComposerList;
69     typedef KSharedPtr<Genre> GenrePtr;
70     typedef QList<GenrePtr> GenreList;
71     typedef KSharedPtr<Year> YearPtr;
72     typedef QList<YearPtr> YearList;
73     typedef KSharedPtr<Label> LabelPtr;
74     typedef QList<LabelPtr> LabelList;
75
76     class AMAROK_CORE_EXPORT Observer
77     {
78         public:
79             void subscribeTo( TrackPtr );
80             void unsubscribeFrom( TrackPtr );
81             void subscribeTo( ArtistPtr );
82             void unsubscribeFrom( ArtistPtr );
83             void subscribeTo( AlbumPtr );
84             void unsubscribeFrom( AlbumPtr );
85             void subscribeTo( ComposerPtr );
86             void unsubscribeFrom( ComposerPtr );
87             void subscribeTo( GenrePtr );
88             void unsubscribeFrom( GenrePtr );
89             void subscribeTo( YearPtr );
90             void unsubscribeFrom( YearPtr );
91
92             /** This method is called when the metadata of a track has changed.
93                 The called class may not cache the pointer */
94             virtual void metadataChanged( TrackPtr track );
95             virtual void metadataChanged( ArtistPtr artist );
96             virtual void metadataChanged( AlbumPtr album );
97             virtual void metadataChanged( GenrePtr genre );
98             virtual void metadataChanged( ComposerPtr composer );
99             virtual void metadataChanged( YearPtr year );
100             virtual ~Observer();
101
102             // TODO: we really need a deleted notification.
103             // TODO: Why not change this Java-like observer pattern to a normal QObject
104
105         private:
106             QSet<TrackPtr> m_trackSubscriptions;
107             QSet<ArtistPtr> m_artistSubscriptions;
108             QSet<AlbumPtr> m_albumSubscriptions;
109             QSet<ComposerPtr> m_composerSubscriptions;
110             QSet<GenrePtr> m_genreSubscriptions;
111             QSet<YearPtr> m_yearSubscriptions;
112     };
113
114     class AMAROK_CORE_EXPORT MetaCapability
115     {
116     public:
117         virtual ~MetaCapability() {}
118
119         virtual bool hasCapabilityInterface( Capabilities::Capability::Type type ) const;
120
121         virtual Capabilities::Capability* createCapabilityInterface( Capabilities::Capability::Type type );
122
123         /**
124              * Retrieves a specialized interface which represents a capability of this
125              * MetaBase object.
126              *
127              * @returns a pointer to the capability interface if it exists, 0 otherwise
128              */
129         template <class CapIface> CapIface *create()
130         {
131             Capabilities::Capability::Type type = CapIface::capabilityInterfaceType();
132             Capabilities::Capability *iface = createCapabilityInterface( type );
133             return qobject_cast<CapIface *>( iface );
134         }
135
136         /**
137              * Tests if a MetaBase object provides a given capability interface.
138              *
139              * @returns true if the interface is available, false otherwise
140              */
141         template <class CapIface> bool is() const
142         {
143             return hasCapabilityInterface( CapIface::capabilityInterfaceType() );
144         }
145     };
146
147     class AMAROK_CORE_EXPORT MetaBase : public QSharedData, public MetaCapability
148     {
149         friend class Observer;
150
151         Q_PROPERTY( QString name READ name )
152         Q_PROPERTY( QString prettyName READ prettyName )
153         Q_PROPERTY( QString fullPrettyName READ fullPrettyName )
154         Q_PROPERTY( QString sortableName READ sortableName )
155
156         public:
157             MetaBase() {}
158             virtual ~MetaBase() {}
159
160             /** The textual label for this object.
161                 For a track this is the track title, for an album it is the
162                 album name.
163                 If the name is unknown or unset then this returns an empty string.
164             */
165             virtual QString name() const = 0;
166
167             /** This is a nicer representation of the object.
168                 We will try to prevent this name from being empty.
169                 E.g. a track will fall back to the filename if possible.
170             */
171             virtual QString prettyName() const { return name(); };
172
173             /** A exact representation of the object.
174                 This might include the artist name for a track or album.
175             */
176             virtual QString fullPrettyName() const { return prettyName(); }
177
178             /** A name that can be used for sorting.
179                 This should usually mean that "The Beatles" is returned as "Beatles The"
180             */
181             virtual QString sortableName() const { return name(); }
182
183             /**used for showing a fixed name in the tree view. Needed for items that change
184              * their name occasionally such as some streams. These should overwrite this
185              */
186             virtual QString fixedName() const { return prettyName(); }
187
188         protected:
189             virtual void subscribe( Observer *observer );
190             virtual void unsubscribe( Observer *observer );
191
192             virtual void notifyObservers() const = 0;
193
194             QSet<Meta::Observer*> m_observers;
195
196         private: // no copy allowed, since it's not safe with observer list
197             Q_DISABLE_COPY(MetaBase)
198     };
199
200     class AMAROK_CORE_EXPORT Track : public MetaBase
201     {
202         public:
203
204             virtual ~Track() {}
205             /** used to display the trackname, should never be empty, returns prettyUrl() by default if name() is empty */
206             virtual QString prettyName() const;
207             /** an url which can be played by the engine backends */
208             virtual KUrl playableUrl() const = 0;
209             /** an url for display purposes */
210             virtual QString prettyUrl() const = 0;
211             /** an url which is unique for this track. Use this if you need a key for the track.
212                 Actually this is not guaranteed to be an url at all and could be something like
213                 mb-f5a3456bb0 for a MusicBrainz id.
214             */
215             virtual QString uidUrl() const = 0;
216
217             /** Returns whether playableUrl() will return a playable Url
218                 In principle this means that the url is valid.
219              */
220             virtual bool isPlayable() const = 0;
221             /** Returns the album this track belongs to */
222             virtual AlbumPtr album() const = 0;
223             /** Returns the artist of this track */
224             virtual ArtistPtr artist() const = 0;
225             /** Returns the composer of this track */
226             virtual ComposerPtr composer() const = 0;
227             /** Returns the genre of this track */
228             virtual GenrePtr genre() const = 0;
229             /** Returns the year of this track */
230             virtual YearPtr year() const = 0;
231             /**
232               * Returns the labels that are assigned to a track.
233               */
234             virtual Meta::LabelList labels() const;
235             /** Returns the BPM of this track */
236             virtual qreal bpm() const = 0;
237             /** Returns the comment of this track */
238             virtual QString comment() const = 0;
239
240             virtual qint64 length() const = 0;
241             /** Returns the filesize of this track in bytes */
242             virtual int filesize() const = 0;
243             /** Returns the sample rate of this track */
244             virtual int sampleRate() const = 0;
245             /** Returns the bitrate o this track */
246             virtual int bitrate() const = 0;
247             /** Returns the time when the track was added to the collection,
248                 or an invalid QDateTime if the time is not known. */
249             virtual QDateTime createDate() const;
250             /** Returns the time when the track was last modified (before being added to the collection)
251                 or an invalid QDateTime if the time is not known. */
252             virtual QDateTime modifyDate() const;
253             /** Returns the track number of this track */
254             virtual int trackNumber() const = 0;
255             /** Returns the discnumber of this track */
256             virtual int discNumber() const = 0;
257
258             /**
259              * Returns the gain adjustment for a given replay gain mode.
260              *
261              * Should return @c 0 if no replay gain value is known.
262              *
263              * Should return the track replay gain if the album gain is requested but
264              * is not available.
265              */
266             virtual qreal replayGain( ReplayGainTag mode ) const;
267
268             /** Returns the type of this track, e.g. "ogg", "mp3", "stream" */
269             virtual QString type() const = 0;
270
271             /** tell the track to perform any prerequisite
272              * operations before playing */
273             virtual void prepareToPlay();
274
275             /** returns true if the track is part of a collection false otherwise */
276             virtual bool inCollection() const;
277             /**
278                 returns the collection that the track is part of, or 0 iff
279                 inCollection() returns false */
280             virtual Collections::Collection* collection() const;
281
282             /** get the cached lyrics for the track. returns an empty string if
283                 no cached lyrics are available */
284             virtual QString cachedLyrics() const;
285             /**
286                 set the cached lyrics for the track
287             */
288             virtual void setCachedLyrics( const QString &lyrics );
289
290             /**
291               Adds a label to the track.
292               Does nothing if the track already has the given label.
293              */
294             virtual void addLabel( const QString &label );
295             /**
296               Adds a label to the track.
297               Does nothing if the track already has the given label.
298              */
299             virtual void addLabel( const Meta::LabelPtr &label );
300
301             /**
302               Removes a lbel from a track.
303               Does nothing if the track does not actually have the label assigned to it.
304              */
305             virtual void removeLabel( const Meta::LabelPtr &label );
306
307             /** Returns the statistics object associated with this track.
308                 The returned object should not be freed by the caller and will only exist
309                 as long as the track exists.
310                 This function will never return a 0 pointer.
311             */
312             virtual Statistics::TrackStatistics *statistics();
313
314             virtual bool operator==( const Track &track ) const;
315
316             static bool lessThan( const TrackPtr& left, const TrackPtr& right );
317
318         protected:
319             virtual void notifyObservers() const;
320
321     };
322
323     class AMAROK_CORE_EXPORT Artist : public MetaBase
324     {
325         Q_PROPERTY( TrackList tracks READ tracks )
326         public:
327
328             virtual ~Artist() {}
329
330             virtual QString prettyName() const;
331
332             /** returns all tracks by this artist */
333             virtual TrackList tracks() = 0;
334
335             virtual bool operator==( const Meta::Artist &artist ) const;
336
337             virtual QString sortableName() const;
338
339         protected:
340             virtual void notifyObservers() const;
341
342         private:
343             mutable QString m_sortableName;
344     };
345
346     /** Represents an album.
347         Most collections do not store a specific album object. Instead an album
348         is just a property of a track, a container containing one or more tracks.
349
350         Collections should proved an album for every track as the collection browser
351         will, depending on the setting, only display tracks inside albums.
352
353         For all albums in a compilation the pair album-title/album-artist should
354         be unique as this pair is used as a key in several places.
355
356         Albums without an artist are called compilations.
357         Albums without a title but with an artist should contain all singles of
358          the specific artist.
359         There should be one album without title and artist for all the rest.
360     */
361     class AMAROK_CORE_EXPORT Album : public MetaBase
362     {
363         Q_PROPERTY( bool compilation READ isCompilation )
364         Q_PROPERTY( bool hasAlbumArtist READ hasAlbumArtist )
365         Q_PROPERTY( ArtistPtr albumArtist READ albumArtist )
366         Q_PROPERTY( TrackList tracks READ tracks )
367         Q_PROPERTY( bool hasImage READ hasImage )
368         // Q_PROPERTY( QPixmap image READ image WRITE setImage )
369         Q_PROPERTY( bool supressImageAutoFetch READ suppressImageAutoFetch WRITE setSuppressImageAutoFetch )
370
371         public:
372             Album() {}
373             virtual ~Album() {}
374
375             virtual QString prettyName() const;
376
377             virtual bool isCompilation() const = 0;
378
379             /** Returns true if this album has an album artist */
380             virtual bool hasAlbumArtist() const = 0;
381             /** Returns a pointer to the album's artist */
382             virtual ArtistPtr albumArtist() const = 0;
383             /** returns all tracks on this album */
384             virtual TrackList tracks() = 0;
385
386             /**
387              * A note about image sizes:
388              *  when size is <= 1, return the full size image
389              */
390             /** returns true if the album has a cover set */
391             virtual bool hasImage( int size = 0 ) const { Q_UNUSED( size ); return false; }
392
393             /** Returns the image for the album, usually the cover image.
394                 The default implementation returns an null image.
395                 If you need a pixmap call The::coverCache()->getCover( album, size )
396                 instead. That function also returns a "nocover" pixmap
397             */
398             virtual QImage image( int size = 0 ) const;
399
400             /** Returns the image location on disk.
401                 The mpris interface is using this information for notifications so
402                 it better is a local file url.
403             */
404             virtual KUrl imageLocation( int size = 0 ) { Q_UNUSED( size ); return KUrl(); }
405
406             /** Returns true if it is possible to update the cover of the album */
407             virtual bool canUpdateImage() const { return false; }
408
409             /** updates the cover of the album
410                 @param image The large scale image that should be used as cover for the album.
411                 Note: the parameter should not be a QPixmap as a pixmap can only be created reliable in a UI thread.
412             */
413             virtual void setImage( const QImage &image ) { Q_UNUSED( image ); }
414
415             /** removes the album art */
416             virtual void removeImage() { }
417
418             /** don't automatically fetch artwork */
419             virtual void setSuppressImageAutoFetch( const bool suppress ) { Q_UNUSED( suppress ); }
420             /** should automatic artwork retrieval be suppressed? */
421             virtual bool suppressImageAutoFetch() const { return false; }
422
423             virtual bool operator==( const Meta::Album &album ) const;
424
425         protected:
426             virtual void notifyObservers() const;
427     };
428
429     class AMAROK_CORE_EXPORT Composer : public MetaBase
430     {
431         Q_PROPERTY( TrackList tracks READ tracks )
432         public:
433
434             virtual ~Composer() {}
435             virtual QString prettyName() const;
436             /** returns all tracks by this composer */
437             virtual TrackList tracks() = 0;
438
439             virtual bool operator==( const Meta::Composer &composer ) const;
440
441         protected:
442             virtual void notifyObservers() const;
443     };
444
445     class AMAROK_CORE_EXPORT Genre : public MetaBase
446     {
447         Q_PROPERTY( TrackList tracks READ tracks )
448         public:
449
450             virtual ~Genre() {}
451             virtual QString prettyName() const;
452             /** returns all tracks which belong to the genre */
453             virtual TrackList tracks() = 0;
454
455             virtual bool operator==( const Meta::Genre &genre ) const;
456
457         protected:
458             virtual void notifyObservers() const;
459     };
460
461     class AMAROK_CORE_EXPORT Year : public MetaBase
462     {
463         Q_PROPERTY( TrackList tracks READ tracks )
464         public:
465
466             virtual ~Year() {}
467
468             /** Returns the year this object represents.
469                 A number of 0 is considered unset.
470             */
471             virtual int year() const { return name().toInt(); }
472
473             /** returns all tracks which are tagged with this year */
474             virtual TrackList tracks() = 0;
475
476             virtual bool operator==( const Meta::Year &year ) const;
477
478         protected:
479             virtual void notifyObservers() const;
480     };
481
482     /**
483       A Label represents an arbitrary classification of a Track.
484       */
485     class AMAROK_CORE_EXPORT Label : public MetaBase
486     {
487     public:
488         /**
489           Constructs a new Label.
490           */
491         Label() : MetaBase() {}
492         /**
493           Destructs an existing Label.
494           */
495         virtual ~ Label() {}
496
497     protected:
498         virtual void notifyObservers() const;
499     };
500 }
501
502 Q_DECLARE_METATYPE( Meta::DataPtr )
503 Q_DECLARE_METATYPE( Meta::DataList )
504 Q_DECLARE_METATYPE( Meta::TrackPtr )
505 Q_DECLARE_METATYPE( Meta::TrackList )
506 Q_DECLARE_METATYPE( Meta::ArtistPtr )
507 Q_DECLARE_METATYPE( Meta::ArtistList )
508 Q_DECLARE_METATYPE( Meta::AlbumPtr )
509 Q_DECLARE_METATYPE( Meta::AlbumList )
510 Q_DECLARE_METATYPE( Meta::ComposerPtr )
511 Q_DECLARE_METATYPE( Meta::ComposerList )
512 Q_DECLARE_METATYPE( Meta::GenrePtr )
513 Q_DECLARE_METATYPE( Meta::GenreList )
514 Q_DECLARE_METATYPE( Meta::YearPtr )
515 Q_DECLARE_METATYPE( Meta::YearList )
516 Q_DECLARE_METATYPE( Meta::LabelPtr )
517 Q_DECLARE_METATYPE( Meta::LabelList )
518
519
520
521 #endif /* AMAROK_META_H */