strawberry-audio-player-win.../src/core/song.h

342 lines
9.4 KiB
C
Raw Normal View History

2018-02-27 18:06:05 +01:00
/*
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
2018-09-08 12:38:02 +02:00
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
2018-02-27 18:06:05 +01:00
*
* Strawberry 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.
*
* Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
2018-08-09 18:10:03 +02:00
*
2018-02-27 18:06:05 +01:00
*/
#ifndef SONG_H
#define SONG_H
#include "config.h"
#include <stdbool.h>
#include <QtGlobal>
#include <QSharedData>
2018-02-27 18:06:05 +01:00
#include <QSharedDataPointer>
#include <QMetaType>
#include <QList>
#include <QSet>
#include <QVariant>
#include <QString>
#include <QStringList>
#include <QRegExp>
#include <QUrl>
#include <QImage>
2018-09-08 12:38:02 +02:00
#include <QIcon>
#include <QTextCodec>
#include <QSqlQuery>
2018-02-27 18:06:05 +01:00
namespace Engine {
struct SimpleMetaBundle;
} // namespace Engine
2018-02-27 18:06:05 +01:00
namespace pb {
namespace tagreader {
class SongMetadata;
} // namespace tagreader
} // namespace pb
#ifdef HAVE_LIBGPOD
struct _Itdb_Track;
#endif
#ifdef HAVE_LIBMTP
struct LIBMTP_track_struct;
#endif
class SqlRow;
class Song {
public:
Song();
Song(const Song &other);
~Song();
static const QStringList kColumns;
static const QString kColumnSpec;
static const QString kBindSpec;
static const QString kUpdateSpec;
static const QStringList kFtsColumns;
static const QString kFtsColumnSpec;
static const QString kFtsBindSpec;
static const QString kFtsUpdateSpec;
static const QString kManuallyUnsetCover;
static const QString kEmbeddedCover;
2018-10-02 00:38:52 +02:00
static const QRegExp kCoverRemoveDisc;
2018-02-27 18:06:05 +01:00
static QString JoinSpec(const QString &table);
// Don't change these values - they're stored in the database, and defined in the tag reader protobuf.
2018-02-27 18:06:05 +01:00
// If a new lossless file is added, also add it to IsFileLossless().
2018-09-08 12:38:02 +02:00
enum Source {
Source_Unknown = 0,
Source_LocalFile = 1,
Source_Collection = 2,
Source_CDDA = 3,
Source_Device = 4,
Source_Stream = 5,
Source_Tidal = 6,
2018-10-14 00:08:33 +02:00
Source_Deezer = 7,
2018-09-08 12:38:02 +02:00
};
2018-02-27 18:06:05 +01:00
enum FileType {
2018-09-08 12:38:02 +02:00
FileType_Unknown = 0,
FileType_WAV = 1,
FileType_FLAC = 2,
FileType_WavPack = 3,
FileType_OggFlac = 4,
FileType_OggVorbis = 5,
FileType_OggOpus = 6,
FileType_OggSpeex = 7,
FileType_MPEG = 8,
FileType_MP4 = 9,
FileType_ASF = 10,
FileType_AIFF = 11,
FileType_MPC = 12,
FileType_TrueAudio = 13,
FileType_DSF = 14,
FileType_DSDIFF = 15,
2018-10-23 20:21:01 +02:00
FileType_PCM = 16,
2018-09-08 12:38:02 +02:00
FileType_CDDA = 90,
FileType_Stream = 91,
2018-02-27 18:06:05 +01:00
};
2018-09-08 12:38:02 +02:00
static QString TextForSource(Source source);
static QIcon IconForSource(Source source);
static QString TextForFiletype(FileType filetype);
2018-09-12 21:52:30 +02:00
static QIcon IconForFiletype(FileType filetype);
2018-09-08 12:38:02 +02:00
QString TextForSource() const { return TextForSource(source()); }
QIcon IconForSource() const { return IconForSource(source()); }
2018-02-27 18:06:05 +01:00
QString TextForFiletype() const { return TextForFiletype(filetype()); }
2018-09-12 21:52:30 +02:00
QIcon IconForFiletype() const { return IconForFiletype(filetype()); }
2018-09-08 12:38:02 +02:00
2018-02-27 18:06:05 +01:00
bool IsFileLossless() const;
2018-09-06 22:34:18 +02:00
static FileType FiletypeByExtension(QString ext);
2018-02-27 18:06:05 +01:00
// Sort songs alphabetically using their pretty title
static void SortSongsListAlphabetically(QList<Song> *songs);
// Constructors
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);
void InitFromProtobuf(const pb::tagreader::SongMetadata &pb);
void InitFromQuery(const SqlRow &query, bool reliable_metadata, int col = 0);
void InitFromFilePartial(const QString &filename); // Just store the filename: incomplete but fast
2018-03-04 20:13:05 +01:00
void InitArtManual(); // Check if there is already a art in the cache and store the filename in art_manual
2018-02-27 18:06:05 +01:00
void MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle);
#ifdef HAVE_LIBGPOD
void InitFromItdb(const _Itdb_Track *track, const QString &prefix);
void ToItdb(_Itdb_Track *track) const;
#endif
#ifdef HAVE_LIBMTP
void InitFromMTP(const LIBMTP_track_struct *track, const QString &host);
void ToMTP(LIBMTP_track_struct *track) const;
#endif
// 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.
2018-02-27 18:06:05 +01:00
void MergeUserSetData(const Song &other);
static QString Decode(const QString &tag, const QTextCodec *codec = nullptr);
// Save
void BindToQuery(QSqlQuery *query) const;
void BindToFtsQuery(QSqlQuery *query) const;
void ToXesam(QVariantMap *map) const;
void ToProtobuf(pb::tagreader::SongMetadata *pb) const;
// Simple accessors
bool is_valid() const;
bool is_unavailable() const;
int id() const;
const QString &title() const;
const QString &album() const;
const QString &artist() const;
const QString &albumartist() const;
int track() const;
int disc() const;
int year() const;
int originalyear() const;
const QString &genre() const;
bool is_compilation() const;
const QString &composer() const;
const QString &performer() const;
const QString &grouping() const;
const QString &comment() const;
const QString &lyrics() const;
2018-02-27 18:06:05 +01:00
int playcount() const;
int skipcount() const;
int lastplayed() const;
int album_id() const;
qint64 beginning_nanosec() const;
qint64 end_nanosec() const;
qint64 length_nanosec() const;
int bitrate() const;
int samplerate() const;
int bitdepth() const;
2018-09-08 12:38:02 +02:00
Source source() const;
2018-02-27 18:06:05 +01:00
int directory_id() const;
const QUrl &url() const;
const QString &basefilename() const;
FileType filetype() const;
int filesize() const;
uint mtime() const;
uint ctime() const;
const QString &art_automatic() const;
const QString &art_manual() const;
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
const QString &cue_path() const;
bool has_cue() const;
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
const QString &effective_album() const;
int effective_originalyear() const;
const QString &effective_albumartist() const;
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
bool is_collection_song() const;
2018-08-09 18:10:03 +02:00
bool is_stream() const;
2018-02-27 18:06:05 +01:00
bool is_cdda() const;
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
// Playlist views are special because you don't want to fill in album artists automatically for compilations, but you do for normal albums:
const QString &playlist_albumartist() const;
// Returns true if this Song had it's cover manually unset by user.
bool has_manually_unset_cover() const;
// This method represents an explicit request to unset this song's cover.
2018-02-27 18:06:05 +01:00
void manually_unset_cover();
// Returns true if this song (it's media file) has an embedded cover.
bool has_embedded_cover() const;
// Sets a flag saying that this song (it's media file) has an embedded cover.
void set_embedded_cover();
const QImage &image() const;
// Pretty accessors
QString PrettyTitle() const;
QString PrettyTitleWithArtist() const;
QString PrettyLength() const;
QString PrettyYear() const;
QString TitleWithCompilationArtist() const;
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
QString SampleRateBitDepthToText() const;
// Setters
bool IsEditable() const;
void set_id(int id);
void set_album_id(int v);
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_track(int v);
void set_disc(int v);
void set_year(int v);
void set_originalyear(int v);
void set_genre(const QString &v);
void set_genre_id3(int id);
void set_compilation(bool v);
void set_composer(const QString &v);
void set_performer(const QString &v);
void set_grouping(const QString &v);
void set_comment(const QString &v);
void set_lyrics(const QString &v);
2018-02-27 18:06:05 +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_bitdepth(int v);
2018-09-08 12:38:02 +02:00
void set_source(Source v);
2018-02-27 18:06:05 +01:00
void set_directory_id(int v);
void set_url(const QUrl &v);
void set_basefilename(const QString &v);
void set_filetype(FileType v);
void set_filesize(int v);
void set_mtime(int v);
void set_ctime(int v);
void set_unavailable(bool v);
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
void set_playcount(int v);
void set_skipcount(int v);
void set_lastplayed(int v);
void set_compilation_detected(bool v);
void set_compilation_on(bool v);
void set_compilation_off(bool v);
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
void set_art_automatic(const QString &v);
void set_art_manual(const QString &v);
void set_cue_path(const QString &v);
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
void set_image(const QImage &i);
// Comparison functions
bool IsMetadataEqual(const Song &other) const;
bool IsOnSameAlbum(const Song &other) const;
bool IsSimilar(const Song &other) const;
bool operator==(const Song &other) const;
// 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.
2018-02-27 18:06:05 +01:00
QString AlbumKey() const;
Song &operator=(const Song &other);
private:
struct Private;
2018-02-27 18:06:05 +01:00
QSharedDataPointer<Private> d;
};
Q_DECLARE_METATYPE(Song);
typedef QList<Song> SongList;
Q_DECLARE_METATYPE(QList<Song>);
uint qHash(const Song &song);
// Hash function using field checked in IsSimilar function
uint HashSimilar(const Song &song);
#endif // SONG_H