2010-03-24 00:11:46 +01:00
|
|
|
/* This file is part of Clementine.
|
2014-11-02 19:36:21 +01:00
|
|
|
Copyright 2009-2012, David Sansome <me@davidsansome.com>
|
|
|
|
Copyright 2010-2011, Paweł Bara <keirangtp@gmail.com>
|
|
|
|
Copyright 2010, 2012, 2014, John Maguire <john.maguire@gmail.com>
|
|
|
|
Copyright 2011-2012, 2014, Arnaud Bienner <arnaud.bienner@gmail.com>
|
|
|
|
Copyright 2011, Angus Gratton <gus@projectgus.com>
|
|
|
|
Copyright 2012, Kacper "mattrick" Banasik <mattrick@jabster.pl>
|
|
|
|
Copyright 2013, Martin Brodbeck <martin@brodbeck-online.de>
|
|
|
|
Copyright 2013, Joel Bradshaw <cincodenada@gmail.com>
|
|
|
|
Copyright 2013, Uwe Klotz <uwe.klotz@gmail.com>
|
|
|
|
Copyright 2013, Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>
|
2014-12-10 01:25:52 +01:00
|
|
|
Copyright 2014, Andreas <asfa194@gmail.com>
|
2014-11-02 19:36:21 +01:00
|
|
|
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
2010-03-24 00:11:46 +01:00
|
|
|
|
|
|
|
Clementine is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Clementine is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2014-11-01 19:26:05 +01:00
|
|
|
#ifndef CORE_SONG_H_
|
|
|
|
#define CORE_SONG_H_
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-02-25 01:18:32 +01:00
|
|
|
#include <QImage>
|
2010-08-03 21:29:49 +02:00
|
|
|
#include <QMetaType>
|
2010-01-15 22:57:22 +01:00
|
|
|
#include <QSharedDataPointer>
|
2011-10-16 22:57:53 +02:00
|
|
|
#include <QVariantMap>
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-07-04 22:52:45 +02:00
|
|
|
#include "config.h"
|
2010-04-04 19:50:11 +02:00
|
|
|
#include "engines/engine_fwd.h"
|
2010-02-03 23:20:31 +01:00
|
|
|
|
2021-02-20 22:20:04 +01:00
|
|
|
namespace cpb {
|
2012-12-06 14:23:27 +01:00
|
|
|
namespace tagreader {
|
|
|
|
class SongMetadata;
|
|
|
|
} // namespace tagreader
|
2021-02-20 22:20:04 +01:00
|
|
|
} // namespace cpb
|
2012-12-06 14:23:27 +01:00
|
|
|
|
2011-11-28 14:51:35 +01:00
|
|
|
class QSqlQuery;
|
|
|
|
class QUrl;
|
|
|
|
|
2010-07-04 22:52:45 +02:00
|
|
|
#ifdef HAVE_LIBGPOD
|
2014-02-07 16:34:20 +01:00
|
|
|
struct _Itdb_Track;
|
2010-07-04 22:52:45 +02:00
|
|
|
#endif
|
|
|
|
|
2010-08-14 17:57:05 +02:00
|
|
|
#ifdef HAVE_LIBMTP
|
2014-02-07 16:34:20 +01:00
|
|
|
struct LIBMTP_track_struct;
|
2010-08-14 17:57:05 +02:00
|
|
|
#endif
|
|
|
|
|
2010-12-18 18:28:02 +01:00
|
|
|
#ifdef HAVE_LIBLASTFM
|
2014-02-07 16:34:20 +01:00
|
|
|
namespace lastfm {
|
|
|
|
class Track;
|
|
|
|
}
|
2010-12-18 18:28:02 +01:00
|
|
|
#endif
|
2009-12-26 23:15:57 +01:00
|
|
|
|
2011-11-28 14:51:35 +01:00
|
|
|
class SqlRow;
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
class Song {
|
|
|
|
public:
|
|
|
|
Song();
|
2010-01-15 22:57:22 +01:00
|
|
|
Song(const Song& other);
|
2011-11-28 14:51:35 +01:00
|
|
|
~Song();
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-04-14 23:03:00 +02:00
|
|
|
static const QStringList kColumns;
|
|
|
|
static const QString kColumnSpec;
|
|
|
|
static const QString kBindSpec;
|
|
|
|
static const QString kUpdateSpec;
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2018-09-04 18:51:33 +02:00
|
|
|
static const QStringList kIntColumns;
|
|
|
|
static const QStringList kFloatColumns;
|
2018-09-08 22:18:44 +02:00
|
|
|
static const QStringList kDateColumns;
|
2018-09-04 18:51:33 +02:00
|
|
|
|
2010-06-20 18:30:10 +02:00
|
|
|
static const QStringList kFtsColumns;
|
|
|
|
static const QString kFtsColumnSpec;
|
|
|
|
static const QString kFtsBindSpec;
|
|
|
|
static const QString kFtsUpdateSpec;
|
|
|
|
|
2011-02-02 22:01:08 +01:00
|
|
|
static const QString kManuallyUnsetCover;
|
|
|
|
static const QString kEmbeddedCover;
|
|
|
|
|
2010-05-10 16:19:43 +02:00
|
|
|
static QString JoinSpec(const QString& table);
|
|
|
|
|
2012-01-02 18:21:07 +01:00
|
|
|
// Don't change these values - they're stored in the database, and defined
|
|
|
|
// in the tag reader protobuf.
|
2014-11-13 22:31:49 +01:00
|
|
|
// If a new lossless file is added, also add it to IsFileLossless().
|
2010-03-07 23:46:41 +01:00
|
|
|
enum FileType {
|
|
|
|
Type_Unknown = 0,
|
|
|
|
Type_Asf = 1,
|
|
|
|
Type_Flac = 2,
|
|
|
|
Type_Mp4 = 3,
|
|
|
|
Type_Mpc = 4,
|
|
|
|
Type_Mpeg = 5,
|
|
|
|
Type_OggFlac = 6,
|
|
|
|
Type_OggSpeex = 7,
|
|
|
|
Type_OggVorbis = 8,
|
|
|
|
Type_Aiff = 9,
|
|
|
|
Type_Wav = 10,
|
|
|
|
Type_TrueAudio = 11,
|
2011-06-10 01:08:43 +02:00
|
|
|
Type_Cdda = 12,
|
2013-01-26 12:18:24 +01:00
|
|
|
Type_OggOpus = 13,
|
2018-05-01 19:29:47 +02:00
|
|
|
Type_WavPack = 14,
|
2018-06-09 08:58:03 +02:00
|
|
|
Type_Spc = 15,
|
2018-06-18 15:26:11 +02:00
|
|
|
Type_VGM = 16,
|
2019-02-14 07:37:44 +01:00
|
|
|
Type_APE = 17,
|
2010-03-07 23:46:41 +01:00
|
|
|
Type_Stream = 99,
|
|
|
|
};
|
2010-07-31 16:14:03 +02:00
|
|
|
static QString TextForFiletype(FileType type);
|
|
|
|
QString TextForFiletype() const { return TextForFiletype(filetype()); }
|
2014-11-13 22:31:49 +01:00
|
|
|
bool IsFileLossless() const;
|
2010-03-07 23:46:41 +01:00
|
|
|
|
2012-06-27 01:55:51 +02:00
|
|
|
// Sort songs alphabetically using their pretty title
|
|
|
|
static void SortSongsListAlphabetically(QList<Song>* songs);
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
// Constructors
|
2014-02-07 16:34:20 +01:00
|
|
|
void Init(const QString& title, const QString& artist, const QString& album,
|
|
|
|
qint64 length_nanosec);
|
|
|
|
void Init(const QString& title, const QString& artist, const QString& album,
|
|
|
|
qint64 beginning, qint64 end);
|
2021-02-20 22:20:04 +01:00
|
|
|
void InitFromProtobuf(const cpb::tagreader::SongMetadata& pb);
|
2011-06-17 22:00:10 +02:00
|
|
|
void InitFromQuery(const SqlRow& query, bool reliable_metadata, int col = 0);
|
2014-02-07 16:34:20 +01:00
|
|
|
void InitFromFilePartial(
|
|
|
|
const QString& filename); // Just store the filename: incomplete but fast
|
|
|
|
void InitArtManual(); // Check if there is already a art in the cache and
|
|
|
|
// store the filename in art_manual
|
2010-12-18 18:28:02 +01:00
|
|
|
#ifdef HAVE_LIBLASTFM
|
2009-12-26 23:15:57 +01:00
|
|
|
void InitFromLastFM(const lastfm::Track& track);
|
2010-12-18 18:28:02 +01:00
|
|
|
#endif
|
2010-07-04 22:52:45 +02:00
|
|
|
|
2010-04-21 16:04:40 +02:00
|
|
|
void MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle& bundle);
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-07-04 22:52:45 +02:00
|
|
|
#ifdef HAVE_LIBGPOD
|
2011-11-28 14:51:35 +01:00
|
|
|
void InitFromItdb(const _Itdb_Track* track, const QString& prefix);
|
|
|
|
void ToItdb(_Itdb_Track* track) const;
|
2010-07-04 22:52:45 +02:00
|
|
|
#endif
|
|
|
|
|
2010-08-14 17:57:05 +02:00
|
|
|
#ifdef HAVE_LIBMTP
|
2011-11-28 14:51:35 +01:00
|
|
|
void InitFromMTP(const LIBMTP_track_struct* track, const QString& host);
|
|
|
|
void ToMTP(LIBMTP_track_struct* track) const;
|
2010-08-14 17:57:05 +02:00
|
|
|
#endif
|
|
|
|
|
2012-12-25 14:48:16 +01:00
|
|
|
// Copies important statistics from the other song to this one, overwriting
|
|
|
|
// any data that already exists. Useful when you want updated tags from disk
|
|
|
|
// but you want to keep user stats.
|
|
|
|
void MergeUserSetData(const Song& other);
|
|
|
|
|
2014-02-21 17:24:49 +01:00
|
|
|
static QString Decode(const QString& tag, const QTextCodec* codec = nullptr);
|
2010-06-03 14:36:43 +02:00
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
// Save
|
|
|
|
void BindToQuery(QSqlQuery* query) const;
|
2010-06-20 18:30:10 +02:00
|
|
|
void BindToFtsQuery(QSqlQuery* query) const;
|
2010-12-18 18:28:02 +01:00
|
|
|
#ifdef HAVE_LIBLASTFM
|
2012-05-13 17:04:55 +02:00
|
|
|
void ToLastFM(lastfm::Track* track, bool prefer_album_artist) const;
|
2010-12-18 18:28:02 +01:00
|
|
|
#endif
|
2011-10-16 22:57:53 +02:00
|
|
|
void ToXesam(QVariantMap* map) const;
|
2021-02-20 22:20:04 +01:00
|
|
|
void ToProtobuf(cpb::tagreader::SongMetadata* pb) const;
|
2009-12-24 20:16:07 +01:00
|
|
|
|
|
|
|
// Simple accessors
|
2011-11-28 14:51:35 +01:00
|
|
|
bool is_valid() const;
|
|
|
|
bool is_unavailable() const;
|
|
|
|
int id() const;
|
|
|
|
|
|
|
|
const QString& title() const;
|
|
|
|
const QString& album() const;
|
2017-03-04 19:20:49 +01:00
|
|
|
const QString& effective_album() const;
|
2011-11-28 14:51:35 +01:00
|
|
|
const QString& artist() const;
|
|
|
|
const QString& albumartist() const;
|
|
|
|
const QString& effective_albumartist() const;
|
2014-02-07 16:34:20 +01:00
|
|
|
// Playlist views are special because you don't want to fill in album artists
|
|
|
|
// automatically for
|
2011-11-28 07:05:13 +01:00
|
|
|
// compilations, but you do for normal albums:
|
2011-11-28 14:51:35 +01:00
|
|
|
const QString& playlist_albumartist() const;
|
|
|
|
const QString& composer() const;
|
2013-03-03 13:00:24 +01:00
|
|
|
const QString& performer() const;
|
|
|
|
const QString& grouping() const;
|
2015-04-10 21:05:07 +02:00
|
|
|
const QString& lyrics() const;
|
2011-11-28 14:51:35 +01:00
|
|
|
int track() const;
|
|
|
|
int disc() const;
|
|
|
|
float bpm() const;
|
|
|
|
int year() const;
|
2015-06-30 18:34:34 +02:00
|
|
|
int originalyear() const;
|
|
|
|
int effective_originalyear() const;
|
2011-11-28 14:51:35 +01:00
|
|
|
const QString& genre() const;
|
|
|
|
const QString& comment() const;
|
|
|
|
bool is_compilation() const;
|
|
|
|
float rating() const;
|
|
|
|
int playcount() const;
|
|
|
|
int skipcount() const;
|
|
|
|
int lastplayed() const;
|
|
|
|
int score() const;
|
2013-02-02 10:22:08 +01:00
|
|
|
int album_id() const;
|
2011-11-28 14:51:35 +01:00
|
|
|
|
|
|
|
const QString& cue_path() const;
|
|
|
|
bool has_cue() const;
|
|
|
|
|
|
|
|
qint64 beginning_nanosec() const;
|
|
|
|
qint64 end_nanosec() const;
|
|
|
|
|
|
|
|
qint64 length_nanosec() const;
|
|
|
|
|
|
|
|
int bitrate() const;
|
|
|
|
int samplerate() const;
|
|
|
|
|
|
|
|
int directory_id() const;
|
|
|
|
const QUrl& url() const;
|
|
|
|
const QString& basefilename() const;
|
|
|
|
uint mtime() const;
|
|
|
|
uint ctime() const;
|
|
|
|
int filesize() const;
|
|
|
|
FileType filetype() const;
|
|
|
|
bool is_stream() const;
|
|
|
|
bool is_cdda() const;
|
2014-10-26 17:08:12 +01:00
|
|
|
// Guess if it is a library song using fields set. Might not be 100% reliable.
|
|
|
|
bool is_library_song() const;
|
2011-11-28 14:51:35 +01:00
|
|
|
|
|
|
|
const QString& art_automatic() const;
|
|
|
|
const QString& art_manual() const;
|
2010-02-28 01:35:20 +01:00
|
|
|
|
2012-07-27 16:04:12 +02:00
|
|
|
const QString& etag() const;
|
|
|
|
|
2011-02-02 22:01:08 +01:00
|
|
|
// Returns true if this Song had it's cover manually unset by user.
|
2011-11-28 14:51:35 +01:00
|
|
|
bool has_manually_unset_cover() const;
|
2011-02-02 22:01:08 +01:00
|
|
|
// This method represents an explicit request to unset this song's
|
|
|
|
// cover.
|
2011-11-28 14:51:35 +01:00
|
|
|
void manually_unset_cover();
|
2011-02-02 22:01:08 +01:00
|
|
|
|
|
|
|
// Returns true if this song (it's media file) has an embedded cover.
|
2011-11-28 14:51:35 +01:00
|
|
|
bool has_embedded_cover() const;
|
2011-02-02 22:01:08 +01:00
|
|
|
// Sets a flag saying that this song (it's media file) has an embedded
|
|
|
|
// cover.
|
2011-11-28 14:51:35 +01:00
|
|
|
void set_embedded_cover();
|
2011-02-02 22:01:08 +01:00
|
|
|
|
2011-11-28 14:51:35 +01:00
|
|
|
const QImage& image() const;
|
2010-02-25 01:18:32 +01:00
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
// Pretty accessors
|
2013-02-26 15:49:30 +01:00
|
|
|
QString PrettyRating() const;
|
2009-12-24 20:16:07 +01:00
|
|
|
QString PrettyTitle() const;
|
|
|
|
QString PrettyTitleWithArtist() const;
|
|
|
|
QString PrettyLength() const;
|
2010-12-06 00:41:41 +01:00
|
|
|
QString PrettyYear() const;
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-11-21 22:36:27 +01:00
|
|
|
QString TitleWithCompilationArtist() const;
|
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
// Setters
|
2010-06-25 01:36:39 +02:00
|
|
|
bool IsEditable() const;
|
2010-01-16 17:12:47 +01:00
|
|
|
|
2011-11-28 14:51:35 +01:00
|
|
|
void set_id(int id);
|
|
|
|
void set_valid(bool v);
|
|
|
|
void set_title(const QString& v);
|
|
|
|
|
|
|
|
void set_album(const QString& v);
|
|
|
|
void set_artist(const QString& v);
|
|
|
|
void set_albumartist(const QString& v);
|
|
|
|
void set_composer(const QString& v);
|
2013-03-03 13:00:24 +01:00
|
|
|
void set_performer(const QString& v);
|
|
|
|
void set_grouping(const QString& v);
|
2015-04-10 21:05:07 +02:00
|
|
|
void set_lyrics(const QString& v);
|
2011-11-28 14:51:35 +01:00
|
|
|
void set_track(int v);
|
|
|
|
void set_disc(int v);
|
|
|
|
void set_bpm(float v);
|
|
|
|
void set_year(int v);
|
2015-06-30 18:34:34 +02:00
|
|
|
void set_originalyear(int v);
|
2011-11-28 14:51:35 +01:00
|
|
|
void set_genre(const QString& v);
|
2011-02-27 18:16:22 +01:00
|
|
|
void set_genre_id3(int id);
|
2011-11-28 14:51:35 +01:00
|
|
|
void set_comment(const QString& v);
|
|
|
|
void set_compilation(bool v);
|
|
|
|
void set_sampler(bool v);
|
2013-02-02 10:22:08 +01:00
|
|
|
void set_album_id(int v);
|
2011-11-28 14:51:35 +01:00
|
|
|
void set_beginning_nanosec(qint64 v);
|
|
|
|
void set_end_nanosec(qint64 v);
|
|
|
|
void set_length_nanosec(qint64 v);
|
|
|
|
void set_bitrate(int v);
|
|
|
|
void set_samplerate(int v);
|
|
|
|
void set_mtime(int v);
|
|
|
|
void set_ctime(int v);
|
|
|
|
void set_filesize(int v);
|
|
|
|
void set_filetype(FileType v);
|
|
|
|
void set_art_automatic(const QString& v);
|
|
|
|
void set_art_manual(const QString& v);
|
|
|
|
void set_image(const QImage& i);
|
|
|
|
void set_forced_compilation_on(bool v);
|
|
|
|
void set_forced_compilation_off(bool v);
|
|
|
|
void set_rating(float v);
|
|
|
|
void set_playcount(int v);
|
|
|
|
void set_skipcount(int v);
|
|
|
|
void set_lastplayed(int v);
|
|
|
|
void set_score(int v);
|
|
|
|
void set_cue_path(const QString& v);
|
|
|
|
void set_unavailable(bool v);
|
2012-07-27 16:04:12 +02:00
|
|
|
void set_etag(const QString& etag);
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2010-03-03 00:37:12 +01:00
|
|
|
// Setters that should only be used by tests
|
2011-11-28 14:51:35 +01:00
|
|
|
void set_url(const QUrl& v);
|
|
|
|
void set_basefilename(const QString& v);
|
|
|
|
void set_directory_id(int v);
|
2010-03-03 00:37:12 +01:00
|
|
|
|
2009-12-24 20:16:07 +01:00
|
|
|
// Comparison functions
|
|
|
|
bool IsMetadataEqual(const Song& other) const;
|
2011-03-13 19:37:46 +01:00
|
|
|
bool IsOnSameAlbum(const Song& other) const;
|
2012-11-22 02:06:29 +01:00
|
|
|
bool IsSimilar(const Song& other) const;
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2011-01-17 00:46:58 +01:00
|
|
|
bool operator==(const Song& other) const;
|
|
|
|
|
2011-11-27 16:01:10 +01:00
|
|
|
// Two songs that are on the same album will have the same AlbumKey. It is
|
|
|
|
// more efficient to use IsOnSameAlbum, but this function can be used when
|
|
|
|
// you need to hash the key to do fast lookups.
|
|
|
|
QString AlbumKey() const;
|
|
|
|
|
2011-11-28 14:51:35 +01:00
|
|
|
Song& operator=(const Song& other);
|
|
|
|
|
2010-03-07 23:46:41 +01:00
|
|
|
private:
|
2011-11-28 14:51:35 +01:00
|
|
|
struct Private;
|
2010-03-07 23:46:41 +01:00
|
|
|
QSharedDataPointer<Private> d;
|
2009-12-24 20:16:07 +01:00
|
|
|
};
|
2019-11-10 00:30:18 +01:00
|
|
|
Q_DECLARE_METATYPE(Song)
|
2009-12-24 20:16:07 +01:00
|
|
|
|
|
|
|
typedef QList<Song> SongList;
|
2019-11-10 00:30:18 +01:00
|
|
|
Q_DECLARE_METATYPE(QList<Song>)
|
2009-12-24 20:16:07 +01:00
|
|
|
|
2011-07-01 22:48:18 +02:00
|
|
|
uint qHash(const Song& song);
|
2012-11-22 02:06:29 +01:00
|
|
|
// Hash function using field checked in IsSimilar function
|
|
|
|
uint HashSimilar(const Song& song);
|
2011-07-01 22:48:18 +02:00
|
|
|
|
2014-11-01 19:26:05 +01:00
|
|
|
#endif // CORE_SONG_H_
|