158
159
#ifdef HAVE_LIBLASTFM
159
160
void ToLastFM(lastfm::Track* track) const;
162
void ToXesam(QVariantMap* map) const;
162
164
// Simple accessors
163
bool is_valid() const { return d->valid_; }
164
int id() const { return d->id_; }
166
const QString& title() const { return d->title_; }
167
const QString& album() const { return d->album_; }
168
const QString& artist() const { return d->artist_; }
169
const QString& albumartist() const { return d->albumartist_; }
170
const QString& composer() const { return d->composer_; }
171
int track() const { return d->track_; }
172
int disc() const { return d->disc_; }
173
float bpm() const { return d->bpm_; }
174
int year() const { return d->year_; }
175
const QString& genre() const { return d->genre_; }
176
const QString& comment() const { return d->comment_; }
177
bool is_compilation() const {
178
return (d->compilation_ || d->sampler_ || d->forced_compilation_on_)
179
&& ! d->forced_compilation_off_;
181
float rating() const { return d->rating_; }
182
int playcount() const { return d->playcount_; }
183
int skipcount() const { return d->skipcount_; }
184
int lastplayed() const { return d->lastplayed_; }
185
int score() const { return d->score_; }
187
const QString& cue_path() const { return d->cue_path_; }
188
bool has_cue() const { return !d->cue_path_.isEmpty(); }
190
qint64 beginning_nanosec() const { return d->beginning_; }
191
qint64 end_nanosec() const { return d->end_; }
193
qint64 length_nanosec() const { return d->end_ - d->beginning_; }
195
int bitrate() const { return d->bitrate_; }
196
int samplerate() const { return d->samplerate_; }
198
int directory_id() const { return d->directory_id_; }
199
const QString& filename() const { return d->filename_; }
200
// Returns this Song's URL which may point either to a file or to another type
203
const QString& basefilename() const { return d->basefilename_; }
204
uint mtime() const { return d->mtime_; }
205
uint ctime() const { return d->ctime_; }
206
int filesize() const { return d->filesize_; }
207
FileType filetype() const { return d->filetype_; }
208
bool is_stream() const { return d->filetype_ == Type_Stream; }
210
const QString& art_automatic() const { return d->art_automatic_; }
211
const QString& art_manual() const { return d->art_manual_; }
165
bool is_valid() const;
166
bool is_unavailable() const;
169
const QString& title() const;
170
const QString& album() const;
171
const QString& artist() const;
172
const QString& albumartist() const;
173
const QString& effective_albumartist() const;
174
// Playlist views are special because you don't want to fill in album artists automatically for
175
// compilations, but you do for normal albums:
176
const QString& playlist_albumartist() const;
177
const QString& composer() const;
182
const QString& genre() const;
183
const QString& comment() const;
184
bool is_compilation() const;
185
float rating() const;
186
int playcount() const;
187
int skipcount() const;
188
int lastplayed() const;
191
const QString& cue_path() const;
192
bool has_cue() const;
194
qint64 beginning_nanosec() const;
195
qint64 end_nanosec() const;
197
qint64 length_nanosec() const;
200
int samplerate() const;
202
int directory_id() const;
203
const QUrl& url() const;
204
const QString& basefilename() const;
207
int filesize() const;
208
FileType filetype() const;
209
bool is_stream() const;
210
bool is_cdda() const;
212
const QString& art_automatic() const;
213
const QString& art_manual() const;
213
215
// Returns true if this Song had it's cover manually unset by user.
214
bool has_manually_unset_cover() const { return d->art_manual_ == kManuallyUnsetCover; }
216
bool has_manually_unset_cover() const;
215
217
// This method represents an explicit request to unset this song's
217
void manually_unset_cover() { d->art_manual_ = kManuallyUnsetCover; }
219
void manually_unset_cover();
219
221
// Returns true if this song (it's media file) has an embedded cover.
220
bool has_embedded_cover() const { return d->art_automatic_ == kEmbeddedCover; }
222
bool has_embedded_cover() const;
221
223
// Sets a flag saying that this song (it's media file) has an embedded
223
void set_embedded_cover() { d->art_automatic_ = kEmbeddedCover; }
225
void set_embedded_cover();
225
const QImage& image() const { return d->image_; }
227
const QImage& image() const;
227
229
// Pretty accessors
228
230
QString PrettyTitle() const;
237
239
bool Save() const;
238
240
QFuture<bool> BackgroundSave() const;
240
void set_id(int id) { d->id_ = id; }
241
void set_valid(bool v) { d->valid_ = v; }
242
void set_title(const QString& v) { d->title_ = v; }
243
void set_valid(bool v);
244
void set_title(const QString& v);
244
void set_album(const QString& v) { d->album_ = v; }
245
void set_artist(const QString& v) { d->artist_ = v; }
246
void set_albumartist(const QString& v) { d->albumartist_ = v; }
247
void set_composer(const QString& v) { d->composer_ = v; }
248
void set_track(int v) { d->track_ = v; }
249
void set_disc(int v) { d->disc_ = v; }
250
void set_bpm(float v) { d->bpm_ = v; }
251
void set_year(int v) { d->year_ = v; }
252
void set_genre(const QString& v) { d->genre_ = v; }
246
void set_album(const QString& v);
247
void set_artist(const QString& v);
248
void set_albumartist(const QString& v);
249
void set_composer(const QString& v);
250
void set_track(int v);
251
void set_disc(int v);
252
void set_bpm(float v);
253
void set_year(int v);
254
void set_genre(const QString& v);
253
255
void set_genre_id3(int id);
254
void set_comment(const QString& v) { d->comment_ = v; }
255
void set_compilation(bool v) { d->compilation_ = v; }
256
void set_sampler(bool v) { d->sampler_ = v; }
257
void set_beginning_nanosec(qint64 v) { d->beginning_ = qMax(0ll, v); }
258
void set_end_nanosec(qint64 v) { d->end_ = v; }
259
void set_length_nanosec(qint64 v) { d->end_ = d->beginning_ + v; }
260
void set_bitrate(int v) { d->bitrate_ = v; }
261
void set_samplerate(int v) { d->samplerate_ = v; }
262
void set_mtime(int v) { d->mtime_ = v; }
263
void set_ctime(int v) { d->ctime_ = v; }
264
void set_filesize(int v) { d->filesize_ = v; }
265
void set_filetype(FileType v) { d->filetype_ = v; }
266
void set_art_automatic(const QString& v) { d->art_automatic_ = v; }
267
void set_art_manual(const QString& v) { d->art_manual_ = v; }
268
void set_image(const QImage& i) { d->image_ = i; }
269
void set_forced_compilation_on(bool v) { d->forced_compilation_on_ = v; }
270
void set_forced_compilation_off(bool v) { d->forced_compilation_off_ = v; }
271
void set_rating(float v) { d->rating_ = v; }
272
void set_playcount(int v) { d->playcount_ = v; }
273
void set_skipcount(int v) { d->skipcount_ = v; }
274
void set_lastplayed(int v) { d->lastplayed_ = v; }
275
void set_score(int v) { d->score_ = qBound(0, v, 100); }
276
void set_cue_path(const QString& v) { d->cue_path_ = v; }
256
void set_comment(const QString& v);
257
void set_compilation(bool v);
258
void set_sampler(bool v);
259
void set_beginning_nanosec(qint64 v);
260
void set_end_nanosec(qint64 v);
261
void set_length_nanosec(qint64 v);
262
void set_bitrate(int v);
263
void set_samplerate(int v);
264
void set_mtime(int v);
265
void set_ctime(int v);
266
void set_filesize(int v);
267
void set_filetype(FileType v);
268
void set_art_automatic(const QString& v);
269
void set_art_manual(const QString& v);
270
void set_image(const QImage& i);
271
void set_forced_compilation_on(bool v);
272
void set_forced_compilation_off(bool v);
273
void set_rating(float v);
274
void set_playcount(int v);
275
void set_skipcount(int v);
276
void set_lastplayed(int v);
277
void set_score(int v);
278
void set_cue_path(const QString& v);
279
void set_unavailable(bool v);
278
281
// Setters that should only be used by tests
279
void set_filename(const QString& v) { d->filename_ = v; }
280
void set_basefilename(const QString& v) { d->basefilename_ = v; }
281
void set_directory_id(int v) { d->directory_id_ = v; }
282
void set_url(const QUrl& v);
283
void set_basefilename(const QString& v);
284
void set_directory_id(int v);
283
286
// Comparison functions
284
287
bool IsMetadataEqual(const Song& other) const;
296
306
void ParseFMPSFrame(const QString& name, const QString& value);
299
struct Private : public QSharedData {
308
QString albumartist_;
316
bool compilation_; // From the file tag
317
bool sampler_; // From the library scanner
318
bool forced_compilation_on_; // Set by the user
319
bool forced_compilation_off_; // Set by the user
327
// The beginning of the song in seconds. In case of single-part media
328
// streams, this will equal to 0. In case of multi-part streams on the
329
// other hand, this will mark the beginning of a section represented by
330
// this Song object. This is always greater than 0.
332
// The end of the song in seconds. In case of single-part media
333
// streams, this will equal to the song's length. In case of multi-part
334
// streams on the other hand, this will mark the end of a section
335
// represented by this Song object.
336
// This may be negative indicating that the length of this song is
345
QString basefilename_;
351
// If the song has a CUE, this contains it's path.
354
// Filenames to album art for this song.
355
QString art_automatic_; // Guessed by LibraryWatcher
356
QString art_manual_; // Set by the user - should take priority
360
// Whether this song was loaded from a file using taglib.
361
bool init_from_file_;
362
// Whether our encoding guesser thinks these tags might be incorrectly encoded.
363
bool suspicious_tags_;
366
void ParseOggTag(const TagLib::Ogg::FieldListMap& map, const QTextCodec* codec, QString* disc, QString* compilation);
369
310
QSharedDataPointer<Private> d;
370
312
FileRefFactory* factory_;
372
314
static TagLibFileRefFactory kDefaultFactory;
374
static QMutex taglib_mutex_;
316
static QMutex sTaglibMutex;
376
318
Q_DECLARE_METATYPE(Song);
378
320
typedef QList<Song> SongList;
379
Q_DECLARE_METATYPE(SongList);
321
Q_DECLARE_METATYPE(QList<Song>);
323
uint qHash(const Song& song);