1 /* This file is part of Clementine. 2 Copyright 2009-2012, David Sansome <me@davidsansome.com> 3 Copyright 2010-2011, Paweł Bara <keirangtp@gmail.com> 4 Copyright 2010, 2012, 2014, John Maguire <john.maguire@gmail.com> 5 Copyright 2011-2012, 2014, Arnaud Bienner <arnaud.bienner@gmail.com> 6 Copyright 2011, Angus Gratton <gus@projectgus.com> 7 Copyright 2012, Kacper "mattrick" Banasik <mattrick@jabster.pl> 8 Copyright 2013, Martin Brodbeck <martin@brodbeck-online.de> 9 Copyright 2013, Joel Bradshaw <cincodenada@gmail.com> 10 Copyright 2013, Uwe Klotz <uwe.klotz@gmail.com> 11 Copyright 2013, Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk> 12 Copyright 2014, Andreas <asfa194@gmail.com> 13 Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com> 14 15 Clementine is free software: you can redistribute it and/or modify 16 it under the terms of the GNU General Public License as published by 17 the Free Software Foundation, either version 3 of the License, or 18 (at your option) any later version. 19 20 Clementine is distributed in the hope that it will be useful, 21 but WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 GNU General Public License for more details. 24 25 You should have received a copy of the GNU General Public License 26 along with Clementine. If not, see <http://www.gnu.org/licenses/>. 27 */ 28 29 #ifndef CORE_SONG_H_ 30 #define CORE_SONG_H_ 31 32 #include <QImage> 33 #include <QMetaType> 34 #include <QSharedDataPointer> 35 #include <QVariantMap> 36 37 #include "config.h" 38 #include "engines/engine_fwd.h" 39 40 namespace pb { 41 namespace tagreader { 42 class SongMetadata; 43 } // namespace tagreader 44 } // namespace pb 45 46 class QSqlQuery; 47 class QUrl; 48 49 #ifdef HAVE_LIBGPOD 50 struct _Itdb_Track; 51 #endif 52 53 #ifdef HAVE_LIBMTP 54 struct LIBMTP_track_struct; 55 #endif 56 57 #ifdef HAVE_LIBLASTFM 58 namespace lastfm { 59 class Track; 60 } 61 #endif 62 63 class SqlRow; 64 65 class Song { 66 public: 67 Song(); 68 Song(const Song& other); 69 ~Song(); 70 71 static const QStringList kColumns; 72 static const QString kColumnSpec; 73 static const QString kBindSpec; 74 static const QString kUpdateSpec; 75 76 static const QStringList kIntColumns; 77 static const QStringList kFloatColumns; 78 static const QStringList kDateColumns; 79 80 static const QStringList kFtsColumns; 81 static const QString kFtsColumnSpec; 82 static const QString kFtsBindSpec; 83 static const QString kFtsUpdateSpec; 84 85 static const QString kManuallyUnsetCover; 86 static const QString kEmbeddedCover; 87 88 static QString JoinSpec(const QString& table); 89 90 // Don't change these values - they're stored in the database, and defined 91 // in the tag reader protobuf. 92 // If a new lossless file is added, also add it to IsFileLossless(). 93 enum FileType { 94 Type_Unknown = 0, 95 Type_Asf = 1, 96 Type_Flac = 2, 97 Type_Mp4 = 3, 98 Type_Mpc = 4, 99 Type_Mpeg = 5, 100 Type_OggFlac = 6, 101 Type_OggSpeex = 7, 102 Type_OggVorbis = 8, 103 Type_Aiff = 9, 104 Type_Wav = 10, 105 Type_TrueAudio = 11, 106 Type_Cdda = 12, 107 Type_OggOpus = 13, 108 Type_WavPack = 14, 109 Type_Spc = 15, 110 Type_VGM = 16, 111 Type_APE = 17, 112 Type_Stream = 99, 113 }; 114 static QString TextForFiletype(FileType type); TextForFiletype()115 QString TextForFiletype() const { return TextForFiletype(filetype()); } 116 bool IsFileLossless() const; 117 118 // Sort songs alphabetically using their pretty title 119 static void SortSongsListAlphabetically(QList<Song>* songs); 120 121 // Constructors 122 void Init(const QString& title, const QString& artist, const QString& album, 123 qint64 length_nanosec); 124 void Init(const QString& title, const QString& artist, const QString& album, 125 qint64 beginning, qint64 end); 126 void InitFromProtobuf(const pb::tagreader::SongMetadata& pb); 127 void InitFromQuery(const SqlRow& query, bool reliable_metadata, int col = 0); 128 void InitFromFilePartial( 129 const QString& filename); // Just store the filename: incomplete but fast 130 void InitArtManual(); // Check if there is already a art in the cache and 131 // store the filename in art_manual 132 #ifdef HAVE_LIBLASTFM 133 void InitFromLastFM(const lastfm::Track& track); 134 #endif 135 136 void MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle& bundle); 137 138 #ifdef HAVE_LIBGPOD 139 void InitFromItdb(const _Itdb_Track* track, const QString& prefix); 140 void ToItdb(_Itdb_Track* track) const; 141 #endif 142 143 #ifdef HAVE_LIBMTP 144 void InitFromMTP(const LIBMTP_track_struct* track, const QString& host); 145 void ToMTP(LIBMTP_track_struct* track) const; 146 #endif 147 148 // Copies important statistics from the other song to this one, overwriting 149 // any data that already exists. Useful when you want updated tags from disk 150 // but you want to keep user stats. 151 void MergeUserSetData(const Song& other); 152 153 static QString Decode(const QString& tag, const QTextCodec* codec = nullptr); 154 155 // Save 156 void BindToQuery(QSqlQuery* query) const; 157 void BindToFtsQuery(QSqlQuery* query) const; 158 #ifdef HAVE_LIBLASTFM 159 void ToLastFM(lastfm::Track* track, bool prefer_album_artist) const; 160 #endif 161 void ToXesam(QVariantMap* map) const; 162 void ToProtobuf(pb::tagreader::SongMetadata* pb) const; 163 164 // Simple accessors 165 bool is_valid() const; 166 bool is_unavailable() const; 167 int id() const; 168 169 const QString& title() const; 170 const QString& album() const; 171 const QString& effective_album() const; 172 const QString& artist() const; 173 const QString& albumartist() const; 174 const QString& effective_albumartist() const; 175 // Playlist views are special because you don't want to fill in album artists 176 // automatically for 177 // compilations, but you do for normal albums: 178 const QString& playlist_albumartist() const; 179 const QString& composer() const; 180 const QString& performer() const; 181 const QString& grouping() const; 182 const QString& lyrics() const; 183 int track() const; 184 int disc() const; 185 float bpm() const; 186 int year() const; 187 int originalyear() const; 188 int effective_originalyear() const; 189 const QString& genre() const; 190 const QString& comment() const; 191 bool is_compilation() const; 192 float rating() const; 193 int playcount() const; 194 int skipcount() const; 195 int lastplayed() const; 196 int score() const; 197 int album_id() const; 198 199 const QString& cue_path() const; 200 bool has_cue() const; 201 202 qint64 beginning_nanosec() const; 203 qint64 end_nanosec() const; 204 205 qint64 length_nanosec() const; 206 207 int bitrate() const; 208 int samplerate() const; 209 210 int directory_id() const; 211 const QUrl& url() const; 212 const QString& basefilename() const; 213 uint mtime() const; 214 uint ctime() const; 215 int filesize() const; 216 FileType filetype() const; 217 bool is_stream() const; 218 bool is_cdda() const; 219 // Guess if it is a library song using fields set. Might not be 100% reliable. 220 bool is_library_song() const; 221 222 const QString& art_automatic() const; 223 const QString& art_manual() const; 224 225 const QString& etag() const; 226 227 // Returns true if this Song had it's cover manually unset by user. 228 bool has_manually_unset_cover() const; 229 // This method represents an explicit request to unset this song's 230 // cover. 231 void manually_unset_cover(); 232 233 // Returns true if this song (it's media file) has an embedded cover. 234 bool has_embedded_cover() const; 235 // Sets a flag saying that this song (it's media file) has an embedded 236 // cover. 237 void set_embedded_cover(); 238 239 const QImage& image() const; 240 241 // Pretty accessors 242 QString PrettyRating() const; 243 QString PrettyTitle() const; 244 QString PrettyTitleWithArtist() const; 245 QString PrettyLength() const; 246 QString PrettyYear() const; 247 248 QString TitleWithCompilationArtist() const; 249 250 // Setters 251 bool IsEditable() const; 252 253 void set_id(int id); 254 void set_valid(bool v); 255 void set_title(const QString& v); 256 257 void set_album(const QString& v); 258 void set_artist(const QString& v); 259 void set_albumartist(const QString& v); 260 void set_composer(const QString& v); 261 void set_performer(const QString& v); 262 void set_grouping(const QString& v); 263 void set_lyrics(const QString& v); 264 void set_track(int v); 265 void set_disc(int v); 266 void set_bpm(float v); 267 void set_year(int v); 268 void set_originalyear(int v); 269 void set_genre(const QString& v); 270 void set_genre_id3(int id); 271 void set_comment(const QString& v); 272 void set_compilation(bool v); 273 void set_sampler(bool v); 274 void set_album_id(int v); 275 void set_beginning_nanosec(qint64 v); 276 void set_end_nanosec(qint64 v); 277 void set_length_nanosec(qint64 v); 278 void set_bitrate(int v); 279 void set_samplerate(int v); 280 void set_mtime(int v); 281 void set_ctime(int v); 282 void set_filesize(int v); 283 void set_filetype(FileType v); 284 void set_art_automatic(const QString& v); 285 void set_art_manual(const QString& v); 286 void set_image(const QImage& i); 287 void set_forced_compilation_on(bool v); 288 void set_forced_compilation_off(bool v); 289 void set_rating(float v); 290 void set_playcount(int v); 291 void set_skipcount(int v); 292 void set_lastplayed(int v); 293 void set_score(int v); 294 void set_cue_path(const QString& v); 295 void set_unavailable(bool v); 296 void set_etag(const QString& etag); 297 298 // Setters that should only be used by tests 299 void set_url(const QUrl& v); 300 void set_basefilename(const QString& v); 301 void set_directory_id(int v); 302 303 // Comparison functions 304 bool IsMetadataEqual(const Song& other) const; 305 bool IsOnSameAlbum(const Song& other) const; 306 bool IsSimilar(const Song& other) const; 307 308 bool operator==(const Song& other) const; 309 310 // Two songs that are on the same album will have the same AlbumKey. It is 311 // more efficient to use IsOnSameAlbum, but this function can be used when 312 // you need to hash the key to do fast lookups. 313 QString AlbumKey() const; 314 315 Song& operator=(const Song& other); 316 317 private: 318 struct Private; 319 QSharedDataPointer<Private> d; 320 }; 321 Q_DECLARE_METATYPE(Song) 322 323 typedef QList<Song> SongList; 324 Q_DECLARE_METATYPE(QList<Song>) 325 326 uint qHash(const Song& song); 327 // Hash function using field checked in IsSimilar function 328 uint HashSimilar(const Song& song); 329 330 #endif // CORE_SONG_H_ 331