PageRenderTime 338ms CodeModel.GetById 113ms app.highlight 101ms RepoModel.GetById 70ms app.codeStats 1ms

/thirdparty/liblastfm2/src/types/Track.h

http://github.com/tomahawk-player/tomahawk
C++ Header | 359 lines | 237 code | 64 blank | 58 comment | 4 complexity | bb006b0148b8ba62653c0ce03809dadd MD5 | raw file
  1/*
  2   Copyright 2009-2010 Last.fm Ltd.
  3      - Primarily authored by Max Howell, Jono Cole, Doug Mansell and Michael Coffey
  4
  5   This file is part of liblastfm.
  6
  7   liblastfm is free software: you can redistribute it and/or modify
  8   it under the terms of the GNU General Public License as published by
  9   the Free Software Foundation, either version 3 of the License, or
 10   (at your option) any later version.
 11
 12   liblastfm is distributed in the hope that it will be useful,
 13   but WITHOUT ANY WARRANTY; without even the implied warranty of
 14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15   GNU General Public License for more details.
 16
 17   You should have received a copy of the GNU General Public License
 18   along with liblastfm.  If not, see <http://www.gnu.org/licenses/>.
 19*/
 20#ifndef LASTFM_TRACK_H
 21#define LASTFM_TRACK_H
 22
 23#include <lastfm/AbstractType>
 24#include <lastfm/Album>
 25#include <lastfm/Mbid>
 26#include <QDateTime>
 27#include <QDomElement>
 28#include <QExplicitlySharedDataPointer>
 29#include <QString>
 30#include <QMap>
 31#include <QUrl>
 32
 33
 34namespace lastfm {
 35
 36class LASTFM_DLLEXPORT TrackContext
 37{
 38public:
 39    enum Type
 40    {
 41        Unknown,
 42        User,
 43        Friend,
 44        Neighbour,
 45        Artist
 46    };
 47
 48    TrackContext();
 49    TrackContext( const QString& type, const QList<QString>& values );
 50
 51    Type type() const;
 52    QList<QString> values() const;
 53private:
 54    static Type getType( const QString& type );
 55
 56private:
 57    Type m_type;
 58    QList<QString> m_values;
 59};
 60
 61class TrackData : public QObject, public QSharedData
 62{
 63    Q_OBJECT
 64
 65    friend class Track;
 66    friend class MutableTrack;
 67public:
 68    TrackData();
 69
 70public:
 71    QString artist;
 72    QString albumArtist;
 73    QString album;
 74    QString title;
 75    QString correctedArtist;
 76    QString correctedAlbumArtist;
 77    QString correctedAlbum;
 78    QString correctedTitle;
 79    TrackContext context;
 80    uint trackNumber;
 81    uint duration;
 82    short source;
 83    short rating;
 84    QString mbid; /// musicbrainz id
 85    uint fpid;
 86    QUrl url;
 87    QDateTime time; /// the time the track was started at
 88    bool loved;
 89    QMap<lastfm::ImageSize, QUrl> m_images;
 90    short scrobbleStatus;
 91    short scrobbleError;
 92    QString scrobbleErrorText;
 93
 94    //FIXME I hate this, but is used for radio trackauth etc.
 95    QMap<QString,QString> extras;
 96    
 97    bool null;
 98
 99private:
100    void forceLoveToggled( bool love ) { emit loveToggled( love );}
101    void forceScrobbleStatusChanged() { emit scrobbleStatusChanged(); }
102    void forceCorrected( QString correction ) { emit corrected( correction ); }
103
104private slots:
105    void onLoveFinished();
106    void onUnloveFinished();
107    void onGotInfo();
108
109signals:
110    void loveToggled( bool love );
111    void loveFinished();
112    void unlovedFinished();
113    void gotInfo( const QByteArray& );
114    void scrobbleStatusChanged();
115    void corrected( QString correction );
116};
117
118
119/** Our track type. It's quite good, you may want to use it as your track type
120  * in general. It is explicitly shared. Which means when you make a copy, they
121  * both point to the same data still. This is like Qt's implicitly shared
122  * classes, eg. QString, however if you mod a copy of a QString, the copy
123  * detaches first, so then you have two copies. Our Track object doesn't
124  * detach, which is very handy for our usage in the client, but perhaps not
125  * what you want. If you need a deep copy for eg. work in a thread, call 
126  * clone(). */
127class LASTFM_DLLEXPORT Track : public AbstractType
128{
129public:
130    friend class TrackSignalProxy;
131
132    enum Source
133    {
134        // DO NOT UNDER ANY CIRCUMSTANCES CHANGE THE ORDER OR VALUES OF THIS ENUM!
135        // you will cause broken settings and b0rked scrobbler cache submissions
136
137        Unknown = 0,
138        LastFmRadio,
139        Player,
140        MediaDevice,
141        NonPersonalisedBroadcast, // eg Shoutcast, BBC Radio 1, etc.
142        PersonalisedRecommendation, // eg Pandora, but not Last.fm
143    };
144
145    enum ScrobbleStatus
146    {
147        Null = 0,
148        Cached,
149        Submitted,
150        Error
151    };
152
153    enum Corrections
154    {
155        Original = 0,
156        Corrected
157    };
158
159    enum ScrobbleError
160    {
161        None = 0,
162        FilteredArtistName = 113,
163        FilteredTrackName = 114,
164        FilteredAlbumName = 115,
165        FilteredTimestamp = 116,
166        ExceededMaxDailyScrobbles = 118,
167        InvalidStreamAuth = 119
168    };
169
170    Track();
171    explicit Track( const QDomElement& );
172
173    /** this track and that track point to the same object, so they are the same
174      * in fact. This doesn't do a deep data comparison. So even if all the 
175      * fields are the same it will return false if they aren't in fact spawned
176      * from the same initial Track object */
177    bool sameObject( const Track& that )
178    {
179        return (this->d == that.d);
180    }
181
182    bool operator==( const Track& that ) const
183    {
184        return ( this->title() == that.title() &&
185                 this->album() == that.album() &&
186                 this->artist() == that.artist());
187    }
188    bool operator!=( const Track& that ) const
189    {
190        return !operator==( that );
191    }
192
193    QObject* signalProxy() const { return d.data(); }
194
195    /** only a Track() is null */
196    bool isNull() const { return d->null; }
197
198    bool corrected() const;
199
200    Artist artist( Corrections corrected = Original ) const;
201    Artist albumArtist( Corrections corrected = Original ) const;
202    Album album( Corrections corrected = Original ) const;
203    QString title( Corrections corrected = Original ) const;
204
205    uint trackNumber() const { return d->trackNumber; }
206    uint duration() const { return d->duration; } /// in seconds
207    Mbid mbid() const { return Mbid(d->mbid); }
208    QUrl url() const { return d->url; }
209    QDateTime timestamp() const { return d->time; }
210    Source source() const { return static_cast<Source>(d->source); }
211    uint fingerprintId() const { return d->fpid; }
212    bool isLoved() const { return d->loved; }
213    QUrl imageUrl( lastfm::ImageSize size, bool square ) const;
214
215    QString durationString() const { return durationString( d->duration ); }
216    static QString durationString( int seconds );
217
218    ScrobbleStatus scrobbleStatus() const { return static_cast<ScrobbleStatus>(d->scrobbleStatus); }
219    ScrobbleError scrobbleError() const { return static_cast<ScrobbleError>(d->scrobbleError); }
220    QString scrobbleErrorText() const { return d->scrobbleErrorText; }
221
222    /** default separator is an en-dash */
223    QString toString() const { return toString( Corrected ); }
224    QString toString( Corrections corrections ) const { return toString( QChar(8211), corrections );}
225    QString toString( const QChar& separator, Corrections corrections = Original ) const;
226    /** the standard representation of this object as an XML node */
227    QDomElement toDomElement( class QDomDocument& ) const;
228
229    TrackContext context() const { return d->context; }
230    
231    QString extra( const QString& key ) const{ return d->extras[ key ]; }
232
233    bool operator<( const Track &that ) const
234    {
235        return this->d->time < that.d->time;
236    }
237    
238    bool isMp3() const;
239    
240    operator QVariant() const { return QVariant::fromValue( *this ); }
241    
242//////////// lastfm::Ws
243    
244    /** See last.fm/api Track section */
245    QNetworkReply* share( const QStringList& recipients, const QString& message = "", bool isPublic = true ) const;
246
247    /** you can get any QNetworkReply TagList using Tag::list( QNetworkReply* ) */
248    QNetworkReply* getTags() const; // for the logged in user
249    QNetworkReply* getTopTags() const;
250    QNetworkReply* getTopFans() const;
251    void getInfo() const;
252    QNetworkReply* getBuyLinks( const QString& country ) const;
253
254    /** you can only add 10 tags, we submit everything you give us, but the
255      * docs state 10 only. Will return 0 if the list is empty. */
256    QNetworkReply* addTags( const QStringList& ) const;
257    /** will return 0 if the string is "" */
258    QNetworkReply* removeTag( const QString& ) const;
259
260    /** scrobble the track */
261    QNetworkReply* updateNowPlaying() const;
262    QNetworkReply* updateNowPlaying( int duration ) const;
263    QNetworkReply* removeNowPlaying() const;
264    QNetworkReply* scrobble() const;
265    static QNetworkReply* scrobble(const QList<lastfm::Track>& tracks);
266
267    /** the url for this track's page at last.fm */
268    QUrl www() const;
269
270protected:
271    QExplicitlySharedDataPointer<TrackData> d;
272    QMap<QString, QString> params( const QString& method, bool use_mbid = false ) const;
273    void invalidateGetInfo();
274private:
275    Track( TrackData* that_d ) : d( that_d )
276    {}
277};
278
279
280
281/** This class allows you to change Track objects, it is easy to use:
282  * MutableTrack( some_track_object ).setTitle( "Arse" );
283  *
284  * We have a separate MutableTrack class because in our usage, tracks
285  * only get mutated once, and then after that, very rarely. This pattern
286  * encourages such usage, which is generally sensible. You can feel more
287  * comfortable that the data hasn't accidently changed behind your back.
288  */
289class LASTFM_DLLEXPORT MutableTrack : public Track
290{
291public:
292    MutableTrack()
293    {
294        d->null = false;
295    }
296
297    /** NOTE that passing a Track() to this ctor will automatically make it non
298      * null. Which may not be what you want. So be careful
299      * Rationale: this is the most maintainable way to do it 
300      */
301    MutableTrack( const Track& that ) : Track( that )
302    {
303        d->null = false;
304    }
305
306    void setFromLfm( const XmlQuery& lfm );
307    void setImageUrl( lastfm::ImageSize size, const QString& url );
308    
309    void setArtist( QString artist ) { d->artist = artist.trimmed(); }
310    void setAlbumArtist( QString albumArtist ) { d->albumArtist = albumArtist.trimmed(); }
311    void setAlbum( QString album ) { d->album = album.trimmed(); }
312    void setTitle( QString title ) { d->title = title.trimmed(); }
313    void setCorrections( QString title, QString album, QString artist, QString albumArtist );
314    void setTrackNumber( uint n ) { d->trackNumber = n; }
315    void setDuration( uint duration ) { d->duration = duration; }
316    void setUrl( QUrl url ) { d->url = url; }
317    void setSource( Source s ) { d->source = s; }
318    void setLoved( bool loved ) { d->loved = loved; }
319    
320    void setMbid( Mbid id ) { d->mbid = id; }
321    void setFingerprintId( uint id ) { d->fpid = id; }
322
323    void setScrobbleStatus( ScrobbleStatus scrobbleStatus )
324    {
325        d->scrobbleStatus = scrobbleStatus;
326        d->forceScrobbleStatusChanged();
327    }
328    void setScrobbleError( ScrobbleError scrobbleError ) { d->scrobbleError = scrobbleError; }
329    void setScrobbleErrorText( const QString& scrobbleErrorText ) { d->scrobbleErrorText = scrobbleErrorText; }
330    
331    /** you also must scrobble this track for the love to become permenant */
332    void love();
333    void unlove();
334    QNetworkReply* ban();
335    
336    void stamp() { d->time = QDateTime::currentDateTime(); }
337
338    void setExtra( const QString& key, const QString& value ) { d->extras[key] = value; }
339    void removeExtra( QString key ) { d->extras.remove( key ); }
340    void setTimeStamp( const QDateTime& dt ) { d->time = dt; }
341
342    void setContext( TrackContext context ) { d->context = context;}
343};
344
345
346} //namespace lastfm
347
348
349inline QDebug operator<<( QDebug d, const lastfm::Track& t )
350{
351    return !t.isNull() 
352            ? d << t.toString( '-' ) << t.url()
353            : d << "Null Track object";
354}
355
356
357Q_DECLARE_METATYPE( lastfm::Track );
358
359#endif //LASTFM_TRACK_H