[Windows] Remove redundant DirectSound error codes
[xbmc.git] / xbmc / interfaces / AnnouncementManager.cpp
blob5aacb974c8c891e6e4873450a2c21d89f9d36d0f
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 return AddAnnouncer(listener, ANNOUNCE_ALL);
61 void CAnnouncementManager::AddAnnouncer(IAnnouncer* listener, int flagMask)
63 if (!listener)
64 return;
66 std::unique_lock<CCriticalSection> lock(m_announcersCritSection);
67 m_announcers.emplace(listener, flagMask);
70 void CAnnouncementManager::RemoveAnnouncer(IAnnouncer *listener)
72 if (!listener)
73 return;
75 std::unique_lock<CCriticalSection> lock(m_announcersCritSection);
76 m_announcers.erase(listener);
79 void CAnnouncementManager::Announce(AnnouncementFlag flag, const std::string& message)
81 CVariant data;
82 Announce(flag, ANNOUNCEMENT_SENDER, message, CFileItemPtr(), data);
85 void CAnnouncementManager::Announce(AnnouncementFlag flag,
86 const std::string& message,
87 const CVariant& data)
89 Announce(flag, ANNOUNCEMENT_SENDER, message, CFileItemPtr(), data);
92 void CAnnouncementManager::Announce(AnnouncementFlag flag,
93 const std::string& message,
94 const std::shared_ptr<const CFileItem>& item)
96 CVariant data;
97 Announce(flag, ANNOUNCEMENT_SENDER, message, item, data);
100 void CAnnouncementManager::Announce(AnnouncementFlag flag,
101 const std::string& message,
102 const std::shared_ptr<const CFileItem>& item,
103 const CVariant& data)
105 Announce(flag, ANNOUNCEMENT_SENDER, message, item, data);
109 void CAnnouncementManager::Announce(AnnouncementFlag flag,
110 const std::string& sender,
111 const std::string& message)
113 CVariant data;
114 Announce(flag, sender, message, CFileItemPtr(), data);
117 void CAnnouncementManager::Announce(AnnouncementFlag flag,
118 const std::string& sender,
119 const std::string& message,
120 const CVariant& data)
122 Announce(flag, sender, message, CFileItemPtr(), data);
125 void CAnnouncementManager::Announce(AnnouncementFlag flag,
126 const std::string& sender,
127 const std::string& message,
128 const std::shared_ptr<const CFileItem>& item,
129 const CVariant& data)
131 CAnnounceData announcement;
132 announcement.flag = flag;
133 announcement.sender = sender;
134 announcement.message = message;
135 announcement.data = data;
137 if (item != nullptr)
138 announcement.item = std::make_shared<CFileItem>(*item);
141 std::unique_lock<CCriticalSection> lock(m_queueCritSection);
142 m_announcementQueue.push_back(announcement);
144 m_queueEvent.Set();
147 void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag,
148 const std::string& sender,
149 const std::string& message,
150 const CVariant& data)
152 CLog::Log(LOGDEBUG, LOGANNOUNCE, "CAnnouncementManager - Announcement: {} from {}", message, sender);
154 std::unique_lock<CCriticalSection> lock(m_announcersCritSection);
156 // Make a copy of announcers. They may be removed or even remove themselves during execution of IAnnouncer::Announce()!
157 std::unordered_map<IAnnouncer*, int> announcers{m_announcers};
158 for (const auto& [announcer, flagMask] : announcers)
160 if (flag & flagMask)
162 announcer->Announce(flag, sender, message, data);
167 void CAnnouncementManager::DoAnnounce(AnnouncementFlag flag,
168 const std::string& sender,
169 const std::string& message,
170 const std::shared_ptr<CFileItem>& item,
171 const CVariant& data)
173 if (item == nullptr)
175 DoAnnounce(flag, sender, message, data);
176 return;
179 // Extract db id of item
180 CVariant object = data.isNull() || data.isObject() ? data : CVariant::VariantTypeObject;
181 std::string type;
182 int id = 0;
184 if(item->HasPVRChannelInfoTag())
186 const std::shared_ptr<PVR::CPVRChannel> channel(item->GetPVRChannelInfoTag());
187 id = channel->ChannelID();
188 type = "channel";
190 object["item"]["title"] = channel->ChannelName();
191 object["item"]["channeltype"] = channel->IsRadio() ? "radio" : "tv";
193 if (data.isMember("player") && data["player"].isMember("playerid"))
195 object["player"]["playerid"] = channel->IsRadio()
196 ? static_cast<int>(PLAYLIST::Id::TYPE_MUSIC)
197 : static_cast<int>(PLAYLIST::Id::TYPE_VIDEO);
200 else if (item->HasVideoInfoTag() && !item->HasPVRRecordingInfoTag())
202 id = item->GetVideoInfoTag()->m_iDbId;
204 //! @todo Can be removed once this is properly handled when starting playback of a file
205 if (id <= 0 && !item->GetPath().empty() &&
206 (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean()))
208 CVideoDatabase videodatabase;
209 if (videodatabase.Open())
211 std::string path = item->GetPath();
212 std::string videoInfoTagPath(item->GetVideoInfoTag()->m_strFileNameAndPath);
213 if (StringUtils::StartsWith(videoInfoTagPath, "removable://"))
214 path = videoInfoTagPath;
215 if (videodatabase.LoadVideoInfo(path, *item->GetVideoInfoTag(), VideoDbDetailsNone))
216 id = item->GetVideoInfoTag()->m_iDbId;
218 videodatabase.Close();
222 if (!item->GetVideoInfoTag()->m_type.empty())
223 type = item->GetVideoInfoTag()->m_type;
224 else
225 CVideoDatabase::VideoContentTypeToString(item->GetVideoContentType(), type);
227 if (id <= 0)
229 //! @todo Can be removed once this is properly handled when starting playback of a file
230 item->SetProperty(LOOKUP_PROPERTY, false);
232 std::string title = item->GetVideoInfoTag()->m_strTitle;
233 if (title.empty())
234 title = item->GetLabel();
235 object["item"]["title"] = title;
237 switch (item->GetVideoContentType())
239 case VideoDbContentType::MOVIES:
240 if (item->GetVideoInfoTag()->HasYear())
241 object["item"]["year"] = item->GetVideoInfoTag()->GetYear();
242 break;
243 case VideoDbContentType::EPISODES:
244 if (item->GetVideoInfoTag()->m_iEpisode >= 0)
245 object["item"]["episode"] = item->GetVideoInfoTag()->m_iEpisode;
246 if (item->GetVideoInfoTag()->m_iSeason >= 0)
247 object["item"]["season"] = item->GetVideoInfoTag()->m_iSeason;
248 if (!item->GetVideoInfoTag()->m_strShowTitle.empty())
249 object["item"]["showtitle"] = item->GetVideoInfoTag()->m_strShowTitle;
250 break;
251 case VideoDbContentType::MUSICVIDEOS:
252 if (!item->GetVideoInfoTag()->m_strAlbum.empty())
253 object["item"]["album"] = item->GetVideoInfoTag()->m_strAlbum;
254 if (!item->GetVideoInfoTag()->m_artist.empty())
255 object["item"]["artist"] = StringUtils::Join(item->GetVideoInfoTag()->m_artist, " / ");
256 break;
257 default:
258 break;
262 else if (item->HasMusicInfoTag())
264 id = item->GetMusicInfoTag()->GetDatabaseId();
265 type = MediaTypeSong;
267 //! @todo Can be removed once this is properly handled when starting playback of a file
268 if (id <= 0 && !item->GetPath().empty() &&
269 (!item->HasProperty(LOOKUP_PROPERTY) || item->GetProperty(LOOKUP_PROPERTY).asBoolean()))
271 CMusicDatabase musicdatabase;
272 if (musicdatabase.Open())
274 CSong song;
275 if (musicdatabase.GetSongByFileName(item->GetPath(), song, item->GetStartOffset()))
277 item->GetMusicInfoTag()->SetSong(song);
278 id = item->GetMusicInfoTag()->GetDatabaseId();
281 musicdatabase.Close();
285 if (id <= 0)
287 //! @todo Can be removed once this is properly handled when starting playback of a file
288 item->SetProperty(LOOKUP_PROPERTY, false);
290 std::string title = item->GetMusicInfoTag()->GetTitle();
291 if (title.empty())
292 title = item->GetLabel();
293 object["item"]["title"] = title;
295 if (item->GetMusicInfoTag()->GetTrackNumber() > 0)
296 object["item"]["track"] = item->GetMusicInfoTag()->GetTrackNumber();
297 if (!item->GetMusicInfoTag()->GetAlbum().empty())
298 object["item"]["album"] = item->GetMusicInfoTag()->GetAlbum();
299 if (!item->GetMusicInfoTag()->GetArtist().empty())
300 object["item"]["artist"] = item->GetMusicInfoTag()->GetArtist();
303 else if (VIDEO::IsVideo(*item))
305 // video item but has no video info tag.
306 type = "movie";
307 object["item"]["title"] = item->GetLabel();
309 else if (item->HasPictureInfoTag())
311 type = "picture";
312 object["item"]["file"] = item->GetPath();
314 else
315 type = "unknown";
317 object["item"]["type"] = type;
318 if (id > 0)
319 object["item"]["id"] = id;
321 DoAnnounce(flag, sender, message, object);
324 void CAnnouncementManager::Process()
326 SetPriority(ThreadPriority::LOWEST);
328 while (!m_bStop)
330 std::unique_lock<CCriticalSection> lock(m_queueCritSection);
331 if (!m_announcementQueue.empty())
333 auto announcement = m_announcementQueue.front();
334 m_announcementQueue.pop_front();
336 CSingleExit ex(m_queueCritSection);
337 DoAnnounce(announcement.flag, announcement.sender, announcement.message, announcement.item,
338 announcement.data);
341 else
343 CSingleExit ex(m_queueCritSection);
344 m_queueEvent.Wait();