2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "MusicInfoTag.h"
22 #include "music/Album.h"
23 #include "music/Artist.h"
24 #include "utils/StringUtils.h"
25 #include "settings/AdvancedSettings.h"
26 #include "utils/Variant.h"
28 using namespace MUSIC_INFO;
30 EmbeddedArtInfo::EmbeddedArtInfo(size_t siz, const std::string &mim)
35 void EmbeddedArtInfo::set(size_t siz, const std::string &mim)
41 void EmbeddedArtInfo::clear()
47 bool EmbeddedArtInfo::empty() const
52 bool EmbeddedArtInfo::matches(const EmbeddedArtInfo &right) const
54 return (size == right.size &&
58 EmbeddedArt::EmbeddedArt(const uint8_t *dat, size_t siz, const std::string &mim)
63 void EmbeddedArt::set(const uint8_t *dat, size_t siz, const std::string &mim)
65 EmbeddedArtInfo::set(siz, mim);
67 memcpy(&data[0], dat, siz);
70 CMusicInfoTag::CMusicInfoTag(void)
75 CMusicInfoTag::CMusicInfoTag(const CMusicInfoTag& tag)
80 CMusicInfoTag::~CMusicInfoTag()
83 const CMusicInfoTag& CMusicInfoTag::operator =(const CMusicInfoTag& tag)
85 if (this == &tag) return * this;
87 m_strURL = tag.m_strURL;
88 m_artist = tag.m_artist;
89 m_albumArtist = tag.m_albumArtist;
90 m_strAlbum = tag.m_strAlbum;
91 m_genre = tag.m_genre;
92 m_strTitle = tag.m_strTitle;
93 m_strMusicBrainzTrackID = tag.m_strMusicBrainzTrackID;
94 m_musicBrainzArtistID = tag.m_musicBrainzArtistID;
95 m_strMusicBrainzAlbumID = tag.m_strMusicBrainzAlbumID;
96 m_musicBrainzAlbumArtistID = tag.m_musicBrainzAlbumArtistID;
97 m_strMusicBrainzTRMID = tag.m_strMusicBrainzTRMID;
98 m_strComment = tag.m_strComment;
99 m_strLyrics = tag.m_strLyrics;
100 m_lastPlayed = tag.m_lastPlayed;
101 m_bCompilation = tag.m_bCompilation;
102 m_iDuration = tag.m_iDuration;
103 m_iTrack = tag.m_iTrack;
104 m_bLoaded = tag.m_bLoaded;
105 m_rating = tag.m_rating;
106 m_listeners = tag.m_listeners;
107 m_iTimesPlayed = tag.m_iTimesPlayed;
108 m_iDbId = tag.m_iDbId;
110 m_iAlbumId = tag.m_iAlbumId;
111 m_iTrackGain = tag.m_iTrackGain;
112 m_iAlbumGain = tag.m_iAlbumGain;
113 m_fTrackPeak = tag.m_fTrackPeak;
114 m_fAlbumPeak = tag.m_fAlbumPeak;
115 m_iHasGainInfo = tag.m_iHasGainInfo;
117 memcpy(&m_dwReleaseDate, &tag.m_dwReleaseDate, sizeof(m_dwReleaseDate) );
118 m_coverArt = tag.m_coverArt;
122 bool CMusicInfoTag::operator !=(const CMusicInfoTag& tag) const
124 if (this == &tag) return false;
125 if (m_strURL != tag.m_strURL) return true;
126 if (m_strTitle != tag.m_strTitle) return true;
127 if (m_bCompilation != tag.m_bCompilation) return true;
128 if (m_artist != tag.m_artist) return true;
129 if (m_albumArtist != tag.m_albumArtist) return true;
130 if (m_strAlbum != tag.m_strAlbum) return true;
131 if (m_iDuration != tag.m_iDuration) return true;
132 if (m_iTrack != tag.m_iTrack) return true;
136 int CMusicInfoTag::GetTrackNumber() const
138 return (m_iTrack & 0xffff);
141 int CMusicInfoTag::GetDiscNumber() const
143 return (m_iTrack >> 16);
146 int CMusicInfoTag::GetTrackAndDiskNumber() const
151 int CMusicInfoTag::GetDuration() const
156 const CStdString& CMusicInfoTag::GetTitle() const
161 const CStdString& CMusicInfoTag::GetURL() const
166 const std::vector<std::string>& CMusicInfoTag::GetArtist() const
171 const CStdString& CMusicInfoTag::GetAlbum() const
176 int CMusicInfoTag::GetAlbumId() const
181 const std::vector<std::string>& CMusicInfoTag::GetAlbumArtist() const
183 return m_albumArtist;
186 const std::vector<std::string>& CMusicInfoTag::GetGenre() const
191 void CMusicInfoTag::GetReleaseDate(SYSTEMTIME& dateTime) const
193 memcpy(&dateTime, &m_dwReleaseDate, sizeof(m_dwReleaseDate) );
196 int CMusicInfoTag::GetYear() const
198 return m_dwReleaseDate.wYear;
201 int CMusicInfoTag::GetDatabaseId() const
206 const std::string &CMusicInfoTag::GetType() const
211 CStdString CMusicInfoTag::GetYearString() const
213 return m_dwReleaseDate.wYear ? StringUtils::Format("%i", m_dwReleaseDate.wYear) : StringUtils::Empty;
216 const CStdString &CMusicInfoTag::GetComment() const
221 const CStdString &CMusicInfoTag::GetLyrics() const
226 char CMusicInfoTag::GetRating() const
231 int CMusicInfoTag::GetListeners() const
236 int CMusicInfoTag::GetPlayCount() const
238 return m_iTimesPlayed;
241 const CDateTime &CMusicInfoTag::GetLastPlayed() const
246 bool CMusicInfoTag::GetCompilation() const
248 return m_bCompilation;
251 const EmbeddedArtInfo &CMusicInfoTag::GetCoverArtInfo() const
256 int CMusicInfoTag::GetReplayGainTrackGain() const
261 int CMusicInfoTag::GetReplayGainAlbumGain() const
266 float CMusicInfoTag::GetReplayGainTrackPeak() const
271 float CMusicInfoTag::GetReplayGainAlbumPeak() const
276 int CMusicInfoTag::HasReplayGainInfo() const
278 return m_iHasGainInfo;
281 void CMusicInfoTag::SetURL(const CStdString& strURL)
286 void CMusicInfoTag::SetTitle(const CStdString& strTitle)
288 m_strTitle = Trim(strTitle);
291 void CMusicInfoTag::SetArtist(const CStdString& strArtist)
293 if (!strArtist.empty())
294 SetArtist(StringUtils::Split(strArtist, g_advancedSettings.m_musicItemSeparator));
299 void CMusicInfoTag::SetArtist(const std::vector<std::string>& artists)
304 void CMusicInfoTag::SetAlbum(const CStdString& strAlbum)
306 m_strAlbum = Trim(strAlbum);
309 void CMusicInfoTag::SetAlbumId(const int iAlbumId)
311 m_iAlbumId = iAlbumId;
314 void CMusicInfoTag::SetAlbumArtist(const CStdString& strAlbumArtist)
316 if (!strAlbumArtist.empty())
317 SetAlbumArtist(StringUtils::Split(strAlbumArtist, g_advancedSettings.m_musicItemSeparator));
319 m_albumArtist.clear();
322 void CMusicInfoTag::SetAlbumArtist(const std::vector<std::string>& albumArtists)
324 m_albumArtist = albumArtists;
327 void CMusicInfoTag::SetGenre(const CStdString& strGenre)
329 if (!strGenre.empty())
330 SetGenre(StringUtils::Split(strGenre, g_advancedSettings.m_musicItemSeparator));
335 void CMusicInfoTag::SetGenre(const std::vector<std::string>& genres)
340 void CMusicInfoTag::SetYear(int year)
342 memset(&m_dwReleaseDate, 0, sizeof(m_dwReleaseDate) );
343 m_dwReleaseDate.wYear = year;
346 void CMusicInfoTag::SetDatabaseId(long id, const std::string &type)
352 void CMusicInfoTag::SetReleaseDate(SYSTEMTIME& dateTime)
354 memcpy(&m_dwReleaseDate, &dateTime, sizeof(m_dwReleaseDate) );
357 void CMusicInfoTag::SetTrackNumber(int iTrack)
359 m_iTrack = (m_iTrack & 0xffff0000) | (iTrack & 0xffff);
362 void CMusicInfoTag::SetPartOfSet(int iPartOfSet)
364 m_iTrack = (m_iTrack & 0xffff) | (iPartOfSet << 16);
367 void CMusicInfoTag::SetTrackAndDiskNumber(int iTrackAndDisc)
369 m_iTrack=iTrackAndDisc;
372 void CMusicInfoTag::SetDuration(int iSec)
377 void CMusicInfoTag::SetComment(const CStdString& comment)
379 m_strComment = comment;
382 void CMusicInfoTag::SetLyrics(const CStdString& lyrics)
384 m_strLyrics = lyrics;
387 void CMusicInfoTag::SetRating(char rating)
392 void CMusicInfoTag::SetListeners(int listeners)
394 m_listeners = listeners;
397 void CMusicInfoTag::SetPlayCount(int playcount)
399 m_iTimesPlayed = playcount;
402 void CMusicInfoTag::SetLastPlayed(const CStdString& lastplayed)
404 m_lastPlayed.SetFromDBDateTime(lastplayed);
407 void CMusicInfoTag::SetLastPlayed(const CDateTime& lastplayed)
409 m_lastPlayed = lastplayed;
412 void CMusicInfoTag::SetCompilation(bool compilation)
414 m_bCompilation = compilation;
417 void CMusicInfoTag::SetLoaded(bool bOnOff)
422 bool CMusicInfoTag::Loaded() const
427 const CStdString& CMusicInfoTag::GetMusicBrainzTrackID() const
429 return m_strMusicBrainzTrackID;
432 const std::vector<std::string>& CMusicInfoTag::GetMusicBrainzArtistID() const
434 return m_musicBrainzArtistID;
437 const CStdString& CMusicInfoTag::GetMusicBrainzAlbumID() const
439 return m_strMusicBrainzAlbumID;
442 const std::vector<std::string>& CMusicInfoTag::GetMusicBrainzAlbumArtistID() const
444 return m_musicBrainzAlbumArtistID;
447 const CStdString& CMusicInfoTag::GetMusicBrainzTRMID() const
449 return m_strMusicBrainzTRMID;
452 void CMusicInfoTag::SetMusicBrainzTrackID(const CStdString& strTrackID)
454 m_strMusicBrainzTrackID=strTrackID;
457 void CMusicInfoTag::SetMusicBrainzArtistID(const std::vector<std::string>& musicBrainzArtistId)
459 m_musicBrainzArtistID = musicBrainzArtistId;
462 void CMusicInfoTag::SetMusicBrainzAlbumID(const CStdString& strAlbumID)
464 m_strMusicBrainzAlbumID=strAlbumID;
467 void CMusicInfoTag::SetMusicBrainzAlbumArtistID(const std::vector<std::string>& musicBrainzAlbumArtistId)
469 m_musicBrainzAlbumArtistID = musicBrainzAlbumArtistId;
472 void CMusicInfoTag::SetMusicBrainzTRMID(const CStdString& strTRMID)
474 m_strMusicBrainzTRMID=strTRMID;
477 void CMusicInfoTag::SetCoverArtInfo(size_t size, const std::string &mimeType)
479 m_coverArt.set(size, mimeType);
482 void CMusicInfoTag::SetReplayGainTrackGain(int trackGain)
484 m_iTrackGain = trackGain;
485 m_iHasGainInfo |= REPLAY_GAIN_HAS_TRACK_INFO;
488 void CMusicInfoTag::SetReplayGainAlbumGain(int albumGain)
490 m_iAlbumGain = albumGain;
491 m_iHasGainInfo |= REPLAY_GAIN_HAS_ALBUM_INFO;
494 void CMusicInfoTag::SetReplayGainTrackPeak(float trackPeak)
496 m_fTrackPeak = trackPeak;
497 m_iHasGainInfo |= REPLAY_GAIN_HAS_TRACK_PEAK;
500 void CMusicInfoTag::SetReplayGainAlbumPeak(float albumPeak)
502 m_fAlbumPeak = albumPeak;
503 m_iHasGainInfo |= REPLAY_GAIN_HAS_ALBUM_PEAK;
506 void CMusicInfoTag::SetArtist(const CArtist& artist)
508 SetArtist(artist.strArtist);
509 SetAlbumArtist(artist.strArtist);
510 SetGenre(artist.genre);
511 m_iDbId = artist.idArtist;
516 void CMusicInfoTag::SetAlbum(const CAlbum& album)
518 SetArtist(album.artist);
519 SetAlbumId(album.idAlbum);
520 SetAlbum(album.strAlbum);
521 SetTitle(album.strAlbum);
522 SetAlbumArtist(album.artist);
523 SetGenre(album.genre);
524 SetRating('0' + album.iRating);
525 SetCompilation(album.bCompilation);
527 stTime.wYear = album.iYear;
528 SetReleaseDate(stTime);
529 m_iTimesPlayed = album.iTimesPlayed;
530 m_iDbId = album.idAlbum;
535 void CMusicInfoTag::SetSong(const CSong& song)
537 SetTitle(song.strTitle);
538 SetGenre(song.genre);
539 SetArtist(song.artist);
540 SetAlbum(song.strAlbum);
541 SetAlbumArtist(song.albumArtist);
542 SetMusicBrainzTrackID(song.strMusicBrainzTrackID);
543 SetComment(song.strComment);
544 SetPlayCount(song.iTimesPlayed);
545 SetLastPlayed(song.lastPlayed);
546 m_rating = song.rating;
547 m_strURL = song.strFileName;
549 stTime.wYear = song.iYear;
550 SetReleaseDate(stTime);
551 m_iTrack = song.iTrack;
552 m_iDuration = song.iDuration;
553 m_iDbId = song.idSong;
556 m_iTimesPlayed = song.iTimesPlayed;
557 m_iAlbumId = song.idAlbum;
560 void CMusicInfoTag::Serialize(CVariant& value) const
562 value["url"] = m_strURL;
563 value["title"] = m_strTitle;
564 if (m_type.compare("artist") == 0 && m_artist.size() == 1)
565 value["artist"] = m_artist[0];
567 value["artist"] = m_artist;
568 value["displayartist"] = StringUtils::Join(m_artist, g_advancedSettings.m_musicItemSeparator);
569 value["album"] = m_strAlbum;
570 value["albumartist"] = m_albumArtist;
571 value["genre"] = m_genre;
572 value["duration"] = m_iDuration;
573 value["track"] = GetTrackNumber();
574 value["disc"] = GetDiscNumber();
575 value["loaded"] = m_bLoaded;
576 value["year"] = m_dwReleaseDate.wYear;
577 value["musicbrainztrackid"] = m_strMusicBrainzTrackID;
578 value["musicbrainzartistid"] = StringUtils::Join(m_musicBrainzArtistID, " / ");
579 value["musicbrainzalbumid"] = m_strMusicBrainzAlbumID;
580 value["musicbrainzalbumartistid"] = StringUtils::Join(m_musicBrainzAlbumArtistID, " / ");
581 value["musicbrainztrmid"] = m_strMusicBrainzTRMID;
582 value["comment"] = m_strComment;
583 value["rating"] = (int)(m_rating - '0');
584 value["playcount"] = m_iTimesPlayed;
585 value["lastplayed"] = m_lastPlayed.IsValid() ? m_lastPlayed.GetAsDBDateTime() : StringUtils::EmptyString;
586 value["lyrics"] = m_strLyrics;
587 value["albumid"] = m_iAlbumId;
588 value["compilationartist"] = m_bCompilation;
591 void CMusicInfoTag::ToSortable(SortItem& sortable, Field field) const
595 case FieldTitle: sortable[FieldTitle] = m_strTitle; break;
596 case FieldArtist: sortable[FieldArtist] = m_artist; break;
597 case FieldAlbum: sortable[FieldAlbum] = m_strAlbum; break;
598 case FieldAlbumArtist: sortable[FieldAlbumArtist] = m_albumArtist; break;
599 case FieldGenre: sortable[FieldGenre] = m_genre; break;
600 case FieldTime: sortable[FieldTime] = m_iDuration; break;
601 case FieldTrackNumber: sortable[FieldTrackNumber] = m_iTrack; break;
602 case FieldYear: sortable[FieldYear] = m_dwReleaseDate.wYear; break;
603 case FieldComment: sortable[FieldComment] = m_strComment; break;
604 case FieldRating: sortable[FieldRating] = (float)(m_rating - '0'); break;
605 case FieldPlaycount: sortable[FieldPlaycount] = m_iTimesPlayed; break;
606 case FieldLastPlayed: sortable[FieldLastPlayed] = m_lastPlayed.IsValid() ? m_lastPlayed.GetAsDBDateTime() : StringUtils::EmptyString; break;
607 case FieldListeners: sortable[FieldListeners] = m_listeners; break;
608 case FieldId: sortable[FieldId] = (int64_t)m_iDbId; break;
613 void CMusicInfoTag::Archive(CArchive& ar)
626 ar << m_dwReleaseDate;
627 ar << m_strMusicBrainzTrackID;
628 ar << m_musicBrainzArtistID;
629 ar << m_strMusicBrainzAlbumID;
630 ar << m_musicBrainzAlbumArtistID;
631 ar << m_strMusicBrainzTRMID;
635 ar << m_iTimesPlayed;
640 ar << m_bCompilation;
654 ar >> m_dwReleaseDate;
655 ar >> m_strMusicBrainzTrackID;
656 ar >> m_musicBrainzArtistID;
657 ar >> m_strMusicBrainzAlbumID;
658 ar >> m_musicBrainzAlbumArtistID;
659 ar >> m_strMusicBrainzTRMID;
663 ar >> m_iTimesPlayed;
668 ar >> m_bCompilation;
673 void CMusicInfoTag::Clear()
678 m_albumArtist.clear();
681 m_strMusicBrainzTrackID.clear();
682 m_musicBrainzArtistID.clear();
683 m_strMusicBrainzAlbumID.clear();
684 m_musicBrainzAlbumArtistID.clear();
685 m_strMusicBrainzTRMID.clear();
689 m_lastPlayed.Reset();
690 m_bCompilation = false;
691 m_strComment.clear();
696 memset(&m_dwReleaseDate, 0, sizeof(m_dwReleaseDate) );
706 void CMusicInfoTag::AppendArtist(const CStdString &artist)
708 for (unsigned int index = 0; index < m_artist.size(); index++)
710 if (artist.Equals(m_artist.at(index).c_str()))
714 m_artist.push_back(artist);
717 void CMusicInfoTag::AppendAlbumArtist(const CStdString &albumArtist)
719 for (unsigned int index = 0; index < m_albumArtist.size(); index++)
721 if (albumArtist.Equals(m_albumArtist.at(index).c_str()))
725 m_albumArtist.push_back(albumArtist);
728 void CMusicInfoTag::AppendGenre(const CStdString &genre)
730 for (unsigned int index = 0; index < m_genre.size(); index++)
732 if (genre.Equals(m_genre.at(index).c_str()))
736 m_genre.push_back(genre);
739 CStdString CMusicInfoTag::Trim(const CStdString &value) const
741 CStdString trimmedValue(value);
742 trimmedValue.TrimLeft(' ');
743 trimmedValue.TrimRight(" \n\r");