[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / interfaces / AnnouncementManager.cpp
blob26836829f4307bd60abef57733b080197ed78f11
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 "AnnouncementManager.h"
11 #include "FileItem.h"
12 #include "music/MusicDatabase.h"
13 #include "music/tags/MusicInfoTag.h"
14 #include "playlists/PlayListTypes.h"
15 #include "pvr/channels/PVRChannel.h"
16 #include "threads/SingleLock.h"
17 #include "utils/StringUtils.h"
18 #include "utils/Variant.h"
19 #include "utils/log.h"
20 #include "video/VideoDatabase.h"
21 #include "video/VideoFileItemClassify.h"
23 #include <memory>
24 #include <mutex>
26 #define LOOKUP_PROPERTY "database-lookup"
28 using namespace ANNOUNCEMENT;
29 using namespace KODI;
31 const std::string CAnnouncementManager::ANNOUNCEMENT_SENDER = "xbmc";
33 CAnnouncementManager::CAnnouncementManager() : CThread("Announce")
37 CAnnouncementManager::~CAnnouncementManager()
39 Deinitialize();
42 void CAnnouncementManager::Start()
44 Create();
47 void CAnnouncementManager::Deinitialize()
49 m_bStop = true;
50 m_queueEvent.Set();
51 StopThread();
52 std::unique_lock<CCriticalSection> lock(m_announcersCritSection);
53 m_announcers.clear();
56 void CAnnouncementManager::AddAnnouncer(IAnnouncer *listener)
58 if (!listener)
59 return;
61 std::unique_lock<CCriticalSection> lock(m_announcersCritSection);
62 m_announcers.push_back(listener);
65 void CAnnouncementManager::RemoveAnnouncer(IAnnouncer *listener)
67 if (!listener)
68 return;
70 std::unique_lock<CCriticalSection> lock(m_announcersCritSection);
71 for (unsigned int i = 0; i < m_announcers.size(); i++)
73 if (m_announcers[i] == listener)
75 m_announcers.erase(m_announcers.begin() + i);
76 return;
81 void CAnnouncementManager::Announce(AnnouncementFlag flag, const std::string& message)
83 CVariant data;
84 Announce(flag, ANNOUNCEMENT_SENDER, message, CFileItemPtr(), data);
87 void CAnnouncementManager::Announce(AnnouncementFlag flag,
88 const std::string& message,
89 const CVariant& data)
91 Announce(flag, ANNOUNCEMENT_SENDER, message, CFileItemPtr(), data);
94 void CAnnouncementManager::Announce(AnnouncementFlag flag,
95 const std::string& message,
96 const std::shared_ptr<const CFileItem>& item)
98 CVariant data;
99 Announce(flag, ANNOUNCEMENT_SENDER, message, item, data);
102 void CAnnouncementManager::Announce(AnnouncementFlag flag,
103 const std::string& message,
104 const std::shared_ptr<const CFileItem>& item,
105 const CVariant& data)
107 Announce(flag, ANNOUNCEMENT_SENDER, message, item, data);
111 void CAnnouncementManager::Announce(AnnouncementFlag flag,
112 const std::string& sender,
113 const std::string& message)
115 CVariant data;
116 Announce(flag, sender, message, CFileItemPtr(), data);
119 void CAnnouncementManager::Announce(AnnouncementFlag flag,
120 const std::string& sender,
121 const std::string& message,
122 const CVariant& data)
124 Announce(flag, sender, message, CFileItemPtr(), data);
127 void CAnnouncementManager::Announce(AnnouncementFlag flag,
128 const std::string& sender,
129 const std::string& message,
130 const std::shared_ptr<const CFileItem>& item,
131 const CVariant& data)
133 CAnnounceData announcement;
134 announcement.flag = flag;
135 announcement.sender = sender;
136 announcement.message = message;
137 announcement.data = data;
139 if (item != nullptr)
140 announcement.item = std::make_shared<CFileItem>(*item);
143 std::unique_lock<CCriticalSection> lock(m_queueCritSection);
144 m_announcementQueue.push_back(announcement);
146 m_queueEvent.Set();
149 void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag,
150 const std::string& sender,
151 const std::string& message,
152 const CVariant& data)
154 CLog::Log(LOGDEBUG, LOGANNOUNCE, "CAnnouncementManager - Announcement: {} from {}", message, sender);
156 std::unique_lock<CCriticalSection> lock(m_announcersCritSection);
158 // Make a copy of announcers. They may be removed or even remove themselves during execution of IAnnouncer::Announce()!
160 std::vector<IAnnouncer *> announcers(m_announcers);
161 for (unsigned int i = 0; i < announcers.size(); i++)
162 announcers[i]->Announce(flag, sender, message, data);
165 void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag,
166 const std::string& sender,
167 const std::string& message,
168 const std::shared_ptr<CFileItem>& item,
169 const CVariant& data)
171 if (item == nullptr)
173 DoAnnounce(flag, sender, message, data);
174 return;
177 // Extract db id of item
178 CVariant object = data.isNull() || data.isObject() ? data : CVariant::VariantTypeObject;
179 std::string type;
180 int id = 0;
182 if(item->HasPVRChannelInfoTag())
184 const std::shared_ptr<PVR::CPVRChannel> channel(item->GetPVRChannelInfoTag());
185 id = channel->ChannelID();
186 type = "channel";
188 object["item"]["title"] = channel->ChannelName();
189 object["item"]["channeltype"] = channel->IsRadio() ? "radio" : "tv";
191 if (data.isMember("player") && data["player"].isMember("playerid"))
193 object["player"]["playerid"] = channel->IsRadio()
194 ? static_cast<int>(PLAYLIST::Id::TYPE_MUSIC)
195 : static_cast<int>(PLAYLIST::Id::TYPE_VIDEO);
198 else if (item->HasVideoInfoTag() && !item->HasPVRRecordingInfoTag())
200 id = item->GetVideoInfoTag()->m_iDbId;
202 //! @todo Can be removed once this is properly handled when starting playback of a file
203 if (id <= 0 && !item->GetPath().empty() &&
204 (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean()))
206 CVideoDatabase videodatabase;
207 if (videodatabase.Open())
209 std::string path = item->GetPath();
210 std::string videoInfoTagPath(item->GetVideoInfoTag()->m_strFileNameAndPath);
211 if (StringUtils::StartsWith(videoInfoTagPath, "removable://"))
212 path = videoInfoTagPath;
213 if (videodatabase.LoadVideoInfo(path, *item->GetVideoInfoTag(), VideoDbDetailsNone))
214 id = item->GetVideoInfoTag()->m_iDbId;
216 videodatabase.Close();
220 if (!item->GetVideoInfoTag()->m_type.empty())
221 type = item->GetVideoInfoTag()->m_type;
222 else
223 CVideoDatabase::VideoContentTypeToString(item->GetVideoContentType(), type);
225 if (id <= 0)
227 //! @todo Can be removed once this is properly handled when starting playback of a file
228 item->SetProperty(LOOKUP_PROPERTY, false);
230 std::string title = item->GetVideoInfoTag()->m_strTitle;
231 if (title.empty())
232 title = item->GetLabel();
233 object["item"]["title"] = title;
235 switch (item->GetVideoContentType())
237 case VideoDbContentType::MOVIES:
238 if (item->GetVideoInfoTag()->HasYear())
239 object["item"]["year"] = item->GetVideoInfoTag()->GetYear();
240 break;
241 case VideoDbContentType::EPISODES:
242 if (item->GetVideoInfoTag()->m_iEpisode >= 0)
243 object["item"]["episode"] = item->GetVideoInfoTag()->m_iEpisode;
244 if (item->GetVideoInfoTag()->m_iSeason >= 0)
245 object["item"]["season"] = item->GetVideoInfoTag()->m_iSeason;
246 if (!item->GetVideoInfoTag()->m_strShowTitle.empty())
247 object["item"]["showtitle"] = item->GetVideoInfoTag()->m_strShowTitle;
248 break;
249 case VideoDbContentType::MUSICVIDEOS:
250 if (!item->GetVideoInfoTag()->m_strAlbum.empty())
251 object["item"]["album"] = item->GetVideoInfoTag()->m_strAlbum;
252 if (!item->GetVideoInfoTag()->m_artist.empty())
253 object["item"]["artist"] = StringUtils::Join(item->GetVideoInfoTag()->m_artist, " / ");
254 break;
255 default:
256 break;
260 else if (item->HasMusicInfoTag())
262 id = item->GetMusicInfoTag()->GetDatabaseId();
263 type = MediaTypeSong;
265 //! @todo Can be removed once this is properly handled when starting playback of a file
266 if (id <= 0 && !item->GetPath().empty() &&
267 (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean()))
269 CMusicDatabase musicdatabase;
270 if (musicdatabase.Open())
272 CSong song;
273 if (musicdatabase.GetSongByFileName(item->GetPath(), song, item->GetStartOffset()))
275 item->GetMusicInfoTag()->SetSong(song);
276 id = item->GetMusicInfoTag()->GetDatabaseId();
279 musicdatabase.Close();
283 if (id <= 0)
285 //! @todo Can be removed once this is properly handled when starting playback of a file
286 item->SetProperty(LOOKUP_PROPERTY, false);
288 std::string title = item->GetMusicInfoTag()->GetTitle();
289 if (title.empty())
290 title = item->GetLabel();
291 object["item"]["title"] = title;
293 if (item->GetMusicInfoTag()->GetTrackNumber() > 0)
294 object["item"]["track"] = item->GetMusicInfoTag()->GetTrackNumber();
295 if (!item->GetMusicInfoTag()->GetAlbum().empty())
296 object["item"]["album"] = item->GetMusicInfoTag()->GetAlbum();
297 if (!item->GetMusicInfoTag()->GetArtist().empty())
298 object["item"]["artist"] = item->GetMusicInfoTag()->GetArtist();
301 else if (VIDEO::IsVideo(*item))
303 // video item but has no video info tag.
304 type = "movie";
305 object["item"]["title"] = item->GetLabel();
307 else if (item->HasPictureInfoTag())
309 type = "picture";
310 object["item"]["file"] = item->GetPath();
312 else
313 type = "unknown";
315 object["item"]["type"] = type;
316 if (id > 0)
317 object["item"]["id"] = id;
319 DoAnnounce(flag, sender, message, object);
322 void CAnnouncementManager::Process()
324 SetPriority(ThreadPriority::LOWEST);
326 while (!m_bStop)
328 std::unique_lock<CCriticalSection> lock(m_queueCritSection);
329 if (!m_announcementQueue.empty())
331 auto announcement = m_announcementQueue.front();
332 m_announcementQueue.pop_front();
334 CSingleExit ex(m_queueCritSection);
335 DoAnnounce(announcement.flag, announcement.sender, announcement.message, announcement.item,
336 announcement.data);
339 else
341 CSingleExit ex(m_queueCritSection);
342 m_queueEvent.Wait();