[WASAPI] fix stream types and frequencies enumeration
[xbmc.git] / xbmc / video / dialogs / GUIDialogSubtitles.cpp
blobc22eda971780fdb26fbdc4bddf224255cf68439a
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 "GUIDialogSubtitles.h"
11 #include "FileItem.h"
12 #include "FileItemList.h"
13 #include "LangInfo.h"
14 #include "ServiceBroker.h"
15 #include "URL.h"
16 #include "Util.h"
17 #include "addons/AddonManager.h"
18 #include "addons/addoninfo/AddonInfo.h"
19 #include "addons/addoninfo/AddonType.h"
20 #include "addons/gui/GUIDialogAddonSettings.h"
21 #include "application/Application.h"
22 #include "application/ApplicationComponents.h"
23 #include "application/ApplicationPlayer.h"
24 #include "cores/IPlayer.h"
25 #include "dialogs/GUIDialogContextMenu.h"
26 #include "dialogs/GUIDialogKaiToast.h"
27 #include "filesystem/AddonsDirectory.h"
28 #include "filesystem/Directory.h"
29 #include "filesystem/File.h"
30 #include "filesystem/SpecialProtocol.h"
31 #include "filesystem/StackDirectory.h"
32 #include "guilib/GUIComponent.h"
33 #include "guilib/GUIKeyboardFactory.h"
34 #include "guilib/GUIWindowManager.h"
35 #include "guilib/LocalizeStrings.h"
36 #include "input/actions/ActionIDs.h"
37 #include "settings/Settings.h"
38 #include "settings/SettingsComponent.h"
39 #include "settings/lib/Setting.h"
40 #include "utils/JobManager.h"
41 #include "utils/LangCodeExpander.h"
42 #include "utils/StringUtils.h"
43 #include "utils/URIUtils.h"
44 #include "utils/Variant.h"
45 #include "utils/log.h"
46 #include "video/VideoDatabase.h"
48 #include <mutex>
50 using namespace ADDON;
51 using namespace XFILE;
53 namespace
55 constexpr int CONTROL_NAMELABEL = 100;
56 constexpr int CONTROL_NAMELOGO = 110;
57 constexpr int CONTROL_SUBLIST = 120;
58 constexpr int CONTROL_SUBSEXIST = 130;
59 constexpr int CONTROL_SUBSTATUS = 140;
60 constexpr int CONTROL_SERVICELIST = 150;
61 constexpr int CONTROL_MANUALSEARCH = 160;
63 enum class SUBTITLE_SERVICE_CONTEXT_BUTTONS
65 ADDON_SETTINGS,
66 ADDON_DISABLE
68 } // namespace
70 /*! \brief simple job to retrieve a directory and store a string (language)
72 class CSubtitlesJob: public CJob
74 public:
75 CSubtitlesJob(const CURL &url, const std::string &language) : m_url(url), m_language(language)
77 m_items = new CFileItemList;
79 ~CSubtitlesJob() override
81 delete m_items;
83 bool DoWork() override
85 CDirectory::GetDirectory(m_url.Get(), *m_items, "", DIR_FLAG_DEFAULTS);
86 return true;
88 bool operator==(const CJob *job) const override
90 if (strcmp(job->GetType(),GetType()) == 0)
92 const CSubtitlesJob* rjob = dynamic_cast<const CSubtitlesJob*>(job);
93 if (rjob)
95 return m_url.Get() == rjob->m_url.Get() &&
96 m_language == rjob->m_language;
99 return false;
101 const CFileItemList *GetItems() const { return m_items; }
102 const CURL &GetURL() const { return m_url; }
103 const std::string &GetLanguage() const { return m_language; }
104 private:
105 CURL m_url;
106 CFileItemList *m_items;
107 std::string m_language;
110 CGUIDialogSubtitles::CGUIDialogSubtitles(void)
111 : CGUIDialog(WINDOW_DIALOG_SUBTITLES, "DialogSubtitles.xml")
112 , m_subtitles(new CFileItemList)
113 , m_serviceItems(new CFileItemList)
115 m_loadType = KEEP_IN_MEMORY;
118 CGUIDialogSubtitles::~CGUIDialogSubtitles(void)
120 CancelJobs();
121 delete m_subtitles;
122 delete m_serviceItems;
125 bool CGUIDialogSubtitles::OnMessage(CGUIMessage& message)
127 if (message.GetMessage() == GUI_MSG_CLICKED)
129 int iControl = message.GetSenderId();
130 bool selectAction = (message.GetParam1() == ACTION_SELECT_ITEM ||
131 message.GetParam1() == ACTION_MOUSE_LEFT_CLICK);
133 bool contextMenuAction = (message.GetParam1() == ACTION_CONTEXT_MENU ||
134 message.GetParam1() == ACTION_MOUSE_RIGHT_CLICK);
136 if (selectAction && iControl == CONTROL_SUBLIST)
138 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_SUBLIST);
139 OnMessage(msg);
141 int item = msg.GetParam1();
142 if (item >= 0 && item < m_subtitles->Size())
143 Download(*m_subtitles->Get(item));
144 return true;
146 else if (selectAction && iControl == CONTROL_SERVICELIST)
148 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_SERVICELIST);
149 OnMessage(msg);
151 int item = msg.GetParam1();
152 if (item >= 0 && item < m_serviceItems->Size())
154 SetService(m_serviceItems->Get(item)->GetProperty("Addon.ID").asString());
155 Search();
157 return true;
159 else if (contextMenuAction && iControl == CONTROL_SERVICELIST)
161 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_SERVICELIST);
162 OnMessage(msg);
164 const int itemIdx = msg.GetParam1();
165 if (itemIdx >= 0 && itemIdx < m_serviceItems->Size())
167 OnSubtitleServiceContextMenu(itemIdx);
170 else if (iControl == CONTROL_MANUALSEARCH)
172 //manual search
173 if (CGUIKeyboardFactory::ShowAndGetInput(m_strManualSearch, CVariant{g_localizeStrings.Get(24121)}, true))
175 Search(m_strManualSearch);
176 return true;
180 else if (message.GetMessage() == GUI_MSG_WINDOW_DEINIT)
182 auto& components = CServiceBroker::GetAppComponents();
183 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
184 // Resume the video if the user has requested it
185 if (appPlayer->IsPaused() && m_pausedOnRun)
186 appPlayer->Pause();
188 CGUIDialog::OnMessage(message);
190 ClearSubtitles();
191 ClearServices();
192 return true;
194 return CGUIDialog::OnMessage(message);
197 void CGUIDialogSubtitles::OnInitWindow()
199 // Pause the video if the user has requested it
200 m_pausedOnRun = false;
201 auto& components = CServiceBroker::GetAppComponents();
202 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
203 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
204 CSettings::SETTING_SUBTITLES_PAUSEONSEARCH) &&
205 !appPlayer->IsPaused())
207 appPlayer->Pause();
208 m_pausedOnRun = true;
211 FillServices();
212 CGUIWindow::OnInitWindow();
213 Search();
216 void CGUIDialogSubtitles::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
218 if (m_bInvalidated)
220 // take copies of our variables to ensure we don't hold the lock for long.
221 std::string status;
222 CFileItemList subs;
224 std::unique_lock<CCriticalSection> lock(m_critsection);
225 status = m_status;
226 subs.Assign(*m_subtitles);
228 SET_CONTROL_LABEL(CONTROL_SUBSTATUS, status);
230 if (m_updateSubsList)
232 CGUIMessage message(GUI_MSG_LABEL_BIND, GetID(), CONTROL_SUBLIST, 0, 0, &subs);
233 OnMessage(message);
234 if (!subs.IsEmpty())
236 // focus subtitles list
237 CGUIMessage msg(GUI_MSG_SETFOCUS, GetID(), CONTROL_SUBLIST);
238 OnMessage(msg);
240 m_updateSubsList = false;
243 int control = GetFocusedControlID();
244 // nothing has focus
245 if (!control)
247 CGUIMessage msg(GUI_MSG_SETFOCUS, GetID(), m_subtitles->IsEmpty() ?
248 CONTROL_SERVICELIST : CONTROL_SUBLIST);
249 OnMessage(msg);
251 // subs list is focused but we have no subs
252 else if (control == CONTROL_SUBLIST && m_subtitles->IsEmpty())
254 CGUIMessage msg(GUI_MSG_SETFOCUS, GetID(), CONTROL_SERVICELIST);
255 OnMessage(msg);
258 CGUIDialog::Process(currentTime, dirtyregions);
261 void CGUIDialogSubtitles::FillServices()
263 ClearServices();
265 VECADDONS addons;
266 CServiceBroker::GetAddonMgr().GetAddons(addons, AddonType::SUBTITLE_MODULE);
268 if (addons.empty())
270 UpdateStatus(NO_SERVICES);
271 return;
274 std::string defaultService;
275 const CFileItem &item = g_application.CurrentUnstackedItem();
276 if (item.GetVideoContentType() == VideoDbContentType::TVSHOWS ||
277 item.GetVideoContentType() == VideoDbContentType::EPISODES)
278 // Set default service for tv shows
279 defaultService = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_SUBTITLES_TV);
280 else
281 // Set default service for filemode and movies
282 defaultService = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_SUBTITLES_MOVIE);
284 std::string service = addons.front()->ID();
285 for (VECADDONS::const_iterator addonIt = addons.begin(); addonIt != addons.end(); ++addonIt)
287 CFileItemPtr item(CAddonsDirectory::FileItemFromAddon(*addonIt, "plugin://" + (*addonIt)->ID(), false));
288 m_serviceItems->Add(item);
289 if ((*addonIt)->ID() == defaultService)
290 service = (*addonIt)->ID();
293 // Bind our services to the UI
294 CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), CONTROL_SERVICELIST, 0, 0, m_serviceItems);
295 OnMessage(msg);
297 SetService(service);
300 bool CGUIDialogSubtitles::SetService(const std::string &service)
302 if (service != m_currentService)
304 m_currentService = service;
305 CLog::Log(LOGDEBUG, "New Service [{}] ", m_currentService);
307 CFileItemPtr currentService = GetService();
308 // highlight this item in the skin
309 for (int i = 0; i < m_serviceItems->Size(); i++)
311 CFileItemPtr pItem = m_serviceItems->Get(i);
312 pItem->Select(pItem == currentService);
315 SET_CONTROL_LABEL(CONTROL_NAMELABEL, currentService->GetLabel());
317 if (currentService->HasAddonInfo())
319 std::string icon = URIUtils::AddFileToFolder(currentService->GetAddonInfo()->Path(), "logo.png");
320 SET_CONTROL_FILENAME(CONTROL_NAMELOGO, icon);
323 const auto& components = CServiceBroker::GetAppComponents();
324 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
325 if (appPlayer->GetSubtitleCount() == 0)
326 SET_CONTROL_HIDDEN(CONTROL_SUBSEXIST);
327 else
328 SET_CONTROL_VISIBLE(CONTROL_SUBSEXIST);
330 return true;
332 return false;
335 const CFileItemPtr CGUIDialogSubtitles::GetService() const
337 for (int i = 0; i < m_serviceItems->Size(); i++)
339 if (m_serviceItems->Get(i)->GetProperty("Addon.ID") == m_currentService)
340 return m_serviceItems->Get(i);
342 return CFileItemPtr();
345 void CGUIDialogSubtitles::Search(const std::string &search/*=""*/)
347 if (m_currentService.empty())
348 return; // no services available
350 UpdateStatus(SEARCHING);
351 ClearSubtitles();
353 CURL url("plugin://" + m_currentService + "/");
354 if (!search.empty())
356 url.SetOption("action", "manualsearch");
357 url.SetOption("searchstring", search);
359 else
360 url.SetOption("action", "search");
362 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
363 SettingConstPtr setting = settings->GetSetting(CSettings::SETTING_SUBTITLES_LANGUAGES);
364 if (setting)
365 url.SetOption("languages", setting->ToString());
367 // Check for stacking
368 if (g_application.CurrentFileItem().IsStack())
369 url.SetOption("stack", "1");
371 std::string preferredLanguage = settings->GetString(CSettings::SETTING_LOCALE_SUBTITLELANGUAGE);
373 if (StringUtils::EqualsNoCase(preferredLanguage, "original"))
375 AudioStreamInfo info;
376 std::string strLanguage;
378 const auto& components = CServiceBroker::GetAppComponents();
379 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
380 appPlayer->GetAudioStreamInfo(CURRENT_STREAM, info);
382 if (!g_LangCodeExpander.Lookup(info.language, strLanguage))
383 strLanguage = "Unknown";
385 preferredLanguage = strLanguage;
387 else if (StringUtils::EqualsNoCase(preferredLanguage, "default"))
388 preferredLanguage = g_langInfo.GetEnglishLanguageName();
390 url.SetOption("preferredlanguage", preferredLanguage);
392 AddJob(new CSubtitlesJob(url, ""));
395 void CGUIDialogSubtitles::OnJobComplete(unsigned int jobID, bool success, CJob *job)
397 const CURL &url = static_cast<CSubtitlesJob*>(job)->GetURL();
398 const CFileItemList *items = static_cast<CSubtitlesJob*>(job)->GetItems();
399 const std::string &language = static_cast<CSubtitlesJob*>(job)->GetLanguage();
400 if (url.GetOption("action") == "search" || url.GetOption("action") == "manualsearch")
401 OnSearchComplete(items);
402 else
403 OnDownloadComplete(items, language);
404 CJobQueue::OnJobComplete(jobID, success, job);
407 void CGUIDialogSubtitles::OnSearchComplete(const CFileItemList *items)
409 std::unique_lock<CCriticalSection> lock(m_critsection);
410 m_subtitles->Assign(*items);
411 UpdateStatus(SEARCH_COMPLETE);
412 m_updateSubsList = true;
413 MarkDirtyRegion();
415 const auto& components = CServiceBroker::GetAppComponents();
416 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
417 if (!items->IsEmpty() && appPlayer->GetSubtitleCount() == 0 &&
418 m_LastAutoDownloaded != g_application.CurrentFile() &&
419 CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
420 CSettings::SETTING_SUBTITLES_DOWNLOADFIRST))
422 CFileItemPtr item = items->Get(0);
423 CLog::Log(LOGDEBUG, "{} - Automatically download first subtitle: {}", __FUNCTION__,
424 item->GetLabel2());
425 m_LastAutoDownloaded = g_application.CurrentFile();
426 Download(*item);
429 SetInvalid();
432 void CGUIDialogSubtitles::OnSubtitleServiceContextMenu(int itemIdx)
434 const auto service = m_serviceItems->Get(itemIdx);
436 CContextButtons buttons;
437 // Subtitle addon settings
438 buttons.Add(static_cast<int>(SUBTITLE_SERVICE_CONTEXT_BUTTONS::ADDON_SETTINGS),
439 g_localizeStrings.Get(21417));
440 // Disable addon
441 buttons.Add(static_cast<int>(SUBTITLE_SERVICE_CONTEXT_BUTTONS::ADDON_DISABLE),
442 g_localizeStrings.Get(24021));
444 auto idx = static_cast<SUBTITLE_SERVICE_CONTEXT_BUTTONS>(CGUIDialogContextMenu::Show(buttons));
445 switch (idx)
447 case SUBTITLE_SERVICE_CONTEXT_BUTTONS::ADDON_SETTINGS:
449 AddonPtr addon;
450 if (CServiceBroker::GetAddonMgr().GetAddon(service->GetProperty("Addon.ID").asString(), addon,
451 AddonType::SUBTITLE_MODULE,
452 OnlyEnabled::CHOICE_YES))
454 CGUIDialogAddonSettings::ShowForAddon(addon);
456 else
458 CLog::Log(LOGERROR, "{} - Could not open settings for addon: {}", __FUNCTION__,
459 service->GetProperty("Addon.ID").asString());
461 break;
463 case SUBTITLE_SERVICE_CONTEXT_BUTTONS::ADDON_DISABLE:
465 CServiceBroker::GetAddonMgr().DisableAddon(service->GetProperty("Addon.ID").asString(),
466 AddonDisabledReason::USER);
467 const bool currentActiveServiceWasDisabled =
468 m_currentService == service->GetProperty("Addon.ID").asString();
469 FillServices();
470 // restart search if the current active service was disabled
471 if (currentActiveServiceWasDisabled && !m_serviceItems->IsEmpty())
473 Search();
475 // if no more services are available make sure the subtitle list is cleaned up
476 else if (m_serviceItems->IsEmpty())
478 ClearSubtitles();
480 break;
482 default:
483 break;
487 void CGUIDialogSubtitles::UpdateStatus(STATUS status)
489 std::unique_lock<CCriticalSection> lock(m_critsection);
490 std::string label;
491 switch (status)
493 case NO_SERVICES:
494 label = g_localizeStrings.Get(24114);
495 break;
496 case SEARCHING:
497 label = g_localizeStrings.Get(24107);
498 break;
499 case SEARCH_COMPLETE:
500 if (!m_subtitles->IsEmpty())
501 label = StringUtils::Format(g_localizeStrings.Get(24108), m_subtitles->Size());
502 else
503 label = g_localizeStrings.Get(24109);
504 break;
505 case DOWNLOADING:
506 label = g_localizeStrings.Get(24110);
507 break;
508 default:
509 break;
511 if (label != m_status)
513 m_status = label;
514 SetInvalid();
518 void CGUIDialogSubtitles::Download(const CFileItem &subtitle)
520 UpdateStatus(DOWNLOADING);
522 // subtitle URL should be of the form plugin://<addonid>/?param=foo&param=bar
523 // we just append (if not already present) the action=download parameter.
524 CURL url(subtitle.GetURL());
525 if (url.GetOption("action").empty())
526 url.SetOption("action", "download");
528 AddJob(new CSubtitlesJob(url, subtitle.GetLabel()));
531 void CGUIDialogSubtitles::OnDownloadComplete(const CFileItemList *items, const std::string &language)
533 if (items->IsEmpty())
535 CFileItemPtr service = GetService();
536 if (service)
537 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, service->GetLabel(), g_localizeStrings.Get(24113));
538 UpdateStatus(SEARCH_COMPLETE);
539 return;
542 SUBTITLE_STORAGEMODE storageMode = (SUBTITLE_STORAGEMODE) CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_SUBTITLES_STORAGEMODE);
544 // Get (unstacked) path
545 std::string strCurrentFile = g_application.CurrentUnstackedItem().GetDynPath();
547 std::string strDownloadPath = "special://temp";
548 std::string strDestPath;
549 std::vector<std::string> vecFiles;
551 std::string strCurrentFilePath;
552 const std::string subPath = CSpecialProtocol::TranslatePath("special://subtitles");
554 if (subPath.empty() && URIUtils::IsHTTP(strCurrentFile))
556 strCurrentFile = "TempSubtitle";
557 vecFiles.push_back(strCurrentFile);
559 else
561 if (!subPath.empty())
562 strDownloadPath = subPath;
564 /** Get item's folder for sub storage, special case for RAR/ZIP items
565 * @todo We need some way to avoid special casing this all over the place
566 * for rar/zip (perhaps modify GetDirectory?)
568 if (URIUtils::IsInRAR(strCurrentFile) || URIUtils::IsInZIP(strCurrentFile))
569 strCurrentFilePath = URIUtils::GetDirectory(CURL(strCurrentFile).GetHostName());
570 else
571 strCurrentFilePath = URIUtils::GetDirectory(strCurrentFile);
573 // Handle stacks
574 if (g_application.CurrentFileItem().IsStack() && items->Size() > 1)
576 CStackDirectory::GetPaths(g_application.CurrentFileItem().GetPath(), vecFiles);
577 // Make sure (stack) size is the same as the size of the items handed to us, else fallback to single item
578 if (items->Size() != (int) vecFiles.size())
580 vecFiles.clear();
581 vecFiles.push_back(strCurrentFile);
584 else
586 vecFiles.push_back(strCurrentFile);
589 if (storageMode == SUBTITLE_STORAGEMODE_MOVIEPATH &&
590 CUtil::SupportsWriteFileOperations(strCurrentFilePath))
592 strDestPath = strCurrentFilePath;
596 // Use fallback?
597 if (strDestPath.empty())
598 strDestPath = strDownloadPath;
600 // Extract the language and appropriate extension
601 std::string strSubLang;
602 g_LangCodeExpander.ConvertToISO6391(language, strSubLang);
604 // Iterate over all items to transfer
605 for (unsigned int i = 0; i < vecFiles.size() && i < (unsigned int) items->Size(); i++)
607 std::string strUrl = items->Get(i)->GetPath();
608 std::string strFileName = URIUtils::GetFileName(vecFiles[i]);
609 URIUtils::RemoveExtension(strFileName);
611 // construct subtitle path
612 std::string strSubExt = URIUtils::GetExtension(strUrl);
613 std::string strSubName = StringUtils::Format("{}.{}{}", strFileName, strSubLang, strSubExt);
615 // Handle URL encoding:
616 std::string strDownloadFile = URIUtils::ChangeBasePath(strCurrentFilePath, strSubName, strDownloadPath);
617 std::string strDestFile = strDownloadFile;
619 if (!CFile::Copy(strUrl, strDownloadFile))
621 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, strSubName, g_localizeStrings.Get(24113));
622 CLog::Log(LOGERROR, "{} - Saving of subtitle {} to {} failed", __FUNCTION__, strUrl,
623 strDownloadFile);
625 else
627 if (strDestPath != strDownloadPath)
629 // Handle URL encoding:
630 std::string strTryDestFile = URIUtils::ChangeBasePath(strCurrentFilePath, strSubName, strDestPath);
632 /* Copy the file from temp to our final destination, if that fails fallback to download path
633 * (ie. special://subtitles or use special://temp). Note that after the first item strDownloadPath equals strDestpath
634 * so that all remaining items (including the .idx below) are copied directly to their final destination and thus all
635 * items end up in the same folder
637 CLog::Log(LOGDEBUG, "{} - Saving subtitle {} to {}", __FUNCTION__, strDownloadFile,
638 strTryDestFile);
639 if (CFile::Copy(strDownloadFile, strTryDestFile))
641 CFile::Delete(strDownloadFile);
642 strDestFile = strTryDestFile;
643 strDownloadPath = strDestPath; // Update download path so all the other items get directly downloaded to our final destination
645 else
647 CLog::Log(LOGWARNING, "{} - Saving of subtitle {} to {} failed. Falling back to {}",
648 __FUNCTION__, strDownloadFile, strTryDestFile, strDownloadPath);
649 strDestPath = strDownloadPath; // Copy failed, use fallback for the rest of the items
652 else
654 CLog::Log(LOGDEBUG, "{} - Saved subtitle {} to {}", __FUNCTION__, strUrl, strDownloadFile);
657 // for ".sub" subtitles we check if ".idx" counterpart exists and copy that as well
658 if (StringUtils::EqualsNoCase(strSubExt, ".sub"))
660 strUrl = URIUtils::ReplaceExtension(strUrl, ".idx");
661 if(CFile::Exists(strUrl))
663 std::string strSubNameIdx = StringUtils::Format("{}.{}.idx", strFileName, strSubLang);
664 // Handle URL encoding:
665 strDestFile = URIUtils::ChangeBasePath(strCurrentFilePath, strSubNameIdx, strDestPath);
666 CFile::Copy(strUrl, strDestFile);
670 // Set sub for currently playing (stack) item
671 if (vecFiles[i] == strCurrentFile)
672 SetSubtitles(strDestFile);
676 // Notify window manager that a subtitle was downloaded
677 CGUIMessage msg(GUI_MSG_SUBTITLE_DOWNLOADED, 0, 0);
678 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
680 // Close the window
681 Close();
684 void CGUIDialogSubtitles::ClearSubtitles()
686 CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_SUBLIST);
687 OnMessage(msg);
688 std::unique_lock<CCriticalSection> lock(m_critsection);
689 m_subtitles->Clear();
692 void CGUIDialogSubtitles::ClearServices()
694 CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_SERVICELIST);
695 OnMessage(msg);
696 m_serviceItems->Clear();
697 m_currentService.clear();
700 void CGUIDialogSubtitles::SetSubtitles(const std::string &subtitle)
702 auto& components = CServiceBroker::GetAppComponents();
703 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
704 appPlayer->AddSubtitle(subtitle);