summaryrefslogtreecommitdiffstats
path: root/xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp')
-rw-r--r--xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp426
1 files changed, 426 insertions, 0 deletions
diff --git a/xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp b/xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp
new file mode 100644
index 0000000..24f2618
--- /dev/null
+++ b/xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "GUIDialogSubtitleSettings.h"
+
+#include "FileItem.h"
+#include "GUIDialogSubtitles.h"
+#include "GUIPassword.h"
+#include "ServiceBroker.h"
+#include "URL.h"
+#include "addons/Skin.h"
+#include "addons/VFSEntry.h"
+#include "application/Application.h"
+#include "application/ApplicationComponents.h"
+#include "application/ApplicationPlayer.h"
+#include "cores/IPlayer.h"
+#include "dialogs/GUIDialogFileBrowser.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "profiles/ProfileManager.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/MediaSettings.h"
+#include "settings/MediaSourceSettings.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "settings/lib/Setting.h"
+#include "settings/lib/SettingDefinitions.h"
+#include "settings/lib/SettingsManager.h"
+#include "utils/FileUtils.h"
+#include "utils/LangCodeExpander.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+#include "video/VideoDatabase.h"
+
+#include <string>
+#include <vector>
+
+#define SETTING_SUBTITLE_ENABLE "subtitles.enable"
+#define SETTING_SUBTITLE_DELAY "subtitles.delay"
+#define SETTING_SUBTITLE_STREAM "subtitles.stream"
+#define SETTING_SUBTITLE_BROWSER "subtitles.browser"
+#define SETTING_SUBTITLE_SEARCH "subtitles.search"
+#define SETTING_MAKE_DEFAULT "audio.makedefault"
+
+CGUIDialogSubtitleSettings::CGUIDialogSubtitleSettings()
+ : CGUIDialogSettingsManualBase(WINDOW_DIALOG_SUBTITLE_OSD_SETTINGS, "DialogSettings.xml")
+{ }
+
+CGUIDialogSubtitleSettings::~CGUIDialogSubtitleSettings() = default;
+
+void CGUIDialogSubtitleSettings::FrameMove()
+{
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ if (appPlayer->HasPlayer())
+ {
+ const CVideoSettings videoSettings = appPlayer->GetVideoSettings();
+
+ // these settings can change on the fly
+ //! @todo m_settingsManager->SetBool(SETTING_SUBTITLE_ENABLE, g_application.GetAppPlayer().GetSubtitleVisible());
+ // \-> Unless subtitle visibility can change on the fly, while Dialog is up, this code should be removed.
+ GetSettingsManager()->SetNumber(SETTING_SUBTITLE_DELAY,
+ static_cast<double>(videoSettings.m_SubtitleDelay));
+ //! @todo (needs special handling): m_settingsManager->SetInt(SETTING_SUBTITLE_STREAM, g_application.GetAppPlayer().GetSubtitle());
+ }
+
+ CGUIDialogSettingsManualBase::FrameMove();
+}
+
+bool CGUIDialogSubtitleSettings::OnMessage(CGUIMessage& message)
+{
+ if (message.GetMessage() == GUI_MSG_SUBTITLE_DOWNLOADED)
+ {
+ Close();
+ }
+ return CGUIDialogSettingsManualBase::OnMessage(message);
+}
+
+void CGUIDialogSubtitleSettings::OnSettingChanged(const std::shared_ptr<const CSetting>& setting)
+{
+ if (setting == NULL)
+ return;
+
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+
+ CGUIDialogSettingsManualBase::OnSettingChanged(setting);
+
+ const std::string &settingId = setting->GetId();
+ if (settingId == SETTING_SUBTITLE_ENABLE)
+ {
+ bool value = std::static_pointer_cast<const CSettingBool>(setting)->GetValue();
+ if (value)
+ {
+ // Ensure that we use/store the subtitle stream the user currently sees in the dialog.
+ appPlayer->SetSubtitle(m_subtitleStream);
+ }
+ appPlayer->SetSubtitleVisible(value);
+ }
+ else if (settingId == SETTING_SUBTITLE_DELAY)
+ {
+ float value = static_cast<float>(std::static_pointer_cast<const CSettingNumber>(setting)->GetValue());
+ appPlayer->SetSubTitleDelay(value);
+ }
+ else if (settingId == SETTING_SUBTITLE_STREAM)
+ {
+ m_subtitleStream = std::static_pointer_cast<const CSettingInt>(setting)->GetValue();
+ appPlayer->SetSubtitle(m_subtitleStream);
+ }
+}
+
+std::string CGUIDialogSubtitleSettings::BrowseForSubtitle()
+{
+ std::string extras;
+ for (const auto& vfsAddon : CServiceBroker::GetVFSAddonCache().GetAddonInstances())
+ {
+ if (vfsAddon->ID() == "vfs.rar" || vfsAddon->ID() == "vfs.libarchive")
+ extras += '|' + vfsAddon->GetExtensions();
+ }
+
+ std::string strPath;
+ if (URIUtils::IsInRAR(g_application.CurrentFileItem().GetPath()) || URIUtils::IsInZIP(g_application.CurrentFileItem().GetPath()))
+ {
+ strPath = CURL(g_application.CurrentFileItem().GetPath()).GetHostName();
+ }
+ else if (!URIUtils::IsPlugin(g_application.CurrentFileItem().GetPath()))
+ {
+ strPath = g_application.CurrentFileItem().GetPath();
+ }
+
+ std::string strMask =
+ ".utf|.utf8|.utf-8|.sub|.srt|.smi|.rt|.txt|.ssa|.aqt|.jss|.ass|.vtt|.idx|.zip|.sup";
+
+ if (g_application.GetCurrentPlayer() == "VideoPlayer")
+ strMask = ".srt|.zip|.ifo|.smi|.sub|.idx|.ass|.ssa|.vtt|.txt|.sup";
+
+ strMask += extras;
+
+ VECSOURCES shares(*CMediaSourceSettings::GetInstance().GetSources("video"));
+ if (CMediaSettings::GetInstance().GetAdditionalSubtitleDirectoryChecked() != -1 && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_SUBTITLES_CUSTOMPATH).empty())
+ {
+ CMediaSource share;
+ std::vector<std::string> paths;
+ if (!strPath.empty())
+ {
+ paths.push_back(URIUtils::GetDirectory(strPath));
+ }
+ paths.push_back(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_SUBTITLES_CUSTOMPATH));
+ share.FromNameAndPaths("video",g_localizeStrings.Get(21367),paths);
+ shares.push_back(share);
+ strPath = share.strPath;
+ URIUtils::AddSlashAtEnd(strPath);
+ }
+
+ if (CGUIDialogFileBrowser::ShowAndGetFile(shares, strMask, g_localizeStrings.Get(293), strPath, false, true)) // "subtitles"
+ {
+ if (URIUtils::HasExtension(strPath, ".sub"))
+ {
+ if (CFileUtils::Exists(URIUtils::ReplaceExtension(strPath, ".idx")))
+ strPath = URIUtils::ReplaceExtension(strPath, ".idx");
+ }
+
+ return strPath;
+ }
+
+ return "";
+}
+
+void CGUIDialogSubtitleSettings::OnSettingAction(const std::shared_ptr<const CSetting>& setting)
+{
+ if (setting == NULL)
+ return;
+
+ CGUIDialogSettingsManualBase::OnSettingAction(setting);
+
+ const std::string &settingId = setting->GetId();
+ if (settingId == SETTING_SUBTITLE_BROWSER)
+ {
+ std::string strPath = BrowseForSubtitle();
+ if (!strPath.empty())
+ {
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ appPlayer->AddSubtitle(strPath);
+ Close();
+ }
+ }
+ else if (settingId == SETTING_SUBTITLE_SEARCH)
+ {
+ auto dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSubtitles>(WINDOW_DIALOG_SUBTITLES);
+ if (dialog)
+ {
+ dialog->Open();
+ m_subtitleStreamSetting->UpdateDynamicOptions();
+ }
+ }
+ else if (settingId == SETTING_MAKE_DEFAULT)
+ Save();
+}
+
+bool CGUIDialogSubtitleSettings::Save()
+{
+ const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
+
+ if (!g_passwordManager.CheckSettingLevelLock(SettingLevel::Expert) &&
+ profileManager->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE)
+ return true;
+
+ // prompt user if they are sure
+ if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{12376}, CVariant{12377}))
+ return true;
+
+ // reset the settings
+ CVideoDatabase db;
+ if (!db.Open())
+ return true;
+
+ db.EraseAllVideoSettings();
+ db.Close();
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+
+ CMediaSettings::GetInstance().GetDefaultVideoSettings() = appPlayer->GetVideoSettings();
+ CMediaSettings::GetInstance().GetDefaultVideoSettings().m_SubtitleStream = -1;
+ CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
+
+ return true;
+}
+
+void CGUIDialogSubtitleSettings::SetupView()
+{
+ CGUIDialogSettingsManualBase::SetupView();
+
+ SetHeading(24133);
+ SET_CONTROL_HIDDEN(CONTROL_SETTINGS_OKAY_BUTTON);
+ SET_CONTROL_HIDDEN(CONTROL_SETTINGS_CUSTOM_BUTTON);
+ SET_CONTROL_LABEL(CONTROL_SETTINGS_CANCEL_BUTTON, 15067);
+}
+
+void CGUIDialogSubtitleSettings::InitializeSettings()
+{
+ CGUIDialogSettingsManualBase::InitializeSettings();
+
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+
+ const std::shared_ptr<CSettingCategory> category = AddCategory("audiosubtitlesettings", -1);
+ if (category == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogSubtitleSettings: unable to setup settings");
+ return;
+ }
+
+ // get all necessary setting groups
+ const std::shared_ptr<CSettingGroup> groupAudio = AddGroup(category);
+ if (groupAudio == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogSubtitleSettings: unable to setup settings");
+ return;
+ }
+ const std::shared_ptr<CSettingGroup> groupSubtitles = AddGroup(category);
+ if (groupSubtitles == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogSubtitleSettings: unable to setup settings");
+ return;
+ }
+ const std::shared_ptr<CSettingGroup> groupSaveAsDefault = AddGroup(category);
+ if (groupSaveAsDefault == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogSubtitleSettings: unable to setup settings");
+ return;
+ }
+
+ bool usePopup = g_SkinInfo->HasSkinFile("DialogSlider.xml");
+
+ const CVideoSettings videoSettings = appPlayer->GetVideoSettings();
+
+ if (appPlayer->HasPlayer())
+ {
+ appPlayer->GetSubtitleCapabilities(m_subtitleCapabilities);
+ }
+
+ // subtitle settings
+ m_subtitleVisible = appPlayer->GetSubtitleVisible();
+
+ // subtitle enabled setting
+ AddToggle(groupSubtitles, SETTING_SUBTITLE_ENABLE, 13397, SettingLevel::Basic, m_subtitleVisible);
+
+ // subtitle delay setting
+ if (SupportsSubtitleFeature(IPC_SUBS_OFFSET))
+ {
+ std::shared_ptr<CSettingNumber> settingSubtitleDelay = AddSlider(groupSubtitles, SETTING_SUBTITLE_DELAY, 22006, SettingLevel::Basic, videoSettings.m_SubtitleDelay, 0, -CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoSubsDelayRange, 0.1f, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoSubsDelayRange, 22006, usePopup);
+ std::static_pointer_cast<CSettingControlSlider>(settingSubtitleDelay->GetControl())->SetFormatter(SettingFormatterDelay);
+ }
+
+ // subtitle stream setting
+ if (SupportsSubtitleFeature(IPC_SUBS_SELECT))
+ AddSubtitleStreams(groupSubtitles, SETTING_SUBTITLE_STREAM);
+
+ // subtitle browser setting
+ if (SupportsSubtitleFeature(IPC_SUBS_EXTERNAL))
+ AddButton(groupSubtitles, SETTING_SUBTITLE_BROWSER, 13250, SettingLevel::Basic);
+
+ AddButton(groupSubtitles, SETTING_SUBTITLE_SEARCH, 24134, SettingLevel::Basic);
+
+ // subtitle stream setting
+ AddButton(groupSaveAsDefault, SETTING_MAKE_DEFAULT, 12376, SettingLevel::Basic);
+}
+
+bool CGUIDialogSubtitleSettings::SupportsSubtitleFeature(int feature)
+{
+ for (auto item : m_subtitleCapabilities)
+ {
+ if (item == feature || item == IPC_SUBS_ALL)
+ return true;
+ }
+ return false;
+}
+
+void CGUIDialogSubtitleSettings::AddSubtitleStreams(const std::shared_ptr<CSettingGroup>& group,
+ const std::string& settingId)
+{
+ if (group == NULL || settingId.empty())
+ return;
+
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+
+ m_subtitleStream = appPlayer->GetSubtitle();
+ if (m_subtitleStream < 0)
+ m_subtitleStream = 0;
+
+ m_subtitleStreamSetting = AddList(group, settingId, 462, SettingLevel::Basic, m_subtitleStream, SubtitleStreamsOptionFiller, 462);
+}
+
+void CGUIDialogSubtitleSettings::SubtitleStreamsOptionFiller(
+ const SettingConstPtr& setting,
+ std::vector<IntegerSettingOption>& list,
+ int& current,
+ void* data)
+{
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+
+ int subtitleStreamCount = appPlayer->GetSubtitleCount();
+
+ // cycle through each subtitle and add it to our entry list
+ for (int i = 0; i < subtitleStreamCount; ++i)
+ {
+ SubtitleStreamInfo info;
+ appPlayer->GetSubtitleStreamInfo(i, info);
+
+ std::string strItem;
+ std::string strLanguage;
+
+ if (!g_LangCodeExpander.Lookup(info.language, strLanguage))
+ strLanguage = g_localizeStrings.Get(13205); // Unknown
+
+ if (info.name.length() == 0)
+ strItem = strLanguage;
+ else
+ strItem = StringUtils::Format("{} - {}", strLanguage, info.name);
+
+ strItem += FormatFlags(info.flags);
+ strItem += StringUtils::Format(" ({}/{})", i + 1, subtitleStreamCount);
+
+ list.emplace_back(strItem, i);
+ }
+
+ // no subtitle streams - just add a "None" entry
+ if (list.empty())
+ {
+ list.emplace_back(g_localizeStrings.Get(231), -1);
+ current = -1;
+ }
+}
+
+std::string CGUIDialogSubtitleSettings::SettingFormatterDelay(
+ const std::shared_ptr<const CSettingControlSlider>& control,
+ const CVariant& value,
+ const CVariant& minimum,
+ const CVariant& step,
+ const CVariant& maximum)
+{
+ if (!value.isDouble())
+ return "";
+
+ float fValue = value.asFloat();
+ float fStep = step.asFloat();
+
+ if (fabs(fValue) < 0.5f * fStep)
+ return StringUtils::Format(g_localizeStrings.Get(22003), 0.0);
+ if (fValue < 0)
+ return StringUtils::Format(g_localizeStrings.Get(22004), fabs(fValue));
+
+ return StringUtils::Format(g_localizeStrings.Get(22005), fValue);
+}
+
+std::string CGUIDialogSubtitleSettings::FormatFlags(StreamFlags flags)
+{
+ std::vector<std::string> localizedFlags;
+ if (flags & StreamFlags::FLAG_DEFAULT)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39105));
+ if (flags & StreamFlags::FLAG_FORCED)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39106));
+ if (flags & StreamFlags::FLAG_HEARING_IMPAIRED)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39107));
+ if (flags & StreamFlags::FLAG_VISUAL_IMPAIRED)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39108));
+
+ std::string formated = StringUtils::Join(localizedFlags, ", ");
+
+ if (!formated.empty())
+ formated = StringUtils::Format(" [{}]", formated);
+
+ return formated;
+}