Merge pull request #4857 from t-nelson/Gotham_13.2_backports
[vuplus_xbmc] / xbmc / music / Song.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 #include "Song.h"
22 #include "music/tags/MusicInfoTag.h"
23 #include "utils/Variant.h"
24 #include "FileItem.h"
25 #include "settings/AdvancedSettings.h"
26 #include "utils/StringUtils.h"
27
28 using namespace std;
29 using namespace MUSIC_INFO;
30
31 CSong::CSong(CFileItem& item)
32 {
33   CMusicInfoTag& tag = *item.GetMusicInfoTag();
34   SYSTEMTIME stTime;
35   tag.GetReleaseDate(stTime);
36   strTitle = tag.GetTitle();
37   genre = tag.GetGenre();
38   artist = tag.GetArtist();
39   if (!tag.GetMusicBrainzArtistID().empty())
40   { // have musicbrainz artist info, so use it
41     for (size_t i = 0; i < tag.GetMusicBrainzArtistID().size(); i++)
42     {
43       CStdString artistId = tag.GetMusicBrainzArtistID()[i];
44       CStdString artistName;
45       /*
46        We try and get the corresponding artist name from the album artist tag.
47        We match on the same index, and if that fails just use the first name we have.
48        */
49       if (!artist.empty())
50         artistName = (i < artist.size()) ? artist[i] : artist[0];
51       if (artistName.empty())
52         artistName = artistId;
53       CStdString strJoinPhrase = (i == tag.GetMusicBrainzArtistID().size()-1) ? "" : g_advancedSettings.m_musicItemSeparator;
54       CArtistCredit artistCredit(artistName, artistId, strJoinPhrase);
55       artistCredits.push_back(artistCredit);
56     }
57   }
58   else
59   { // no musicbrainz info, so fill in directly
60     for (vector<string>::const_iterator it = tag.GetArtist().begin(); it != tag.GetArtist().end(); ++it)
61     {
62       CStdString strJoinPhrase = (it == --tag.GetArtist().end() ? "" : g_advancedSettings.m_musicItemSeparator);
63       CArtistCredit artistCredit(*it, "", strJoinPhrase);
64       artistCredits.push_back(artistCredit);
65     }
66   }
67   strAlbum = tag.GetAlbum();
68   albumArtist = tag.GetAlbumArtist();
69   strMusicBrainzTrackID = tag.GetMusicBrainzTrackID();
70   strComment = tag.GetComment();
71   rating = tag.GetRating();
72   iYear = stTime.wYear;
73   iTrack = tag.GetTrackAndDiskNumber();
74   iDuration = tag.GetDuration();
75   bCompilation = tag.GetCompilation();
76   embeddedArt = tag.GetCoverArtInfo();
77   strFileName = tag.GetURL().empty() ? item.GetPath() : tag.GetURL();
78   strThumb = item.GetUserMusicThumb(true);
79   iStartOffset = item.m_lStartOffset;
80   iEndOffset = item.m_lEndOffset;
81   idSong = -1;
82   iTimesPlayed = 0;
83   iKaraokeNumber = 0;
84   iKaraokeDelay = 0;         //! Karaoke song lyrics-music delay in 1/10 seconds.
85   idAlbum = -1;
86 }
87
88 CSong::CSong()
89 {
90   Clear();
91 }
92
93 void CSong::MergeScrapedSong(const CSong& source, bool override)
94 {
95   if ((override && !source.strTitle.empty()) || strTitle.empty())
96     strTitle = source.strTitle;
97   if ((override && source.iTrack != 0) || iTrack == 0)
98     iTrack = source.iTrack;
99   // artist = source.artist; // artist is read-only from the database
100   if (override)
101     artistCredits = source.artistCredits;
102   else if (source.artistCredits.size() > artistCredits.size())
103     artistCredits.insert(artistCredits.end(), source.artistCredits.begin()+artistCredits.size(), source.artistCredits.end());
104 }
105
106 void CSong::Serialize(CVariant& value) const
107 {
108   value["filename"] = strFileName;
109   value["title"] = strTitle;
110   value["artist"] = artist;
111   value["album"] = strAlbum;
112   value["albumartist"] = albumArtist;
113   value["genre"] = genre;
114   value["duration"] = iDuration;
115   value["track"] = iTrack;
116   value["year"] = iYear;
117   value["musicbrainztrackid"] = strMusicBrainzTrackID;
118   value["comment"] = strComment;
119   value["rating"] = rating;
120   value["timesplayed"] = iTimesPlayed;
121   value["lastplayed"] = lastPlayed.IsValid() ? lastPlayed.GetAsDBDateTime() : "";
122   value["karaokenumber"] = (int64_t) iKaraokeNumber;
123   value["albumid"] = idAlbum;
124 }
125
126 void CSong::Clear()
127 {
128   strFileName.clear();
129   strTitle.clear();
130   artist.clear();
131   strAlbum.clear();
132   albumArtist.clear();
133   genre.clear();
134   strThumb.clear();
135   strMusicBrainzTrackID.clear();
136   strComment.clear();
137   rating = '0';
138   iTrack = 0;
139   iDuration = 0;
140   iYear = 0;
141   iStartOffset = 0;
142   iEndOffset = 0;
143   idSong = -1;
144   iTimesPlayed = 0;
145   lastPlayed.Reset();
146   iKaraokeNumber = 0;
147   strKaraokeLyrEncoding.clear();
148   iKaraokeDelay = 0;
149   idAlbum = -1;
150   bCompilation = false;
151   embeddedArt.clear();
152 }
153
154 bool CSong::HasArt() const
155 {
156   if (!strThumb.empty()) return true;
157   if (!embeddedArt.empty()) return true;
158   return false;
159 }
160
161 bool CSong::ArtMatches(const CSong &right) const
162 {
163   return (right.strThumb == strThumb &&
164           embeddedArt.matches(right.embeddedArt));
165 }