MythTV master
musicmetadata.h
Go to the documentation of this file.
1#ifndef MUSICMETADATA_H_
2#define MUSICMETADATA_H_
3
4#if __has_include("libmythbase/mythconfig.h")
5#include "libmythbase/mythconfig.h"
6#else
7#include "mythconfig.h"
8#endif
9
10// C/C++
11#include <array>
12#include <cstdint>
13#include <utility>
14
15// qt
16#include <QCoreApplication>
17#include <QDateTime>
18#include <QImage>
19#include <QMap>
20#include <QMetaType>
21#include <QStringList>
22#include <QTimeZone>
23
24// MythTV
25#include "libmythbase/mthread.h"
28
29class AllMusic;
30class AlbumArtImages;
31class LyricsData;
32class MetaIO;
33
34enum ImageType : std::uint8_t
35{
43};
44
46{
47 public:
49 m_filename(""), m_hostname(""), m_description("") {}
50 explicit AlbumArtImage(const AlbumArtImage * const image) :
51 m_id(image->m_id), m_filename(image->m_filename),
52 m_hostname(image->m_hostname), m_imageType(image->m_imageType),
53 m_description(image->m_description), m_embedded(image->m_embedded) {}
54 int m_id {0};
55 QString m_filename;
56 QString m_hostname;
57 ImageType m_imageType {IT_UNKNOWN};
59 bool m_embedded {false};
60};
61
62using AlbumArtList = QList<AlbumArtImage*>;
63
64enum RepoType : std::uint8_t
65{
67 RT_CD = 1,
68 RT_Radio = 2
69};
70
71static constexpr uint8_t METADATA_BITS_FOR_REPO { 8 };
72static constexpr uint8_t METADATA_REPO_SHIFT { 24 };
73static constexpr uint32_t METADATA_REPO_MASK { 0xff000000 };
74static constexpr uint32_t METADATA_ID_MASK { 0x00ffffff };
75
76static constexpr uint32_t ID_TO_ID(uint32_t x) { return x & METADATA_ID_MASK; };
77static constexpr uint32_t ID_TO_REPO(uint32_t x) { return x >> METADATA_REPO_SHIFT; };
78
79static constexpr const char* METADATA_INVALID_FILENAME { "**NOT FOUND**" };
80
81static constexpr size_t STREAMURLCOUNT { 5 };
82
83using UrlList = std::array<QString,STREAMURLCOUNT>;
84
86{
88
89 public:
90
91 using IdType = uint32_t;
92
93 explicit MusicMetadata(QString lfilename = "", QString lartist = "", QString lcompilation_artist = "",
94 QString lalbum = "", QString ltitle = "", QString lgenre = "",
95 int lyear = 0, int ltracknum = 0, std::chrono::milliseconds llength = 0ms, int lid = 0,
96 int lrating = 0, int lplaycount = 0, QDateTime llastplay = QDateTime(),
97 QDateTime ldateadded = QDateTime(), bool lcompilation = false, QString lformat = "")
98 : m_artist(std::move(lartist)),
99 m_compilationArtist(std::move(lcompilation_artist)),
100 m_album(std::move(lalbum)),
101 m_title(std::move(ltitle)),
102 m_genre(std::move(lgenre)),
103 m_format(std::move(lformat)),
104 m_year(lyear),
105 m_trackNum(ltracknum),
106 m_length(llength),
107 m_rating(lrating),
108 m_lastPlay(std::move(llastplay)),
109 m_dateAdded(std::move(ldateadded)),
110 m_playCount(lplaycount),
111 m_compilation(lcompilation),
112 m_id(lid),
113 m_filename(std::move(lfilename))
114 {
115 checkEmptyFields();
116 }
117
118 MusicMetadata(int lid, QString lbroadcaster, QString lchannel, QString ldescription, const UrlList &lurls, QString llogourl,
119 QString lgenre, QString lmetaformat, QString lcountry, QString llanguage, QString lformat);
120
122
124 {
125 *this = other;
126 }
127
128 MusicMetadata& operator=(const MusicMetadata &rhs);
129
130 QString Artist() const { return m_artist; }
131 QString ArtistSort() const { return m_artistSort; }
132 void setArtist(const QString &lartist,
133 const QString &lartist_sort = nullptr)
134 {
135 m_artist = lartist;
136 m_artistId = -1;
137 m_artistSort = lartist_sort;
138 m_formattedArtist.clear(); m_formattedTitle.clear();
139 ensureSortFields();
140 }
141
142 QString CompilationArtist() const { return m_compilationArtist; }
143 QString CompilationArtistSort() const { return m_compilationArtistSort; }
144 void setCompilationArtist(const QString &lcompilation_artist,
145 const QString &lcompilation_artist_sort = nullptr)
146 {
147 m_compilationArtist = lcompilation_artist;
148 m_compartistId = -1;
149 m_compilationArtistSort = lcompilation_artist_sort;
150 m_formattedArtist.clear(); m_formattedTitle.clear();
151 ensureSortFields();
152 }
153
154 QString Album() const { return m_album; }
155 QString AlbumSort() const { return m_albumSort; }
156 void setAlbum(const QString &lalbum,
157 const QString &lalbum_sort = nullptr)
158 {
159 m_album = lalbum;
160 m_albumId = -1;
161 m_albumSort = lalbum_sort;
162 m_formattedArtist.clear(); m_formattedTitle.clear();
163 ensureSortFields();
164 }
165
166 QString Title() const { return m_title; }
167 QString TitleSort() const { return m_titleSort; }
168 void setTitle(const QString &ltitle,
169 const QString &ltitle_sort = nullptr)
170 {
171 m_title = ltitle;
172 m_titleSort = ltitle_sort;
173 ensureSortFields();
174 }
175
176 QString FormatArtist();
177 QString FormatTitle();
178
179 QString Genre() const { return m_genre; }
180 void setGenre(const QString &lgenre) {
181 m_genre = lgenre;
182 m_genreId = -1;
183 }
184
185 void setDirectoryId(int ldirectoryid) { m_directoryId = ldirectoryid; }
186 int getDirectoryId();
187
188 void setArtistId(int lartistid) { m_artistId = lartistid; }
189 int getArtistId();
190
191 void setCompilationArtistId(int lartistid) { m_compartistId = lartistid; }
192 int getCompilationArtistId();
193
194 void setAlbumId(int lalbumid) { m_albumId = lalbumid; }
195 int getAlbumId();
196
197 void setGenreId(int lgenreid) { m_genreId = lgenreid; }
198 int getGenreId();
199
200 int Year() const { return m_year; }
201 void setYear(int lyear) { m_year = lyear; }
202
203 int Track() const { return m_trackNum; }
204 void setTrack(int ltrack) { m_trackNum = ltrack; }
205
206 int GetTrackCount() const { return m_trackCount; }
207 void setTrackCount(int ltrackcount) { m_trackCount = ltrackcount; }
208
209 std::chrono::milliseconds Length() const { return m_length; }
210#if HAVE_IS_DURATION_V
211 template <typename T, std::enable_if_t<std::chrono::__is_duration_v<T>, bool> = true>
212#else
213 template <typename T, std::enable_if_t<std::chrono::__is_duration<T>::value, bool> = true>
214#endif
215 void setLength(T llength) { m_length = llength; }
216
217 int DiscNumber() const {return m_discNum;}
218 void setDiscNumber(int discnum) { m_discNum = discnum; }
219
220 int DiscCount() const {return m_discCount;}
221 void setDiscCount(int disccount) { m_discCount = disccount; }
222
223 int Playcount() const { return m_playCount; }
224 void setPlaycount(int lplaycount) { m_playCount = lplaycount; }
225
226 IdType ID() const { return m_id; }
227 void setID(IdType lid) { m_id = lid; }
228 void setRepo(RepoType repo) { m_id = (m_id & METADATA_ID_MASK) | (repo << METADATA_REPO_SHIFT); }
229
230 bool isCDTrack(void) const { return ID_TO_REPO(m_id) == RT_CD; }
231 bool isDBTrack(void) const { return ID_TO_REPO(m_id) == RT_Database; }
232 bool isRadio(void) const { return ID_TO_REPO(m_id) == RT_Radio; }
233
234 QString Filename(bool find = true);
235 void setFilename(const QString &lfilename);
236 QString getLocalFilename(void);
237
238 QString Hostname(void) { return m_hostname; }
239 void setHostname(const QString &host) { m_hostname = host; }
240
241 uint64_t FileSize() const { return m_fileSize; }
242 void setFileSize(uint64_t lfilesize) { m_fileSize = lfilesize; }
243
244 QString Format() const { return m_format; }
245 void setFormat(const QString &lformat) { m_format = lformat; }
246
247 int Rating() const { return m_rating; }
248 void decRating();
249 void incRating();
250 void setRating(int lrating) { m_rating = lrating; }
251
252 QDateTime LastPlay() const { return m_lastPlay; }
253 void setLastPlay();
254 void setLastPlay(const QDateTime& lastPlay);
255
256 int PlayCount() const { return m_playCount; }
257 void incPlayCount();
258
259 // track is part of a compilation album
260 bool Compilation() const { return m_compilation; }
261 void setCompilation(bool state)
262 {
263 m_compilation = state;
264 m_formattedArtist.clear();
265 m_formattedTitle.clear();
266 }
267 bool determineIfCompilation(bool cd = false);
268
269 // for radio streams
270 void setBroadcaster(const QString &broadcaster) { m_broadcaster = broadcaster; }
271 QString Broadcaster(void) { return m_broadcaster; }
272
273 void setChannel(const QString &channel) { m_channel = channel; }
274 QString Channel(void) { return m_channel; }
275
276 void setDescription(const QString &description) { m_description = description; }
277 QString Description(void) { return m_description; }
278
279 void setUrl(const QString &url, size_t index = 0);
280 QString Url(size_t index = 0);
281
282 void setLogoUrl(const QString &logourl) { m_logoUrl = logourl; }
283 QString LogoUrl(void) { return m_logoUrl; }
284
285 void setMetadataFormat(const QString &metaformat) { m_metaFormat = metaformat; }
286 QString MetadataFormat(void) { return m_metaFormat; }
287
288 void setCountry(const QString &country) { m_country = country; }
289 QString Country(void) { return m_country; }
290
291 void setLanguage(const QString &language) { m_language = language; }
292 QString Language(void) { return m_language; }
293
294 void setEmbeddedAlbumArt(AlbumArtList &albumart);
295
296 void reloadMetadata(void);
297 void dumpToDatabase(void);
298 void setField(const QString &field, const QString &data);
299 void getField(const QString& field, QString *data);
300 void toMap(InfoMap &metadataMap, const QString &prefix = "");
301
302 void persist(void);
303
304 bool hasChanged(void) const { return m_changed; }
305
306 bool compare(MusicMetadata *mdata) const;
307
308 // static functions
309 static MusicMetadata *createFromFilename(const QString &filename);
310 static MusicMetadata *createFromID(int trackid);
311 static void setArtistAndTrackFormats();
312 static QStringList fillFieldList(const QString& field);
313 static bool updateStreamList(void);
314
315 // this looks for any image available - preferring a front cover if available
316 QString getAlbumArtFile(void);
317 // this looks only for the given image type
318 QString getAlbumArtFile(ImageType type);
319
320 AlbumArtImages *getAlbumArtImages(void);
321 void reloadAlbumArtImages(void);
322
323 LyricsData *getLyricsData(void);
324
325 MetaIO *getTagger(void);
326
327 private:
328 void setCompilationFormatting(bool cd = false);
329 QString formatReplaceSymbols(const QString &format);
330 void checkEmptyFields(void);
331 void ensureSortFields(void);
332 void saveHostname(void);
333
334 QString m_artist;
338 QString m_album;
339 QString m_albumSort;
340 QString m_title;
341 QString m_titleSort;
344 QString m_genre;
345 QString m_format;
346 int m_year {0};
347 int m_trackNum {0};
348 int m_trackCount {0};
349 int m_discNum {0};
350 int m_discCount {0};
351 std::chrono::milliseconds m_length {0ms};
352 int m_rating {0};
353 int m_directoryId {-1};
354 int m_artistId {-1};
355 int m_compartistId {-1};
356 int m_albumId {-1};
357 int m_genreId {-1};
358 QDateTime m_lastPlay;
359 QDateTime m_tempLastPlay;
360 QDateTime m_dateAdded;
361 int m_playCount {0};
362 int m_tempPlayCount {0};
363 bool m_compilation {false};
364
365 AlbumArtImages *m_albumArt {nullptr};
366
367 LyricsData *m_lyricsData {nullptr};
368
369 IdType m_id {0};
370 QString m_filename; // file name as stored in the DB
371 QString m_hostname; // host where file is located as stored in the DB
372 QString m_actualFilename; // actual URL of the file if found
373 uint64_t m_fileSize {0};
374 bool m_changed {false};
375
376 // radio stream stuff
378 QString m_channel;
381 QString m_logoUrl;
383 QString m_country;
384 QString m_language;
385
386 // Various formatting strings
390 static QString s_formatNormalCdTrack;
391
396};
397
400
403
407
408//---------------------------------------------------------------------------
409
411{
412
413 public:
414
415 explicit MetadataLoadingThread(AllMusic *parent_ptr)
416 : MThread("MetadataLoading"), m_parent(parent_ptr) {}
417 void run() override; // MThread
418
419 private:
420
421 AllMusic *m_parent {nullptr};
422};
423
424//---------------------------------------------------------------------------
425
427{
429
430 public:
431
432 AllMusic(void);
433 ~AllMusic();
434
435 MusicMetadata* getMetadata(int an_id);
436 bool updateMetadata(int an_id, MusicMetadata *the_track);
437 int count() const { return m_numPcs; }
438 int countLoaded() const { return m_numLoaded; }
439 void save();
440 bool startLoading(void);
441 void resync(); // After a CD rip, for example
442
443 // cd stuff
444 void clearCDData(void);
445 void addCDTrack(const MusicMetadata &the_track);
446 bool checkCDTrack(MusicMetadata *the_track);
447 MusicMetadata* getCDMetadata(int m_the_track);
448 QString getCDTitle(void) const { return m_cdTitle; }
449 void setCDTitle(const QString &a_title) { m_cdTitle = a_title; }
450 int getCDTrackCount(void) const { return m_cdData.count(); }
451
452 bool doneLoading() const { return m_doneLoading; }
453 bool cleanOutThreads();
454
455 MetadataPtrList *getAllMetadata(void) { return &m_allMusic; }
456 MetadataPtrList *getAllCDMetadata(void) { return &m_cdData; }
457
458 bool isValidID(int an_id);
459
460 private:
462
463 int m_numPcs {0};
464 int m_numLoaded {0};
465
466 using MusicMap = QMap<int, MusicMetadata*>;
468
469 // cd stuff
470 MetadataPtrList m_cdData; // More than one cd player?
471 QString m_cdTitle;
472
473 MetadataLoadingThread *m_metadataLoader {nullptr};
474 bool m_doneLoading {false};
475
476 int m_playCountMin {0};
477 int m_playCountMax {0};
478 qint64 m_lastPlayMin {0};
479 qint64 m_lastPlayMax {0};
480};
481
482using StreamList = QList<MusicMetadata*>;
483
485{
486 public:
487
488 AllStream(void);
489 ~AllStream();
490
491 void loadStreams(void);
492
493 bool isValidID(MusicMetadata::IdType an_id);
494
495 MusicMetadata* getMetadata(MusicMetadata::IdType an_id);
496
497 StreamList *getStreams(void) { return &m_streamList; }
498
499 void addStream(MusicMetadata *mdata);
500 void removeStream(MusicMetadata *mdata);
501 void updateStream(MusicMetadata *mdata);
502
503 private:
505};
506
507//----------------------------------------------------------------------------
508
510{
511 public:
512 explicit AlbumArtScannerThread(QStringList strList) :
513 MThread("AlbumArtScanner"), m_strList(std::move(strList)) {}
514
515 void run() override; // MThread
516
517 QStringList getResult(void) { return m_strList; }
518
519 private:
520 QStringList m_strList;
521};
522
524{
526
527 public:
528 explicit AlbumArtImages(MusicMetadata *metadata, bool loadFromDB = true);
529 explicit AlbumArtImages(MusicMetadata *metadata, const AlbumArtImages &other);
531
532 void scanForImages(void);
533 void addImage(const AlbumArtImage * newImage);
534 uint getImageCount() { return m_imageList.size(); }
535 AlbumArtImage *getImage(ImageType type);
536 AlbumArtImage *getImageByID(int imageID);
537 QStringList getImageFilenames(void) const;
538 AlbumArtList *getImageList(void) { return &m_imageList; }
539 AlbumArtImage *getImageAt(uint index);
540
541 void dumpToDatabase(void);
542
543 static ImageType guessImageType(const QString &filename);
544 static QString getTypeName(ImageType type);
545 static QString getTypeFilename(ImageType type);
546 static ImageType getImageTypeFromName(const QString &name);
547
548 private:
549 void findImages(void);
550
551 MusicMetadata *m_parent {nullptr};
553};
554
556
557#endif
QString m_filename
Definition: musicmetadata.h:55
AlbumArtImage(const AlbumArtImage *const image)
Definition: musicmetadata.h:50
QString m_description
Definition: musicmetadata.h:58
AlbumArtImage(void)
Definition: musicmetadata.h:48
QString m_hostname
Definition: musicmetadata.h:56
uint getImageCount()
AlbumArtList * getImageList(void)
Q_DECLARE_TR_FUNCTIONS(AlbumArtImages)
AlbumArtList m_imageList
QStringList getResult(void)
AlbumArtScannerThread(QStringList strList)
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
QMap< int, MusicMetadata * > MusicMap
MusicMap m_musicMap
int countLoaded() const
int getCDTrackCount(void) const
MetadataPtrList * getAllCDMetadata(void)
MetadataPtrList * getAllMetadata(void)
QString m_cdTitle
Q_DECLARE_TR_FUNCTIONS(AllMusic)
int count() const
QString getCDTitle(void) const
MetadataPtrList m_allMusic
void setCDTitle(const QString &a_title)
MetadataPtrList m_cdData
bool doneLoading() const
StreamList m_streamList
StreamList * getStreams(void)
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
Definition: metaio.h:18
MetadataLoadingThread(AllMusic *parent_ptr)
bool isCDTrack(void) const
void setDirectoryId(int ldirectoryid)
QString m_formattedTitle
void setArtistId(int lartistid)
int Year() const
void setRepo(RepoType repo)
bool isRadio(void) const
QString m_albumSort
QString m_format
void setMetadataFormat(const QString &metaformat)
QString m_description
void setID(IdType lid)
void setYear(int lyear)
QString m_compilationArtistSort
void setChannel(const QString &channel)
QString Language(void)
static QString s_formatCompilationCdArtist
void setHostname(const QString &host)
static QString s_formatNormalCdArtist
QString m_artistSort
void setCompilationArtist(const QString &lcompilation_artist, const QString &lcompilation_artist_sort=nullptr)
void setGenre(const QString &lgenre)
bool isDBTrack(void) const
QString Country(void)
void setFormat(const QString &lformat)
QDateTime LastPlay() const
static QString s_formatNormalCdTrack
QString Hostname(void)
QString CompilationArtist() const
void setCompilation(bool state)
QString AlbumSort() const
void setLogoUrl(const QString &logourl)
QString m_titleSort
std::chrono::milliseconds Length() const
void setCountry(const QString &country)
static QString s_formatNormalFileArtist
void setCompilationArtistId(int lartistid)
QString m_logoUrl
void setTrackCount(int ltrackcount)
void setLength(T llength)
QString Broadcaster(void)
QString m_country
QString Title() const
void setTitle(const QString &ltitle, const QString &ltitle_sort=nullptr)
QString m_artist
void setAlbumId(int lalbumid)
QString MetadataFormat(void)
void setLanguage(const QString &language)
int Playcount() const
QString m_language
QString m_broadcaster
QString m_hostname
QString Channel(void)
QString m_filename
int Track() const
IdType ID() const
QString Artist() const
QString m_actualFilename
void setRating(int lrating)
void setPlaycount(int lplaycount)
QString LogoUrl(void)
int DiscNumber() const
static QString s_formatNormalFileTrack
QString TitleSort() const
void setDiscNumber(int discnum)
int Rating() const
void setGenreId(int lgenreid)
void setAlbum(const QString &lalbum, const QString &lalbum_sort=nullptr)
void setDiscCount(int disccount)
QDateTime m_dateAdded
QString Format() const
QString m_compilationArtist
QString ArtistSort() const
bool Compilation() const
QDateTime m_lastPlay
uint64_t FileSize() const
int PlayCount() const
MusicMetadata(QString lfilename="", QString lartist="", QString lcompilation_artist="", QString lalbum="", QString ltitle="", QString lgenre="", int lyear=0, int ltracknum=0, std::chrono::milliseconds llength=0ms, int lid=0, int lrating=0, int lplaycount=0, QDateTime llastplay=QDateTime(), QDateTime ldateadded=QDateTime(), bool lcompilation=false, QString lformat="")
Definition: musicmetadata.h:93
uint32_t IdType
Definition: musicmetadata.h:91
void setTrack(int ltrack)
QString Genre() const
void setBroadcaster(const QString &broadcaster)
QString Album() const
QDateTime m_tempLastPlay
QString CompilationArtistSort() const
static QString s_formatCompilationFileTrack
QString Description(void)
void setArtist(const QString &lartist, const QString &lartist_sort=nullptr)
QString m_channel
bool hasChanged(void) const
Q_DECLARE_TR_FUNCTIONS(MusicMetadata)
int GetTrackCount() const
QString m_metaFormat
void setFileSize(uint64_t lfilesize)
MusicMetadata(const MusicMetadata &other)
static QString s_formatCompilationFileArtist
int DiscCount() const
static QString s_formatCompilationCdTrack
QString m_formattedArtist
void setDescription(const QString &description)
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
unsigned int uint
Definition: freesurround.h:24
QList< MusicMetadata * > MetadataPtrList
QList< MusicMetadata * > StreamList
ImageType
Definition: musicmetadata.h:35
@ IT_INLAY
Definition: musicmetadata.h:40
@ IT_BACKCOVER
Definition: musicmetadata.h:38
@ IT_LAST
Definition: musicmetadata.h:42
@ IT_UNKNOWN
Definition: musicmetadata.h:36
@ IT_FRONTCOVER
Definition: musicmetadata.h:37
@ IT_ARTIST
Definition: musicmetadata.h:41
@ IT_CD
Definition: musicmetadata.h:39
static constexpr uint8_t METADATA_REPO_SHIFT
Definition: musicmetadata.h:72
RepoType
Definition: musicmetadata.h:65
@ RT_Radio
Definition: musicmetadata.h:68
@ RT_CD
Definition: musicmetadata.h:67
@ RT_Database
Definition: musicmetadata.h:66
static constexpr uint8_t METADATA_BITS_FOR_REPO
Definition: musicmetadata.h:71
bool operator==(MusicMetadata &a, MusicMetadata &b)
bool operator!=(MusicMetadata &a, MusicMetadata &b)
static constexpr const char * METADATA_INVALID_FILENAME
Definition: musicmetadata.h:79
QList< AlbumArtImage * > AlbumArtList
Definition: musicmetadata.h:62
static constexpr uint32_t METADATA_ID_MASK
Definition: musicmetadata.h:74
static constexpr size_t STREAMURLCOUNT
Definition: musicmetadata.h:81
std::array< QString, STREAMURLCOUNT > UrlList
Definition: musicmetadata.h:83
Q_DECLARE_METATYPE(ImageType)
static constexpr uint32_t METADATA_REPO_MASK
Definition: musicmetadata.h:73
static constexpr uint32_t ID_TO_ID(uint32_t x)
Definition: musicmetadata.h:76
static constexpr uint32_t ID_TO_REPO(uint32_t x)
Definition: musicmetadata.h:77
#define META_PUBLIC
Definition: mythmetaexp.h:9
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
void run(const QString &name, Class *object, void(Class::*fn)())
Definition: mconcurrent.h:137
STL namespace.