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