1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "MusicInfoTag.h"
10 
11 #include "ServiceBroker.h"
12 #include "guilib/LocalizeStrings.h"
13 #include "music/Artist.h"
14 #include "settings/AdvancedSettings.h"
15 #include "settings/Settings.h"
16 #include "settings/SettingsComponent.h"
17 #include "utils/Archive.h"
18 #include "utils/StringUtils.h"
19 #include "utils/Variant.h"
20 
21 #include <algorithm>
22 
23 using namespace MUSIC_INFO;
24 
CMusicInfoTag(void)25 CMusicInfoTag::CMusicInfoTag(void)
26 {
27   Clear();
28 }
29 
operator !=(const CMusicInfoTag & tag) const30 bool CMusicInfoTag::operator !=(const CMusicInfoTag& tag) const
31 {
32   if (this == &tag) return false;
33   if (m_strURL != tag.m_strURL) return true;
34   if (m_strTitle != tag.m_strTitle) return true;
35   if (m_bCompilation != tag.m_bCompilation) return true;
36   if (m_artist != tag.m_artist) return true;
37   if (m_albumArtist != tag.m_albumArtist) return true;
38   if (m_strAlbum != tag.m_strAlbum) return true;
39   if (m_iDuration != tag.m_iDuration) return true;
40   if (m_strDiscSubtitle != tag.m_strDiscSubtitle)
41     return true;
42   if (m_iTrack != tag.m_iTrack)
43     return true;
44   if (m_albumReleaseType != tag.m_albumReleaseType) return true;
45   return false;
46 }
47 
GetTrackNumber() const48 int CMusicInfoTag::GetTrackNumber() const
49 {
50   return (m_iTrack & 0xffff);
51 }
52 
GetDiscNumber() const53 int CMusicInfoTag::GetDiscNumber() const
54 {
55   return (m_iTrack >> 16);
56 }
57 
GetTrackAndDiscNumber() const58 int CMusicInfoTag::GetTrackAndDiscNumber() const
59 {
60   return m_iTrack;
61 }
62 
GetDuration() const63 int CMusicInfoTag::GetDuration() const
64 {
65   return m_iDuration;
66 }
67 
GetTitle() const68 const std::string& CMusicInfoTag::GetTitle() const
69 {
70   return m_strTitle;
71 }
72 
GetURL() const73 const std::string& CMusicInfoTag::GetURL() const
74 {
75   return m_strURL;
76 }
77 
GetArtist() const78 const std::vector<std::string>& CMusicInfoTag::GetArtist() const
79 {
80   return m_artist;
81 }
82 
GetArtistString() const83 const std::string CMusicInfoTag::GetArtistString() const
84 {
85   if (!m_strArtistDesc.empty())
86     return m_strArtistDesc;
87   else if (!m_artist.empty())
88     return StringUtils::Join(m_artist, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator);
89   else
90     return StringUtils::Empty;
91 }
92 
GetArtistSort() const93 const std::string& CMusicInfoTag::GetArtistSort() const
94 {
95   return m_strArtistSort;
96 }
97 
GetComposerSort() const98 const std::string& CMusicInfoTag::GetComposerSort() const
99 {
100   return m_strComposerSort;
101 }
102 
GetAlbum() const103 const std::string& CMusicInfoTag::GetAlbum() const
104 {
105   return m_strAlbum;
106 }
107 
GetDiscSubtitle() const108 const std::string& CMusicInfoTag::GetDiscSubtitle() const
109 {
110   return m_strDiscSubtitle;
111 }
112 
GetOriginalDate() const113 const std::string& CMusicInfoTag::GetOriginalDate() const
114 {
115   return m_strOriginalDate;
116 }
117 
GetOriginalYear() const118 const std::string MUSIC_INFO::CMusicInfoTag::GetOriginalYear() const
119 {
120   return StringUtils::Left(m_strOriginalDate, 4);
121 }
122 
GetAlbumId() const123 int CMusicInfoTag::GetAlbumId() const
124 {
125   return m_iAlbumId;
126 }
127 
GetAlbumArtist() const128 const std::vector<std::string>& CMusicInfoTag::GetAlbumArtist() const
129 {
130   return m_albumArtist;
131 }
132 
GetAlbumArtistString() const133 const std::string CMusicInfoTag::GetAlbumArtistString() const
134 {
135   if (!m_strAlbumArtistDesc.empty())
136     return m_strAlbumArtistDesc;
137   if (!m_albumArtist.empty())
138     return StringUtils::Join(m_albumArtist, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator);
139   else
140     return StringUtils::Empty;
141 }
142 
GetAlbumArtistSort() const143 const std::string& CMusicInfoTag::GetAlbumArtistSort() const
144 {
145   return m_strAlbumArtistSort;
146 }
147 
GetGenre() const148 const std::vector<std::string>& CMusicInfoTag::GetGenre() const
149 {
150   return m_genre;
151 }
152 
GetDatabaseId() const153 int CMusicInfoTag::GetDatabaseId() const
154 {
155   return m_iDbId;
156 }
157 
GetType() const158 const std::string &CMusicInfoTag::GetType() const
159 {
160   return m_type;
161 }
162 
GetYear() const163 int CMusicInfoTag::GetYear() const
164 {
165   return atoi(GetYearString().c_str());
166 }
167 
GetYearString() const168 std::string CMusicInfoTag::GetYearString() const
169 {
170   /* Get year as YYYY from release or original dates depending on setting
171      This is how GUI and by year sorting swiches to using original year.
172      For ripper and non-library items (libray entries have both values):
173      when release date missing try to fallback to original date
174      when original date missing use release date
175   */
176   std::string value;
177   value = GetReleaseYear();
178   if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
179     CSettings::SETTING_MUSICLIBRARY_USEORIGINALDATE) ||
180     value.empty())
181   {
182     std::string origvalue = GetOriginalYear();
183     if (!origvalue.empty())
184       return origvalue;
185   }
186   return value;
187 }
188 
GetComment() const189 const std::string &CMusicInfoTag::GetComment() const
190 {
191   return m_strComment;
192 }
193 
GetMood() const194 const std::string &CMusicInfoTag::GetMood() const
195 {
196   return m_strMood;
197 }
198 
GetRecordLabel() const199 const std::string &CMusicInfoTag::GetRecordLabel() const
200 {
201   return m_strRecordLabel;
202 }
203 
GetLyrics() const204 const std::string &CMusicInfoTag::GetLyrics() const
205 {
206   return m_strLyrics;
207 }
208 
GetCueSheet() const209 const std::string &CMusicInfoTag::GetCueSheet() const
210 {
211   return m_cuesheet;
212 }
213 
GetRating() const214 float CMusicInfoTag::GetRating() const
215 {
216   return m_Rating;
217 }
218 
GetUserrating() const219 int CMusicInfoTag::GetUserrating() const
220 {
221   return m_Userrating;
222 }
223 
GetVotes() const224 int CMusicInfoTag::GetVotes() const
225 {
226   return m_Votes;
227 }
228 
GetListeners() const229 int CMusicInfoTag::GetListeners() const
230 {
231  return m_listeners;
232 }
233 
GetPlayCount() const234 int CMusicInfoTag::GetPlayCount() const
235 {
236   return m_iTimesPlayed;
237 }
238 
GetLastPlayed() const239 const CDateTime &CMusicInfoTag::GetLastPlayed() const
240 {
241   return m_lastPlayed;
242 }
243 
GetDateAdded() const244 const CDateTime &CMusicInfoTag::GetDateAdded() const
245 {
246   return m_dateAdded;
247 }
248 
GetCompilation() const249 bool CMusicInfoTag::GetCompilation() const
250 {
251   return m_bCompilation;
252 }
253 
GetBoxset() const254 bool CMusicInfoTag::GetBoxset() const
255 {
256   return m_bBoxset;
257 }
258 
GetTotalDiscs() const259 int CMusicInfoTag::GetTotalDiscs() const
260 {
261   return m_iDiscTotal;
262 }
263 
GetCoverArtInfo() const264 const EmbeddedArtInfo &CMusicInfoTag::GetCoverArtInfo() const
265 {
266   return m_coverArt;
267 }
268 
GetReplayGain() const269 const ReplayGain& CMusicInfoTag::GetReplayGain() const
270 {
271   return m_replayGain;
272 }
273 
GetAlbumReleaseType() const274 CAlbum::ReleaseType CMusicInfoTag::GetAlbumReleaseType() const
275 {
276   return m_albumReleaseType;
277 }
278 
GetBPM() const279 int CMusicInfoTag::GetBPM() const
280 {
281   return m_iBPM;
282 }
283 
GetBitRate() const284 int CMusicInfoTag::GetBitRate() const
285 {
286   return m_bitrate;
287 }
288 
GetSampleRate() const289 int CMusicInfoTag::GetSampleRate() const
290 {
291   return m_samplerate;
292 }
293 
GetNoOfChannels() const294 int CMusicInfoTag::GetNoOfChannels() const
295 {
296   return m_channels;
297 }
298 
GetReleaseDate() const299 const std::string& CMusicInfoTag::GetReleaseDate() const
300 {
301   return m_strReleaseDate;
302 }
303 
GetReleaseYear() const304 const std::string MUSIC_INFO::CMusicInfoTag::GetReleaseYear() const
305 {
306   return StringUtils::Left(m_strReleaseDate, 4);
307 }
308 
309 // This is the Musicbrainz release status tag. See https://musicbrainz.org/doc/Release#Status
310 
GetAlbumReleaseStatus() const311 const std::string& CMusicInfoTag::GetAlbumReleaseStatus() const
312 {
313   return m_strReleaseStatus;
314 }
315 
GetStationName() const316 const std::string& CMusicInfoTag::GetStationName() const
317 {
318   return m_stationName;
319 }
320 
GetStationArt() const321 const std::string& CMusicInfoTag::GetStationArt() const
322 {
323   return m_stationArt;
324 }
325 
SetURL(const std::string & strURL)326 void CMusicInfoTag::SetURL(const std::string& strURL)
327 {
328   m_strURL = strURL;
329 }
330 
SetTitle(const std::string & strTitle)331 void CMusicInfoTag::SetTitle(const std::string& strTitle)
332 {
333   m_strTitle = Trim(strTitle);
334 }
335 
SetArtist(const std::string & strArtist)336 void CMusicInfoTag::SetArtist(const std::string& strArtist)
337 {
338   if (!strArtist.empty())
339   {
340     SetArtistDesc(strArtist);
341     SetArtist(StringUtils::Split(strArtist, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator));
342   }
343   else
344   {
345     m_strArtistDesc.clear();
346     m_artist.clear();
347   }
348 }
349 
SetArtist(const std::vector<std::string> & artists,bool FillDesc)350 void CMusicInfoTag::SetArtist(const std::vector<std::string>& artists, bool FillDesc /* = false*/)
351 {
352   m_artist = artists;
353   if (m_strArtistDesc.empty() || FillDesc)
354   {
355     SetArtistDesc(StringUtils::Join(artists, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator));
356   }
357 }
358 
SetArtistDesc(const std::string & strArtistDesc)359 void CMusicInfoTag::SetArtistDesc(const std::string& strArtistDesc)
360 {
361   m_strArtistDesc = strArtistDesc;
362 }
363 
SetArtistSort(const std::string & strArtistsort)364 void CMusicInfoTag::SetArtistSort(const std::string& strArtistsort)
365 {
366   m_strArtistSort = strArtistsort;
367 }
368 
SetComposerSort(const std::string & strComposerSort)369 void CMusicInfoTag::SetComposerSort(const std::string& strComposerSort)
370 {
371   m_strComposerSort = strComposerSort;
372 }
373 
SetAlbum(const std::string & strAlbum)374 void CMusicInfoTag::SetAlbum(const std::string& strAlbum)
375 {
376   m_strAlbum = Trim(strAlbum);
377 }
378 
SetAlbumId(const int iAlbumId)379 void CMusicInfoTag::SetAlbumId(const int iAlbumId)
380 {
381   m_iAlbumId = iAlbumId;
382 }
383 
SetAlbumArtist(const std::string & strAlbumArtist)384 void CMusicInfoTag::SetAlbumArtist(const std::string& strAlbumArtist)
385 {
386   if (!strAlbumArtist.empty())
387   {
388     SetAlbumArtistDesc(strAlbumArtist);
389     SetAlbumArtist(StringUtils::Split(strAlbumArtist, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator));
390   }
391   else
392   {
393     m_strAlbumArtistDesc.clear();
394     m_albumArtist.clear();
395   }
396 }
397 
SetAlbumArtist(const std::vector<std::string> & albumArtists,bool FillDesc)398 void CMusicInfoTag::SetAlbumArtist(const std::vector<std::string>& albumArtists, bool FillDesc /* = false*/)
399 {
400   m_albumArtist = albumArtists;
401   if (m_strAlbumArtistDesc.empty() || FillDesc)
402     SetAlbumArtistDesc(StringUtils::Join(albumArtists, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator));
403 }
404 
SetAlbumArtistDesc(const std::string & strAlbumArtistDesc)405 void CMusicInfoTag::SetAlbumArtistDesc(const std::string& strAlbumArtistDesc)
406 {
407   m_strAlbumArtistDesc = strAlbumArtistDesc;
408 }
409 
SetAlbumArtistSort(const std::string & strAlbumArtistSort)410 void CMusicInfoTag::SetAlbumArtistSort(const std::string& strAlbumArtistSort)
411 {
412   m_strAlbumArtistSort = strAlbumArtistSort;
413 }
414 
SetGenre(const std::string & strGenre,bool bTrim)415 void CMusicInfoTag::SetGenre(const std::string& strGenre, bool bTrim /* = false*/)
416 {
417   if (!strGenre.empty())
418     SetGenre(StringUtils::Split(strGenre, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator), bTrim);
419   else
420     m_genre.clear();
421 }
422 
SetGenre(const std::vector<std::string> & genres,bool bTrim)423 void CMusicInfoTag::SetGenre(const std::vector<std::string>& genres, bool bTrim /* = false*/)
424 {
425   m_genre = genres;
426   if (bTrim)
427     for (auto genre : m_genre)
428       StringUtils::Trim(genre);
429 }
430 
SetYear(int year)431 void CMusicInfoTag::SetYear(int year)
432 {
433   // Parse integer year value into YYYY ISO8601 format (partial) date string
434   // Add century for to 2 digit numbers, 41 -> 1941, 40 -> 2040
435   if (year > 99)
436     SetReleaseDate(StringUtils::Format("%04i", year));
437   else if (year > 40)
438     SetReleaseDate(StringUtils::Format("%04i", 19 + year));
439   else  if (year > 0)
440     SetReleaseDate(StringUtils::Format("%04i", 20 + year));
441   else
442     m_strReleaseDate.clear();
443 }
444 
SetDatabaseId(int id,const std::string & type)445 void CMusicInfoTag::SetDatabaseId(int id, const std::string &type)
446 {
447   m_iDbId = id;
448   m_type = type;
449 }
450 
SetTrackNumber(int iTrack)451 void CMusicInfoTag::SetTrackNumber(int iTrack)
452 {
453   m_iTrack = (m_iTrack & 0xffff0000) | (iTrack & 0xffff);
454 }
455 
SetDiscNumber(int iDiscNumber)456 void CMusicInfoTag::SetDiscNumber(int iDiscNumber)
457 {
458   m_iTrack = (m_iTrack & 0xffff) | (iDiscNumber << 16);
459 }
460 
SetDiscSubtitle(const std::string & strDiscSubtitle)461 void CMusicInfoTag::SetDiscSubtitle(const std::string& strDiscSubtitle)
462 {
463   m_strDiscSubtitle = strDiscSubtitle;
464 }
465 
SetTotalDiscs(int iDiscTotal)466 void CMusicInfoTag::SetTotalDiscs(int iDiscTotal)
467 {
468   m_iDiscTotal = iDiscTotal;
469 }
470 
SetReleaseDate(const std::string & strReleaseDate)471 void CMusicInfoTag::SetReleaseDate(const std::string& strReleaseDate)
472 {
473   // Date in ISO8601 YYYY, YYYY-MM or YYYY-MM-DD
474   m_strReleaseDate = strReleaseDate;
475 }
476 
SetOriginalDate(const std::string & strOriginalDate)477 void CMusicInfoTag::SetOriginalDate(const std::string& strOriginalDate)
478 {
479   // Date in ISO8601 YYYY, YYYY-MM or YYYY-MM-DD
480   m_strOriginalDate = strOriginalDate;
481 }
482 
AddOriginalDate(const std::string & strDateYear)483 void CMusicInfoTag::AddOriginalDate(const std::string& strDateYear)
484 {
485   // Avoid overwriting YYYY-MM or YYYY-MM-DD (from DATE tag) with just YYYY (from YEAR tag)
486   if (strDateYear.size() > m_strOriginalDate.size())
487     m_strOriginalDate = strDateYear;
488 }
489 
AddReleaseDate(const std::string & strDateYear,bool isMonth)490 void CMusicInfoTag::AddReleaseDate(const std::string& strDateYear, bool isMonth /*= false*/)
491 {
492   // Given MMDD  (from ID3 v2.3 TDAT tag) set MM-DD part of ISO8601 string
493   if (isMonth && !strDateYear.empty())
494   {
495     std::string strYYYY = GetReleaseYear();
496     if (strYYYY.empty())
497       strYYYY = "0000"; // Fake year when TYER not read yet
498     m_strReleaseDate =
499       StringUtils::Format("%s-%s-%s", strYYYY, StringUtils::Left(strDateYear, 2),
500         StringUtils::Right(strDateYear, 2));
501   }
502   // Given YYYY only (from YEAR tag) and already have YYYY-MM or YYYY-MM-DD (from DATE tag)
503   else if (strDateYear.size() == 4 && (m_strReleaseDate.size() > 4))
504   {
505     // Have 0000-MM-DD where ID3 v2.3 TDAT tag read first, fill YYYY part from TYER
506     if (GetReleaseYear() == "0000")
507       StringUtils::Replace(m_strReleaseDate, "0000", strDateYear);
508   }
509   else
510     m_strReleaseDate = strDateYear;  // Could be YYYY, YYYY-MM or YYYY-MM-DD
511 }
512 
SetTrackAndDiscNumber(int iTrackAndDisc)513 void CMusicInfoTag::SetTrackAndDiscNumber(int iTrackAndDisc)
514 {
515   m_iTrack = iTrackAndDisc;
516 }
517 
SetDuration(int iSec)518 void CMusicInfoTag::SetDuration(int iSec)
519 {
520   m_iDuration = iSec;
521 }
522 
SetBitRate(int bitrate)523 void CMusicInfoTag::SetBitRate(int bitrate)
524 {
525   m_bitrate = bitrate;
526 }
527 
SetNoOfChannels(int channels)528 void CMusicInfoTag::SetNoOfChannels(int channels)
529 {
530   m_channels = channels;
531 }
532 
SetSampleRate(int samplerate)533 void CMusicInfoTag::SetSampleRate(int samplerate)
534 {
535   m_samplerate = samplerate;
536 }
537 
SetComment(const std::string & comment)538 void CMusicInfoTag::SetComment(const std::string& comment)
539 {
540   m_strComment = comment;
541 }
542 
SetMood(const std::string & mood)543 void CMusicInfoTag::SetMood(const std::string& mood)
544 {
545   m_strMood = mood;
546 }
547 
SetRecordLabel(const std::string & publisher)548 void CMusicInfoTag::SetRecordLabel(const std::string& publisher)
549 {
550   m_strRecordLabel = publisher;
551 }
552 
SetCueSheet(const std::string & cueSheet)553 void CMusicInfoTag::SetCueSheet(const std::string& cueSheet)
554 {
555   m_cuesheet = cueSheet;
556 }
557 
SetLyrics(const std::string & lyrics)558 void CMusicInfoTag::SetLyrics(const std::string& lyrics)
559 {
560   m_strLyrics = lyrics;
561 }
562 
SetRating(float rating)563 void CMusicInfoTag::SetRating(float rating)
564 {
565   //This value needs to be between 0-10 - 0 will unset the rating
566   rating = std::max(rating, 0.f);
567   rating = std::min(rating, 10.f);
568 
569   m_Rating = rating;
570 }
571 
SetVotes(int votes)572 void CMusicInfoTag::SetVotes(int votes)
573 {
574   m_Votes = votes;
575 }
576 
SetUserrating(int rating)577 void CMusicInfoTag::SetUserrating(int rating)
578 {
579   //This value needs to be between 0-10 - 0 will unset the userrating
580   rating = std::max(rating, 0);
581   rating = std::min(rating, 10);
582 
583   m_Userrating = rating;
584 }
585 
SetListeners(int listeners)586 void CMusicInfoTag::SetListeners(int listeners)
587 {
588   m_listeners = std::max(listeners, 0);
589 }
590 
SetPlayCount(int playcount)591 void CMusicInfoTag::SetPlayCount(int playcount)
592 {
593   m_iTimesPlayed = playcount;
594 }
595 
SetLastPlayed(const std::string & lastplayed)596 void CMusicInfoTag::SetLastPlayed(const std::string& lastplayed)
597 {
598   m_lastPlayed.SetFromDBDateTime(lastplayed);
599 }
600 
SetLastPlayed(const CDateTime & lastplayed)601 void CMusicInfoTag::SetLastPlayed(const CDateTime& lastplayed)
602 {
603   m_lastPlayed = lastplayed;
604 }
605 
SetDateAdded(const std::string & strDateAdded)606 void CMusicInfoTag::SetDateAdded(const std::string& strDateAdded)
607 {
608   m_dateAdded.SetFromDBDateTime(strDateAdded);
609 }
610 
SetDateAdded(const CDateTime & dateAdded)611 void CMusicInfoTag::SetDateAdded(const CDateTime& dateAdded)
612 {
613   m_dateAdded = dateAdded;
614 }
615 
SetDateUpdated(const std::string & strDateUpdated)616 void MUSIC_INFO::CMusicInfoTag::SetDateUpdated(const std::string& strDateUpdated)
617 {
618   m_dateUpdated.SetFromDBDateTime(strDateUpdated);
619 }
620 
SetDateUpdated(const CDateTime & dateUpdated)621 void MUSIC_INFO::CMusicInfoTag::SetDateUpdated(const CDateTime& dateUpdated)
622 {
623   m_dateUpdated = dateUpdated;
624 }
625 
SetDateNew(const std::string & strDateNew)626 void MUSIC_INFO::CMusicInfoTag::SetDateNew(const std::string& strDateNew)
627 {
628   m_dateNew.SetFromDBDateTime(strDateNew);
629 }
630 
SetDateNew(const CDateTime & dateNew)631 void MUSIC_INFO::CMusicInfoTag::SetDateNew(const CDateTime& dateNew)
632 {
633   m_dateNew = dateNew;
634 }
635 
SetCompilation(bool compilation)636 void CMusicInfoTag::SetCompilation(bool compilation)
637 {
638   m_bCompilation = compilation;
639 }
640 
SetBoxset(bool boxset)641 void CMusicInfoTag::SetBoxset(bool boxset)
642 {
643   m_bBoxset = boxset;
644 }
645 
SetLoaded(bool bOnOff)646 void CMusicInfoTag::SetLoaded(bool bOnOff)
647 {
648   m_bLoaded = bOnOff;
649 }
650 
Loaded() const651 bool CMusicInfoTag::Loaded() const
652 {
653   return m_bLoaded;
654 }
655 
SetBPM(int bpm)656 void CMusicInfoTag::SetBPM(int bpm)
657 {
658   m_iBPM = bpm;
659 }
660 
SetStationName(const std::string & strStationName)661 void CMusicInfoTag::SetStationName(const std::string& strStationName)
662 {
663   m_stationName = strStationName;
664 }
665 
GetMusicBrainzTrackID() const666 const std::string& CMusicInfoTag::GetMusicBrainzTrackID() const
667 {
668   return m_strMusicBrainzTrackID;
669 }
670 
GetMusicBrainzArtistID() const671 const std::vector<std::string>& CMusicInfoTag::GetMusicBrainzArtistID() const
672 {
673   return m_musicBrainzArtistID;
674 }
675 
GetMusicBrainzArtistHints() const676 const std::vector<std::string>& CMusicInfoTag::GetMusicBrainzArtistHints() const
677 {
678   return m_musicBrainzArtistHints;
679 }
680 
GetMusicBrainzAlbumID() const681 const std::string& CMusicInfoTag::GetMusicBrainzAlbumID() const
682 {
683   return m_strMusicBrainzAlbumID;
684 }
685 
GetMusicBrainzReleaseGroupID() const686 const std::string & MUSIC_INFO::CMusicInfoTag::GetMusicBrainzReleaseGroupID() const
687 {
688   return m_strMusicBrainzReleaseGroupID;
689 }
690 
GetMusicBrainzAlbumArtistID() const691 const std::vector<std::string>& CMusicInfoTag::GetMusicBrainzAlbumArtistID() const
692 {
693   return m_musicBrainzAlbumArtistID;
694 }
695 
GetMusicBrainzAlbumArtistHints() const696 const std::vector<std::string>& CMusicInfoTag::GetMusicBrainzAlbumArtistHints() const
697 {
698     return m_musicBrainzAlbumArtistHints;
699 }
700 
GetMusicBrainzReleaseType() const701 const std::string &CMusicInfoTag::GetMusicBrainzReleaseType() const
702 {
703   return m_strMusicBrainzReleaseType;
704 }
705 
SetMusicBrainzTrackID(const std::string & strTrackID)706 void CMusicInfoTag::SetMusicBrainzTrackID(const std::string& strTrackID)
707 {
708   m_strMusicBrainzTrackID = strTrackID;
709 }
710 
SetMusicBrainzArtistID(const std::vector<std::string> & musicBrainzArtistId)711 void CMusicInfoTag::SetMusicBrainzArtistID(const std::vector<std::string>& musicBrainzArtistId)
712 {
713   m_musicBrainzArtistID = musicBrainzArtistId;
714 }
715 
SetMusicBrainzArtistHints(const std::vector<std::string> & musicBrainzArtistHints)716 void CMusicInfoTag::SetMusicBrainzArtistHints(const std::vector<std::string>& musicBrainzArtistHints)
717 {
718   m_musicBrainzArtistHints = musicBrainzArtistHints;
719 }
720 
SetMusicBrainzAlbumID(const std::string & strAlbumID)721 void CMusicInfoTag::SetMusicBrainzAlbumID(const std::string& strAlbumID)
722 {
723   m_strMusicBrainzAlbumID = strAlbumID;
724 }
725 
SetMusicBrainzAlbumArtistID(const std::vector<std::string> & musicBrainzAlbumArtistId)726 void CMusicInfoTag::SetMusicBrainzAlbumArtistID(const std::vector<std::string>& musicBrainzAlbumArtistId)
727 {
728   m_musicBrainzAlbumArtistID = musicBrainzAlbumArtistId;
729 }
730 
SetMusicBrainzAlbumArtistHints(const std::vector<std::string> & musicBrainzAlbumArtistHints)731 void CMusicInfoTag::SetMusicBrainzAlbumArtistHints(const std::vector<std::string>& musicBrainzAlbumArtistHints)
732 {
733     m_musicBrainzAlbumArtistHints = musicBrainzAlbumArtistHints;
734 }
735 
SetMusicBrainzReleaseGroupID(const std::string & strReleaseGroupID)736 void MUSIC_INFO::CMusicInfoTag::SetMusicBrainzReleaseGroupID(const std::string & strReleaseGroupID)
737 {
738   m_strMusicBrainzReleaseGroupID = strReleaseGroupID;
739 }
740 
SetMusicBrainzReleaseType(const std::string & ReleaseType)741 void CMusicInfoTag::SetMusicBrainzReleaseType(const std::string& ReleaseType)
742 {
743   m_strMusicBrainzReleaseType = ReleaseType;
744 }
745 
SetCoverArtInfo(size_t size,const std::string & mimeType)746 void CMusicInfoTag::SetCoverArtInfo(size_t size, const std::string &mimeType)
747 {
748   m_coverArt.Set(size, mimeType);
749 }
750 
SetReplayGain(const ReplayGain & aGain)751 void CMusicInfoTag::SetReplayGain(const ReplayGain& aGain)
752 {
753   m_replayGain = aGain;
754 }
755 
SetAlbumReleaseType(CAlbum::ReleaseType releaseType)756 void CMusicInfoTag::SetAlbumReleaseType(CAlbum::ReleaseType releaseType)
757 {
758   m_albumReleaseType = releaseType;
759 }
760 
SetType(const MediaType & mediaType)761 void CMusicInfoTag::SetType(const MediaType& mediaType)
762 {
763   m_type = mediaType;
764 }
765 
766 // This is the Musicbrainz release status tag. See https://musicbrainz.org/doc/Release#Status
767 
SetAlbumReleaseStatus(const std::string & ReleaseStatus)768 void CMusicInfoTag::SetAlbumReleaseStatus(const std::string& ReleaseStatus)
769 {
770   m_strReleaseStatus = ReleaseStatus;
771 }
772 
SetStationArt(const std::string & strStationArt)773 void CMusicInfoTag::SetStationArt(const std::string& strStationArt)
774 {
775   m_stationArt = strStationArt;
776 }
777 
SetArtist(const CArtist & artist)778 void CMusicInfoTag::SetArtist(const CArtist& artist)
779 {
780   SetArtist(artist.strArtist);
781   SetArtistSort(artist.strSortName);
782   SetAlbumArtist(artist.strArtist);
783   SetAlbumArtistSort(artist.strSortName);
784   SetMusicBrainzArtistID({ artist.strMusicBrainzArtistID });
785   SetMusicBrainzAlbumArtistID({ artist.strMusicBrainzArtistID });
786   SetGenre(artist.genre);
787   SetMood(StringUtils::Join(artist.moods, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator));
788   SetDateAdded(artist.dateAdded);
789   SetDateUpdated(artist.dateUpdated);
790   SetDateNew(artist.dateNew);
791   SetDatabaseId(artist.idArtist, MediaTypeArtist);
792 
793   SetLoaded();
794 }
795 
SetAlbum(const CAlbum & album)796 void CMusicInfoTag::SetAlbum(const CAlbum& album)
797 {
798   Clear();
799   //Set all artist infomation from album artist credits and artist description
800   SetArtistDesc(album.GetAlbumArtistString());
801   SetArtist(album.GetAlbumArtist());
802   SetArtistSort(album.GetAlbumArtistSort());
803   SetMusicBrainzArtistID(album.GetMusicBrainzAlbumArtistID());
804   SetAlbumArtistDesc(album.GetAlbumArtistString());
805   SetAlbumArtist(album.GetAlbumArtist());
806   SetAlbumArtistSort(album.GetAlbumArtistSort());
807   SetMusicBrainzAlbumArtistID(album.GetMusicBrainzAlbumArtistID());
808   SetAlbumId(album.idAlbum);
809   SetAlbum(album.strAlbum);
810   SetTitle(album.strAlbum);
811   SetMusicBrainzAlbumID(album.strMusicBrainzAlbumID);
812   SetMusicBrainzReleaseGroupID(album.strReleaseGroupMBID);
813   SetMusicBrainzReleaseType(album.strType);
814   SetAlbumReleaseStatus(album.strReleaseStatus);
815   SetGenre(album.genre);
816   SetMood(StringUtils::Join(album.moods, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator));
817   SetRecordLabel(album.strLabel);
818   SetRating(album.fRating);
819   SetUserrating(album.iUserrating);
820   SetVotes(album.iVotes);
821   SetCompilation(album.bCompilation);
822   SetOriginalDate(album.strOrigReleaseDate);
823   SetReleaseDate(album.strReleaseDate);
824   SetBoxset(album.bBoxedSet);
825   SetAlbumReleaseType(album.releaseType);
826   SetDateAdded(album.dateAdded);
827   SetDateUpdated(album.dateUpdated);
828   SetDateNew(album.dateNew);
829   SetPlayCount(album.iTimesPlayed);
830   SetDatabaseId(album.idAlbum, MediaTypeAlbum);
831   SetLastPlayed(album.lastPlayed);
832   SetTotalDiscs(album.iTotalDiscs);
833   SetDuration(album.iAlbumDuration);
834 
835   SetLoaded();
836 }
837 
SetSong(const CSong & song)838 void CMusicInfoTag::SetSong(const CSong& song)
839 {
840   Clear();
841   SetTitle(song.strTitle);
842   SetGenre(song.genre);
843   /* Set all artist infomation from song artist credits and artist description.
844      During processing e.g. Cue Sheets, song may only have artist description string
845      rather than a fully populated artist credits vector.
846   */
847   if (!song.HasArtistCredits())
848     SetArtist(song.GetArtistString()); //Sets both artist description string and artist vector from string
849   else
850   {
851     SetArtistDesc(song.GetArtistString());
852     SetArtist(song.GetArtist());
853     SetMusicBrainzArtistID(song.GetMusicBrainzArtistID());
854   }
855   SetArtistSort(song.GetArtistSort());
856   SetAlbum(song.strAlbum);
857   SetAlbumArtist(song.GetAlbumArtist()); //Only have album artist in song as vector, no desc or MBID
858   SetAlbumArtistSort(song.GetAlbumArtistSort());
859   SetMusicBrainzTrackID(song.strMusicBrainzTrackID);
860   SetContributors(song.GetContributors());
861   SetComment(song.strComment);
862   SetCueSheet(song.strCueSheet);
863   SetPlayCount(song.iTimesPlayed);
864   SetLastPlayed(song.lastPlayed);
865   SetDateAdded(song.dateAdded);
866   SetDateUpdated(song.dateUpdated);
867   SetDateNew(song.dateNew);
868   SetCoverArtInfo(song.embeddedArt.m_size, song.embeddedArt.m_mime);
869   SetRating(song.rating);
870   SetUserrating(song.userrating);
871   SetVotes(song.votes);
872   SetURL(song.strFileName);
873   SetReleaseDate(song.strReleaseDate);
874   SetOriginalDate(song.strOrigReleaseDate);
875   SetTrackAndDiscNumber(song.iTrack);
876   SetDiscSubtitle(song.strDiscSubtitle);
877   SetDuration(song.iDuration);
878   SetMood(song.strMood);
879   SetCompilation(song.bCompilation);
880   SetAlbumId(song.idAlbum);
881   SetDatabaseId(song.idSong, MediaTypeSong);
882   SetBPM(song.iBPM);
883   SetBitRate(song.iBitRate);
884   SetSampleRate(song.iSampleRate);
885   SetNoOfChannels(song.iChannels);
886 
887   if (song.replayGain.Get(ReplayGain::TRACK).Valid())
888     m_replayGain.Set(ReplayGain::TRACK, song.replayGain.Get(ReplayGain::TRACK));
889   if (song.replayGain.Get(ReplayGain::ALBUM).Valid())
890     m_replayGain.Set(ReplayGain::ALBUM, song.replayGain.Get(ReplayGain::ALBUM));
891 
892   SetLoaded();
893 }
894 
Serialize(CVariant & value) const895 void CMusicInfoTag::Serialize(CVariant& value) const
896 {
897   value["url"] = m_strURL;
898   value["title"] = m_strTitle;
899   if (m_type.compare(MediaTypeArtist) == 0 && m_artist.size() == 1)
900     value["artist"] = m_artist[0];
901   else
902     value["artist"] = m_artist;
903   // There are situations where the individual artist(s) are not queried from the song_artist and artist tables e.g. playlist,
904   // only artist description from song table. Since processing of the ARTISTS tag was added the individual artists may not always
905   // be accurately derived by simply splitting the artist desc. Hence m_artist is only populated when the individual artists are
906   // queried, whereas GetArtistString() will always return the artist description.
907   // To avoid empty artist array in JSON, when m_artist is empty then an attempt is made to split the artist desc into artists.
908   // A longer term solution would be to ensure that when individual artists are to be returned then the song_artist and artist tables
909   // are queried.
910   if (m_artist.empty())
911     value["artist"] = StringUtils::Split(GetArtistString(), CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator);
912 
913   value["displayartist"] = GetArtistString();
914   value["displayalbumartist"] = GetAlbumArtistString();
915   value["sortartist"] = GetArtistSort();
916   value["album"] = m_strAlbum;
917   value["albumartist"] = m_albumArtist;
918   value["sortalbumartist"] = m_strAlbumArtistSort;
919   value["genre"] = m_genre;
920   value["duration"] = m_iDuration;
921   value["track"] = GetTrackNumber();
922   value["disc"] = GetDiscNumber();
923   value["loaded"] = m_bLoaded;
924   value["year"] = GetYear(); // Optionally from m_strOriginalDate
925   value["musicbrainztrackid"] = m_strMusicBrainzTrackID;
926   value["musicbrainzartistid"] = m_musicBrainzArtistID;
927   value["musicbrainzalbumid"] = m_strMusicBrainzAlbumID;
928   value["musicbrainzreleasegroupid"] = m_strMusicBrainzReleaseGroupID;
929   value["musicbrainzalbumartistid"] = m_musicBrainzAlbumArtistID;
930   value["comment"] = m_strComment;
931   value["contributors"] = CVariant(CVariant::VariantTypeArray);
932   for (const auto& role : m_musicRoles)
933   {
934     CVariant contributor;
935     contributor["name"] = role.GetArtist();
936     contributor["role"] = role.GetRoleDesc();
937     contributor["roleid"] = role.GetRoleId();
938     contributor["artistid"] = (int)(role.GetArtistId());
939     value["contributors"].push_back(contributor);
940   }
941   value["displaycomposer"] = GetArtistStringForRole("composer");   //TCOM
942   value["displayconductor"] = GetArtistStringForRole("conductor"); //TPE3
943   value["displayorchestra"] = GetArtistStringForRole("orchestra");
944   value["displaylyricist"] = GetArtistStringForRole("lyricist");   //TEXT
945   value["mood"] = StringUtils::Split(m_strMood, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator);
946   value["recordlabel"] = m_strRecordLabel;
947   value["rating"] = m_Rating;
948   value["userrating"] = m_Userrating;
949   value["votes"] = m_Votes;
950   value["playcount"] = m_iTimesPlayed;
951   value["lastplayed"] = m_lastPlayed.IsValid() ? m_lastPlayed.GetAsDBDateTime() : StringUtils::Empty;
952   value["dateadded"] = m_dateAdded.IsValid() ? m_dateAdded.GetAsDBDateTime() : StringUtils::Empty;
953   value["datenew"] = m_dateNew.IsValid() ? m_dateNew.GetAsDBDateTime() : StringUtils::Empty;
954   value["datemodified"] =
955       m_dateUpdated.IsValid() ? m_dateUpdated.GetAsDBDateTime() : StringUtils::Empty;
956   value["lyrics"] = m_strLyrics;
957   value["albumid"] = m_iAlbumId;
958   value["compilationartist"] = m_bCompilation;
959   value["compilation"] = m_bCompilation;
960   if (m_type.compare(MediaTypeAlbum) == 0)
961     value["releasetype"] = CAlbum::ReleaseTypeToString(m_albumReleaseType);
962   else if (m_type.compare(MediaTypeSong) == 0)
963     value["albumreleasetype"] = CAlbum::ReleaseTypeToString(m_albumReleaseType);
964   value["isboxset"] = m_bBoxset;
965   value["totaldiscs"] = m_iDiscTotal;
966   value["disctitle"] = m_strDiscSubtitle;
967   value["releasedate"] = m_strReleaseDate;
968   value["originaldate"] = m_strOriginalDate;
969   value["albumstatus"] = m_strReleaseStatus;
970   value["bpm"] = m_iBPM;
971   value["bitrate"] = m_bitrate;
972   value["samplerate"] = m_samplerate;
973   value["channels"] = m_channels;
974 }
975 
ToSortable(SortItem & sortable,Field field) const976 void CMusicInfoTag::ToSortable(SortItem& sortable, Field field) const
977 {
978   switch (field)
979   {
980   case FieldTitle:
981   {
982     // make sure not to overwrite an existing path with an empty one
983     std::string title = m_strTitle;
984     if (!title.empty() || sortable.find(FieldTitle) == sortable.end())
985       sortable[FieldTitle] = title;
986     break;
987   }
988   case FieldArtist:      sortable[FieldArtist] = m_strArtistDesc; break;
989   case FieldArtistSort:  sortable[FieldArtistSort] = m_strArtistSort; break;
990   case FieldAlbum:       sortable[FieldAlbum] = m_strAlbum; break;
991   case FieldAlbumArtist: sortable[FieldAlbumArtist] = m_strAlbumArtistDesc; break;
992   case FieldGenre:       sortable[FieldGenre] = m_genre; break;
993   case FieldTime:        sortable[FieldTime] = m_iDuration; break;
994   case FieldTrackNumber: sortable[FieldTrackNumber] = m_iTrack; break;
995   case FieldTotalDiscs:
996     sortable[FieldTotalDiscs] = m_iDiscTotal;
997     break;
998   case FieldYear:
999     sortable[FieldYear] = GetYear();  // Optionally from m_strOriginalDate
1000     break;
1001   case FieldComment:     sortable[FieldComment] = m_strComment; break;
1002   case FieldMoods:       sortable[FieldMoods] = m_strMood; break;
1003   case FieldRating:      sortable[FieldRating] = m_Rating; break;
1004   case FieldUserRating:  sortable[FieldUserRating] = m_Userrating; break;
1005   case FieldVotes:       sortable[FieldVotes] = m_Votes; break;
1006   case FieldPlaycount:   sortable[FieldPlaycount] = m_iTimesPlayed; break;
1007   case FieldLastPlayed:  sortable[FieldLastPlayed] = m_lastPlayed.IsValid() ? m_lastPlayed.GetAsDBDateTime() : StringUtils::Empty; break;
1008   case FieldDateAdded:   sortable[FieldDateAdded] = m_dateAdded.IsValid() ? m_dateAdded.GetAsDBDateTime() : StringUtils::Empty; break;
1009   case FieldListeners:   sortable[FieldListeners] = m_listeners; break;
1010   case FieldId:          sortable[FieldId] = (int64_t)m_iDbId; break;
1011   case FieldOrigDate:    sortable[FieldOrigDate] = m_strOriginalDate; break;
1012   case FieldBPM:         sortable[FieldBPM] = m_iBPM; break;
1013   default: break;
1014   }
1015 }
1016 
Archive(CArchive & ar)1017 void CMusicInfoTag::Archive(CArchive& ar)
1018 {
1019   if (ar.IsStoring())
1020   {
1021     ar << m_strURL;
1022     ar << m_strTitle;
1023     ar << m_artist;
1024     ar << m_strArtistSort;
1025     ar << m_strArtistDesc;
1026     ar << m_strAlbum;
1027     ar << m_albumArtist;
1028     ar << m_strAlbumArtistDesc;
1029     ar << m_genre;
1030     ar << m_iDuration;
1031     ar << m_iTrack;
1032     ar << m_bLoaded;
1033     ar << m_strReleaseDate;
1034     ar << m_strOriginalDate;
1035     ar << m_strMusicBrainzTrackID;
1036     ar << m_musicBrainzArtistID;
1037     ar << m_strMusicBrainzAlbumID;
1038     ar << m_strMusicBrainzReleaseGroupID;
1039     ar << m_musicBrainzAlbumArtistID;
1040     ar << m_strDiscSubtitle;
1041     ar << m_bBoxset;
1042     ar << m_iDiscTotal;
1043     ar << m_strMusicBrainzReleaseType;
1044     ar << m_lastPlayed;
1045     ar << m_dateAdded;
1046     ar << m_strComment;
1047     ar << (int)m_musicRoles.size();
1048     for (const auto& credit : m_musicRoles)
1049     {
1050       ar << credit.GetRoleId();
1051       ar << credit.GetRoleDesc();
1052       ar << credit.GetArtist();
1053       ar << credit.GetArtistId();
1054     }
1055     ar << m_strMood;
1056     ar << m_strRecordLabel;
1057     ar << m_Rating;
1058     ar << m_Userrating;
1059     ar << m_Votes;
1060     ar << m_iTimesPlayed;
1061     ar << m_iAlbumId;
1062     ar << m_iDbId;
1063     ar << m_type;
1064     ar << m_strReleaseStatus;
1065     ar << m_strLyrics;
1066     ar << m_bCompilation;
1067     ar << m_listeners;
1068     ar << m_coverArt;
1069     ar << m_cuesheet;
1070     ar << static_cast<int>(m_albumReleaseType);
1071     ar << m_iBPM;
1072     ar << m_samplerate;
1073     ar << m_bitrate;
1074     ar << m_channels;
1075   }
1076   else
1077   {
1078     ar >> m_strURL;
1079     ar >> m_strTitle;
1080     ar >> m_artist;
1081     ar >> m_strArtistSort;
1082     ar >> m_strArtistDesc;
1083     ar >> m_strAlbum;
1084     ar >> m_albumArtist;
1085     ar >> m_strAlbumArtistDesc;
1086     ar >> m_genre;
1087     ar >> m_iDuration;
1088     ar >> m_iTrack;
1089     ar >> m_bLoaded;
1090     ar >> m_strReleaseDate;
1091     ar >> m_strOriginalDate;
1092     ar >> m_strMusicBrainzTrackID;
1093     ar >> m_musicBrainzArtistID;
1094     ar >> m_strMusicBrainzAlbumID;
1095     ar >> m_strMusicBrainzReleaseGroupID;
1096     ar >> m_musicBrainzAlbumArtistID;
1097     ar >> m_strDiscSubtitle;
1098     ar >> m_bBoxset;
1099     ar >> m_iDiscTotal;
1100     ar >> m_strMusicBrainzReleaseType;
1101     ar >> m_lastPlayed;
1102     ar >> m_dateAdded;
1103     ar >> m_strComment;
1104     int iMusicRolesSize;
1105     ar >> iMusicRolesSize;
1106     m_musicRoles.reserve(iMusicRolesSize);
1107     for (int i = 0; i < iMusicRolesSize; ++i)
1108     {
1109       int idRole;
1110       int idArtist;
1111       std::string strArtist;
1112       std::string strRole;
1113       ar >> idRole;
1114       ar >> strRole;
1115       ar >> strArtist;
1116       ar >> idArtist;
1117       m_musicRoles.emplace_back(idRole, strRole, strArtist, idArtist);
1118     }
1119     ar >> m_strMood;
1120     ar >> m_strRecordLabel;
1121     ar >> m_Rating;
1122     ar >> m_Userrating;
1123     ar >> m_Votes;
1124     ar >> m_iTimesPlayed;
1125     ar >> m_iAlbumId;
1126     ar >> m_iDbId;
1127     ar >> m_type;
1128     ar >> m_strReleaseStatus;
1129     ar >> m_strLyrics;
1130     ar >> m_bCompilation;
1131     ar >> m_listeners;
1132     ar >> m_coverArt;
1133     ar >> m_cuesheet;
1134 
1135     int albumReleaseType;
1136     ar >> albumReleaseType;
1137     m_albumReleaseType = static_cast<CAlbum::ReleaseType>(albumReleaseType);
1138     ar >> m_iBPM;
1139     ar >> m_samplerate;
1140     ar >> m_bitrate;
1141     ar >> m_channels;
1142   }
1143 }
1144 
Clear()1145 void CMusicInfoTag::Clear()
1146 {
1147   m_strURL.clear();
1148   m_artist.clear();
1149   m_strArtistSort.clear();
1150   m_strComposerSort.clear();
1151   m_strAlbum.clear();
1152   m_albumArtist.clear();
1153   m_genre.clear();
1154   m_strTitle.clear();
1155   m_strMusicBrainzTrackID.clear();
1156   m_musicBrainzArtistID.clear();
1157   m_strMusicBrainzAlbumID.clear();
1158   m_strMusicBrainzReleaseGroupID.clear();
1159   m_musicBrainzAlbumArtistID.clear();
1160   m_strMusicBrainzReleaseType.clear();
1161   m_musicRoles.clear();
1162   m_iDuration = 0;
1163   m_iTrack = 0;
1164   m_bLoaded = false;
1165   m_lastPlayed.Reset();
1166   m_dateAdded.Reset();
1167   m_dateNew.Reset();
1168   m_dateUpdated.Reset();
1169   m_bCompilation = false;
1170   m_bBoxset = false;
1171   m_strDiscSubtitle.clear();
1172   m_strComment.clear();
1173   m_strMood.clear();
1174   m_strRecordLabel.clear();
1175   m_cuesheet.clear();
1176   m_iDbId = -1;
1177   m_type.clear();
1178   m_strReleaseStatus.clear();
1179   m_iTimesPlayed = 0;
1180   m_strReleaseDate.clear();
1181   m_strOriginalDate.clear();
1182   m_iAlbumId = -1;
1183   m_coverArt.Clear();
1184   m_replayGain = ReplayGain();
1185   m_albumReleaseType = CAlbum::Album;
1186   m_listeners = 0;
1187   m_Rating = 0;
1188   m_Userrating = 0;
1189   m_Votes = 0;
1190   m_iDiscTotal = 0;
1191   m_iBPM = 0;
1192   m_samplerate = 0;
1193   m_bitrate = 0;
1194   m_channels = 0;
1195   m_stationName.clear();
1196   m_stationArt.clear();
1197 }
1198 
AppendArtist(const std::string & artist)1199 void CMusicInfoTag::AppendArtist(const std::string &artist)
1200 {
1201   for (unsigned int index = 0; index < m_artist.size(); index++)
1202   {
1203     if (StringUtils::EqualsNoCase(artist, m_artist.at(index)))
1204       return;
1205   }
1206 
1207   m_artist.push_back(artist);
1208 }
1209 
AppendAlbumArtist(const std::string & albumArtist)1210 void CMusicInfoTag::AppendAlbumArtist(const std::string &albumArtist)
1211 {
1212   for (unsigned int index = 0; index < m_albumArtist.size(); index++)
1213   {
1214     if (StringUtils::EqualsNoCase(albumArtist, m_albumArtist.at(index)))
1215       return;
1216   }
1217 
1218   m_albumArtist.push_back(albumArtist);
1219 }
1220 
AppendGenre(const std::string & genre)1221 void CMusicInfoTag::AppendGenre(const std::string &genre)
1222 {
1223   for (unsigned int index = 0; index < m_genre.size(); index++)
1224   {
1225     if (StringUtils::EqualsNoCase(genre, m_genre.at(index)))
1226       return;
1227   }
1228 
1229   m_genre.push_back(genre);
1230 }
1231 
AddArtistRole(const std::string & Role,const std::string & strArtist)1232 void CMusicInfoTag::AddArtistRole(const std::string& Role, const std::string& strArtist)
1233 {
1234   if (!strArtist.empty() && !Role.empty())
1235     AddArtistRole(Role, StringUtils::Split(strArtist, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator));
1236 }
1237 
AddArtistRole(const std::string & Role,const std::vector<std::string> & artists)1238 void CMusicInfoTag::AddArtistRole(const std::string& Role, const std::vector<std::string>& artists)
1239 {
1240   for (unsigned int index = 0; index < artists.size(); index++)
1241   {
1242     CMusicRole ArtistCredit(Role, Trim(artists.at(index)));
1243     //Prevent duplicate entries
1244     auto credit = find(m_musicRoles.begin(), m_musicRoles.end(), ArtistCredit);
1245     if (credit == m_musicRoles.end())
1246       m_musicRoles.push_back(ArtistCredit);
1247   }
1248 }
1249 
AppendArtistRole(const CMusicRole & ArtistRole)1250 void CMusicInfoTag::AppendArtistRole(const CMusicRole& ArtistRole)
1251 {
1252   //Append contributor, no check for duplicates as from database
1253   m_musicRoles.push_back(ArtistRole);
1254 }
1255 
GetArtistStringForRole(const std::string & strRole) const1256 const std::string CMusicInfoTag::GetArtistStringForRole(const std::string& strRole) const
1257 {
1258   std::vector<std::string> artistvector;
1259   for (const auto& credit : m_musicRoles)
1260   {
1261     if (StringUtils::EqualsNoCase(credit.GetRoleDesc(), strRole))
1262       artistvector.push_back(credit.GetArtist());
1263   }
1264   return StringUtils::Join(artistvector, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator);
1265 }
1266 
GetContributorsText() const1267 const std::string CMusicInfoTag::GetContributorsText() const
1268 {
1269   std::string strLabel;
1270   for (const auto& credit : m_musicRoles)
1271   {
1272     strLabel += StringUtils::Format("%s\n", credit.GetArtist().c_str());
1273   }
1274   return StringUtils::TrimRight(strLabel, "\n");
1275 }
1276 
GetContributorsAndRolesText() const1277 const std::string CMusicInfoTag::GetContributorsAndRolesText() const
1278 {
1279   std::string strLabel;
1280   for (const auto& credit : m_musicRoles)
1281   {
1282     strLabel +=
1283         StringUtils::Format("%s - %s\n", credit.GetRoleDesc().c_str(), credit.GetArtist().c_str());
1284   }
1285   return StringUtils::TrimRight(strLabel, "\n");
1286 }
1287 
1288 
GetContributors() const1289 const VECMUSICROLES &CMusicInfoTag::GetContributors()  const
1290 {
1291   return m_musicRoles;
1292 }
1293 
SetContributors(const VECMUSICROLES & contributors)1294 void CMusicInfoTag::SetContributors(const VECMUSICROLES& contributors)
1295 {
1296   m_musicRoles = contributors;
1297 }
1298 
Trim(const std::string & value) const1299 std::string CMusicInfoTag::Trim(const std::string &value) const
1300 {
1301   std::string trimmedValue(value);
1302   StringUtils::TrimLeft(trimmedValue, " ");
1303   StringUtils::TrimRight(trimmedValue, " \n\r");
1304   return trimmedValue;
1305 }
1306