[XAudio2] avoid leak + fix voice creation for closest match
[xbmc.git] / xbmc / music / Artist.cpp
blobc5626c58ebd0d98aada5a263ba818e019394649a
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "Artist.h"
11 #include "ServiceBroker.h"
12 #include "settings/AdvancedSettings.h"
13 #include "settings/SettingsComponent.h"
14 #include "utils/Fanart.h"
15 #include "utils/XMLUtils.h"
17 #include <algorithm>
19 void CArtist::MergeScrapedArtist(const CArtist& source, bool override /* = true */)
22 Initial scraping of artist information when the mbid is derived from tags is done directly
23 using that ID, otherwise the lookup is based on name and can mis-identify the artist
24 (many have same name). It is useful to store the scraped mbid, but we need to be
25 able to correct any mistakes. Hence a manual refresh of artist information uses either
26 the mbid is derived from tags or the artist name, not any previously scraped mbid.
28 A Musicbrainz artist ID derived from music file tags is always taken as accurate and so can
29 not be overwritten by a scraped value. When the artist does not already have an mbid or has
30 a previously scraped mbid, merge the new scraped value, flagging it as being from the
31 scraper rather than derived from music file tags.
33 if (!source.strMusicBrainzArtistID.empty() && (strMusicBrainzArtistID.empty() || bScrapedMBID))
35 strMusicBrainzArtistID = source.strMusicBrainzArtistID;
36 bScrapedMBID = true;
39 if ((override && !source.strArtist.empty()) || strArtist.empty())
40 strArtist = source.strArtist;
42 if ((override && !source.strSortName.empty()) || strSortName.empty())
43 strSortName = source.strSortName;
45 strType = source.strType;
46 strGender = source.strGender;
47 strDisambiguation = source.strDisambiguation;
48 genre = source.genre;
49 strBiography = source.strBiography;
50 styles = source.styles;
51 moods = source.moods;
52 instruments = source.instruments;
53 strBorn = source.strBorn;
54 strFormed = source.strFormed;
55 strDied = source.strDied;
56 strDisbanded = source.strDisbanded;
57 yearsActive = source.yearsActive;
59 thumbURL = source.thumbURL; // Available remote art
60 // Current artwork - thumb, fanart etc., to be stored in art table
61 if (!source.art.empty())
62 art = source.art;
64 discography = source.discography;
65 videolinks = source.videolinks;
69 bool CArtist::Load(const TiXmlElement *artist, bool append, bool prioritise)
71 if (!artist) return false;
72 if (!append)
73 Reset();
75 const std::string itemSeparator = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator;
77 XMLUtils::GetString(artist, "name", strArtist);
78 XMLUtils::GetString(artist, "musicBrainzArtistID", strMusicBrainzArtistID);
79 XMLUtils::GetString(artist, "sortname", strSortName);
80 XMLUtils::GetString(artist, "type", strType);
81 XMLUtils::GetString(artist, "gender", strGender);
82 XMLUtils::GetString(artist, "disambiguation", strDisambiguation);
83 XMLUtils::GetStringArray(artist, "genre", genre, prioritise, itemSeparator);
84 XMLUtils::GetStringArray(artist, "style", styles, prioritise, itemSeparator);
85 XMLUtils::GetStringArray(artist, "mood", moods, prioritise, itemSeparator);
86 XMLUtils::GetStringArray(artist, "yearsactive", yearsActive, prioritise, itemSeparator);
87 XMLUtils::GetStringArray(artist, "instruments", instruments, prioritise, itemSeparator);
89 XMLUtils::GetString(artist, "born", strBorn);
90 XMLUtils::GetString(artist, "formed", strFormed);
91 XMLUtils::GetString(artist, "biography", strBiography);
92 XMLUtils::GetString(artist, "died", strDied);
93 XMLUtils::GetString(artist, "disbanded", strDisbanded);
95 size_t iThumbCount = thumbURL.GetUrls().size();
96 std::string xmlAdd = thumbURL.GetData();
98 // Available artist thumbs
99 const TiXmlElement* thumb = artist->FirstChildElement("thumb");
100 while (thumb)
102 thumbURL.ParseAndAppendUrl(thumb);
103 if (prioritise)
105 std::string temp;
106 temp << *thumb;
107 xmlAdd = temp+xmlAdd;
109 thumb = thumb->NextSiblingElement("thumb");
111 // prefix thumbs from nfos
112 if (prioritise && iThumbCount && iThumbCount != thumbURL.GetUrls().size())
114 auto thumbUrls = thumbURL.GetUrls();
115 rotate(thumbUrls.begin(), thumbUrls.begin() + iThumbCount, thumbUrls.end());
116 thumbURL.SetUrls(thumbUrls);
117 thumbURL.SetData(xmlAdd);
120 // Discography
121 const TiXmlElement* node = artist->FirstChildElement("album");
122 if (node)
123 discography.clear();
124 while (node)
126 if (node->FirstChild())
128 CDiscoAlbum album;
129 XMLUtils::GetString(node, "title", album.strAlbum);
130 XMLUtils::GetString(node, "year", album.strYear);
131 XMLUtils::GetString(node, "musicbrainzreleasegroupid", album.strReleaseGroupMBID);
132 discography.push_back(album);
134 node = node->NextSiblingElement("album");
137 //song video links
138 const TiXmlElement* songurls = artist->FirstChildElement("videourl");
139 if (songurls)
140 videolinks.clear();
141 while (songurls)
143 if (songurls->FirstChild())
145 ArtistVideoLinks videoLink;
146 XMLUtils::GetString(songurls, "title", videoLink.title);
147 XMLUtils::GetString(songurls, "musicbrainztrackid", videoLink.mbTrackID);
148 XMLUtils::GetString(songurls, "url", videoLink.videoURL);
149 XMLUtils::GetString(songurls, "thumburl", videoLink.thumbURL);
150 videolinks.emplace_back(std::move(videoLink));
152 songurls = songurls->NextSiblingElement("videourl");
155 // Support old style <fanart></fanart> for backwards compatibility of old nfo files and scrapers
156 const TiXmlElement *fanart2 = artist->FirstChildElement("fanart");
157 if (fanart2)
159 CFanart fanart;
160 // we prefix to handle mixed-mode nfo's with fanart set
161 if (prioritise)
163 std::string temp;
164 temp << *fanart2;
165 fanart.m_xml = temp+fanart.m_xml;
167 else
168 fanart.m_xml << *fanart2;
169 fanart.Unpack();
170 // Append fanart to other image URLs
171 for (unsigned int i = 0; i < fanart.GetNumFanarts(); i++)
172 thumbURL.AddParsedUrl(fanart.GetImageURL(i), "fanart", fanart.GetPreviewURL(i));
175 // Current artwork - thumb, fanart etc. (the chosen art, not the lists of those available)
176 node = artist->FirstChildElement("art");
177 if (node)
179 const TiXmlNode *artdetailNode = node->FirstChild();
180 while (artdetailNode && artdetailNode->FirstChild())
182 art.insert(make_pair(artdetailNode->ValueStr(), artdetailNode->FirstChild()->ValueStr()));
183 artdetailNode = artdetailNode->NextSibling();
187 return true;
190 bool CArtist::Save(TiXmlNode *node, const std::string &tag, const std::string& strPath)
192 if (!node) return false;
194 // we start with a <tag> tag
195 TiXmlElement artistElement(tag.c_str());
196 TiXmlNode *artist = node->InsertEndChild(artistElement);
198 if (!artist) return false;
200 XMLUtils::SetString(artist, "name", strArtist);
201 XMLUtils::SetString(artist, "musicBrainzArtistID", strMusicBrainzArtistID);
202 XMLUtils::SetString(artist, "sortname", strSortName);
203 XMLUtils::SetString(artist, "type", strType);
204 XMLUtils::SetString(artist, "gender", strGender);
205 XMLUtils::SetString(artist, "disambiguation", strDisambiguation);
206 XMLUtils::SetStringArray(artist, "genre", genre);
207 XMLUtils::SetStringArray(artist, "style", styles);
208 XMLUtils::SetStringArray(artist, "mood", moods);
209 XMLUtils::SetStringArray(artist, "yearsactive", yearsActive);
210 XMLUtils::SetStringArray(artist, "instruments", instruments);
211 XMLUtils::SetString(artist, "born", strBorn);
212 XMLUtils::SetString(artist, "formed", strFormed);
213 XMLUtils::SetString(artist, "biography", strBiography);
214 XMLUtils::SetString(artist, "died", strDied);
215 XMLUtils::SetString(artist, "disbanded", strDisbanded);
216 // Available remote art
217 if (thumbURL.HasData())
219 CXBMCTinyXML doc;
220 doc.Parse(thumbURL.GetData());
221 const TiXmlNode* thumb = doc.FirstChild("thumb");
222 while (thumb)
224 artist->InsertEndChild(*thumb);
225 thumb = thumb->NextSibling("thumb");
228 XMLUtils::SetString(artist, "path", strPath);
230 // Discography
231 for (const auto& it : discography)
233 // add a <album> tag
234 TiXmlElement discoElement("album");
235 TiXmlNode* node = artist->InsertEndChild(discoElement);
236 XMLUtils::SetString(node, "title", it.strAlbum);
237 XMLUtils::SetString(node, "year", it.strYear);
238 XMLUtils::SetString(node, "musicbrainzreleasegroupid", it.strReleaseGroupMBID);
240 // song video links
241 for (const auto& it : videolinks)
243 TiXmlElement videolinkElement("videourl");
244 TiXmlNode* node = artist->InsertEndChild(videolinkElement);
245 XMLUtils::SetString(node, "title", it.title);
246 XMLUtils::SetString(node, "musicbrainztrackid", it.mbTrackID);
247 XMLUtils::SetString(node, "url", it.videoURL);
248 XMLUtils::SetString(node, "thumburl", it.thumbURL);
251 return true;
254 void CArtist::SetDateAdded(const std::string& strDateAdded)
256 dateAdded.SetFromDBDateTime(strDateAdded);
259 void CArtist::SetDateUpdated(const std::string& strDateUpdated)
261 dateUpdated.SetFromDBDateTime(strDateUpdated);
264 void CArtist::SetDateNew(const std::string& strDateNew)
266 dateNew.SetFromDBDateTime(strDateNew);