diff options
Diffstat (limited to 'xbmc/guilib/guiinfo')
40 files changed, 8176 insertions, 0 deletions
diff --git a/xbmc/guilib/guiinfo/AddonsGUIInfo.cpp b/xbmc/guilib/guiinfo/AddonsGUIInfo.cpp new file mode 100644 index 0000000..6630fa1 --- /dev/null +++ b/xbmc/guilib/guiinfo/AddonsGUIInfo.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/AddonsGUIInfo.h" + +#include "FileItem.h" +#include "ServiceBroker.h" +#include "addons/Addon.h" +#include "addons/AddonManager.h" +#include "addons/addoninfo/AddonInfo.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "utils/StringUtils.h" + +using namespace KODI::GUILIB::GUIINFO; + +bool CAddonsGUIInfo::InitCurrentItem(CFileItem *item) +{ + return false; +} + +bool CAddonsGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + const std::shared_ptr<const ADDON::IAddon> addonInfo = item->GetAddonInfo(); + if (addonInfo) + { + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_ADDON_NAME: + value = addonInfo->Name(); + return true; + case LISTITEM_ADDON_VERSION: + value = addonInfo->Version().asString(); + return true; + case LISTITEM_ADDON_CREATOR: + value = addonInfo->Author(); + return true; + case LISTITEM_ADDON_SUMMARY: + value = addonInfo->Summary(); + return true; + case LISTITEM_ADDON_DESCRIPTION: + value = addonInfo->Description(); + return true; + case LISTITEM_ADDON_DISCLAIMER: + value = addonInfo->Disclaimer(); + return true; + case LISTITEM_ADDON_NEWS: + value = addonInfo->ChangeLog(); + return true; + case LISTITEM_ADDON_BROKEN: + { + // Fallback for old GUI info + if (addonInfo->LifecycleState() == ADDON::AddonLifecycleState::BROKEN) + value = addonInfo->LifecycleStateDescription(); + else + value = ""; + return true; + } + case LISTITEM_ADDON_LIFECYCLE_TYPE: + { + const ADDON::AddonLifecycleState state = addonInfo->LifecycleState(); + switch (state) + { + case ADDON::AddonLifecycleState::BROKEN: + value = g_localizeStrings.Get(24171); // "Broken" + break; + case ADDON::AddonLifecycleState::DEPRECATED: + value = g_localizeStrings.Get(24170); // "Deprecated"; + break; + case ADDON::AddonLifecycleState::NORMAL: + default: + value = g_localizeStrings.Get(24169); // "Normal"; + break; + } + return true; + } + case LISTITEM_ADDON_LIFECYCLE_DESC: + value = addonInfo->LifecycleStateDescription(); + return true; + case LISTITEM_ADDON_TYPE: + value = ADDON::CAddonInfo::TranslateType(addonInfo->Type(), true); + return true; + case LISTITEM_ADDON_INSTALL_DATE: + value = addonInfo->InstallDate().GetAsLocalizedDateTime(); + return true; + case LISTITEM_ADDON_LAST_UPDATED: + if (addonInfo->LastUpdated().IsValid()) + { + value = addonInfo->LastUpdated().GetAsLocalizedDateTime(); + return true; + } + break; + case LISTITEM_ADDON_LAST_USED: + if (addonInfo->LastUsed().IsValid()) + { + value = addonInfo->LastUsed().GetAsLocalizedDateTime(); + return true; + } + break; + case LISTITEM_ADDON_ORIGIN: + { + if (item->GetAddonInfo()->Origin() == ADDON::ORIGIN_SYSTEM) + { + value = g_localizeStrings.Get(24992); + return true; + } + if (!item->GetAddonInfo()->OriginName().empty()) + { + value = item->GetAddonInfo()->OriginName(); + return true; + } + else if (!item->GetAddonInfo()->Origin().empty()) + { + value = item->GetAddonInfo()->Origin(); + return true; + } + value = g_localizeStrings.Get(25014); + return true; + } + case LISTITEM_ADDON_SIZE: + { + uint64_t packageSize = item->GetAddonInfo()->PackageSize(); + if (packageSize > 0) + { + value = StringUtils::FormatFileSize(packageSize); + return true; + } + break; + } + } + } + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // ADDON_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case ADDON_SETTING_STRING: + { + ADDON::AddonPtr addon; + if (!CServiceBroker::GetAddonMgr().GetAddon(info.GetData3(), addon, + ADDON::OnlyEnabled::CHOICE_YES)) + { + return false; + } + value = addon->GetSetting(info.GetData5()); + return true; + } + /////////////////////////////////////////////////////////////////////////////////////////////// + // SYSTEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SYSTEM_ADDON_TITLE: + case SYSTEM_ADDON_ICON: + case SYSTEM_ADDON_VERSION: + { + // This logic does not check/care whether an addon has been disabled/marked as broken, + // it simply retrieves it's name or icon that means if an addon is placed on the home screen it + // will stay there even if it's disabled/marked as broken. This might need to be changed/fixed + // in the future. + ADDON::AddonPtr addon; + if (!info.GetData3().empty()) + { + bool success = CServiceBroker::GetAddonMgr().GetAddon(info.GetData3(), addon, + ADDON::OnlyEnabled::CHOICE_YES); + if (!success || !addon) + break; + + if (info.m_info == SYSTEM_ADDON_TITLE) + { + value = addon->Name(); + return true; + } + if (info.m_info == SYSTEM_ADDON_ICON) + { + value = addon->Icon(); + return true; + } + if (info.m_info == SYSTEM_ADDON_VERSION) + { + value = addon->Version().asString(); + return true; + } + } + break; + } + } + + return false; +} + +bool CAddonsGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // ADDON_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case ADDON_SETTING_INT: + { + ADDON::AddonPtr addon; + if (!CServiceBroker::GetAddonMgr().GetAddon(info.GetData3(), addon, + ADDON::OnlyEnabled::CHOICE_YES)) + { + return false; + } + return addon->GetSettingInt(info.GetData5(), value); + } + } + return false; +} + +bool CAddonsGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // ADDON_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case ADDON_SETTING_BOOL: + { + ADDON::AddonPtr addon; + if (!CServiceBroker::GetAddonMgr().GetAddon(info.GetData3(), addon, + ADDON::OnlyEnabled::CHOICE_YES)) + { + return false; + } + return addon->GetSettingBool(info.GetData5(), value); + } + /////////////////////////////////////////////////////////////////////////////////////////////// + // SYSTEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SYSTEM_HAS_ADDON: + { + ADDON::AddonPtr addon; + value = CServiceBroker::GetAddonMgr().IsAddonInstalled(info.GetData3()); + return true; + } + case SYSTEM_ADDON_IS_ENABLED: + { + value = false; + ADDON::AddonPtr addon; + if (CServiceBroker::GetAddonMgr().GetAddon(info.GetData3(), addon, + ADDON::OnlyEnabled::CHOICE_YES)) + value = !CServiceBroker::GetAddonMgr().IsAddonDisabled(info.GetData3()); + return true; + } + case LISTITEM_ISAUTOUPDATEABLE: + { + value = true; + const CFileItem* item = static_cast<const CFileItem*>(gitem); + if (item->GetAddonInfo()) + value = CServiceBroker::GetAddonMgr().IsAutoUpdateable(item->GetAddonInfo()->ID()) || + !CServiceBroker::GetAddonMgr().IsAddonInstalled(item->GetAddonInfo()->ID(), + item->GetAddonInfo()->Origin()); + + //! @Todo: store origin of not-autoupdateable installed addons in table 'update_rules' + // of the addon database. this is needed to pin ambiguous addon-id's that are + // available from multiple origins accordingly. + // + // after this is done the above call should be changed to + // + // value = CServiceBroker::GetAddonMgr().IsAutoUpdateable(item->GetAddonInfo()->ID(), + // item->GetAddonInfo()->Origin()); + + return true; + } + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/AddonsGUIInfo.h b/xbmc/guilib/guiinfo/AddonsGUIInfo.h new file mode 100644 index 0000000..e06ef51 --- /dev/null +++ b/xbmc/guilib/guiinfo/AddonsGUIInfo.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CAddonsGUIInfo : public CGUIInfoProvider +{ +public: + CAddonsGUIInfo() = default; + ~CAddonsGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/CMakeLists.txt b/xbmc/guilib/guiinfo/CMakeLists.txt new file mode 100644 index 0000000..9203511 --- /dev/null +++ b/xbmc/guilib/guiinfo/CMakeLists.txt @@ -0,0 +1,42 @@ +set(SOURCES GUIInfo.cpp + GUIInfoHelper.cpp + GUIInfoProviders.cpp + GUIInfoLabel.cpp + GUIInfoBool.cpp + GUIInfoColor.cpp + AddonsGUIInfo.cpp + GamesGUIInfo.cpp + GUIControlsGUIInfo.cpp + LibraryGUIInfo.cpp + MusicGUIInfo.cpp + PicturesGUIInfo.cpp + PlayerGUIInfo.cpp + SkinGUIInfo.cpp + SystemGUIInfo.cpp + VideoGUIInfo.cpp + VisualisationGUIInfo.cpp + WeatherGUIInfo.cpp) + +set(HEADERS GUIInfo.h + GUIInfoHelper.h + GUIInfoLabels.h + GUIInfoProvider.h + GUIInfoProviders.h + GUIInfoLabel.h + GUIInfoBool.h + GUIInfoColor.h + IGUIInfoProvider.h + AddonsGUIInfo.h + GamesGUIInfo.h + GUIControlsGUIInfo.h + LibraryGUIInfo.h + MusicGUIInfo.h + PicturesGUIInfo.h + PlayerGUIInfo.h + SkinGUIInfo.h + SystemGUIInfo.h + VideoGUIInfo.h + VisualisationGUIInfo.h + WeatherGUIInfo.h) + +core_add_library(guilib_guiinfo) diff --git a/xbmc/guilib/guiinfo/GUIControlsGUIInfo.cpp b/xbmc/guilib/guiinfo/GUIControlsGUIInfo.cpp new file mode 100644 index 0000000..a5ee133 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIControlsGUIInfo.cpp @@ -0,0 +1,814 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/GUIControlsGUIInfo.h" + +#include "FileItem.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "dialogs/GUIDialogKeyboardGeneric.h" +#include "dialogs/GUIDialogNumeric.h" +#include "dialogs/GUIDialogProgress.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIControlGroupList.h" +#include "guilib/GUITextBox.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/IGUIContainer.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoHelper.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "music/dialogs/GUIDialogMusicInfo.h" +#include "music/dialogs/GUIDialogSongInfo.h" +#include "music/tags/MusicInfoTag.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "video/VideoInfoTag.h" +#include "video/dialogs/GUIDialogVideoInfo.h" +#include "view/GUIViewState.h" +#include "windows/GUIMediaWindow.h" + +using namespace KODI::GUILIB; +using namespace KODI::GUILIB::GUIINFO; + +void CGUIControlsGUIInfo::SetContainerMoving(int id, bool next, bool scrolling) +{ + // magnitude 2 indicates a scroll, sign indicates direction + m_containerMoves[id] = (next ? 1 : -1) * (scrolling ? 2 : 1); +} + +void CGUIControlsGUIInfo::ResetContainerMovingCache() +{ + m_containerMoves.clear(); +} + +bool CGUIControlsGUIInfo::InitCurrentItem(CFileItem *item) +{ + return false; +} + +bool CGUIControlsGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // CONTAINER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case CONTAINER_FOLDERPATH: + case CONTAINER_FOLDERNAME: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + if (info.m_info == CONTAINER_FOLDERNAME) + value = window->CurrentDirectory().GetLabel(); + else + value = CURL(window->CurrentDirectory().GetPath()).GetWithoutUserDetails(); + return true; + } + break; + } + case CONTAINER_PLUGINNAME: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + const CURL url(window->CurrentDirectory().GetPath()); + if (url.IsProtocol("plugin")) + { + value = URIUtils::GetFileName(url.GetHostName()); + return true; + } + } + break; + } + case CONTAINER_VIEWCOUNT: + case CONTAINER_VIEWMODE: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + const CGUIControl *control = window->GetControl(window->GetViewContainerID()); + if (control && control->IsContainer()) + { + if (info.m_info == CONTAINER_VIEWMODE) + { + value = static_cast<const IGUIContainer*>(control)->GetLabel(); + return true; + } + else if (info.m_info == CONTAINER_VIEWCOUNT) + { + value = std::to_string(window->GetViewCount()); + return true; + } + } + } + break; + } + case CONTAINER_SORT_METHOD: + case CONTAINER_SORT_ORDER: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + const CGUIViewState *viewState = window->GetViewState(); + if (viewState) + { + if (info.m_info == CONTAINER_SORT_METHOD) + { + value = g_localizeStrings.Get(viewState->GetSortMethodLabel()); + return true; + } + else if (info.m_info == CONTAINER_SORT_ORDER) + { + value = g_localizeStrings.Get(viewState->GetSortOrderLabel()); + return true; + } + } + } + break; + } + case CONTAINER_PROPERTY: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetProperty(info.GetData3()).asString(); + return true; + } + break; + } + case CONTAINER_ART: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetArt(info.GetData3()); + return true; + } + break; + } + case CONTAINER_CONTENT: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetContent(); + return true; + } + break; + } + case CONTAINER_SHOWPLOT: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetProperty("showplot").asString(); + return true; + } + break; + } + case CONTAINER_SHOWTITLE: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetProperty("showtitle").asString(); + return true; + } + break; + } + case CONTAINER_PLUGINCATEGORY: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetProperty("plugincategory").asString(); + return true; + } + break; + } + case CONTAINER_TOTALTIME: + case CONTAINER_TOTALWATCHED: + case CONTAINER_TOTALUNWATCHED: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + int count = 0; + const CFileItemList& items = window->CurrentDirectory(); + for (const auto& item : items) + { + // Iterate through container and count watched, unwatched and total duration. + if (info.m_info == CONTAINER_TOTALWATCHED && item->HasVideoInfoTag() && item->GetVideoInfoTag()->GetPlayCount() > 0) + count += 1; + else if (info.m_info == CONTAINER_TOTALUNWATCHED && item->HasVideoInfoTag() && item->GetVideoInfoTag()->GetPlayCount() == 0) + count += 1; + else if (info.m_info == CONTAINER_TOTALTIME && item->HasMusicInfoTag()) + count += item->GetMusicInfoTag()->GetDuration(); + else if (info.m_info == CONTAINER_TOTALTIME && item->HasVideoInfoTag()) + count += item->GetVideoInfoTag()->m_streamDetails.GetVideoDuration(); + } + if (info.m_info == CONTAINER_TOTALTIME && count > 0) + { + value = StringUtils::SecondsToTimeString(count); + return true; + } + else if (info.m_info == CONTAINER_TOTALWATCHED || info.m_info == CONTAINER_TOTALUNWATCHED) + { + value = std::to_string(count); + return true; + } + } + break; + } + case CONTAINER_NUM_PAGES: + case CONTAINER_CURRENT_PAGE: + case CONTAINER_NUM_ITEMS: + case CONTAINER_POSITION: + case CONTAINER_ROW: + case CONTAINER_COLUMN: + case CONTAINER_CURRENT_ITEM: + case CONTAINER_NUM_ALL_ITEMS: + case CONTAINER_NUM_NONFOLDER_ITEMS: + { + const CGUIControl *control = nullptr; + if (info.GetData1()) + { // container specified + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + control = window->GetControl(info.GetData1()); + } + else + { // no container specified - assume a mediawindow + CGUIMediaWindow *window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + control = window->GetControl(window->GetViewContainerID()); + } + if (control) + { + if (control->IsContainer()) + value = static_cast<const IGUIContainer*>(control)->GetLabel(info.m_info); + else if (control->GetControlType() == CGUIControl::GUICONTROL_GROUPLIST) + value = static_cast<const CGUIControlGroupList*>(control)->GetLabel(info.m_info); + else if (control->GetControlType() == CGUIControl::GUICONTROL_TEXTBOX) + value = static_cast<const CGUITextBox*>(control)->GetLabel(info.m_info); + return true; + } + break; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // CONTROL_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case CONTROL_GET_LABEL: + { + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + { + const CGUIControl *control = window->GetControl(info.GetData1()); + if (control) + { + int data2 = info.GetData2(); + if (data2) + value = control->GetDescriptionByIndex(data2); + else + value = control->GetDescription(); + return true; + } + } + break; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // WINDOW_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case WINDOW_PROPERTY: + { + CGUIWindow *window = nullptr; + if (info.GetData1()) + { // window specified + window = CServiceBroker::GetGUI()->GetWindowManager().GetWindow(info.GetData1()); + } + else + { // no window specified - assume active + window = GUIINFO::GetWindow(contextWindow); + } + if (window) + { + value = window->GetProperty(info.GetData3()).asString(); + return true; + } + break; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // SYSTEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SYSTEM_CURRENT_WINDOW: + value = g_localizeStrings.Get(CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindowOrDialog()); + return true; + case SYSTEM_STARTUP_WINDOW: + value = std::to_string(CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt( + CSettings::SETTING_LOOKANDFEEL_STARTUPWINDOW)); + return true; + case SYSTEM_CURRENT_CONTROL: + case SYSTEM_CURRENT_CONTROL_ID: + { + CGUIWindow *window = CServiceBroker::GetGUI()->GetWindowManager().GetWindow(CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindowOrDialog()); + if (window) + { + CGUIControl *control = window->GetFocusedControl(); + if (control) + { + if (info.m_info == SYSTEM_CURRENT_CONTROL_ID) + value = std::to_string(control->GetID()); + else if (info.m_info == SYSTEM_CURRENT_CONTROL) + value = control->GetDescription(); + return true; + } + } + break; + } + case SYSTEM_PROGRESS_BAR: + { + CGUIDialogProgress *bar = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogProgress>(WINDOW_DIALOG_PROGRESS); + if (bar && bar->IsDialogRunning()) + value = std::to_string(bar->GetPercentage()); + return true; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // FANART_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case FANART_COLOR1: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetProperty("fanart_color1").asString(); + return true; + } + break; + } + case FANART_COLOR2: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetProperty("fanart_color2").asString(); + return true; + } + break; + } + case FANART_COLOR3: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetProperty("fanart_color3").asString(); + return true; + } + break; + } + case FANART_IMAGE: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetArt("fanart"); + return true; + } + break; + } + } + + return false; +} + +bool CGUIControlsGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // SYSTEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SYSTEM_PROGRESS_BAR: + { + CGUIDialogProgress *bar = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogProgress>(WINDOW_DIALOG_PROGRESS); + if (bar && bar->IsDialogRunning()) + value = bar->GetPercentage(); + return true; + } + } + + return false; +} + +bool CGUIControlsGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // CONTAINER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case CONTAINER_HASFILES: + case CONTAINER_HASFOLDERS: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + const CFileItemList& items = window->CurrentDirectory(); + for (const auto& item : items) + { + if ((!item->m_bIsFolder && info.m_info == CONTAINER_HASFILES) || + (item->m_bIsFolder && !item->IsParentFolder() && info.m_info == CONTAINER_HASFOLDERS)) + { + value = true; + return true; + } + } + } + break; + } + case CONTAINER_STACKED: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().GetProperty("isstacked").asBoolean(); + return true; + } + break; + } + case CONTAINER_HAS_THUMB: + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CurrentDirectory().HasArt("thumb"); + return true; + } + break; + } + case CONTAINER_CAN_FILTER: + { + CGUIMediaWindow *window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = !window->CanFilterAdvanced(); + return true; + } + break; + } + case CONTAINER_CAN_FILTERADVANCED: + { + CGUIMediaWindow *window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->CanFilterAdvanced(); + return true; + } + break; + } + case CONTAINER_FILTERED: + { + CGUIMediaWindow *window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = window->IsFiltered(); + return true; + } + break; + } + case CONTAINER_SORT_METHOD: + { + CGUIMediaWindow *window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + const CGUIViewState *viewState = window->GetViewState(); + if (viewState) + { + value = (static_cast<int>(viewState->GetSortMethod().sortBy) == info.GetData2()); + return true; + } + } + break; + } + case CONTAINER_SORT_DIRECTION: + { + CGUIMediaWindow *window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + const CGUIViewState *viewState = window->GetViewState(); + if (viewState) + { + value = (static_cast<unsigned int>(viewState->GetSortOrder()) == info.GetData1()); + return true; + } + } + break; + } + case CONTAINER_CONTENT: + { + std::string content; + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + { + if (window->GetID() == WINDOW_DIALOG_MUSIC_INFO) + content = static_cast<CGUIDialogMusicInfo*>(window)->GetContent(); + else if (window->GetID() == WINDOW_DIALOG_SONG_INFO) + content = static_cast<CGUIDialogSongInfo*>(window)->GetContent(); + else if (window->GetID() == WINDOW_DIALOG_VIDEO_INFO) + content = static_cast<CGUIDialogVideoInfo*>(window)->CurrentDirectory().GetContent(); + } + if (content.empty()) + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + content = window->CurrentDirectory().GetContent(); + } + value = StringUtils::EqualsNoCase(info.GetData3(), content); + return true; + } + case CONTAINER_ROW: + case CONTAINER_COLUMN: + case CONTAINER_POSITION: + case CONTAINER_HAS_NEXT: + case CONTAINER_HAS_PREVIOUS: + case CONTAINER_SCROLLING: + case CONTAINER_SUBITEM: + case CONTAINER_ISUPDATING: + case CONTAINER_HAS_PARENT_ITEM: + { + if (info.GetData1()) + { + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + { + const CGUIControl *control = window->GetControl(info.GetData1()); + if (control) + { + value = control->GetCondition(info.m_info, info.GetData2()); + return true; + } + } + } + else + { + const CGUIControl *activeContainer = GUIINFO::GetActiveContainer(0, contextWindow); + if (activeContainer) + { + value = activeContainer->GetCondition(info.m_info, info.GetData2()); + return true; + } + } + break; + } + case CONTAINER_HAS_FOCUS: + { // grab our container + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + { + const CGUIControl *control = window->GetControl(info.GetData1()); + if (control && control->IsContainer()) + { + const CFileItemPtr item = std::static_pointer_cast<CFileItem>(static_cast<const IGUIContainer*>(control)->GetListItem(0)); + if (item && item->m_iprogramCount == info.GetData2()) // programcount used to store item id + { + value = true; + return true; + } + } + } + break; + } + case CONTAINER_SCROLL_PREVIOUS: + case CONTAINER_MOVE_PREVIOUS: + case CONTAINER_MOVE_NEXT: + case CONTAINER_SCROLL_NEXT: + { + int containerId = -1; + if (info.GetData1()) + { + containerId = info.GetData1(); + } + else + { + // no parameters, so we assume it's just requested for a media window. It therefore + // can only happen if the list has focus. + CGUIMediaWindow *window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + containerId = window->GetViewContainerID(); + } + if (containerId != -1) + { + const std::map<int,int>::const_iterator it = m_containerMoves.find(containerId); + if (it != m_containerMoves.end()) + { + if (info.m_info == CONTAINER_SCROLL_PREVIOUS) + value = it->second <= -2; + else if (info.m_info == CONTAINER_MOVE_PREVIOUS) + value = it->second <= -1; + else if (info.m_info == CONTAINER_MOVE_NEXT) + value = it->second >= 1; + else if (info.m_info == CONTAINER_SCROLL_NEXT) + value = it->second >= 2; + return true; + } + } + break; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // CONTROL_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case CONTROL_IS_VISIBLE: + { + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + { + // Note: This'll only work for unique id's + const CGUIControl *control = window->GetControl(info.GetData1()); + if (control) + { + value = control->IsVisible(); + return true; + } + } + break; + } + case CONTROL_IS_ENABLED: + { + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + { + // Note: This'll only work for unique id's + const CGUIControl *control = window->GetControl(info.GetData1()); + if (control) + { + value = !control->IsDisabled(); + return true; + } + } + break; + } + case CONTROL_HAS_FOCUS: + { + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + { + value = (window->GetFocusedControlID() == static_cast<int>(info.GetData1())); + return true; + } + break; + } + case CONTROL_GROUP_HAS_FOCUS: + { + CGUIWindow *window = GUIINFO::GetWindow(contextWindow); + if (window) + { + value = window->ControlGroupHasFocus(info.GetData1(), info.GetData2()); + return true; + } + break; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // WINDOW_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case WINDOW_IS_MEDIA: + { // note: This doesn't return true for dialogs (content, favourites, login, videoinfo) + CGUIWindowManager& windowMgr = CServiceBroker::GetGUI()->GetWindowManager(); + CGUIWindow *window = windowMgr.GetWindow(windowMgr.GetActiveWindow()); + if (window) + { + value = window->IsMediaWindow(); + return true; + } + break; + } + case WINDOW_IS: + { + if (info.GetData1()) + { + CGUIWindowManager& windowMgr = CServiceBroker::GetGUI()->GetWindowManager(); + CGUIWindow *window = windowMgr.GetWindow(contextWindow); + if (!window) + { + // try topmost dialog + window = windowMgr.GetWindow(windowMgr.GetTopmostModalDialog()); + if (!window) + { + // try active window + window = windowMgr.GetWindow(windowMgr.GetActiveWindow()); + } + } + if (window) + { + value = (window && window->GetID() == static_cast<int>(info.GetData1())); + return true; + } + } + break; + } + case WINDOW_IS_VISIBLE: + { + if (info.GetData1()) + value = CServiceBroker::GetGUI()->GetWindowManager().IsWindowVisible(info.GetData1()); + else + value = CServiceBroker::GetGUI()->GetWindowManager().IsWindowVisible(info.GetData3()); + return true; + } + case WINDOW_IS_ACTIVE: + { + if (info.GetData1()) + value = CServiceBroker::GetGUI()->GetWindowManager().IsWindowActive(info.GetData1()); + else + value = CServiceBroker::GetGUI()->GetWindowManager().IsWindowActive(info.GetData3()); + return true; + } + case WINDOW_IS_DIALOG_TOPMOST: + { + if (info.GetData1()) + value = CServiceBroker::GetGUI()->GetWindowManager().IsDialogTopmost(info.GetData1()); + else + value = CServiceBroker::GetGUI()->GetWindowManager().IsDialogTopmost(info.GetData3()); + return true; + } + case WINDOW_IS_MODAL_DIALOG_TOPMOST: + { + if (info.GetData1()) + value = CServiceBroker::GetGUI()->GetWindowManager().IsModalDialogTopmost(info.GetData1()); + else + value = CServiceBroker::GetGUI()->GetWindowManager().IsModalDialogTopmost(info.GetData3()); + return true; + } + case WINDOW_NEXT: + { + if (info.GetData1()) + { + value = (static_cast<int>(info.GetData1()) == m_nextWindowID); + return true; + } + else + { + CGUIWindow *window = CServiceBroker::GetGUI()->GetWindowManager().GetWindow(m_nextWindowID); + if (window && StringUtils::EqualsNoCase(URIUtils::GetFileName(window->GetProperty("xmlfile").asString()), info.GetData3())) + { + value = true; + return true; + } + } + break; + } + case WINDOW_PREVIOUS: + { + if (info.GetData1()) + { + value = (static_cast<int>(info.GetData1()) == m_prevWindowID); + return true; + } + else + { + CGUIWindow *window = CServiceBroker::GetGUI()->GetWindowManager().GetWindow(m_prevWindowID); + if (window && StringUtils::EqualsNoCase(URIUtils::GetFileName(window->GetProperty("xmlfile").asString()), info.GetData3())) + { + value = true; + return true; + } + } + break; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // SYSTEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SYSTEM_HAS_ACTIVE_MODAL_DIALOG: + value = CServiceBroker::GetGUI()->GetWindowManager().HasModalDialog(true); + return true; + case SYSTEM_HAS_VISIBLE_MODAL_DIALOG: + value = CServiceBroker::GetGUI()->GetWindowManager().HasVisibleModalDialog(); + return true; + case SYSTEM_HAS_INPUT_HIDDEN: + { + CGUIDialogNumeric *pNumeric = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogNumeric>(WINDOW_DIALOG_NUMERIC); + CGUIDialogKeyboardGeneric *pKeyboard = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogKeyboardGeneric>(WINDOW_DIALOG_KEYBOARD); + + if (pNumeric && pNumeric->IsActive()) + value = pNumeric->IsInputHidden(); + else if (pKeyboard && pKeyboard->IsActive()) + value = pKeyboard->IsInputHidden(); + return true; + } + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/GUIControlsGUIInfo.h b/xbmc/guilib/guiinfo/GUIControlsGUIInfo.h new file mode 100644 index 0000000..f6b8b68 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIControlsGUIInfo.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/WindowIDs.h" +#include "guilib/guiinfo/GUIInfoProvider.h" + +#include <map> + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CGUIControlsGUIInfo : public CGUIInfoProvider +{ +public: + ~CGUIControlsGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + + void SetNextWindow(int windowID) { m_nextWindowID = windowID; } + void SetPreviousWindow(int windowID) { m_prevWindowID = windowID; } + + /*! \brief containers call this to specify that the focus is changing + \param id control id + \param next true if we're moving to the next item, false if previous + \param scrolling true if the container is scrolling, false if the movement requires no scroll + */ + void SetContainerMoving(int id, bool next, bool scrolling); + void ResetContainerMovingCache(); + +private: + int m_nextWindowID = WINDOW_INVALID; + int m_prevWindowID = WINDOW_INVALID; + + std::map<int, int> m_containerMoves; // direction of list moving +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/GUIInfo.cpp b/xbmc/guilib/guiinfo/GUIInfo.cpp new file mode 100644 index 0000000..5542a78 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfo.cpp @@ -0,0 +1,33 @@ +/* + * 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 "GUIInfo.h" + +#include <assert.h> + +using namespace KODI::GUILIB::GUIINFO; + +void CGUIInfo::SetInfoFlag(uint32_t flag) +{ + assert(flag >= (1 << 24)); + m_data1 |= flag; +} + +uint32_t CGUIInfo::GetInfoFlag() const +{ + // we strip out the bottom 24 bits, where we keep data + // and return the flag only + return m_data1 & 0xff000000; +} + +uint32_t CGUIInfo::GetData1() const +{ + // we strip out the top 8 bits, where we keep flags + // and return the unflagged data + return m_data1 & ((1 << 24) -1); +} diff --git a/xbmc/guilib/guiinfo/GUIInfo.h b/xbmc/guilib/guiinfo/GUIInfo.h new file mode 100644 index 0000000..c5bffe8 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfo.h @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#pragma once + +#include <stdint.h> +#include <string> + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +// class to hold multiple integer data +// for storage referenced from a single integer +class CGUIInfo +{ +public: + CGUIInfo(int info, uint32_t data1, int data2, uint32_t flag, const std::string& data3, int data4) + : m_info(info), + m_data1(data1), + m_data2(data2), + m_data3(data3), + m_data4(data4) + { + if (flag) + SetInfoFlag(flag); + } + + explicit CGUIInfo(int info, uint32_t data1 = 0, int data2 = 0, uint32_t flag = 0) + : m_info(info), + m_data1(data1), + m_data2(data2), + m_data4(0) + { + if (flag) + SetInfoFlag(flag); + } + + CGUIInfo(int info, uint32_t data1, int data2, const std::string& data3) + : m_info(info), m_data1(data1), m_data2(data2), m_data3(data3), m_data4(0) + { + } + + CGUIInfo(int info, uint32_t data1, const std::string& data3) + : m_info(info), + m_data1(data1), + m_data2(0), + m_data3(data3), + m_data4(0) + { + } + + CGUIInfo(int info, const std::string& data3) + : m_info(info), + m_data1(0), + m_data2(0), + m_data3(data3), + m_data4(0) + { + } + + CGUIInfo(int info, const std::string& data3, int data2) + : m_info(info), + m_data1(0), + m_data2(data2), + m_data3(data3), + m_data4(0) + { + } + + CGUIInfo(int info, const std::string& data3, const std::string& data5) + : m_info(info), m_data1(0), m_data3(data3), m_data4(0), m_data5(data5) + { + } + + bool operator ==(const CGUIInfo &right) const + { + return (m_info == right.m_info && m_data1 == right.m_data1 && m_data2 == right.m_data2 && + m_data3 == right.m_data3 && m_data4 == right.m_data4 && m_data5 == right.m_data5); + } + + uint32_t GetInfoFlag() const; + uint32_t GetData1() const; + int GetData2() const { return m_data2; } + const std::string& GetData3() const { return m_data3; } + int GetData4() const { return m_data4; } + const std::string& GetData5() const { return m_data5; } + + int m_info; +private: + void SetInfoFlag(uint32_t flag); + + uint32_t m_data1; + int m_data2; + std::string m_data3; + int m_data4; + std::string m_data5; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/GUIInfoBool.cpp b/xbmc/guilib/guiinfo/GUIInfoBool.cpp new file mode 100644 index 0000000..2f6b4f9 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoBool.cpp @@ -0,0 +1,41 @@ +/* + * 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 "guilib/guiinfo/GUIInfoBool.h" + +#include "GUIInfoManager.h" +#include "ServiceBroker.h" +#include "guilib/GUIComponent.h" + +using namespace KODI::GUILIB::GUIINFO; + +CGUIInfoBool::CGUIInfoBool(bool value) +{ + m_value = value; +} + +CGUIInfoBool::~CGUIInfoBool() = default; + +void CGUIInfoBool::Parse(const std::string &expression, int context) +{ + if (expression == "true") + m_value = true; + else if (expression == "false") + m_value = false; + else + { + m_info = CServiceBroker::GetGUI()->GetInfoManager().Register(expression, context); + Update(context); + } +} + +void CGUIInfoBool::Update(int contextWindow, const CGUIListItem* item /*= nullptr*/) +{ + if (m_info) + m_value = m_info->Get(contextWindow, item); +} diff --git a/xbmc/guilib/guiinfo/GUIInfoBool.h b/xbmc/guilib/guiinfo/GUIInfoBool.h new file mode 100644 index 0000000..1913684 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoBool.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#pragma once + +/*! +\file GUIInfoBool.h +\brief +*/ + +#include "interfaces/info/InfoBool.h" + +#include <string> + +class CGUIListItem; + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfoBool +{ +public: + explicit CGUIInfoBool(bool value = false); + ~CGUIInfoBool(); + + operator bool() const { return m_value; } + + void Update(int contextWindow, const CGUIListItem* item = nullptr); + void Parse(const std::string &expression, int context); +private: + INFO::InfoPtr m_info; + bool m_value; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/GUIInfoColor.cpp b/xbmc/guilib/guiinfo/GUIInfoColor.cpp new file mode 100644 index 0000000..c20326d --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoColor.cpp @@ -0,0 +1,69 @@ +/* + * 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 "guilib/guiinfo/GUIInfoColor.h" + +#include "FileItem.h" +#include "GUIInfoManager.h" +#include "ServiceBroker.h" +#include "addons/Skin.h" +#include "guilib/GUIColorManager.h" +#include "guilib/GUIComponent.h" +#include "utils/StringUtils.h" + +using namespace KODI::GUILIB::GUIINFO; + +bool CGUIInfoColor::Update(const CGUIListItem* item /* = nullptr */) +{ + if (!m_info) + return false; // no infolabel + + // Expand the infolabel, and then convert it to a color + std::string infoLabel; + if (item && item->IsFileItem()) + infoLabel = CServiceBroker::GetGUI()->GetInfoManager().GetItemLabel( + static_cast<const CFileItem*>(item), 0, m_info); + else + infoLabel = CServiceBroker::GetGUI()->GetInfoManager().GetLabel(m_info, INFO::DEFAULT_CONTEXT); + + UTILS::COLOR::Color color = + !infoLabel.empty() ? CServiceBroker::GetGUI()->GetColorManager().GetColor(infoLabel) : 0; + if (m_color != color) + { + m_color = color; + return true; + } + else + return false; +} + +void CGUIInfoColor::Parse(const std::string &label, int context) +{ + if (label.empty()) + return; + + CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager(); + + // Check for the standard $INFO[] block layout, and strip it if present + std::string label2 = label; + if (StringUtils::StartsWithNoCase(label, "$var[")) + { + label2 = label.substr(5, label.length() - 6); + m_info = infoMgr.TranslateSkinVariableString(label2, context); + if (!m_info) + m_info = infoMgr.RegisterSkinVariableString(g_SkinInfo->CreateSkinVariable(label2, context)); + return; + } + + if (StringUtils::StartsWithNoCase(label, "$info[")) + label2 = label.substr(6, label.length()-7); + + m_info = infoMgr.TranslateString(label2); + if (!m_info) + m_color = CServiceBroker::GetGUI()->GetColorManager().GetColor(label); +} diff --git a/xbmc/guilib/guiinfo/GUIInfoColor.h b/xbmc/guilib/guiinfo/GUIInfoColor.h new file mode 100644 index 0000000..a711047 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoColor.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#pragma once + +/*! +\file GUIInfoColor.h +\brief +*/ + +#include "guilib/GUIListItem.h" +#include "utils/ColorUtils.h" + +#include <string> + +class CGUIListItem; + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfoColor +{ +public: + constexpr CGUIInfoColor(UTILS::COLOR::Color color = 0) : m_color(color) {} + + constexpr operator UTILS::COLOR::Color() const { return m_color; } + + bool Update(const CGUIListItem* item = nullptr); + void Parse(const std::string &label, int context); + + /*! + * @brief Check if the infocolor has an info condition bound to its color definition (or otherwise, if it's constant color) + * @return true if the color depends on an info condition, false otherwise + */ + bool HasInfo() const { return m_info != 0; } + +private: + int m_info = 0; + UTILS::COLOR::Color m_color; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/GUIInfoHelper.cpp b/xbmc/guilib/guiinfo/GUIInfoHelper.cpp new file mode 100644 index 0000000..f025b5e --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoHelper.cpp @@ -0,0 +1,205 @@ +/* + * 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 "GUIInfoHelper.h" + +#include "FileItem.h" +#include "PlayListPlayer.h" +#include "ServiceBroker.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindow.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/IGUIContainer.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "playlists/PlayList.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "windows/GUIMediaWindow.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +// conditions for window retrieval +static const int WINDOW_CONDITION_HAS_LIST_ITEMS = 1; +static const int WINDOW_CONDITION_IS_MEDIA_WINDOW = 2; + +std::string GetPlaylistLabel(int item, PLAYLIST::Id playlistId /* = TYPE_NONE */) +{ + PLAYLIST::CPlayListPlayer& player = CServiceBroker::GetPlaylistPlayer(); + + if (playlistId == PLAYLIST::TYPE_NONE) + playlistId = player.GetCurrentPlaylist(); + + switch (item) + { + case PLAYLIST_LENGTH: + { + return std::to_string(player.GetPlaylist(playlistId).size()); + } + case PLAYLIST_POSITION: + { + int currentSong = player.GetCurrentSong(); + if (currentSong > -1) + return std::to_string(currentSong + 1); + break; + } + case PLAYLIST_RANDOM: + { + if (player.IsShuffled(playlistId)) + return g_localizeStrings.Get(16041); // 16041: On + else + return g_localizeStrings.Get(591); // 591: Off + } + case PLAYLIST_REPEAT: + { + PLAYLIST::RepeatState state = player.GetRepeat(playlistId); + if (state == PLAYLIST::RepeatState::ONE) + return g_localizeStrings.Get(592); // 592: One + else if (state == PLAYLIST::RepeatState::ALL) + return g_localizeStrings.Get(593); // 593: All + else + return g_localizeStrings.Get(594); // 594: Off + } + } + return std::string(); +} + +namespace +{ + +bool CheckWindowCondition(CGUIWindow *window, int condition) +{ + // check if it satisfies our condition + if (!window) + return false; + if ((condition & WINDOW_CONDITION_HAS_LIST_ITEMS) && !window->HasListItems()) + return false; + if ((condition & WINDOW_CONDITION_IS_MEDIA_WINDOW) && !window->IsMediaWindow()) + return false; + return true; +} + +CGUIWindow* GetWindowWithCondition(int contextWindow, int condition) +{ + const CGUIWindowManager& windowMgr = CServiceBroker::GetGUI()->GetWindowManager(); + + CGUIWindow *window = windowMgr.GetWindow(contextWindow); + if (CheckWindowCondition(window, condition)) + return window; + + // try topmost dialog + window = windowMgr.GetWindow(windowMgr.GetTopmostModalDialog()); + if (CheckWindowCondition(window, condition)) + return window; + + // try active window + window = windowMgr.GetWindow(windowMgr.GetActiveWindow()); + if (CheckWindowCondition(window, condition)) + return window; + + return nullptr; +} + +} // unnamed namespace + +CGUIWindow* GetWindow(int contextWindow) +{ + return GetWindowWithCondition(contextWindow, 0); +} + +CFileItemPtr GetCurrentListItemFromWindow(int contextWindow) +{ + CGUIWindow* window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_HAS_LIST_ITEMS); + if (window) + return window->GetCurrentListItem(); + + return CFileItemPtr(); +} + +CGUIMediaWindow* GetMediaWindow(int contextWindow) +{ + CGUIWindow* window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW); + if (window) + return static_cast<CGUIMediaWindow*>(window); + + return nullptr; +} + +CGUIControl* GetActiveContainer(int containerId, int contextWindow) +{ + CGUIWindow *window = GetWindow(contextWindow); + if (!window) + return nullptr; + + CGUIControl *control = nullptr; + if (!containerId) // No container specified, so we lookup the current view container + { + if (window->IsMediaWindow()) + containerId = static_cast<CGUIMediaWindow*>(window)->GetViewContainerID(); + else + control = window->GetFocusedControl(); + } + + if (!control) + control = window->GetControl(containerId); + + if (control && control->IsContainer()) + return control; + + return nullptr; +} + +CGUIListItemPtr GetCurrentListItem(int contextWindow, int containerId /* = 0 */, int itemOffset /* = 0 */, unsigned int itemFlags /* = 0 */) +{ + CGUIListItemPtr item; + + if (containerId == 0 && + itemOffset == 0 && + !(itemFlags & INFOFLAG_LISTITEM_CONTAINER) && + !(itemFlags & INFOFLAG_LISTITEM_ABSOLUTE) && + !(itemFlags & INFOFLAG_LISTITEM_POSITION)) + item = GetCurrentListItemFromWindow(contextWindow); + + if (!item) + { + CGUIControl* activeContainer = GetActiveContainer(containerId, contextWindow); + if (activeContainer) + item = static_cast<IGUIContainer *>(activeContainer)->GetListItem(itemOffset, itemFlags); + } + + return item; +} + +std::string GetFileInfoLabelValueFromPath(int info, const std::string& filenameAndPath) +{ + std::string value = filenameAndPath; + + if (info == PLAYER_PATH) + { + // do this twice since we want the path outside the archive if this is to be of use. + if (URIUtils::IsInArchive(value)) + value = URIUtils::GetParentPath(value); + + value = URIUtils::GetParentPath(value); + } + else if (info == PLAYER_FILENAME) + { + value = URIUtils::GetFileName(value); + } + + return value; +} + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/GUIInfoHelper.h b/xbmc/guilib/guiinfo/GUIInfoHelper.h new file mode 100644 index 0000000..ce5191e --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoHelper.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#pragma once + +#include "playlists/PlayListTypes.h" + +#include <memory> +#include <string> + +class CFileItem; + +class CGUIListItem; +typedef std::shared_ptr<CGUIListItem> CGUIListItemPtr; + +class CGUIControl; +class CGUIMediaWindow; +class CGUIWindow; + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +std::string GetPlaylistLabel(int item, PLAYLIST::Id playlistid = PLAYLIST::TYPE_NONE); + +CGUIWindow* GetWindow(int contextWindow); +CGUIControl* GetActiveContainer(int containerId, int contextWindow); +CGUIMediaWindow* GetMediaWindow(int contextWindow); +CGUIListItemPtr GetCurrentListItem(int contextWindow, int containerId = 0, int itemOffset = 0, unsigned int itemFlags = 0); + +std::string GetFileInfoLabelValueFromPath(int info, const std::string& filenameAndPath); + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/GUIInfoLabel.cpp b/xbmc/guilib/guiinfo/GUIInfoLabel.cpp new file mode 100644 index 0000000..4a6ce13 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoLabel.cpp @@ -0,0 +1,337 @@ +/* + * 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 "guilib/guiinfo/GUIInfoLabel.h" + +#include "FileItem.h" +#include "GUIInfoManager.h" +#include "addons/Skin.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIListItem.h" +#include "guilib/LocalizeStrings.h" +#include "utils/StringUtils.h" +#include "utils/log.h" + +using namespace KODI::GUILIB::GUIINFO; + +CGUIInfoLabel::CGUIInfoLabel(const std::string &label, const std::string &fallback /*= ""*/, int context /*= 0*/) +{ + SetLabel(label, fallback, context); +} + +int CGUIInfoLabel::GetIntValue(int contextWindow) const +{ + const std::string label = GetLabel(contextWindow); + if (!label.empty()) + return strtol(label.c_str(), NULL, 10); + + return 0; +} + +void CGUIInfoLabel::SetLabel(const std::string &label, const std::string &fallback, int context /*= 0*/) +{ + m_fallback = fallback; + Parse(label, context); +} + +const std::string &CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, std::string *fallback /*= NULL*/) const +{ + bool needsUpdate = m_dirty; + if (!m_info.empty()) + { + CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager(); + for (const auto &portion : m_info) + { + if (portion.m_info) + { + std::string infoLabel; + if (preferImage) + infoLabel = infoMgr.GetImage(portion.m_info, contextWindow, fallback); + if (infoLabel.empty()) + infoLabel = infoMgr.GetLabel(portion.m_info, contextWindow, fallback); + needsUpdate |= portion.NeedsUpdate(infoLabel); + } + } + } + else + needsUpdate = !m_label.empty(); + + return CacheLabel(needsUpdate); +} + +const std::string &CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImages, std::string *fallback /*= NULL*/) const +{ + bool needsUpdate = m_dirty; + if (item->IsFileItem() && !m_info.empty()) + { + CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager(); + for (const auto &portion : m_info) + { + if (portion.m_info) + { + std::string infoLabel; + if (preferImages) + infoLabel = infoMgr.GetItemImage(item, 0, portion.m_info, fallback); + else + infoLabel = infoMgr.GetItemLabel(static_cast<const CFileItem *>(item), 0, portion.m_info, fallback); + needsUpdate |= portion.NeedsUpdate(infoLabel); + } + } + } + else + needsUpdate = !m_label.empty(); + + return CacheLabel(needsUpdate); +} + +const std::string &CGUIInfoLabel::CacheLabel(bool rebuild) const +{ + if (rebuild) + { + m_label.clear(); + for (const auto &portion : m_info) + m_label += portion.Get(); + m_dirty = false; + } + if (m_label.empty()) // empty label, use the fallback + return m_fallback; + return m_label; +} + +bool CGUIInfoLabel::IsEmpty() const +{ + return m_info.empty(); +} + +bool CGUIInfoLabel::IsConstant() const +{ + return m_info.empty() || (m_info.size() == 1 && m_info[0].m_info == 0); +} + +bool CGUIInfoLabel::ReplaceSpecialKeywordReferences(const std::string &strInput, const std::string &strKeyword, const StringReplacerFunc &func, std::string &strOutput) +{ + // replace all $strKeyword[value] with resolved strings + const std::string dollarStrPrefix = "$" + strKeyword + "["; + + size_t index = 0; + size_t startPos; + + while ((startPos = strInput.find(dollarStrPrefix, index)) != std::string::npos) + { + size_t valuePos = startPos + dollarStrPrefix.size(); + size_t endPos = StringUtils::FindEndBracket(strInput, '[', ']', valuePos); + if (endPos != std::string::npos) + { + if (index == 0) // first occurrence? + strOutput.clear(); + strOutput.append(strInput, index, startPos - index); // append part from the left side + strOutput += func(strInput.substr(valuePos, endPos - valuePos)); // resolve and append value part + index = endPos + 1; + } + else + { + // if closing bracket is missing, report error and leave incomplete reference in + CLog::Log(LOGERROR, "Error parsing value - missing ']' in \"{}\"", strInput); + break; + } + } + + if (index) // if we replaced anything + { + strOutput.append(strInput, index, std::string::npos); // append leftover from the right side + return true; + } + + return false; +} + +bool CGUIInfoLabel::ReplaceSpecialKeywordReferences(std::string &work, const std::string &strKeyword, const StringReplacerFunc &func) +{ + std::string output; + if (ReplaceSpecialKeywordReferences(work, strKeyword, func, output)) + { + work = std::move(output); + return true; + } + return false; +} + +std::string LocalizeReplacer(const std::string &str) +{ + std::string replace = g_localizeStringsTemp.Get(atoi(str.c_str())); + if (replace.empty()) + replace = g_localizeStrings.Get(atoi(str.c_str())); + return replace; +} + +std::string AddonReplacer(const std::string &str) +{ + // assumes "addon.id #####" + size_t length = str.find(' '); + const std::string addonid = str.substr(0, length); + int stringid = atoi(str.substr(length + 1).c_str()); + return g_localizeStrings.GetAddonString(addonid, stringid); +} + +std::string NumberReplacer(const std::string &str) +{ + return str; +} + +std::string CGUIInfoLabel::ReplaceLocalize(const std::string &label) +{ + std::string work(label); + ReplaceSpecialKeywordReferences(work, "LOCALIZE", LocalizeReplacer); + ReplaceSpecialKeywordReferences(work, "NUMBER", NumberReplacer); + return work; +} + +std::string CGUIInfoLabel::ReplaceAddonStrings(std::string &&label) +{ + ReplaceSpecialKeywordReferences(label, "ADDON", AddonReplacer); + return std::move(label); +} + +enum EINFOFORMAT { NONE = 0, FORMATINFO, FORMATESCINFO, FORMATVAR, FORMATESCVAR }; + +typedef struct +{ + const char *str; + EINFOFORMAT val; +} infoformat; + +const static infoformat infoformatmap[] = {{ "$INFO[", FORMATINFO}, + { "$ESCINFO[", FORMATESCINFO}, + { "$VAR[", FORMATVAR}, + { "$ESCVAR[", FORMATESCVAR}}; + +void CGUIInfoLabel::Parse(const std::string &label, int context) +{ + m_info.clear(); + m_dirty = true; + // Step 1: Replace all $LOCALIZE[number] with the real string + std::string work = ReplaceLocalize(label); + // Step 2: Replace all $ADDON[id number] with the real string + work = ReplaceAddonStrings(std::move(work)); + // Step 3: Find all $INFO[info,prefix,postfix] blocks + EINFOFORMAT format; + do + { + format = NONE; + size_t pos1 = work.size(); + size_t pos2; + size_t len = 0; + for (const infoformat& infoformat : infoformatmap) + { + pos2 = work.find(infoformat.str); + if (pos2 != std::string::npos && pos2 < pos1) + { + pos1 = pos2; + len = strlen(infoformat.str); + format = infoformat.val; + } + } + + if (format != NONE) + { + if (pos1 > 0) + m_info.emplace_back(0, work.substr(0, pos1), ""); + + pos2 = StringUtils::FindEndBracket(work, '[', ']', pos1 + len); + if (pos2 != std::string::npos) + { + // decipher the block + std::vector<std::string> params = StringUtils::Split(work.substr(pos1 + len, pos2 - pos1 - len), ","); + if (!params.empty()) + { + CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager(); + + int info; + if (format == FORMATVAR || format == FORMATESCVAR) + { + info = infoMgr.TranslateSkinVariableString(params[0], context); + if (info == 0) + info = infoMgr.RegisterSkinVariableString(g_SkinInfo->CreateSkinVariable(params[0], context)); + if (info == 0) // skinner didn't define this conditional label! + CLog::Log(LOGWARNING, "Label Formatting: $VAR[{}] is not defined", params[0]); + } + else + info = infoMgr.TranslateString(params[0]); + std::string prefix, postfix; + if (params.size() > 1) + prefix = params[1]; + if (params.size() > 2) + postfix = params[2]; + m_info.emplace_back(info, prefix, postfix, format == FORMATESCINFO || format == FORMATESCVAR); + } + // and delete it from our work string + work.erase(0, pos2 + 1); + } + else + { + CLog::Log(LOGERROR, "Error parsing label - missing ']' in \"{}\"", label); + return; + } + } + } + while (format != NONE); + + if (!work.empty()) + m_info.emplace_back(0, work, ""); +} + +CGUIInfoLabel::CInfoPortion::CInfoPortion(int info, const std::string &prefix, const std::string &postfix, bool escaped /*= false */): + m_prefix(prefix), + m_postfix(postfix) +{ + m_info = info; + m_escaped = escaped; + // filter our prefix and postfix for comma's + StringUtils::Replace(m_prefix, "$COMMA", ","); + StringUtils::Replace(m_postfix, "$COMMA", ","); + StringUtils::Replace(m_prefix, "$LBRACKET", "["); StringUtils::Replace(m_prefix, "$RBRACKET", "]"); + StringUtils::Replace(m_postfix, "$LBRACKET", "["); StringUtils::Replace(m_postfix, "$RBRACKET", "]"); +} + +bool CGUIInfoLabel::CInfoPortion::NeedsUpdate(const std::string &label) const +{ + if (m_label != label) + { + m_label = label; + return true; + } + return false; +} + +std::string CGUIInfoLabel::CInfoPortion::Get() const +{ + if (!m_info) + return m_prefix; + else if (m_label.empty()) + return ""; + std::string label = m_prefix + m_label + m_postfix; + if (m_escaped) // escape all quotes and backslashes, then quote + { + StringUtils::Replace(label, "\\", "\\\\"); + StringUtils::Replace(label, "\"", "\\\""); + return "\"" + label + "\""; + } + return label; +} + +std::string CGUIInfoLabel::GetLabel(const std::string &label, int contextWindow /*= 0*/, bool preferImage /*= false */) +{ // translate the label + const CGUIInfoLabel info(label, "", contextWindow); + return info.GetLabel(contextWindow, preferImage); +} + +std::string CGUIInfoLabel::GetItemLabel(const std::string &label, const CGUIListItem *item, bool preferImage /*= false */) +{ // translate the label + const CGUIInfoLabel info(label); + return info.GetItemLabel(item, preferImage); +} diff --git a/xbmc/guilib/guiinfo/GUIInfoLabel.h b/xbmc/guilib/guiinfo/GUIInfoLabel.h new file mode 100644 index 0000000..c9ae1a8 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoLabel.h @@ -0,0 +1,146 @@ +/* + * 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. + */ + +#pragma once + +/*! +\file GUIInfoLabel.h +\brief +*/ + +#include "interfaces/info/Info.h" + +#include <functional> +#include <string> +#include <vector> + +class CGUIListItem; + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfoLabel +{ +public: + CGUIInfoLabel() = default; + CGUIInfoLabel(const std::string& label, + const std::string& fallback = "", + int context = INFO::DEFAULT_CONTEXT); + + void SetLabel(const std::string& label, + const std::string& fallback, + int context = INFO::DEFAULT_CONTEXT); + + /*! + \brief Gets a label (or image) for a given window context from the info manager. + \param contextWindow the context in which to evaluate the expression. + \param preferImage caller is specifically wanting an image rather than a label. Defaults to false. + \param fallback if non-NULL, is set to an alternate value to use should the actual value be not appropriate. Defaults to NULL. + \return label (or image). + */ + const std::string &GetLabel(int contextWindow, bool preferImage = false, std::string *fallback = NULL) const; + + /*! + \brief Gets the label and returns it as an int value + \param contextWindow the context in which to evaluate the expression. + \return int value. + \sa GetLabel + */ + int GetIntValue(int contextWindow) const; + + /*! + \brief Gets a label (or image) for a given listitem from the info manager. + \param item listitem in question. + \param preferImage caller is specifically wanting an image rather than a label. Defaults to false. + \param fallback if non-NULL, is set to an alternate value to use should the actual value be not appropriate. Defaults to NULL. + \return label (or image). + */ + const std::string &GetItemLabel(const CGUIListItem *item, bool preferImage = false, std::string *fallback = NULL) const; + + bool IsConstant() const; + bool IsEmpty() const; + + const std::string& GetFallback() const { return m_fallback; } + + static std::string GetLabel(const std::string& label, + int contextWindow, + bool preferImage = false); + static std::string GetItemLabel(const std::string &label, const CGUIListItem *item, bool preferImage = false); + + /*! + \brief Replaces instances of $LOCALIZE[number] with the appropriate localized string + \param label text to replace + \return text with any localized strings filled in. + */ + static std::string ReplaceLocalize(const std::string &label); + + /*! + \brief Replaces instances of $ADDON[id number] with the appropriate localized addon string + \param label text to replace + \return text with any localized strings filled in. + */ + static std::string ReplaceAddonStrings(std::string &&label); + + typedef std::function<std::string(const std::string&)> StringReplacerFunc; + + /*! + \brief Replaces instances of $strKeyword[value] with the appropriate resolved string + \param strInput text to replace + \param strKeyword keyword to look for + \param func function that does the actual replacement of each bracketed value found + \param strOutput the output string + \return whether anything has been replaced. + */ + static bool ReplaceSpecialKeywordReferences(const std::string &strInput, const std::string &strKeyword, const StringReplacerFunc &func, std::string &strOutput); + + /*! + \brief Replaces instances of $strKeyword[value] with the appropriate resolved string in-place + \param work text to replace in-place + \param strKeyword keyword to look for + \param func function that does the actual replacement of each bracketed value found + \return whether anything has been replaced. + */ + static bool ReplaceSpecialKeywordReferences(std::string &work, const std::string &strKeyword, const StringReplacerFunc &func); + +private: + void Parse(const std::string &label, int context); + + /*! \brief return (and cache) built label from info portions. + \param rebuild whether we need to rebuild the label + \sa GetLabel, GetItemLabel + */ + const std::string &CacheLabel(bool rebuild) const; + + class CInfoPortion + { + public: + CInfoPortion(int info, const std::string &prefix, const std::string &postfix, bool escaped = false); + bool NeedsUpdate(const std::string &label) const; + std::string Get() const; + int m_info; + private: + bool m_escaped; + mutable std::string m_label; + std::string m_prefix; + std::string m_postfix; + }; + + mutable bool m_dirty = false; + mutable std::string m_label; + std::string m_fallback; + std::vector<CInfoPortion> m_info; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI + diff --git a/xbmc/guilib/guiinfo/GUIInfoLabels.h b/xbmc/guilib/guiinfo/GUIInfoLabels.h new file mode 100644 index 0000000..3e2b163 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoLabels.h @@ -0,0 +1,985 @@ +/* + * 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. + */ + +#pragma once + +// clang-format off +#define PLAYER_HAS_MEDIA 1 +#define PLAYER_HAS_AUDIO 2 +#define PLAYER_HAS_VIDEO 3 +#define PLAYER_PLAYING 4 +#define PLAYER_PAUSED 5 +#define PLAYER_REWINDING 6 +#define PLAYER_REWINDING_2x 7 +#define PLAYER_REWINDING_4x 8 +#define PLAYER_REWINDING_8x 9 +#define PLAYER_REWINDING_16x 10 +#define PLAYER_REWINDING_32x 11 +#define PLAYER_FORWARDING 12 +#define PLAYER_FORWARDING_2x 13 +#define PLAYER_FORWARDING_4x 14 +#define PLAYER_FORWARDING_8x 15 +#define PLAYER_FORWARDING_16x 16 +#define PLAYER_FORWARDING_32x 17 +#define PLAYER_CACHING 20 +// unused id 21 +#define PLAYER_PROGRESS 22 +#define PLAYER_SEEKBAR 23 +#define PLAYER_SEEKTIME 24 +#define PLAYER_SEEKING 25 +#define PLAYER_SHOWTIME 26 +#define PLAYER_TIME 27 +#define PLAYER_TIME_REMAINING 28 +#define PLAYER_DURATION 29 +#define PLAYER_HASPERFORMEDSEEK 30 +#define PLAYER_SHOWINFO 31 +#define PLAYER_VOLUME 32 +#define PLAYER_MUTED 33 +#define PLAYER_HASDURATION 34 +#define PLAYER_CHAPTER 35 +#define PLAYER_CHAPTERCOUNT 36 +#define PLAYER_TIME_SPEED 37 +#define PLAYER_FINISH_TIME 38 +#define PLAYER_CACHELEVEL 39 +#define PLAYER_CHAPTERNAME 41 +#define PLAYER_SUBTITLE_DELAY 42 +#define PLAYER_AUDIO_DELAY 43 +#define PLAYER_PASSTHROUGH 44 +// unused 45 +// unused 46 +#define PLAYER_SEEKOFFSET 47 +#define PLAYER_PROGRESS_CACHE 48 +#define PLAYER_ITEM_ART 49 +#define PLAYER_CAN_PAUSE 50 +#define PLAYER_CAN_SEEK 51 +#define PLAYER_START_TIME 52 +// unused 53 +#define PLAYER_ISINTERNETSTREAM 54 +// unused 55 +#define PLAYER_SEEKSTEPSIZE 56 +#define PLAYER_IS_CHANNEL_PREVIEW_ACTIVE 57 +#define PLAYER_SUPPORTS_TEMPO 58 +#define PLAYER_IS_TEMPO 59 +#define PLAYER_PLAYSPEED 60 +#define PLAYER_SEEKNUMERIC 61 +#define PLAYER_HAS_GAME 62 +#define PLAYER_HAS_PROGRAMS 63 +#define PLAYER_HAS_RESOLUTIONS 64 +#define PLAYER_FRAMEADVANCE 65 +#define PLAYER_ICON 66 +#define PLAYER_CUTLIST 67 +#define PLAYER_CHAPTERS 68 +#define PLAYER_EDITLIST 69 +#define PLAYER_CUTS 70 +#define PLAYER_SCENE_MARKERS 71 +#define PLAYER_HAS_SCENE_MARKERS 72 +// Keep player infolabels that work with offset and position together +#define PLAYER_PATH 81 +#define PLAYER_FILEPATH 82 +#define PLAYER_TITLE 83 +#define PLAYER_FILENAME 84 + +// Range of player infolabels that work with offset and position +#define PLAYER_OFFSET_POSITION_FIRST PLAYER_PATH +#define PLAYER_OFFSET_POSITION_LAST PLAYER_FILENAME + +#define WEATHER_CONDITIONS_TEXT 100 +#define WEATHER_TEMPERATURE 101 +#define WEATHER_LOCATION 102 +#define WEATHER_IS_FETCHED 103 +#define WEATHER_FANART_CODE 104 +#define WEATHER_PLUGIN 105 +#define WEATHER_CONDITIONS_ICON 106 + +#define SYSTEM_TEMPERATURE_UNITS 107 +#define SYSTEM_PROGRESS_BAR 108 +#define SYSTEM_LANGUAGE 109 +#define SYSTEM_TIME 110 +#define SYSTEM_DATE 111 +#define SYSTEM_CPU_TEMPERATURE 112 +#define SYSTEM_GPU_TEMPERATURE 113 +#define SYSTEM_FAN_SPEED 114 +#define SYSTEM_FREE_SPACE_C 115 +// #define SYSTEM_FREE_SPACE_D 116 //116 is reserved for space on D +#define SYSTEM_FREE_SPACE_E 117 +#define SYSTEM_FREE_SPACE_F 118 +#define SYSTEM_FREE_SPACE_G 119 +#define SYSTEM_BUILD_VERSION 120 +#define SYSTEM_BUILD_DATE 121 +#define SYSTEM_ETHERNET_LINK_ACTIVE 122 +#define SYSTEM_FPS 123 +#define SYSTEM_ALWAYS_TRUE 125 // useful for <visible fade="10" start="hidden">true</visible>, to fade in a control +#define SYSTEM_ALWAYS_FALSE 126 // used for <visible fade="10">false</visible>, to fade out a control (ie not particularly useful!) +#define SYSTEM_MEDIA_DVD 127 +#define SYSTEM_DVDREADY 128 +#define SYSTEM_HAS_ALARM 129 +#define SYSTEM_SUPPORTS_CPU_USAGE 130 +#define SYSTEM_SCREEN_MODE 132 +#define SYSTEM_SCREEN_WIDTH 133 +#define SYSTEM_SCREEN_HEIGHT 134 +#define SYSTEM_CURRENT_WINDOW 135 +#define SYSTEM_CURRENT_CONTROL 136 +#define SYSTEM_CURRENT_CONTROL_ID 137 +#define SYSTEM_DVD_LABEL 138 +#define SYSTEM_HASLOCKS 140 +#define SYSTEM_ISMASTER 141 +#define SYSTEM_TRAYOPEN 142 +#define SYSTEM_SHOW_EXIT_BUTTON 143 +#define SYSTEM_ALARM_POS 144 +#define SYSTEM_LOGGEDON 145 +#define SYSTEM_PROFILENAME 146 +#define SYSTEM_PROFILETHUMB 147 +#define SYSTEM_HAS_LOGINSCREEN 148 +#define SYSTEM_HAS_ACTIVE_MODAL_DIALOG 149 +#define SYSTEM_HDD_SMART 150 +#define SYSTEM_HDD_TEMPERATURE 151 +#define SYSTEM_HDD_MODEL 152 +#define SYSTEM_HDD_SERIAL 153 +#define SYSTEM_HDD_FIRMWARE 154 +#define SYSTEM_HAS_VISIBLE_MODAL_DIALOG 155 +#define SYSTEM_HDD_PASSWORD 156 +#define SYSTEM_HDD_LOCKSTATE 157 +#define SYSTEM_HDD_LOCKKEY 158 +#define SYSTEM_INTERNET_STATE 159 +#define SYSTEM_HAS_INPUT_HIDDEN 160 +#define SYSTEM_HAS_PVR_ADDON 161 +#define SYSTEM_ALARM_LESS_OR_EQUAL 180 +#define SYSTEM_PROFILECOUNT 181 +#define SYSTEM_ISFULLSCREEN 182 +#define SYSTEM_ISSTANDALONE 183 +#define SYSTEM_IDLE_SHUTDOWN_INHIBITED 184 +#define SYSTEM_HAS_SHUTDOWN 185 +#define SYSTEM_HAS_PVR 186 +#define SYSTEM_STARTUP_WINDOW 187 +#define SYSTEM_STEREOSCOPIC_MODE 188 +#define SYSTEM_BUILD_VERSION_SHORT 189 + +#define NETWORK_IP_ADDRESS 190 +#define NETWORK_MAC_ADDRESS 191 +#define NETWORK_IS_DHCP 192 +#define NETWORK_LINK_STATE 193 +#define NETWORK_SUBNET_MASK 194 +#define NETWORK_GATEWAY_ADDRESS 195 +#define NETWORK_DNS1_ADDRESS 196 +#define NETWORK_DNS2_ADDRESS 197 +#define NETWORK_DHCP_ADDRESS 198 + +// Keep musicplayer infolabels that work with offset and position together +#define MUSICPLAYER_TITLE 200 +#define MUSICPLAYER_ALBUM 201 +#define MUSICPLAYER_ARTIST 202 +#define MUSICPLAYER_GENRE 203 +#define MUSICPLAYER_YEAR 204 +#define MUSICPLAYER_DURATION 205 +#define MUSICPLAYER_TRACK_NUMBER 208 +#define MUSICPLAYER_COVER 210 +#define MUSICPLAYER_BITRATE 211 +#define MUSICPLAYER_PLAYLISTLEN 212 +#define MUSICPLAYER_PLAYLISTPOS 213 +#define MUSICPLAYER_CHANNELS 214 +#define MUSICPLAYER_BITSPERSAMPLE 215 +#define MUSICPLAYER_SAMPLERATE 216 +#define MUSICPLAYER_CODEC 217 +#define MUSICPLAYER_DISC_NUMBER 218 +#define MUSICPLAYER_RATING 219 +#define MUSICPLAYER_COMMENT 220 +#define MUSICPLAYER_LYRICS 221 +#define MUSICPLAYER_ALBUM_ARTIST 222 +#define MUSICPLAYER_PLAYCOUNT 223 +#define MUSICPLAYER_LASTPLAYED 224 +#define MUSICPLAYER_USER_RATING 225 +#define MUSICPLAYER_RATING_AND_VOTES 226 +#define MUSICPLAYER_VOTES 227 +#define MUSICPLAYER_MOOD 228 +#define MUSICPLAYER_CONTRIBUTORS 229 +#define MUSICPLAYER_CONTRIBUTOR_AND_ROLE 230 +#define MUSICPLAYER_DBID 231 +#define MUSICPLAYER_DISC_TITLE 232 +#define MUSICPLAYER_RELEASEDATE 233 +#define MUSICPLAYER_ORIGINALDATE 234 +#define MUSICPLAYER_BPM 235 + +// Range of musicplayer infolabels that work with offset and position +#define MUSICPLAYER_OFFSET_POSITION_FIRST MUSICPLAYER_TITLE +#define MUSICPLAYER_OFFSET_POSITION_LAST MUSICPLAYER_BPM + +#define MUSICPLAYER_PROPERTY 236 +#define MUSICPLAYER_CHANNEL_NAME 237 +#define MUSICPLAYER_CHANNEL_GROUP 238 +#define MUSICPLAYER_CHANNEL_NUMBER 239 +#define MUSICPLAYER_TOTALDISCS 240 +#define MUSICPLAYER_STATIONNAME 241 + +// Musicplayer infobools +#define MUSICPLAYER_HASPREVIOUS 242 +#define MUSICPLAYER_HASNEXT 243 +#define MUSICPLAYER_EXISTS 244 +#define MUSICPLAYER_PLAYLISTPLAYING 245 +#define MUSICPLAYER_CONTENT 246 +#define MUSICPLAYER_ISMULTIDISC 247 + +// Videoplayer infolabels +#define VIDEOPLAYER_HDR_TYPE 249 +// Keep videoplayer infolabels that work with offset and position together +#define VIDEOPLAYER_TITLE 250 +#define VIDEOPLAYER_GENRE 251 +#define VIDEOPLAYER_DIRECTOR 252 +#define VIDEOPLAYER_YEAR 253 +#define VIDEOPLAYER_COVER 254 +#define VIDEOPLAYER_ORIGINALTITLE 255 +#define VIDEOPLAYER_PLOT 256 +#define VIDEOPLAYER_PLOT_OUTLINE 257 +#define VIDEOPLAYER_EPISODE 258 +#define VIDEOPLAYER_SEASON 259 +#define VIDEOPLAYER_RATING 260 +#define VIDEOPLAYER_TVSHOW 261 +#define VIDEOPLAYER_PREMIERED 262 +#define VIDEOPLAYER_STUDIO 263 +#define VIDEOPLAYER_MPAA 264 +#define VIDEOPLAYER_ARTIST 265 +#define VIDEOPLAYER_ALBUM 266 +#define VIDEOPLAYER_WRITER 267 +#define VIDEOPLAYER_TAGLINE 268 +#define VIDEOPLAYER_TOP250 269 +#define VIDEOPLAYER_RATING_AND_VOTES 270 +#define VIDEOPLAYER_TRAILER 271 +#define VIDEOPLAYER_COUNTRY 272 +#define VIDEOPLAYER_PLAYCOUNT 273 +#define VIDEOPLAYER_LASTPLAYED 274 +#define VIDEOPLAYER_VOTES 275 +#define VIDEOPLAYER_IMDBNUMBER 276 +#define VIDEOPLAYER_USER_RATING 277 +#define VIDEOPLAYER_DBID 278 +#define VIDEOPLAYER_TVSHOWDBID 279 +#define VIDEOPLAYER_ART 280 + +// Range of videoplayer infolabels that work with offset and position +#define VIDEOPLAYER_OFFSET_POSITION_FIRST VIDEOPLAYER_TITLE +#define VIDEOPLAYER_OFFSET_POSITION_LAST VIDEOPLAYER_ART + +#define VIDEOPLAYER_AUDIO_BITRATE 281 +#define VIDEOPLAYER_VIDEO_BITRATE 282 +#define VIDEOPLAYER_VIDEO_CODEC 283 +#define VIDEOPLAYER_VIDEO_RESOLUTION 284 +#define VIDEOPLAYER_AUDIO_CODEC 285 +#define VIDEOPLAYER_AUDIO_CHANNELS 286 +#define VIDEOPLAYER_VIDEO_ASPECT 287 +#define VIDEOPLAYER_SUBTITLES_LANG 288 +#define VIDEOPLAYER_AUDIO_LANG 290 +#define VIDEOPLAYER_STEREOSCOPIC_MODE 291 +#define VIDEOPLAYER_CAST 292 +#define VIDEOPLAYER_CAST_AND_ROLE 293 +#define VIDEOPLAYER_UNIQUEID 294 +#define VIDEOPLAYER_AUDIOSTREAMCOUNT 295 + +// Videoplayer infobools +#define VIDEOPLAYER_HASSUBTITLES 300 +#define VIDEOPLAYER_SUBTITLESENABLED 301 +#define VIDEOPLAYER_USING_OVERLAYS 302 +#define VIDEOPLAYER_ISFULLSCREEN 303 +#define VIDEOPLAYER_HASMENU 304 +#define VIDEOPLAYER_PLAYLISTLEN 305 +#define VIDEOPLAYER_PLAYLISTPOS 306 +#define VIDEOPLAYER_CONTENT 307 +#define VIDEOPLAYER_HAS_INFO 308 +#define VIDEOPLAYER_HASTELETEXT 309 +#define VIDEOPLAYER_IS_STEREOSCOPIC 310 + +// PVR infolabels +#define VIDEOPLAYER_EVENT 313 +#define VIDEOPLAYER_EPISODENAME 314 +#define VIDEOPLAYER_STARTTIME 315 +#define VIDEOPLAYER_ENDTIME 316 +#define VIDEOPLAYER_NEXT_TITLE 317 +#define VIDEOPLAYER_NEXT_GENRE 318 +#define VIDEOPLAYER_NEXT_PLOT 319 +#define VIDEOPLAYER_NEXT_PLOT_OUTLINE 320 +#define VIDEOPLAYER_NEXT_STARTTIME 321 +#define VIDEOPLAYER_NEXT_ENDTIME 322 +#define VIDEOPLAYER_NEXT_DURATION 323 +#define VIDEOPLAYER_CHANNEL_NAME 324 +#define VIDEOPLAYER_CHANNEL_GROUP 325 +#define VIDEOPLAYER_PARENTAL_RATING 326 +#define VIDEOPLAYER_CHANNEL_NUMBER 327 + +// PVR infobools +#define VIDEOPLAYER_HAS_EPG 328 +#define VIDEOPLAYER_CAN_RESUME_LIVE_TV 329 + +#define RETROPLAYER_VIDEO_FILTER 330 +#define RETROPLAYER_STRETCH_MODE 331 +#define RETROPLAYER_VIDEO_ROTATION 332 + +#define CONTAINER_HAS_PARENT_ITEM 341 +#define CONTAINER_CAN_FILTER 342 +#define CONTAINER_CAN_FILTERADVANCED 343 +#define CONTAINER_FILTERED 344 + +#define CONTAINER_SCROLL_PREVIOUS 345 +#define CONTAINER_MOVE_PREVIOUS 346 +// unused 347 +#define CONTAINER_MOVE_NEXT 348 +#define CONTAINER_SCROLL_NEXT 349 +#define CONTAINER_ISUPDATING 350 +#define CONTAINER_HASFILES 351 +#define CONTAINER_HASFOLDERS 352 +#define CONTAINER_STACKED 353 +#define CONTAINER_FOLDERNAME 354 +#define CONTAINER_SCROLLING 355 +#define CONTAINER_PLUGINNAME 356 +#define CONTAINER_PROPERTY 357 +#define CONTAINER_SORT_DIRECTION 358 +#define CONTAINER_NUM_ITEMS 359 +#define CONTAINER_FOLDERPATH 360 +#define CONTAINER_CONTENT 361 +#define CONTAINER_HAS_THUMB 362 +#define CONTAINER_SORT_METHOD 363 +#define CONTAINER_CURRENT_ITEM 364 +#define CONTAINER_ART 365 +#define CONTAINER_HAS_FOCUS 366 +#define CONTAINER_ROW 367 +#define CONTAINER_COLUMN 368 +#define CONTAINER_POSITION 369 +#define CONTAINER_VIEWMODE 370 +#define CONTAINER_HAS_NEXT 371 +#define CONTAINER_HAS_PREVIOUS 372 +#define CONTAINER_SUBITEM 373 +#define CONTAINER_NUM_PAGES 374 +#define CONTAINER_CURRENT_PAGE 375 +#define CONTAINER_SHOWPLOT 376 +#define CONTAINER_TOTALTIME 377 +#define CONTAINER_SORT_ORDER 378 +#define CONTAINER_TOTALWATCHED 379 +#define CONTAINER_TOTALUNWATCHED 380 +#define CONTAINER_VIEWCOUNT 381 +#define CONTAINER_SHOWTITLE 382 +#define CONTAINER_PLUGINCATEGORY 383 +#define CONTAINER_NUM_ALL_ITEMS 384 +#define CONTAINER_NUM_NONFOLDER_ITEMS 385 + +#define MUSICPM_ENABLED 390 +#define MUSICPM_SONGSPLAYED 391 +#define MUSICPM_MATCHINGSONGS 392 +#define MUSICPM_MATCHINGSONGSPICKED 393 +#define MUSICPM_MATCHINGSONGSLEFT 394 +#define MUSICPM_RELAXEDSONGSPICKED 395 +#define MUSICPM_RANDOMSONGSPICKED 396 + +#define PLAYLIST_LENGTH 400 +#define PLAYLIST_POSITION 401 +#define PLAYLIST_RANDOM 402 +#define PLAYLIST_REPEAT 403 +#define PLAYLIST_ISRANDOM 404 +#define PLAYLIST_ISREPEAT 405 +#define PLAYLIST_ISREPEATONE 406 + +#define VISUALISATION_LOCKED 410 +#define VISUALISATION_PRESET 411 +#define VISUALISATION_NAME 412 +#define VISUALISATION_ENABLED 413 +#define VISUALISATION_HAS_PRESETS 414 + +#define STRING_IS_EMPTY 420 +#define STRING_IS_EQUAL 421 +#define STRING_STARTS_WITH 422 +#define STRING_ENDS_WITH 423 +#define STRING_CONTAINS 424 + +#define INTEGER_IS_EQUAL 450 +#define INTEGER_GREATER_THAN 451 +#define INTEGER_GREATER_OR_EQUAL 452 +#define INTEGER_LESS_THAN 453 +#define INTEGER_LESS_OR_EQUAL 454 +#define INTEGER_EVEN 455 +#define INTEGER_ODD 456 +#define INTEGER_VALUEOF 457 + +#define SKIN_BOOL 600 +#define SKIN_STRING 601 +#define SKIN_STRING_IS_EQUAL 602 +#define SKIN_THEME 604 +#define SKIN_COLOUR_THEME 605 +#define SKIN_HAS_THEME 606 +#define SKIN_ASPECT_RATIO 607 +#define SKIN_FONT 608 +#define SKIN_INTEGER 609 +#define SKIN_TIMER_IS_RUNNING 610 +#define SKIN_TIMER_ELAPSEDSECS 611 + +#define SYSTEM_IS_SCREENSAVER_INHIBITED 641 +#define SYSTEM_ADDON_UPDATE_COUNT 642 +#define SYSTEM_PRIVACY_POLICY 643 +#define SYSTEM_TOTAL_MEMORY 644 +#define SYSTEM_CPU_USAGE 645 +#define SYSTEM_USED_MEMORY_PERCENT 646 +#define SYSTEM_USED_MEMORY 647 +#define SYSTEM_FREE_MEMORY 648 +#define SYSTEM_FREE_MEMORY_PERCENT 649 +#define SYSTEM_UPTIME 654 +#define SYSTEM_TOTALUPTIME 655 +#define SYSTEM_CPUFREQUENCY 656 +#define SYSTEM_SCREEN_RESOLUTION 659 +#define SYSTEM_VIDEO_ENCODER_INFO 660 +#define SYSTEM_OS_VERSION_INFO 667 +#define SYSTEM_FREE_SPACE 679 +#define SYSTEM_USED_SPACE 680 +#define SYSTEM_TOTAL_SPACE 681 +#define SYSTEM_USED_SPACE_PERCENT 682 +#define SYSTEM_FREE_SPACE_PERCENT 683 +#define SYSTEM_ADDON_IS_ENABLED 703 +#define SYSTEM_GET_BOOL 704 +#define SYSTEM_GET_CORE_USAGE 705 +#define SYSTEM_HAS_CORE_ID 706 +#define SYSTEM_RENDER_VENDOR 707 +#define SYSTEM_RENDER_RENDERER 708 +#define SYSTEM_RENDER_VERSION 709 +#define SYSTEM_SETTING 710 +#define SYSTEM_HAS_ADDON 711 +#define SYSTEM_ADDON_TITLE 712 +#define SYSTEM_ADDON_ICON 713 +#define SYSTEM_BATTERY_LEVEL 714 +#define SYSTEM_IDLE_TIME 715 +#define SYSTEM_FRIENDLY_NAME 716 +#define SYSTEM_SCREENSAVER_ACTIVE 717 +#define SYSTEM_ADDON_VERSION 718 +#define SYSTEM_DPMS_ACTIVE 719 + +#define LIBRARY_HAS_MUSIC 720 +#define LIBRARY_HAS_VIDEO 721 +#define LIBRARY_HAS_MOVIES 722 +#define LIBRARY_HAS_MOVIE_SETS 723 +#define LIBRARY_HAS_TVSHOWS 724 +#define LIBRARY_HAS_MUSICVIDEOS 725 +#define LIBRARY_HAS_SINGLES 726 +#define LIBRARY_HAS_COMPILATIONS 727 +#define LIBRARY_IS_SCANNING 728 +#define LIBRARY_IS_SCANNING_VIDEO 729 +#define LIBRARY_IS_SCANNING_MUSIC 730 +#define LIBRARY_HAS_ROLE 735 +#define LIBRARY_HAS_BOXSETS 736 +#define LIBRARY_HAS_NODE 737 + +#define SYSTEM_PLATFORM_LINUX 741 +#define SYSTEM_PLATFORM_WINDOWS 742 +#define SYSTEM_PLATFORM_DARWIN 743 +#define SYSTEM_PLATFORM_DARWIN_OSX 744 +#define SYSTEM_PLATFORM_DARWIN_IOS 745 +#define SYSTEM_PLATFORM_UWP 746 +#define SYSTEM_PLATFORM_ANDROID 747 +#define SYSTEM_PLATFORM_WINDOWING 748 +#define SYSTEM_PLATFORM_WIN10 749 + +#define SYSTEM_CAN_POWERDOWN 750 +#define SYSTEM_CAN_SUSPEND 751 +#define SYSTEM_CAN_HIBERNATE 752 +#define SYSTEM_CAN_REBOOT 753 +#define SYSTEM_MEDIA_AUDIO_CD 754 + +#define SYSTEM_PLATFORM_DARWIN_TVOS 755 +#define SYSTEM_SUPPORTED_HDR_TYPES 756 + +#define SLIDESHOW_ISPAUSED 800 +#define SLIDESHOW_ISRANDOM 801 +#define SLIDESHOW_ISACTIVE 802 +#define SLIDESHOW_ISVIDEO 803 + +#define SLIDESHOW_LABELS_START 900 +#define SLIDESHOW_FILE_NAME (SLIDESHOW_LABELS_START) +#define SLIDESHOW_FILE_PATH (SLIDESHOW_LABELS_START + 1) +#define SLIDESHOW_FILE_SIZE (SLIDESHOW_LABELS_START + 2) +#define SLIDESHOW_FILE_DATE (SLIDESHOW_LABELS_START + 3) +#define SLIDESHOW_INDEX (SLIDESHOW_LABELS_START + 4) +#define SLIDESHOW_RESOLUTION (SLIDESHOW_LABELS_START + 5) +#define SLIDESHOW_COMMENT (SLIDESHOW_LABELS_START + 6) +#define SLIDESHOW_COLOUR (SLIDESHOW_LABELS_START + 7) +#define SLIDESHOW_PROCESS (SLIDESHOW_LABELS_START + 8) + +#define SLIDESHOW_EXIF_LONG_DATE (SLIDESHOW_LABELS_START + 17) +#define SLIDESHOW_EXIF_LONG_DATE_TIME (SLIDESHOW_LABELS_START + 18) +#define SLIDESHOW_EXIF_DATE (SLIDESHOW_LABELS_START + 19) /* Implementation only to just get localized date */ +#define SLIDESHOW_EXIF_DATE_TIME (SLIDESHOW_LABELS_START + 20) +#define SLIDESHOW_EXIF_DESCRIPTION (SLIDESHOW_LABELS_START + 21) +#define SLIDESHOW_EXIF_CAMERA_MAKE (SLIDESHOW_LABELS_START + 22) +#define SLIDESHOW_EXIF_CAMERA_MODEL (SLIDESHOW_LABELS_START + 23) +#define SLIDESHOW_EXIF_COMMENT (SLIDESHOW_LABELS_START + 24) +#define SLIDESHOW_EXIF_SOFTWARE (SLIDESHOW_LABELS_START + 25) +#define SLIDESHOW_EXIF_APERTURE (SLIDESHOW_LABELS_START + 26) +#define SLIDESHOW_EXIF_FOCAL_LENGTH (SLIDESHOW_LABELS_START + 27) +#define SLIDESHOW_EXIF_FOCUS_DIST (SLIDESHOW_LABELS_START + 28) +#define SLIDESHOW_EXIF_EXPOSURE (SLIDESHOW_LABELS_START + 29) +#define SLIDESHOW_EXIF_EXPOSURE_TIME (SLIDESHOW_LABELS_START + 30) +#define SLIDESHOW_EXIF_EXPOSURE_BIAS (SLIDESHOW_LABELS_START + 31) +#define SLIDESHOW_EXIF_EXPOSURE_MODE (SLIDESHOW_LABELS_START + 32) +#define SLIDESHOW_EXIF_FLASH_USED (SLIDESHOW_LABELS_START + 33) +#define SLIDESHOW_EXIF_WHITE_BALANCE (SLIDESHOW_LABELS_START + 34) +#define SLIDESHOW_EXIF_LIGHT_SOURCE (SLIDESHOW_LABELS_START + 35) +#define SLIDESHOW_EXIF_METERING_MODE (SLIDESHOW_LABELS_START + 36) +#define SLIDESHOW_EXIF_ISO_EQUIV (SLIDESHOW_LABELS_START + 37) +#define SLIDESHOW_EXIF_DIGITAL_ZOOM (SLIDESHOW_LABELS_START + 38) +#define SLIDESHOW_EXIF_CCD_WIDTH (SLIDESHOW_LABELS_START + 39) +#define SLIDESHOW_EXIF_GPS_LATITUDE (SLIDESHOW_LABELS_START + 40) +#define SLIDESHOW_EXIF_GPS_LONGITUDE (SLIDESHOW_LABELS_START + 41) +#define SLIDESHOW_EXIF_GPS_ALTITUDE (SLIDESHOW_LABELS_START + 42) +#define SLIDESHOW_EXIF_ORIENTATION (SLIDESHOW_LABELS_START + 43) +#define SLIDESHOW_EXIF_XPCOMMENT (SLIDESHOW_LABELS_START + 44) + +#define SLIDESHOW_IPTC_SUBLOCATION (SLIDESHOW_LABELS_START + 57) +#define SLIDESHOW_IPTC_IMAGETYPE (SLIDESHOW_LABELS_START + 58) +#define SLIDESHOW_IPTC_TIMECREATED (SLIDESHOW_LABELS_START + 59) +#define SLIDESHOW_IPTC_SUP_CATEGORIES (SLIDESHOW_LABELS_START + 60) +#define SLIDESHOW_IPTC_KEYWORDS (SLIDESHOW_LABELS_START + 61) +#define SLIDESHOW_IPTC_CAPTION (SLIDESHOW_LABELS_START + 62) +#define SLIDESHOW_IPTC_AUTHOR (SLIDESHOW_LABELS_START + 63) +#define SLIDESHOW_IPTC_HEADLINE (SLIDESHOW_LABELS_START + 64) +#define SLIDESHOW_IPTC_SPEC_INSTR (SLIDESHOW_LABELS_START + 65) +#define SLIDESHOW_IPTC_CATEGORY (SLIDESHOW_LABELS_START + 66) +#define SLIDESHOW_IPTC_BYLINE (SLIDESHOW_LABELS_START + 67) +#define SLIDESHOW_IPTC_BYLINE_TITLE (SLIDESHOW_LABELS_START + 68) +#define SLIDESHOW_IPTC_CREDIT (SLIDESHOW_LABELS_START + 69) +#define SLIDESHOW_IPTC_SOURCE (SLIDESHOW_LABELS_START + 70) +#define SLIDESHOW_IPTC_COPYRIGHT_NOTICE (SLIDESHOW_LABELS_START + 71) +#define SLIDESHOW_IPTC_OBJECT_NAME (SLIDESHOW_LABELS_START + 72) +#define SLIDESHOW_IPTC_CITY (SLIDESHOW_LABELS_START + 73) +#define SLIDESHOW_IPTC_STATE (SLIDESHOW_LABELS_START + 74) +#define SLIDESHOW_IPTC_COUNTRY (SLIDESHOW_LABELS_START + 75) +#define SLIDESHOW_IPTC_TX_REFERENCE (SLIDESHOW_LABELS_START + 76) +#define SLIDESHOW_IPTC_DATE (SLIDESHOW_LABELS_START + 77) +#define SLIDESHOW_IPTC_URGENCY (SLIDESHOW_LABELS_START + 78) +#define SLIDESHOW_IPTC_COUNTRY_CODE (SLIDESHOW_LABELS_START + 79) +#define SLIDESHOW_IPTC_REF_SERVICE (SLIDESHOW_LABELS_START + 80) +#define SLIDESHOW_LABELS_END SLIDESHOW_IPTC_REF_SERVICE + +#define FANART_COLOR1 1000 +#define FANART_COLOR2 1001 +#define FANART_COLOR3 1002 +#define FANART_IMAGE 1003 + +#define SYSTEM_PROFILEAUTOLOGIN 1004 + +#define SYSTEM_HAS_CMS 1006 +#define SYSTEM_BUILD_VERSION_CODE 1007 +#define SYSTEM_BUILD_VERSION_GIT 1008 + +#define PVR_CONDITIONS_START 1100 +#define PVR_IS_RECORDING (PVR_CONDITIONS_START) +#define PVR_HAS_TIMER (PVR_CONDITIONS_START + 1) +#define PVR_HAS_NONRECORDING_TIMER (PVR_CONDITIONS_START + 2) +#define PVR_IS_PLAYING_TV (PVR_CONDITIONS_START + 3) +#define PVR_IS_PLAYING_RADIO (PVR_CONDITIONS_START + 4) +#define PVR_IS_PLAYING_RECORDING (PVR_CONDITIONS_START + 5) +#define PVR_ACTUAL_STREAM_ENCRYPTED (PVR_CONDITIONS_START + 6) +#define PVR_HAS_TV_CHANNELS (PVR_CONDITIONS_START + 7) +#define PVR_HAS_RADIO_CHANNELS (PVR_CONDITIONS_START + 8) +#define PVR_IS_TIMESHIFTING (PVR_CONDITIONS_START + 9) +#define PVR_IS_RECORDING_TV (PVR_CONDITIONS_START + 10) +#define PVR_HAS_TV_TIMER (PVR_CONDITIONS_START + 11) +#define PVR_HAS_NONRECORDING_TV_TIMER (PVR_CONDITIONS_START + 12) +#define PVR_IS_RECORDING_RADIO (PVR_CONDITIONS_START + 13) +#define PVR_HAS_RADIO_TIMER (PVR_CONDITIONS_START + 14) +#define PVR_HAS_NONRECORDING_RADIO_TIMER (PVR_CONDITIONS_START + 15) +#define PVR_IS_PLAYING_EPGTAG (PVR_CONDITIONS_START + 16) +#define PVR_CAN_RECORD_PLAYING_CHANNEL (PVR_CONDITIONS_START + 17) +#define PVR_IS_RECORDING_PLAYING_CHANNEL (PVR_CONDITIONS_START + 18) +#define PVR_IS_PLAYING_ACTIVE_RECORDING (PVR_CONDITIONS_START + 19) +#define PVR_CONDITIONS_END PVR_IS_PLAYING_ACTIVE_RECORDING + +#define PVR_STRINGS_START 1200 +#define PVR_NEXT_RECORDING_CHANNEL (PVR_STRINGS_START) +#define PVR_NEXT_RECORDING_CHAN_ICO (PVR_STRINGS_START + 1) +#define PVR_NEXT_RECORDING_DATETIME (PVR_STRINGS_START + 2) +#define PVR_NEXT_RECORDING_TITLE (PVR_STRINGS_START + 3) +#define PVR_NOW_RECORDING_CHANNEL (PVR_STRINGS_START + 4) +#define PVR_NOW_RECORDING_CHAN_ICO (PVR_STRINGS_START + 5) +#define PVR_NOW_RECORDING_DATETIME (PVR_STRINGS_START + 6) +#define PVR_NOW_RECORDING_TITLE (PVR_STRINGS_START + 7) +#define PVR_BACKEND_NAME (PVR_STRINGS_START + 8) +#define PVR_BACKEND_VERSION (PVR_STRINGS_START + 9) +#define PVR_BACKEND_HOST (PVR_STRINGS_START + 10) +#define PVR_BACKEND_DISKSPACE (PVR_STRINGS_START + 11) +#define PVR_BACKEND_CHANNELS (PVR_STRINGS_START + 12) +#define PVR_BACKEND_TIMERS (PVR_STRINGS_START + 13) +#define PVR_BACKEND_RECORDINGS (PVR_STRINGS_START + 14) +#define PVR_BACKEND_DELETED_RECORDINGS (PVR_STRINGS_START + 15) +#define PVR_BACKEND_NUMBER (PVR_STRINGS_START + 16) +#define PVR_TOTAL_DISKSPACE (PVR_STRINGS_START + 17) +#define PVR_NEXT_TIMER (PVR_STRINGS_START + 18) +#define PVR_EPG_EVENT_DURATION (PVR_STRINGS_START + 19) +#define PVR_EPG_EVENT_ELAPSED_TIME (PVR_STRINGS_START + 20) +#define PVR_EPG_EVENT_PROGRESS (PVR_STRINGS_START + 21) +#define PVR_ACTUAL_STREAM_CLIENT (PVR_STRINGS_START + 22) +#define PVR_ACTUAL_STREAM_DEVICE (PVR_STRINGS_START + 23) +#define PVR_ACTUAL_STREAM_STATUS (PVR_STRINGS_START + 24) +#define PVR_ACTUAL_STREAM_SIG (PVR_STRINGS_START + 25) +#define PVR_ACTUAL_STREAM_SNR (PVR_STRINGS_START + 26) +#define PVR_ACTUAL_STREAM_SIG_PROGR (PVR_STRINGS_START + 27) +#define PVR_ACTUAL_STREAM_SNR_PROGR (PVR_STRINGS_START + 28) +#define PVR_ACTUAL_STREAM_BER (PVR_STRINGS_START + 29) +#define PVR_ACTUAL_STREAM_UNC (PVR_STRINGS_START + 30) +#define PVR_ACTUAL_STREAM_CRYPTION (PVR_STRINGS_START + 34) +#define PVR_ACTUAL_STREAM_SERVICE (PVR_STRINGS_START + 35) +#define PVR_ACTUAL_STREAM_MUX (PVR_STRINGS_START + 36) +#define PVR_ACTUAL_STREAM_PROVIDER (PVR_STRINGS_START + 37) +#define PVR_BACKEND_DISKSPACE_PROGR (PVR_STRINGS_START + 38) +#define PVR_TIMESHIFT_START_TIME (PVR_STRINGS_START + 39) +#define PVR_TIMESHIFT_END_TIME (PVR_STRINGS_START + 40) +#define PVR_TIMESHIFT_PLAY_TIME (PVR_STRINGS_START + 41) +#define PVR_TIMESHIFT_PROGRESS (PVR_STRINGS_START + 42) +#define PVR_TV_NOW_RECORDING_TITLE (PVR_STRINGS_START + 43) +#define PVR_TV_NOW_RECORDING_CHANNEL (PVR_STRINGS_START + 44) +#define PVR_TV_NOW_RECORDING_CHAN_ICO (PVR_STRINGS_START + 45) +#define PVR_TV_NOW_RECORDING_DATETIME (PVR_STRINGS_START + 46) +#define PVR_TV_NEXT_RECORDING_TITLE (PVR_STRINGS_START + 47) +#define PVR_TV_NEXT_RECORDING_CHANNEL (PVR_STRINGS_START + 48) +#define PVR_TV_NEXT_RECORDING_CHAN_ICO (PVR_STRINGS_START + 49) +#define PVR_TV_NEXT_RECORDING_DATETIME (PVR_STRINGS_START + 50) +#define PVR_RADIO_NOW_RECORDING_TITLE (PVR_STRINGS_START + 51) +#define PVR_RADIO_NOW_RECORDING_CHANNEL (PVR_STRINGS_START + 52) +#define PVR_RADIO_NOW_RECORDING_CHAN_ICO (PVR_STRINGS_START + 53) +#define PVR_RADIO_NOW_RECORDING_DATETIME (PVR_STRINGS_START + 54) +#define PVR_RADIO_NEXT_RECORDING_TITLE (PVR_STRINGS_START + 55) +#define PVR_RADIO_NEXT_RECORDING_CHANNEL (PVR_STRINGS_START + 56) +#define PVR_RADIO_NEXT_RECORDING_CHAN_ICO (PVR_STRINGS_START + 57) +#define PVR_RADIO_NEXT_RECORDING_DATETIME (PVR_STRINGS_START + 58) +#define PVR_CHANNEL_NUMBER_INPUT (PVR_STRINGS_START + 59) +#define PVR_EPG_EVENT_REMAINING_TIME (PVR_STRINGS_START + 60) +#define PVR_EPG_EVENT_FINISH_TIME (PVR_STRINGS_START + 61) +#define PVR_TIMESHIFT_OFFSET (PVR_STRINGS_START + 62) +#define PVR_EPG_EVENT_SEEK_TIME (PVR_STRINGS_START + 63) +#define PVR_TIMESHIFT_PROGRESS_PLAY_POS (PVR_STRINGS_START + 64) +#define PVR_TIMESHIFT_PROGRESS_DURATION (PVR_STRINGS_START + 65) +#define PVR_TIMESHIFT_PROGRESS_EPG_START (PVR_STRINGS_START + 66) +#define PVR_TIMESHIFT_PROGRESS_EPG_END (PVR_STRINGS_START + 67) +#define PVR_TIMESHIFT_PROGRESS_BUFFER_START (PVR_STRINGS_START + 68) +#define PVR_TIMESHIFT_PROGRESS_BUFFER_END (PVR_STRINGS_START + 69) +#define PVR_TIMESHIFT_PROGRESS_START_TIME (PVR_STRINGS_START + 70) +#define PVR_TIMESHIFT_PROGRESS_END_TIME (PVR_STRINGS_START + 71) +#define PVR_EPG_EVENT_ICON (PVR_STRINGS_START + 72) +#define PVR_TIMESHIFT_SEEKBAR (PVR_STRINGS_START + 73) +#define PVR_BACKEND_PROVIDERS (PVR_STRINGS_START + 74) +#define PVR_BACKEND_CHANNEL_GROUPS (PVR_STRINGS_START + 75) +#define PVR_STRINGS_END PVR_BACKEND_CHANNEL_GROUPS + +#define RDS_DATA_START 1400 +#define RDS_HAS_RDS (RDS_DATA_START) +#define RDS_HAS_RADIOTEXT (RDS_DATA_START + 1) +#define RDS_HAS_RADIOTEXT_PLUS (RDS_DATA_START + 2) +#define RDS_GET_RADIOTEXT_LINE (RDS_DATA_START + 3) +#define RDS_TITLE (RDS_DATA_START + 4) +#define RDS_BAND (RDS_DATA_START + 5) +#define RDS_ARTIST (RDS_DATA_START + 6) +#define RDS_COMPOSER (RDS_DATA_START + 7) +#define RDS_CONDUCTOR (RDS_DATA_START + 8) +#define RDS_ALBUM (RDS_DATA_START + 9) +#define RDS_ALBUM_TRACKNUMBER (RDS_DATA_START + 10) +#define RDS_GET_RADIO_STYLE (RDS_DATA_START + 11) +#define RDS_COMMENT (RDS_DATA_START + 12) +#define RDS_INFO_NEWS (RDS_DATA_START + 13) +#define RDS_INFO_NEWS_LOCAL (RDS_DATA_START + 14) +#define RDS_INFO_STOCK (RDS_DATA_START + 15) +#define RDS_INFO_STOCK_SIZE (RDS_DATA_START + 16) +#define RDS_INFO_SPORT (RDS_DATA_START + 17) +#define RDS_INFO_SPORT_SIZE (RDS_DATA_START + 18) +#define RDS_INFO_LOTTERY (RDS_DATA_START + 19) +#define RDS_INFO_LOTTERY_SIZE (RDS_DATA_START + 20) +#define RDS_INFO_WEATHER (RDS_DATA_START + 21) +#define RDS_INFO_WEATHER_SIZE (RDS_DATA_START + 22) +#define RDS_INFO_CINEMA (RDS_DATA_START + 23) +#define RDS_INFO_CINEMA_SIZE (RDS_DATA_START + 24) +#define RDS_INFO_HOROSCOPE (RDS_DATA_START + 25) +#define RDS_INFO_HOROSCOPE_SIZE (RDS_DATA_START + 26) +#define RDS_INFO_OTHER (RDS_DATA_START + 27) +#define RDS_INFO_OTHER_SIZE (RDS_DATA_START + 28) +#define RDS_PROG_STATION (RDS_DATA_START + 29) +#define RDS_PROG_NOW (RDS_DATA_START + 30) +#define RDS_PROG_NEXT (RDS_DATA_START + 31) +#define RDS_PROG_HOST (RDS_DATA_START + 32) +#define RDS_PROG_EDIT_STAFF (RDS_DATA_START + 33) +#define RDS_PROG_HOMEPAGE (RDS_DATA_START + 34) +#define RDS_PROG_STYLE (RDS_DATA_START + 35) +#define RDS_PHONE_HOTLINE (RDS_DATA_START + 36) +#define RDS_PHONE_STUDIO (RDS_DATA_START + 37) +#define RDS_SMS_STUDIO (RDS_DATA_START + 38) +#define RDS_EMAIL_HOTLINE (RDS_DATA_START + 39) +#define RDS_EMAIL_STUDIO (RDS_DATA_START + 40) +#define RDS_HAS_HOTLINE_DATA (RDS_DATA_START + 41) +#define RDS_HAS_STUDIO_DATA (RDS_DATA_START + 42) +#define RDS_AUDIO_LANG (RDS_DATA_START + 43) +#define RDS_CHANNEL_COUNTRY (RDS_DATA_START + 44) +#define RDS_DATA_END RDS_CHANNEL_COUNTRY + +#define PLAYER_PROCESS 1500 +#define PLAYER_PROCESS_VIDEODECODER (PLAYER_PROCESS) +#define PLAYER_PROCESS_DEINTMETHOD (PLAYER_PROCESS + 1) +#define PLAYER_PROCESS_PIXELFORMAT (PLAYER_PROCESS + 2) +#define PLAYER_PROCESS_VIDEOWIDTH (PLAYER_PROCESS + 3) +#define PLAYER_PROCESS_VIDEOHEIGHT (PLAYER_PROCESS + 4) +#define PLAYER_PROCESS_VIDEOFPS (PLAYER_PROCESS + 5) +#define PLAYER_PROCESS_VIDEODAR (PLAYER_PROCESS + 6) +#define PLAYER_PROCESS_VIDEOHWDECODER (PLAYER_PROCESS + 7) +#define PLAYER_PROCESS_AUDIODECODER (PLAYER_PROCESS + 8) +#define PLAYER_PROCESS_AUDIOCHANNELS (PLAYER_PROCESS + 9) +#define PLAYER_PROCESS_AUDIOSAMPLERATE (PLAYER_PROCESS + 10) +#define PLAYER_PROCESS_AUDIOBITSPERSAMPLE (PLAYER_PROCESS + 11) +#define PLAYER_PROCESS_VIDEOSCANTYPE (PLAYER_PROCESS + 12) + +#define ADDON_INFOS 1600 +#define ADDON_SETTING_STRING (ADDON_INFOS) +#define ADDON_SETTING_BOOL (ADDON_INFOS + 1) +#define ADDON_SETTING_INT (ADDON_INFOS + 2) + +#define WINDOW_PROPERTY 9993 +#define WINDOW_IS_VISIBLE 9995 +#define WINDOW_NEXT 9996 +#define WINDOW_PREVIOUS 9997 +#define WINDOW_IS_MEDIA 9998 +#define WINDOW_IS_ACTIVE 9999 +#define WINDOW_IS 10000 +#define WINDOW_IS_DIALOG_TOPMOST 10001 +#define WINDOW_IS_MODAL_DIALOG_TOPMOST 10002 + +#define CONTROL_GET_LABEL 29996 +#define CONTROL_IS_ENABLED 29997 +#define CONTROL_IS_VISIBLE 29998 +#define CONTROL_GROUP_HAS_FOCUS 29999 +#define CONTROL_HAS_FOCUS 30000 + +#define LISTITEM_START 35000 +#define LISTITEM_THUMB (LISTITEM_START) +#define LISTITEM_LABEL (LISTITEM_START + 1) +#define LISTITEM_TITLE (LISTITEM_START + 2) +#define LISTITEM_TRACKNUMBER (LISTITEM_START + 3) +#define LISTITEM_ARTIST (LISTITEM_START + 4) +#define LISTITEM_ALBUM (LISTITEM_START + 5) +#define LISTITEM_YEAR (LISTITEM_START + 6) +#define LISTITEM_GENRE (LISTITEM_START + 7) +#define LISTITEM_ICON (LISTITEM_START + 8) +#define LISTITEM_DIRECTOR (LISTITEM_START + 9) +#define LISTITEM_OVERLAY (LISTITEM_START + 10) +#define LISTITEM_LABEL2 (LISTITEM_START + 11) +#define LISTITEM_FILENAME (LISTITEM_START + 12) +#define LISTITEM_DATE (LISTITEM_START + 13) +#define LISTITEM_SIZE (LISTITEM_START + 14) +#define LISTITEM_RATING (LISTITEM_START + 15) +#define LISTITEM_PROGRAM_COUNT (LISTITEM_START + 16) +#define LISTITEM_DURATION (LISTITEM_START + 17) +#define LISTITEM_ISPLAYING (LISTITEM_START + 18) +#define LISTITEM_ISSELECTED (LISTITEM_START + 19) +#define LISTITEM_PLOT (LISTITEM_START + 20) +#define LISTITEM_PLOT_OUTLINE (LISTITEM_START + 21) +#define LISTITEM_EPISODE (LISTITEM_START + 22) +#define LISTITEM_SEASON (LISTITEM_START + 23) +#define LISTITEM_TVSHOW (LISTITEM_START + 24) +#define LISTITEM_PREMIERED (LISTITEM_START + 25) +#define LISTITEM_COMMENT (LISTITEM_START + 26) +#define LISTITEM_ACTUAL_ICON (LISTITEM_START + 27) +#define LISTITEM_PATH (LISTITEM_START + 28) +#define LISTITEM_PICTURE_PATH (LISTITEM_START + 29) + +#define LISTITEM_PICTURE_START (LISTITEM_START + 30) +#define LISTITEM_PICTURE_RESOLUTION (LISTITEM_PICTURE_START) // => SLIDESHOW_RESOLUTION +#define LISTITEM_PICTURE_LONGDATE (LISTITEM_START + 31) // => SLIDESHOW_EXIF_LONG_DATE +#define LISTITEM_PICTURE_LONGDATETIME (LISTITEM_START + 32) // => SLIDESHOW_EXIF_LONG_DATE_TIME +#define LISTITEM_PICTURE_DATE (LISTITEM_START + 33) // => SLIDESHOW_EXIF_DATE +#define LISTITEM_PICTURE_DATETIME (LISTITEM_START + 34) // => SLIDESHOW_EXIF_DATE_TIME +#define LISTITEM_PICTURE_COMMENT (LISTITEM_START + 35) // => SLIDESHOW_COMMENT +#define LISTITEM_PICTURE_CAPTION (LISTITEM_START + 36) // => SLIDESHOW_IPTC_CAPTION +#define LISTITEM_PICTURE_DESC (LISTITEM_START + 37) // => SLIDESHOW_EXIF_DESCRIPTION +#define LISTITEM_PICTURE_KEYWORDS (LISTITEM_START + 38) // => SLIDESHOW_IPTC_KEYWORDS +#define LISTITEM_PICTURE_CAM_MAKE (LISTITEM_START + 39) // => SLIDESHOW_EXIF_CAMERA_MAKE +#define LISTITEM_PICTURE_CAM_MODEL (LISTITEM_START + 40) // => SLIDESHOW_EXIF_CAMERA_MODEL +#define LISTITEM_PICTURE_APERTURE (LISTITEM_START + 41) // => SLIDESHOW_EXIF_APERTURE +#define LISTITEM_PICTURE_FOCAL_LEN (LISTITEM_START + 42) // => SLIDESHOW_EXIF_FOCAL_LENGTH +#define LISTITEM_PICTURE_FOCUS_DIST (LISTITEM_START + 43) // => SLIDESHOW_EXIF_FOCUS_DIST +#define LISTITEM_PICTURE_EXP_MODE (LISTITEM_START + 44) // => SLIDESHOW_EXIF_EXPOSURE_MODE +#define LISTITEM_PICTURE_EXP_TIME (LISTITEM_START + 45) // => SLIDESHOW_EXIF_EXPOSURE_TIME +#define LISTITEM_PICTURE_ISO (LISTITEM_START + 46) // => SLIDESHOW_EXIF_ISO_EQUIV +#define LISTITEM_PICTURE_AUTHOR (LISTITEM_START + 47) // => SLIDESHOW_IPTC_AUTHOR +#define LISTITEM_PICTURE_BYLINE (LISTITEM_START + 48) // => SLIDESHOW_IPTC_BYLINE +#define LISTITEM_PICTURE_BYLINE_TITLE (LISTITEM_START + 49) // => SLIDESHOW_IPTC_BYLINE_TITLE +#define LISTITEM_PICTURE_CATEGORY (LISTITEM_START + 50) // => SLIDESHOW_IPTC_CATEGORY +#define LISTITEM_PICTURE_CCD_WIDTH (LISTITEM_START + 51) // => SLIDESHOW_EXIF_CCD_WIDTH +#define LISTITEM_PICTURE_CITY (LISTITEM_START + 52) // => SLIDESHOW_IPTC_CITY +#define LISTITEM_PICTURE_URGENCY (LISTITEM_START + 53) // => SLIDESHOW_IPTC_URGENCY +#define LISTITEM_PICTURE_COPYRIGHT_NOTICE (LISTITEM_START + 54) // => SLIDESHOW_IPTC_COPYRIGHT_NOTICE +#define LISTITEM_PICTURE_COUNTRY (LISTITEM_START + 55) // => SLIDESHOW_IPTC_COUNTRY +#define LISTITEM_PICTURE_COUNTRY_CODE (LISTITEM_START + 56) // => SLIDESHOW_IPTC_COUNTRY_CODE +#define LISTITEM_PICTURE_CREDIT (LISTITEM_START + 57) // => SLIDESHOW_IPTC_CREDIT +#define LISTITEM_PICTURE_IPTCDATE (LISTITEM_START + 58) // => SLIDESHOW_IPTC_DATE +#define LISTITEM_PICTURE_DIGITAL_ZOOM (LISTITEM_START + 59) // => SLIDESHOW_EXIF_DIGITAL_ZOOM +#define LISTITEM_PICTURE_EXPOSURE (LISTITEM_START + 60) // => SLIDESHOW_EXIF_EXPOSURE +#define LISTITEM_PICTURE_EXPOSURE_BIAS (LISTITEM_START + 61) // => SLIDESHOW_EXIF_EXPOSURE_BIAS +#define LISTITEM_PICTURE_FLASH_USED (LISTITEM_START + 62) // => SLIDESHOW_EXIF_FLASH_USED +#define LISTITEM_PICTURE_HEADLINE (LISTITEM_START + 63) // => SLIDESHOW_IPTC_HEADLINE +#define LISTITEM_PICTURE_COLOUR (LISTITEM_START + 64) // => SLIDESHOW_COLOUR +#define LISTITEM_PICTURE_LIGHT_SOURCE (LISTITEM_START + 65) // => SLIDESHOW_EXIF_LIGHT_SOURCE +#define LISTITEM_PICTURE_METERING_MODE (LISTITEM_START + 66) // => SLIDESHOW_EXIF_METERING_MODE +#define LISTITEM_PICTURE_OBJECT_NAME (LISTITEM_START + 67) // => SLIDESHOW_IPTC_OBJECT_NAME +#define LISTITEM_PICTURE_ORIENTATION (LISTITEM_START + 68) // => SLIDESHOW_EXIF_ORIENTATION +#define LISTITEM_PICTURE_PROCESS (LISTITEM_START + 69) // => SLIDESHOW_PROCESS +#define LISTITEM_PICTURE_REF_SERVICE (LISTITEM_START + 70) // => SLIDESHOW_IPTC_REF_SERVICE +#define LISTITEM_PICTURE_SOURCE (LISTITEM_START + 71) // => SLIDESHOW_IPTC_SOURCE +#define LISTITEM_PICTURE_SPEC_INSTR (LISTITEM_START + 72) // => SLIDESHOW_IPTC_SPEC_INSTR +#define LISTITEM_PICTURE_STATE (LISTITEM_START + 73) // => SLIDESHOW_IPTC_STATE +#define LISTITEM_PICTURE_SUP_CATEGORIES (LISTITEM_START + 74) // => SLIDESHOW_IPTC_SUP_CATEGORIES +#define LISTITEM_PICTURE_TX_REFERENCE (LISTITEM_START + 75) // => SLIDESHOW_IPTC_TX_REFERENCE +#define LISTITEM_PICTURE_WHITE_BALANCE (LISTITEM_START + 76) // => SLIDESHOW_EXIF_WHITE_BALANCE +#define LISTITEM_PICTURE_IMAGETYPE (LISTITEM_START + 77) // => SLIDESHOW_IPTC_IMAGETYPE +#define LISTITEM_PICTURE_SUBLOCATION (LISTITEM_START + 78) // => SLIDESHOW_IPTC_SUBLOCATION +#define LISTITEM_PICTURE_TIMECREATED (LISTITEM_START + 79) // => SLIDESHOW_IPTC_TIMECREATED +#define LISTITEM_PICTURE_GPS_LAT (LISTITEM_START + 80) // => SLIDESHOW_EXIF_GPS_LATITUDE +#define LISTITEM_PICTURE_GPS_LON (LISTITEM_START + 81) // => SLIDESHOW_EXIF_GPS_LONGITUDE +#define LISTITEM_PICTURE_GPS_ALT (LISTITEM_START + 82) // => SLIDESHOW_EXIF_GPS_ALTITUDE +#define LISTITEM_PICTURE_END (LISTITEM_PICTURE_GPS_ALT) + +#define LISTITEM_STUDIO (LISTITEM_START + 83) +#define LISTITEM_MPAA (LISTITEM_START + 84) +#define LISTITEM_CAST (LISTITEM_START + 85) +#define LISTITEM_CAST_AND_ROLE (LISTITEM_START + 86) +#define LISTITEM_WRITER (LISTITEM_START + 87) +#define LISTITEM_TAGLINE (LISTITEM_START + 88) +#define LISTITEM_TOP250 (LISTITEM_START + 89) +#define LISTITEM_RATING_AND_VOTES (LISTITEM_START + 90) +#define LISTITEM_TRAILER (LISTITEM_START + 91) +#define LISTITEM_APPEARANCES (LISTITEM_START + 92) +#define LISTITEM_FILENAME_AND_PATH (LISTITEM_START + 93) +#define LISTITEM_SORT_LETTER (LISTITEM_START + 94) +#define LISTITEM_ALBUM_ARTIST (LISTITEM_START + 95) +#define LISTITEM_FOLDERNAME (LISTITEM_START + 96) +#define LISTITEM_VIDEO_CODEC (LISTITEM_START + 97) +#define LISTITEM_VIDEO_RESOLUTION (LISTITEM_START + 98) +#define LISTITEM_VIDEO_ASPECT (LISTITEM_START + 99) +#define LISTITEM_AUDIO_CODEC (LISTITEM_START + 100) +#define LISTITEM_AUDIO_CHANNELS (LISTITEM_START + 101) +#define LISTITEM_AUDIO_LANGUAGE (LISTITEM_START + 102) +#define LISTITEM_SUBTITLE_LANGUAGE (LISTITEM_START + 103) +#define LISTITEM_IS_FOLDER (LISTITEM_START + 104) +#define LISTITEM_ORIGINALTITLE (LISTITEM_START + 105) +#define LISTITEM_COUNTRY (LISTITEM_START + 106) +#define LISTITEM_PLAYCOUNT (LISTITEM_START + 107) +#define LISTITEM_LASTPLAYED (LISTITEM_START + 108) +#define LISTITEM_FOLDERPATH (LISTITEM_START + 109) +#define LISTITEM_DISC_NUMBER (LISTITEM_START + 110) +#define LISTITEM_FILE_EXTENSION (LISTITEM_START + 111) +#define LISTITEM_IS_RESUMABLE (LISTITEM_START + 112) +#define LISTITEM_PERCENT_PLAYED (LISTITEM_START + 113) +#define LISTITEM_DATE_ADDED (LISTITEM_START + 114) +#define LISTITEM_DBTYPE (LISTITEM_START + 115) +#define LISTITEM_DBID (LISTITEM_START + 116) +#define LISTITEM_ART (LISTITEM_START + 117) +#define LISTITEM_STARTTIME (LISTITEM_START + 118) +#define LISTITEM_ENDTIME (LISTITEM_START + 119) +#define LISTITEM_STARTDATE (LISTITEM_START + 120) +#define LISTITEM_ENDDATE (LISTITEM_START + 121) +#define LISTITEM_NEXT_TITLE (LISTITEM_START + 122) +#define LISTITEM_NEXT_GENRE (LISTITEM_START + 123) +#define LISTITEM_NEXT_PLOT (LISTITEM_START + 124) +#define LISTITEM_NEXT_PLOT_OUTLINE (LISTITEM_START + 125) +#define LISTITEM_NEXT_STARTTIME (LISTITEM_START + 126) +#define LISTITEM_NEXT_ENDTIME (LISTITEM_START + 127) +#define LISTITEM_NEXT_STARTDATE (LISTITEM_START + 128) +#define LISTITEM_NEXT_ENDDATE (LISTITEM_START + 129) +#define LISTITEM_NEXT_DURATION (LISTITEM_START + 130) +#define LISTITEM_CHANNEL_NAME (LISTITEM_START + 131) +#define LISTITEM_CHANNEL_GROUP (LISTITEM_START + 132) +#define LISTITEM_HASTIMER (LISTITEM_START + 133) +#define LISTITEM_ISRECORDING (LISTITEM_START + 134) +#define LISTITEM_ISENCRYPTED (LISTITEM_START + 135) +#define LISTITEM_PARENTAL_RATING (LISTITEM_START + 136) +#define LISTITEM_PROGRESS (LISTITEM_START + 137) +#define LISTITEM_HAS_EPG (LISTITEM_START + 138) +#define LISTITEM_VOTES (LISTITEM_START + 139) +#define LISTITEM_STEREOSCOPIC_MODE (LISTITEM_START + 140) +#define LISTITEM_IS_STEREOSCOPIC (LISTITEM_START + 141) +#define LISTITEM_INPROGRESS (LISTITEM_START + 142) +#define LISTITEM_HASRECORDING (LISTITEM_START + 143) +#define LISTITEM_HASREMINDER (LISTITEM_START + 144) +#define LISTITEM_CHANNEL_NUMBER (LISTITEM_START + 145) +#define LISTITEM_IMDBNUMBER (LISTITEM_START + 146) +#define LISTITEM_EPISODENAME (LISTITEM_START + 147) +#define LISTITEM_IS_COLLECTION (LISTITEM_START + 148) +#define LISTITEM_HASTIMERSCHEDULE (LISTITEM_START + 149) +#define LISTITEM_TIMERTYPE (LISTITEM_START + 150) +#define LISTITEM_EPG_EVENT_TITLE (LISTITEM_START + 151) +#define LISTITEM_DATETIME (LISTITEM_START + 152) +#define LISTITEM_USER_RATING (LISTITEM_START + 153) +#define LISTITEM_TAG (LISTITEM_START + 154) +#define LISTITEM_SET (LISTITEM_START + 155) +#define LISTITEM_SETID (LISTITEM_START + 156) +#define LISTITEM_IS_PARENTFOLDER (LISTITEM_START + 157) +#define LISTITEM_MOOD (LISTITEM_START + 158) +#define LISTITEM_CONTRIBUTORS (LISTITEM_START + 159) +#define LISTITEM_CONTRIBUTOR_AND_ROLE (LISTITEM_START + 160) +#define LISTITEM_TIMERISACTIVE (LISTITEM_START + 161) +#define LISTITEM_TIMERHASCONFLICT (LISTITEM_START + 162) +#define LISTITEM_TIMERHASERROR (LISTITEM_START + 163) + +#define LISTITEM_ADDON_NAME (LISTITEM_START + 164) +#define LISTITEM_ADDON_VERSION (LISTITEM_START + 165) +#define LISTITEM_ADDON_CREATOR (LISTITEM_START + 166) +#define LISTITEM_ADDON_SUMMARY (LISTITEM_START + 167) +#define LISTITEM_ADDON_DESCRIPTION (LISTITEM_START + 168) +#define LISTITEM_ADDON_DISCLAIMER (LISTITEM_START + 169) +#define LISTITEM_ADDON_BROKEN (LISTITEM_START + 170) +#define LISTITEM_ADDON_LIFECYCLE_TYPE (LISTITEM_START + 171) +#define LISTITEM_ADDON_LIFECYCLE_DESC (LISTITEM_START + 172) +#define LISTITEM_ADDON_TYPE (LISTITEM_START + 173) +#define LISTITEM_ADDON_INSTALL_DATE (LISTITEM_START + 174) +#define LISTITEM_ADDON_LAST_UPDATED (LISTITEM_START + 175) +#define LISTITEM_ADDON_LAST_USED (LISTITEM_START + 176) +#define LISTITEM_STATUS (LISTITEM_START + 177) +#define LISTITEM_ENDTIME_RESUME (LISTITEM_START + 178) +#define LISTITEM_ADDON_ORIGIN (LISTITEM_START + 179) +#define LISTITEM_ADDON_NEWS (LISTITEM_START + 180) +#define LISTITEM_ADDON_SIZE (LISTITEM_START + 181) +#define LISTITEM_EXPIRATION_DATE (LISTITEM_START + 182) +#define LISTITEM_EXPIRATION_TIME (LISTITEM_START + 183) +#define LISTITEM_PROPERTY (LISTITEM_START + 184) +#define LISTITEM_EPG_EVENT_ICON (LISTITEM_START + 185) +#define LISTITEM_HASREMINDERRULE (LISTITEM_START + 186) +#define LISTITEM_HASARCHIVE (LISTITEM_START + 187) +#define LISTITEM_ISPLAYABLE (LISTITEM_START + 188) +#define LISTITEM_FILENAME_NO_EXTENSION (LISTITEM_START + 189) +#define LISTITEM_CURRENTITEM (LISTITEM_START + 190) +#define LISTITEM_IS_NEW (LISTITEM_START + 191) +#define LISTITEM_DISC_TITLE (LISTITEM_START + 192) +#define LISTITEM_IS_BOXSET (LISTITEM_START + 193) +#define LISTITEM_TOTALDISCS (LISTITEM_START + 194) +#define LISTITEM_RELEASEDATE (LISTITEM_START + 195) +#define LISTITEM_ORIGINALDATE (LISTITEM_START + 196) +#define LISTITEM_BPM (LISTITEM_START + 197) +#define LISTITEM_UNIQUEID (LISTITEM_START + 198) +#define LISTITEM_BITRATE (LISTITEM_START + 199) +#define LISTITEM_SAMPLERATE (LISTITEM_START + 200) +#define LISTITEM_MUSICCHANNELS (LISTITEM_START + 201) +#define LISTITEM_IS_PREMIERE (LISTITEM_START + 202) +#define LISTITEM_IS_FINALE (LISTITEM_START + 203) +#define LISTITEM_IS_LIVE (LISTITEM_START + 204) +#define LISTITEM_TVSHOWDBID (LISTITEM_START + 205) +#define LISTITEM_ALBUMSTATUS (LISTITEM_START + 206) +#define LISTITEM_ISAUTOUPDATEABLE (LISTITEM_START + 207) +#define LISTITEM_VIDEO_HDR_TYPE (LISTITEM_START + 208) + +#define LISTITEM_END (LISTITEM_START + 2500) + +#define CONDITIONAL_LABEL_START (LISTITEM_END + 1) // 37501 +#define CONDITIONAL_LABEL_END 39999 + +// the multiple information vector +#define MULTI_INFO_START 40000 +#define MULTI_INFO_END 99999 +#define COMBINED_VALUES_START 100000 + +// listitem info Flags +// Stored in the top 8 bits of GUIInfo::m_data1 +// therefore we only have room for 8 flags +#define INFOFLAG_LISTITEM_WRAP (static_cast<uint32_t>(1 << 25)) // Wrap ListItem lookups +#define INFOFLAG_LISTITEM_POSITION (static_cast<uint32_t>(1 << 26)) // ListItem lookups based on cursor position +#define INFOFLAG_LISTITEM_ABSOLUTE (static_cast<uint32_t>(1 << 27)) // Absolute ListItem lookups +#define INFOFLAG_LISTITEM_NOWRAP (static_cast<uint32_t>(1 << 28)) // Do not wrap ListItem lookups +#define INFOFLAG_LISTITEM_CONTAINER (static_cast<uint32_t>(1 << 29)) // Lookup the item in given container +// clang-format on diff --git a/xbmc/guilib/guiinfo/GUIInfoProvider.h b/xbmc/guilib/guiinfo/GUIInfoProvider.h new file mode 100644 index 0000000..a03159b --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoProvider.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#pragma once + +#include "cores/VideoPlayer/Interface/StreamInfo.h" +#include "guilib/guiinfo/IGUIInfoProvider.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CGUIInfoProvider : public IGUIInfoProvider +{ +public: + CGUIInfoProvider() = default; + ~CGUIInfoProvider() override = default; + + bool GetFallbackLabel(std::string& value, + const CFileItem* item, + int contextWindow, + const CGUIInfo& info, + std::string* fallback) override + { + return false; + } + + void UpdateAVInfo(const AudioStreamInfo& audioInfo, const VideoStreamInfo& videoInfo, const SubtitleStreamInfo& subtitleInfo) override + { m_audioInfo = audioInfo, m_videoInfo = videoInfo, m_subtitleInfo = subtitleInfo; } + +protected: + VideoStreamInfo m_videoInfo; + AudioStreamInfo m_audioInfo; + SubtitleStreamInfo m_subtitleInfo; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/GUIInfoProviders.cpp b/xbmc/guilib/guiinfo/GUIInfoProviders.cpp new file mode 100644 index 0000000..274318e --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoProviders.cpp @@ -0,0 +1,122 @@ +/* + * 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 "guilib/guiinfo/GUIInfoProviders.h" + +#include "guilib/guiinfo/IGUIInfoProvider.h" + +#include <algorithm> + +using namespace KODI::GUILIB::GUIINFO; + +CGUIInfoProviders::CGUIInfoProviders() +{ + RegisterProvider(&m_guiControlsGUIInfo); + RegisterProvider(&m_videoGUIInfo); // Note: video info provider must be registered before music info provider, + // because of music videos having both a video info tag and a music info tag + // and video info tag always has to be evaluated first. + RegisterProvider(&m_musicGUIInfo); + RegisterProvider(&m_picturesGUIInfo); + RegisterProvider(&m_playerGUIInfo); + RegisterProvider(&m_libraryGUIInfo); + RegisterProvider(&m_addonsGUIInfo); + RegisterProvider(&m_weatherGUIInfo); + RegisterProvider(&m_gamesGUIInfo); + RegisterProvider(&m_systemGUIInfo); + RegisterProvider(&m_visualisationGUIInfo); + RegisterProvider(&m_skinGUIInfo); +} + +CGUIInfoProviders::~CGUIInfoProviders() +{ + UnregisterProvider(&m_skinGUIInfo); + UnregisterProvider(&m_visualisationGUIInfo); + UnregisterProvider(&m_systemGUIInfo); + UnregisterProvider(&m_gamesGUIInfo); + UnregisterProvider(&m_weatherGUIInfo); + UnregisterProvider(&m_addonsGUIInfo); + UnregisterProvider(&m_libraryGUIInfo); + UnregisterProvider(&m_playerGUIInfo); + UnregisterProvider(&m_picturesGUIInfo); + UnregisterProvider(&m_musicGUIInfo); + UnregisterProvider(&m_videoGUIInfo); + UnregisterProvider(&m_guiControlsGUIInfo); +} + +void CGUIInfoProviders::RegisterProvider(IGUIInfoProvider *provider, bool bAppend /* = true */) +{ + auto it = std::find(m_providers.begin(), m_providers.end(), provider); + if (it == m_providers.end()) + { + if (bAppend) + m_providers.emplace_back(provider); + else + m_providers.insert(m_providers.begin(), provider); + } +} + +void CGUIInfoProviders::UnregisterProvider(IGUIInfoProvider *provider) +{ + auto it = std::find(m_providers.begin(), m_providers.end(), provider); + if (it != m_providers.end()) + m_providers.erase(it); +} + +bool CGUIInfoProviders::InitCurrentItem(CFileItem *item) +{ + bool bReturn = false; + + for (const auto& provider : m_providers) + { + bReturn = provider->InitCurrentItem(item); + } + return bReturn; +} + +bool CGUIInfoProviders::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + for (const auto& provider : m_providers) + { + if (provider->GetLabel(value, item, contextWindow, info, fallback)) + return true; + } + for (const auto& provider : m_providers) + { + if (provider->GetFallbackLabel(value, item, contextWindow, info, fallback)) + return true; + } + return false; +} + +bool CGUIInfoProviders::GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const +{ + for (const auto& provider : m_providers) + { + if (provider->GetInt(value, item, contextWindow, info)) + return true; + } + return false; +} + +bool CGUIInfoProviders::GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const +{ + for (const auto& provider : m_providers) + { + if (provider->GetBool(value, item, contextWindow, info)) + return true; + } + return false; +} + +void CGUIInfoProviders::UpdateAVInfo(const AudioStreamInfo& audioInfo, const VideoStreamInfo& videoInfo, const SubtitleStreamInfo& subtitleInfo) +{ + for (const auto& provider : m_providers) + { + provider->UpdateAVInfo(audioInfo, videoInfo, subtitleInfo); + } +} diff --git a/xbmc/guilib/guiinfo/GUIInfoProviders.h b/xbmc/guilib/guiinfo/GUIInfoProviders.h new file mode 100644 index 0000000..1aed710 --- /dev/null +++ b/xbmc/guilib/guiinfo/GUIInfoProviders.h @@ -0,0 +1,157 @@ +/* + * 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. + */ + +#pragma once + +#include "guilib/guiinfo/AddonsGUIInfo.h" +#include "guilib/guiinfo/GUIControlsGUIInfo.h" +#include "guilib/guiinfo/GamesGUIInfo.h" +#include "guilib/guiinfo/LibraryGUIInfo.h" +#include "guilib/guiinfo/MusicGUIInfo.h" +#include "guilib/guiinfo/PicturesGUIInfo.h" +#include "guilib/guiinfo/PlayerGUIInfo.h" +#include "guilib/guiinfo/SkinGUIInfo.h" +#include "guilib/guiinfo/SystemGUIInfo.h" +#include "guilib/guiinfo/VideoGUIInfo.h" +#include "guilib/guiinfo/VisualisationGUIInfo.h" +#include "guilib/guiinfo/WeatherGUIInfo.h" + +#include <string> +#include <vector> + +class CFileItem; +class CGUIListItem; + +struct AudioStreamInfo; +struct VideoStreamInfo; + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; +class IGUIInfoProvider; + +class CGUIInfoProviders +{ +public: + CGUIInfoProviders(); + virtual ~CGUIInfoProviders(); + + /*! + * @brief Register a guiinfo provider. + * @param provider The provider to register. + * @param bAppend True to append to the list of providers, false to insert before the first provider + */ + void RegisterProvider(IGUIInfoProvider *provider, bool bAppend = true); + + /*! + * @brief Unregister a guiinfo provider. + * @param provider The provider to unregister. + */ + void UnregisterProvider(IGUIInfoProvider *provider); + + /*! + * @brief Init a new current guiinfo manager item. Gets called whenever the active guiinfo manager item changes. + * @param item The new item. + * @return True if the item was inited by one of the providers, false otherwise. + */ + bool InitCurrentItem(CFileItem *item); + + /*! + * @brief Get a GUIInfoManager label string from one of the registered providers. + * @param value Will be filled with the requested value. + * @param item The item to get the value for. Can be nullptr. + * @param contextWindow The context window. Can be 0. + * @param info The GUI info (label id + additional data). + * @param fallback A fallback value. Can be nullptr. + * @return True if the value was filled successfully by one of the providers, false otherwise. + */ + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const; + + /*! + * @brief Get a GUIInfoManager integer value from one of the registered providers. + * @param value Will be filled with the requested value. + * @param item The item to get the value for. Can be nullptr. + * @param contextWindow The context window. Can be 0. + * @param info The GUI info (label id + additional data). + * @return True if the value was filled successfully by one of the providers, false otherwise. + */ + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const; + + /*! + * @brief Get a GUIInfoManager bool value from one of the registered providers. + * @param value Will be filled with the requested value. + * @param item The item to get the value for. Can be nullptr. + * @param contextWindow The context window. Can be 0. + * @param info The GUI info (label id + additional data). + * @return True if the value was filled successfully by one of the providers, false otherwise. + */ + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const; + + /*! + * @brief Set new audio/video/subtitle stream info data at all registered providers. + * @param audioInfo New audio stream info. + * @param videoInfo New video stream info. + * @param subtitleInfo New subtitle stream info. + */ + void UpdateAVInfo(const AudioStreamInfo& audioInfo, const VideoStreamInfo& videoInfo, const SubtitleStreamInfo& subtitleInfo); + + /*! + * @brief Get the player guiinfo provider. + * @return The player guiinfo provider. + */ + CPlayerGUIInfo& GetPlayerInfoProvider() { return m_playerGUIInfo; } + + /*! + * @brief Get the system guiinfo provider. + * @return The system guiinfo provider. + */ + CSystemGUIInfo& GetSystemInfoProvider() { return m_systemGUIInfo; } + + /*! + * @brief Get the pictures guiinfo provider. + * @return The pictures guiinfo provider. + */ + CPicturesGUIInfo& GetPicturesInfoProvider() { return m_picturesGUIInfo; } + + /*! + * @brief Get the gui controls guiinfo provider. + * @return The gui controls guiinfo provider. + */ + CGUIControlsGUIInfo& GetGUIControlsInfoProvider() { return m_guiControlsGUIInfo; } + + /*! + * @brief Get the library guiinfo provider. + * @return The library guiinfo provider. + */ + CLibraryGUIInfo& GetLibraryInfoProvider() { return m_libraryGUIInfo; } + +private: + std::vector<IGUIInfoProvider *> m_providers; + + CAddonsGUIInfo m_addonsGUIInfo; + CGamesGUIInfo m_gamesGUIInfo; + CGUIControlsGUIInfo m_guiControlsGUIInfo; + CLibraryGUIInfo m_libraryGUIInfo; + CMusicGUIInfo m_musicGUIInfo; + CPicturesGUIInfo m_picturesGUIInfo; + CPlayerGUIInfo m_playerGUIInfo; + CSkinGUIInfo m_skinGUIInfo; + CSystemGUIInfo m_systemGUIInfo; + CVideoGUIInfo m_videoGUIInfo; + CVisualisationGUIInfo m_visualisationGUIInfo; + CWeatherGUIInfo m_weatherGUIInfo; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/GamesGUIInfo.cpp b/xbmc/guilib/guiinfo/GamesGUIInfo.cpp new file mode 100644 index 0000000..5428c3a --- /dev/null +++ b/xbmc/guilib/guiinfo/GamesGUIInfo.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/GamesGUIInfo.h" + +#include "FileItem.h" +#include "Util.h" +#include "cores/RetroPlayer/RetroPlayerUtils.h" +#include "games/tags/GameInfoTag.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "settings/MediaSettings.h" +#include "utils/StringUtils.h" +#include "utils/Variant.h" +#include "utils/log.h" + +using namespace KODI::GUILIB::GUIINFO; +using namespace KODI::GAME; +using namespace KODI::RETRO; + +//! @todo Savestates were removed from v18 +//#define FILEITEM_PROPERTY_SAVESTATE_DURATION "duration" + +bool CGamesGUIInfo::InitCurrentItem(CFileItem *item) +{ + if (item && item->IsGame()) + { + CLog::Log(LOGDEBUG, "CGamesGUIInfo::InitCurrentItem({})", item->GetPath()); + + item->LoadGameTag(); + CGameInfoTag* tag = item->GetGameInfoTag(); // creates item if not yet set, so no nullptr checks needed + + if (tag->GetTitle().empty()) + { + // No title in tag, show filename only + tag->SetTitle(CUtil::GetTitleFromPath(item->GetPath())); + } + return true; + } + return false; +} + +bool CGamesGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // RETROPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case RETROPLAYER_VIDEO_FILTER: + { + value = CMediaSettings::GetInstance().GetCurrentGameSettings().VideoFilter(); + return true; + } + case RETROPLAYER_STRETCH_MODE: + { + STRETCHMODE stretchMode = CMediaSettings::GetInstance().GetCurrentGameSettings().StretchMode(); + value = CRetroPlayerUtils::StretchModeToIdentifier(stretchMode); + return true; + } + case RETROPLAYER_VIDEO_ROTATION: + { + const unsigned int rotationDegCCW = CMediaSettings::GetInstance().GetCurrentGameSettings().RotationDegCCW(); + value = std::to_string(rotationDegCCW); + return true; + } + default: + break; + } + + return false; +} + +bool CGamesGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + return false; +} + +bool CGamesGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + return false; +} diff --git a/xbmc/guilib/guiinfo/GamesGUIInfo.h b/xbmc/guilib/guiinfo/GamesGUIInfo.h new file mode 100644 index 0000000..5ad78d9 --- /dev/null +++ b/xbmc/guilib/guiinfo/GamesGUIInfo.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CGamesGUIInfo : public CGUIInfoProvider +{ +public: + CGamesGUIInfo() = default; + ~CGamesGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/IGUIInfoProvider.h b/xbmc/guilib/guiinfo/IGUIInfoProvider.h new file mode 100644 index 0000000..4560b08 --- /dev/null +++ b/xbmc/guilib/guiinfo/IGUIInfoProvider.h @@ -0,0 +1,97 @@ +/* + * 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. + */ + +#pragma once + +#include <string> + +class CFileItem; +class CGUIListItem; + +struct AudioStreamInfo; +struct VideoStreamInfo; + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class IGUIInfoProvider +{ +public: + virtual ~IGUIInfoProvider() = default; + + /*! + * @brief Init a new current guiinfo manager item. Gets called whenever the active guiinfo manager item changes. + * @param item The new item. + * @return True if the item was inited by the provider, false otherwise. + */ + virtual bool InitCurrentItem(CFileItem *item) = 0; + + /*! + * @brief Get a GUIInfoManager label string. + * @param value Will be filled with the requested value. + * @param item The item to get the value for. Can be nullptr. + * @param contextWindow The context window. Can be 0. + * @param info The GUI info (label id + additional data). + * @param fallback A fallback value. Can be nullptr. + * @return True if the value was filled successfully, false otherwise. + */ + virtual bool GetLabel(std::string &value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const = 0; + + /*! + * @brief Get a GUIInfoManager label fallback string. Will be called if none of the registered + * provider's GetLabel() implementation has returned success. + * @param value Will be filled with the requested value. + * @param item The item to get the value for. Can be nullptr. + * @param contextWindow The context window. Can be 0. + * @param info The GUI info (label id + additional data). + * @param fallback A fallback value. Can be nullptr. + * @return True if the value was filled successfully, false otherwise. + */ + virtual bool GetFallbackLabel(std::string& value, + const CFileItem* item, + int contextWindow, + const CGUIInfo& info, + std::string* fallback) = 0; + + /*! + * @brief Get a GUIInfoManager integer value. + * @param value Will be filled with the requested value. + * @param item The item to get the value for. Can be nullptr. + * @param contextWindow The context window. Can be 0. + * @param info The GUI info (label id + additional data). + * @return True if the value was filled successfully, false otherwise. + */ + virtual bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const = 0; + + /*! + * @brief Get a GUIInfoManager bool value. + * @param value Will be filled with the requested value. + * @param item The item to get the value for. Can be nullptr. + * @param contextWindow The context window. Can be 0. + * @param info The GUI info (label id + additional data). + * @return True if the value was filled successfully, false otherwise. + */ + virtual bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const = 0; + + /*! + * @brief Set new audio/video stream info data. + * @param audioInfo New audio stream info. + * @param videoInfo New video stream info. + */ + virtual void UpdateAVInfo(const AudioStreamInfo& audioInfo, const VideoStreamInfo& videoInfo, const SubtitleStreamInfo& subtitleInfo) = 0; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/LibraryGUIInfo.cpp b/xbmc/guilib/guiinfo/LibraryGUIInfo.cpp new file mode 100644 index 0000000..fc0f471 --- /dev/null +++ b/xbmc/guilib/guiinfo/LibraryGUIInfo.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/LibraryGUIInfo.h" + +#include "FileItem.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "filesystem/Directory.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "music/MusicDatabase.h" +#include "music/MusicLibraryQueue.h" +#include "profiles/ProfileManager.h" +#include "settings/SettingsComponent.h" +#include "utils/FileUtils.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "video/VideoDatabase.h" +#include "video/VideoLibraryQueue.h" + +using namespace KODI::GUILIB::GUIINFO; + +CLibraryGUIInfo::CLibraryGUIInfo() +{ + ResetLibraryBools(); +} + +bool CLibraryGUIInfo::GetLibraryBool(int condition) const +{ + bool value = false; + GetBool(value, nullptr, 0, CGUIInfo(condition)); + return value; +} + +void CLibraryGUIInfo::SetLibraryBool(int condition, bool value) +{ + switch (condition) + { + case LIBRARY_HAS_MUSIC: + m_libraryHasMusic = value ? 1 : 0; + break; + case LIBRARY_HAS_MOVIES: + m_libraryHasMovies = value ? 1 : 0; + break; + case LIBRARY_HAS_MOVIE_SETS: + m_libraryHasMovieSets = value ? 1 : 0; + break; + case LIBRARY_HAS_TVSHOWS: + m_libraryHasTVShows = value ? 1 : 0; + break; + case LIBRARY_HAS_MUSICVIDEOS: + m_libraryHasMusicVideos = value ? 1 : 0; + break; + case LIBRARY_HAS_SINGLES: + m_libraryHasSingles = value ? 1 : 0; + break; + case LIBRARY_HAS_COMPILATIONS: + m_libraryHasCompilations = value ? 1 : 0; + break; + case LIBRARY_HAS_BOXSETS: + m_libraryHasBoxsets = value ? 1 : 0; + break; + default: + break; + } +} + +void CLibraryGUIInfo::ResetLibraryBools() +{ + m_libraryHasMusic = -1; + m_libraryHasMovies = -1; + m_libraryHasTVShows = -1; + m_libraryHasMusicVideos = -1; + m_libraryHasMovieSets = -1; + m_libraryHasSingles = -1; + m_libraryHasCompilations = -1; + m_libraryHasBoxsets = -1; + m_libraryRoleCounts.clear(); +} + +bool CLibraryGUIInfo::InitCurrentItem(CFileItem *item) +{ + return false; +} + +bool CLibraryGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + return false; +} + +bool CLibraryGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + return false; +} + +bool CLibraryGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // LIBRARY_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case LIBRARY_HAS_MUSIC: + { + if (m_libraryHasMusic < 0) + { // query + CMusicDatabase db; + if (db.Open()) + { + m_libraryHasMusic = (db.GetSongsCount() > 0) ? 1 : 0; + db.Close(); + } + } + value = m_libraryHasMusic > 0; + return true; + } + case LIBRARY_HAS_MOVIES: + { + if (m_libraryHasMovies < 0) + { + CVideoDatabase db; + if (db.Open()) + { + m_libraryHasMovies = db.HasContent(VideoDbContentType::MOVIES) ? 1 : 0; + db.Close(); + } + } + value = m_libraryHasMovies > 0; + return true; + } + case LIBRARY_HAS_MOVIE_SETS: + { + if (m_libraryHasMovieSets < 0) + { + CVideoDatabase db; + if (db.Open()) + { + m_libraryHasMovieSets = db.HasSets() ? 1 : 0; + db.Close(); + } + } + value = m_libraryHasMovieSets > 0; + return true; + } + case LIBRARY_HAS_TVSHOWS: + { + if (m_libraryHasTVShows < 0) + { + CVideoDatabase db; + if (db.Open()) + { + m_libraryHasTVShows = db.HasContent(VideoDbContentType::TVSHOWS) ? 1 : 0; + db.Close(); + } + } + value = m_libraryHasTVShows > 0; + return true; + } + case LIBRARY_HAS_MUSICVIDEOS: + { + if (m_libraryHasMusicVideos < 0) + { + CVideoDatabase db; + if (db.Open()) + { + m_libraryHasMusicVideos = db.HasContent(VideoDbContentType::MUSICVIDEOS) ? 1 : 0; + db.Close(); + } + } + value = m_libraryHasMusicVideos > 0; + return true; + } + case LIBRARY_HAS_SINGLES: + { + if (m_libraryHasSingles < 0) + { + CMusicDatabase db; + if (db.Open()) + { + m_libraryHasSingles = (db.GetSinglesCount() > 0) ? 1 : 0; + db.Close(); + } + } + value = m_libraryHasSingles > 0; + return true; + } + case LIBRARY_HAS_COMPILATIONS: + { + if (m_libraryHasCompilations < 0) + { + CMusicDatabase db; + if (db.Open()) + { + m_libraryHasCompilations = (db.GetCompilationAlbumsCount() > 0) ? 1 : 0; + db.Close(); + } + } + value = m_libraryHasCompilations > 0; + return true; + } + case LIBRARY_HAS_BOXSETS: + { + if (m_libraryHasBoxsets < 0) + { + CMusicDatabase db; + if (db.Open()) + { + m_libraryHasBoxsets = (db.GetBoxsetsCount() > 0) ? 1 : 0; + db.Close(); + } + } + value = m_libraryHasBoxsets > 0; + return true; + } + case LIBRARY_HAS_VIDEO: + { + return (GetBool(value, gitem, contextWindow, CGUIInfo(LIBRARY_HAS_MOVIES)) || + GetBool(value, gitem, contextWindow, CGUIInfo(LIBRARY_HAS_TVSHOWS)) || + GetBool(value, gitem, contextWindow, CGUIInfo(LIBRARY_HAS_MUSICVIDEOS))); + } + case LIBRARY_HAS_ROLE: + { + std::string strRole = info.GetData3(); + // Find value for role if already stored + int artistcount = -1; + for (const auto &role : m_libraryRoleCounts) + { + if (StringUtils::EqualsNoCase(strRole, role.first)) + { + artistcount = role.second; + break; + } + } + // Otherwise get from DB and store + if (artistcount < 0) + { + CMusicDatabase db; + if (db.Open()) + { + artistcount = db.GetArtistCountForRole(strRole); + db.Close(); + m_libraryRoleCounts.emplace_back(std::make_pair(strRole, artistcount)); + } + } + value = artistcount > 0; + return true; + } + case LIBRARY_HAS_NODE: + { + const CURL url(info.GetData3()); + const std::shared_ptr<CProfileManager> profileManager = + CServiceBroker::GetSettingsComponent()->GetProfileManager(); + CFileItemList items; + + std::string libDir = profileManager->GetLibraryFolder(); + XFILE::CDirectory::GetDirectory(libDir, items, "", XFILE::DIR_FLAG_NO_FILE_DIRS); + if (items.Size() == 0) + libDir = "special://xbmc/system/library/"; + + std::string nodePath = URIUtils::AddFileToFolder(libDir, url.GetHostName() + "/"); + nodePath = URIUtils::AddFileToFolder(nodePath, url.GetFileName()); + value = CFileUtils::Exists(nodePath); + return true; + } + case LIBRARY_IS_SCANNING: + { + value = (CMusicLibraryQueue::GetInstance().IsScanningLibrary() || + CVideoLibraryQueue::GetInstance().IsScanningLibrary()); + return true; + } + case LIBRARY_IS_SCANNING_VIDEO: + { + value = CVideoLibraryQueue::GetInstance().IsScanningLibrary(); + return true; + } + case LIBRARY_IS_SCANNING_MUSIC: + { + value = CMusicLibraryQueue::GetInstance().IsScanningLibrary(); + return true; + } + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/LibraryGUIInfo.h b/xbmc/guilib/guiinfo/LibraryGUIInfo.h new file mode 100644 index 0000000..a9d47fc --- /dev/null +++ b/xbmc/guilib/guiinfo/LibraryGUIInfo.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +#include <string> +#include <utility> +#include <vector> + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CLibraryGUIInfo : public CGUIInfoProvider +{ +public: + CLibraryGUIInfo(); + ~CLibraryGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + + bool GetLibraryBool(int condition) const; + void SetLibraryBool(int condition, bool value); + void ResetLibraryBools(); + +private: + mutable int m_libraryHasMusic; + mutable int m_libraryHasMovies; + mutable int m_libraryHasTVShows; + mutable int m_libraryHasMusicVideos; + mutable int m_libraryHasMovieSets; + mutable int m_libraryHasSingles; + mutable int m_libraryHasCompilations; + mutable int m_libraryHasBoxsets; + + //Count of artists in music library contributing to song by role e.g. composers, conductors etc. + //For checking visibility of custom nodes for a role. + mutable std::vector<std::pair<std::string, int>> m_libraryRoleCounts; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/MusicGUIInfo.cpp b/xbmc/guilib/guiinfo/MusicGUIInfo.cpp new file mode 100644 index 0000000..f58a9ae --- /dev/null +++ b/xbmc/guilib/guiinfo/MusicGUIInfo.cpp @@ -0,0 +1,713 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/MusicGUIInfo.h" + +#include "FileItem.h" +#include "PartyModeManager.h" +#include "PlayListPlayer.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "Util.h" +#include "application/Application.h" +#include "application/ApplicationComponents.h" +#include "application/ApplicationPlayer.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoHelper.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "music/MusicInfoLoader.h" +#include "music/MusicThumbLoader.h" +#include "music/tags/MusicInfoTag.h" +#include "playlists/PlayList.h" +#include "settings/AdvancedSettings.h" +#include "settings/SettingsComponent.h" +#include "utils/URIUtils.h" +#include "utils/log.h" + +using namespace KODI::GUILIB; +using namespace KODI::GUILIB::GUIINFO; +using namespace MUSIC_INFO; + +bool CMusicGUIInfo::InitCurrentItem(CFileItem *item) +{ + const auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent<CApplicationPlayer>(); + if (item && (item->IsAudio() || (item->IsInternetStream() && appPlayer->IsPlayingAudio()))) + { + CLog::Log(LOGDEBUG, "CMusicGUIInfo::InitCurrentItem({})", item->GetPath()); + + item->LoadMusicTag(); + + CMusicInfoTag* tag = item->GetMusicInfoTag(); // creates item if not yet set, so no nullptr checks needed + tag->SetLoaded(true); + + // find a thumb for this file. + if (item->IsInternetStream() && !item->IsMusicDb()) + { + if (!g_application.m_strPlayListFile.empty()) + { + CLog::Log(LOGDEBUG, "Streaming media detected... using {} to find a thumb", + g_application.m_strPlayListFile); + CFileItem streamingItem(g_application.m_strPlayListFile,false); + + CMusicThumbLoader loader; + loader.FillThumb(streamingItem); + if (streamingItem.HasArt("thumb")) + item->SetArt("thumb", streamingItem.GetArt("thumb")); + } + } + else + { + CMusicThumbLoader loader; + loader.LoadItem(item); + } + + CMusicInfoLoader::LoadAdditionalTagInfo(item); + return true; + } + return false; +} + +bool CMusicGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + // For musicplayer "offset" and "position" info labels check playlist + if (info.GetData1() && ((info.m_info >= MUSICPLAYER_OFFSET_POSITION_FIRST && + info.m_info <= MUSICPLAYER_OFFSET_POSITION_LAST) || + (info.m_info >= PLAYER_OFFSET_POSITION_FIRST && info.m_info <= PLAYER_OFFSET_POSITION_LAST))) + return GetPlaylistInfo(value, info); + + const CMusicInfoTag* tag = item->GetMusicInfoTag(); + if (tag) + { + switch (info.m_info) + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // PLAYER_* / MUSICPLAYER_* / LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case PLAYER_PATH: + case PLAYER_FILENAME: + case PLAYER_FILEPATH: + value = tag->GetURL(); + if (value.empty()) + value = item->GetPath(); + value = GUIINFO::GetFileInfoLabelValueFromPath(info.m_info, value); + return true; + case PLAYER_TITLE: + value = tag->GetTitle(); + return !value.empty(); + case MUSICPLAYER_TITLE: + value = tag->GetTitle(); + return !value.empty(); + case LISTITEM_TITLE: + value = tag->GetTitle(); + return true; + case MUSICPLAYER_PLAYCOUNT: + case LISTITEM_PLAYCOUNT: + if (tag->GetPlayCount() > 0) + { + value = std::to_string(tag->GetPlayCount()); + return true; + } + break; + case MUSICPLAYER_LASTPLAYED: + case LISTITEM_LASTPLAYED: + { + const CDateTime& dateTime = tag->GetLastPlayed(); + if (dateTime.IsValid()) + { + value = dateTime.GetAsLocalizedDate(); + return true; + } + break; + } + case MUSICPLAYER_TRACK_NUMBER: + case LISTITEM_TRACKNUMBER: + if (tag->Loaded() && tag->GetTrackNumber() > 0) + { + value = StringUtils::Format("{:02}", tag->GetTrackNumber()); + return true; + } + break; + case MUSICPLAYER_DISC_NUMBER: + case LISTITEM_DISC_NUMBER: + if (tag->GetDiscNumber() > 0) + { + value = std::to_string(tag->GetDiscNumber()); + return true; + } + break; + case MUSICPLAYER_TOTALDISCS: + case LISTITEM_TOTALDISCS: + value = std::to_string(tag->GetTotalDiscs()); + return true; + case MUSICPLAYER_DISC_TITLE: + case LISTITEM_DISC_TITLE: + value = tag->GetDiscSubtitle(); + return true; + case MUSICPLAYER_ARTIST: + case LISTITEM_ARTIST: + value = tag->GetArtistString(); + return true; + case MUSICPLAYER_ALBUM_ARTIST: + case LISTITEM_ALBUM_ARTIST: + value = tag->GetAlbumArtistString(); + return true; + case MUSICPLAYER_CONTRIBUTORS: + case LISTITEM_CONTRIBUTORS: + if (tag->HasContributors()) + { + value = tag->GetContributorsText(); + return true; + } + break; + case MUSICPLAYER_CONTRIBUTOR_AND_ROLE: + case LISTITEM_CONTRIBUTOR_AND_ROLE: + if (tag->HasContributors()) + { + value = tag->GetContributorsAndRolesText(); + return true; + } + break; + case MUSICPLAYER_ALBUM: + case LISTITEM_ALBUM: + value = tag->GetAlbum(); + return true; + case MUSICPLAYER_YEAR: + case LISTITEM_YEAR: + value = tag->GetYearString(); + return true; + case MUSICPLAYER_GENRE: + case LISTITEM_GENRE: + value = StringUtils::Join(tag->GetGenre(), CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator); + return true; + case MUSICPLAYER_LYRICS: + value = tag->GetLyrics(); + return true; + case MUSICPLAYER_RATING: + case LISTITEM_RATING: + { + float rating = tag->GetRating(); + if (rating > 0.f) + { + value = StringUtils::FormatNumber(rating); + return true; + } + break; + } + case MUSICPLAYER_RATING_AND_VOTES: + case LISTITEM_RATING_AND_VOTES: + { + float rating = tag->GetRating(); + if (rating > 0.f) + { + int votes = tag->GetVotes(); + if (votes <= 0) + value = StringUtils::FormatNumber(rating); + else + value = + StringUtils::Format(g_localizeStrings.Get(20350), StringUtils::FormatNumber(rating), + StringUtils::FormatNumber(votes)); + return true; + } + break; + } + case MUSICPLAYER_USER_RATING: + case LISTITEM_USER_RATING: + if (tag->GetUserrating() > 0) + { + value = std::to_string(tag->GetUserrating()); + return true; + } + break; + case MUSICPLAYER_COMMENT: + case LISTITEM_COMMENT: + value = tag->GetComment(); + return true; + case MUSICPLAYER_MOOD: + case LISTITEM_MOOD: + value = tag->GetMood(); + return true; + case LISTITEM_DBTYPE: + value = tag->GetType(); + return true; + case MUSICPLAYER_DBID: + case LISTITEM_DBID: + { + int dbId = tag->GetDatabaseId(); + if (dbId > -1) + { + value = std::to_string(dbId); + return true; + } + break; + } + case PLAYER_DURATION: + { + const auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent<CApplicationPlayer>(); + if (!appPlayer->IsPlayingAudio()) + break; + } + [[fallthrough]]; + case MUSICPLAYER_DURATION: + case LISTITEM_DURATION: + { + int iDuration = tag->GetDuration(); + if (iDuration > 0) + { + value = StringUtils::SecondsToTimeString(iDuration, + static_cast<TIME_FORMAT>(info.m_info == LISTITEM_DURATION + ? info.GetData4() + : info.GetData1())); + return true; + } + break; + } + case MUSICPLAYER_BPM: + case LISTITEM_BPM: + if (tag->GetBPM() > 0) + { + value = std::to_string(tag->GetBPM()); + return true; + } + break; + case MUSICPLAYER_STATIONNAME: + // This property can be used for example by addons to enforce/override the station name. + value = item->GetProperty("StationName").asString(); + if (value.empty()) + value = tag->GetStationName(); + return true; + + ///////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_PROPERTY: + if (StringUtils::StartsWithNoCase(info.GetData3(), "Role.")) + { + // "Role.xxxx" properties are held in music tag + std::string property = info.GetData3(); + property.erase(0, 5); //Remove Role. + value = tag->GetArtistStringForRole(property); + return true; + } + break; + case LISTITEM_VOTES: + value = StringUtils::FormatNumber(tag->GetVotes()); + return true; + case MUSICPLAYER_ORIGINALDATE: + case LISTITEM_ORIGINALDATE: + { + value = tag->GetOriginalDate(); + if (!CServiceBroker::GetSettingsComponent() + ->GetAdvancedSettings() + ->m_bMusicLibraryUseISODates) + value = StringUtils::ISODateToLocalizedDate(value); + return true; + } + case MUSICPLAYER_RELEASEDATE: + case LISTITEM_RELEASEDATE: + { + value = tag->GetReleaseDate(); + if (!CServiceBroker::GetSettingsComponent() + ->GetAdvancedSettings() + ->m_bMusicLibraryUseISODates) + value = StringUtils::ISODateToLocalizedDate(value); + return true; + } + break; + case LISTITEM_BITRATE: + { + int BitRate = tag->GetBitRate(); + if (BitRate > 0) + { + value = std::to_string(BitRate); + return true; + } + break; + } + case LISTITEM_SAMPLERATE: + { + int sampleRate = tag->GetSampleRate(); + if (sampleRate > 0) + { + value = StringUtils::Format("{:.5}", static_cast<double>(sampleRate) / 1000.0); + return true; + } + break; + } + case LISTITEM_MUSICCHANNELS: + { + int channels = tag->GetNoOfChannels(); + if (channels > 0) + { + value = std::to_string(channels); + return true; + } + break; + } + case LISTITEM_ALBUMSTATUS: + value = tag->GetAlbumReleaseStatus(); + return true; + case LISTITEM_FILENAME: + case LISTITEM_FILE_EXTENSION: + if (item->IsMusicDb()) + value = URIUtils::GetFileName(tag->GetURL()); + else if (item->HasVideoInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + value = URIUtils::GetFileName(item->GetPath()); + + if (info.m_info == LISTITEM_FILE_EXTENSION) + { + std::string strExtension = URIUtils::GetExtension(value); + value = StringUtils::TrimLeft(strExtension, "."); + } + return true; + case LISTITEM_FOLDERNAME: + case LISTITEM_PATH: + if (item->IsMusicDb()) + value = URIUtils::GetDirectory(tag->GetURL()); + else if (item->HasVideoInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + URIUtils::GetParentPath(item->GetPath(), value); + + value = CURL(value).GetWithoutUserDetails(); + + if (info.m_info == LISTITEM_FOLDERNAME) + { + URIUtils::RemoveSlashAtEnd(value); + value = URIUtils::GetFileName(value); + } + return true; + case LISTITEM_FILENAME_AND_PATH: + if (item->IsMusicDb()) + value = tag->GetURL(); + else if (item->HasVideoInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + value = item->GetPath(); + + value = CURL(value).GetWithoutUserDetails(); + return true; + case LISTITEM_DATE_ADDED: + if (tag->GetDateAdded().IsValid()) + { + value = tag->GetDateAdded().GetAsLocalizedDate(); + return true; + } + break; + } + } + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case MUSICPLAYER_PROPERTY: + if (StringUtils::StartsWithNoCase(info.GetData3(), "Role.") && item->HasMusicInfoTag()) + { + // "Role.xxxx" properties are held in music tag + std::string property = info.GetData3(); + property.erase(0, 5); //Remove Role. + value = item->GetMusicInfoTag()->GetArtistStringForRole(property); + return true; + } + value = item->GetProperty(info.GetData3()).asString(); + return true; + case MUSICPLAYER_PLAYLISTLEN: + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = GUIINFO::GetPlaylistLabel(PLAYLIST_LENGTH); + return true; + } + break; + case MUSICPLAYER_PLAYLISTPOS: + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = GUIINFO::GetPlaylistLabel(PLAYLIST_POSITION); + return true; + } + break; + case MUSICPLAYER_COVER: + { + const auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent<CApplicationPlayer>(); + if (appPlayer->IsPlayingAudio()) + { + if (fallback) + *fallback = "DefaultAlbumCover.png"; + value = item->HasArt("thumb") ? item->GetArt("thumb") : "DefaultAlbumCover.png"; + return true; + } + break; + } + case MUSICPLAYER_BITRATE: + { + int iBitrate = m_audioInfo.bitrate; + if (iBitrate > 0) + { + value = std::to_string(std::lrint(static_cast<double>(iBitrate) / 1000.0)); + return true; + } + break; + } + case MUSICPLAYER_CHANNELS: + { + int iChannels = m_audioInfo.channels; + if (iChannels > 0) + { + value = std::to_string(iChannels); + return true; + } + break; + } + case MUSICPLAYER_BITSPERSAMPLE: + { + int iBPS = m_audioInfo.bitspersample; + if (iBPS > 0) + { + value = std::to_string(iBPS); + return true; + } + break; + } + case MUSICPLAYER_SAMPLERATE: + { + int iSamplerate = m_audioInfo.samplerate; + if (iSamplerate > 0) + { + value = StringUtils::Format("{:.5}", static_cast<double>(iSamplerate) / 1000.0); + return true; + } + break; + } + case MUSICPLAYER_CODEC: + value = m_audioInfo.codecName; + return true; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + if (GetPartyModeLabel(value, info)) + return true; + + return false; +} + +bool CMusicGUIInfo::GetPartyModeLabel(std::string& value, const CGUIInfo &info) const +{ + int iSongs = -1; + + switch (info.m_info) + { + case MUSICPM_SONGSPLAYED: + iSongs = g_partyModeManager.GetSongsPlayed(); + break; + case MUSICPM_MATCHINGSONGS: + iSongs = g_partyModeManager.GetMatchingSongs(); + break; + case MUSICPM_MATCHINGSONGSPICKED: + iSongs = g_partyModeManager.GetMatchingSongsPicked(); + break; + case MUSICPM_MATCHINGSONGSLEFT: + iSongs = g_partyModeManager.GetMatchingSongsLeft(); + break; + case MUSICPM_RELAXEDSONGSPICKED: + iSongs = g_partyModeManager.GetRelaxedSongs(); + break; + case MUSICPM_RANDOMSONGSPICKED: + iSongs = g_partyModeManager.GetRandomSongs(); + break; + } + + if (iSongs >= 0) + { + value = std::to_string(iSongs); + return true; + } + + return false; +} + +bool CMusicGUIInfo::GetPlaylistInfo(std::string& value, const CGUIInfo &info) const +{ + const PLAYLIST::CPlayList& playlist = + CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::TYPE_MUSIC); + if (playlist.size() < 1) + return false; + + int index = info.GetData2(); + if (info.GetData1() == 1) + { // relative index (requires current playlist is TYPE_MUSIC) + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() != PLAYLIST::TYPE_MUSIC) + return false; + + index = CServiceBroker::GetPlaylistPlayer().GetNextSong(index); + } + + if (index < 0 || index >= playlist.size()) + return false; + + const CFileItemPtr playlistItem = playlist[index]; + if (playlistItem->HasMusicInfoTag() && !playlistItem->GetMusicInfoTag()->Loaded()) + { + playlistItem->LoadMusicTag(); + playlistItem->GetMusicInfoTag()->SetLoaded(); + } + // try to set a thumbnail + if (!playlistItem->HasArt("thumb")) + { + CMusicThumbLoader loader; + loader.LoadItem(playlistItem.get()); + // still no thumb? then just the set the default cover + if (!playlistItem->HasArt("thumb")) + playlistItem->SetArt("thumb", "DefaultAlbumCover.png"); + } + if (info.m_info == MUSICPLAYER_PLAYLISTPOS) + { + value = std::to_string(index + 1); + return true; + } + else if (info.m_info == MUSICPLAYER_COVER) + { + value = playlistItem->GetArt("thumb"); + return true; + } + + return GetLabel(value, playlistItem.get(), 0, CGUIInfo(info.m_info), nullptr); +} + +bool CMusicGUIInfo::GetFallbackLabel(std::string& value, + const CFileItem* item, + int contextWindow, + const CGUIInfo& info, + std::string* fallback) +{ + // No fallback for musicplayer "offset" and "position" info labels + if (info.GetData1() && ((info.m_info >= MUSICPLAYER_OFFSET_POSITION_FIRST && + info.m_info <= MUSICPLAYER_OFFSET_POSITION_LAST) || + (info.m_info >= PLAYER_OFFSET_POSITION_FIRST && info.m_info <= PLAYER_OFFSET_POSITION_LAST))) + return false; + + const CMusicInfoTag* tag = item->GetMusicInfoTag(); + if (tag) + { + switch (info.m_info) + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPLAYER_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case MUSICPLAYER_TITLE: + value = item->GetLabel(); + if (value.empty()) + value = CUtil::GetTitleFromPath(item->GetPath()); + return true; + default: + break; + } + } + return false; +} + +bool CMusicGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + return false; +} + +bool CMusicGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + const CFileItem* item = static_cast<const CFileItem*>(gitem); + const CMusicInfoTag* tag = item->GetMusicInfoTag(); + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case MUSICPLAYER_CONTENT: + value = StringUtils::EqualsNoCase(info.GetData3(), "files"); + return value; // if no match for this provider, other providers shall be asked. + case MUSICPLAYER_HASPREVIOUS: + // requires current playlist be TYPE_MUSIC + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = (CServiceBroker::GetPlaylistPlayer().GetCurrentSong() > 0); // not first song + return true; + } + break; + case MUSICPLAYER_HASNEXT: + // requires current playlist be TYPE_MUSIC + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = (CServiceBroker::GetPlaylistPlayer().GetCurrentSong() < + (CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::TYPE_MUSIC).size() - + 1)); // not last song + return true; + } + break; + case MUSICPLAYER_PLAYLISTPLAYING: + { + const auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent<CApplicationPlayer>(); + if (appPlayer->IsPlayingAudio() && + CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = true; + return true; + } + break; + } + case MUSICPLAYER_EXISTS: + { + int index = info.GetData2(); + if (info.GetData1() == 1) + { // relative index + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() != PLAYLIST::TYPE_MUSIC) + { + value = false; + return true; + } + index += CServiceBroker::GetPlaylistPlayer().GetCurrentSong(); + } + value = + (index >= 0 && + index < CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::TYPE_MUSIC).size()); + return true; + } + case MUSICPLAYER_ISMULTIDISC: + if (tag) + { + value = (item->GetMusicInfoTag()->GetTotalDiscs() > 1); + return true; + } + break; + /////////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case MUSICPM_ENABLED: + value = g_partyModeManager.IsEnabled(); + return true; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_IS_BOXSET: + if (tag) + { + value = tag->GetBoxset() == true; + return true; + } + break; + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/MusicGUIInfo.h b/xbmc/guilib/guiinfo/MusicGUIInfo.h new file mode 100644 index 0000000..4132ca6 --- /dev/null +++ b/xbmc/guilib/guiinfo/MusicGUIInfo.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CMusicGUIInfo : public CGUIInfoProvider +{ +public: + CMusicGUIInfo() = default; + ~CMusicGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetFallbackLabel(std::string& value, + const CFileItem* item, + int contextWindow, + const CGUIInfo& info, + std::string* fallback) override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + +private: + bool GetPartyModeLabel(std::string& value, const CGUIInfo &info) const; + bool GetPlaylistInfo(std::string& value, const CGUIInfo &info) const; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/PicturesGUIInfo.cpp b/xbmc/guilib/guiinfo/PicturesGUIInfo.cpp new file mode 100644 index 0000000..6115517 --- /dev/null +++ b/xbmc/guilib/guiinfo/PicturesGUIInfo.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/PicturesGUIInfo.h" + +#include "FileItem.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "pictures/GUIWindowSlideShow.h" +#include "pictures/PictureInfoTag.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "utils/log.h" + +#include <map> + +using namespace KODI::GUILIB::GUIINFO; + +static const std::map<int, int> listitem2slideshow_map = +{ + { LISTITEM_PICTURE_RESOLUTION , SLIDESHOW_RESOLUTION }, + { LISTITEM_PICTURE_LONGDATE , SLIDESHOW_EXIF_LONG_DATE }, + { LISTITEM_PICTURE_LONGDATETIME , SLIDESHOW_EXIF_LONG_DATE_TIME }, + { LISTITEM_PICTURE_DATE , SLIDESHOW_EXIF_DATE }, + { LISTITEM_PICTURE_DATETIME , SLIDESHOW_EXIF_DATE_TIME }, + { LISTITEM_PICTURE_COMMENT , SLIDESHOW_COMMENT }, + { LISTITEM_PICTURE_CAPTION , SLIDESHOW_IPTC_CAPTION }, + { LISTITEM_PICTURE_DESC , SLIDESHOW_EXIF_DESCRIPTION }, + { LISTITEM_PICTURE_KEYWORDS , SLIDESHOW_IPTC_KEYWORDS }, + { LISTITEM_PICTURE_CAM_MAKE , SLIDESHOW_EXIF_CAMERA_MAKE }, + { LISTITEM_PICTURE_CAM_MODEL , SLIDESHOW_EXIF_CAMERA_MODEL }, + { LISTITEM_PICTURE_APERTURE , SLIDESHOW_EXIF_APERTURE }, + { LISTITEM_PICTURE_FOCAL_LEN , SLIDESHOW_EXIF_FOCAL_LENGTH }, + { LISTITEM_PICTURE_FOCUS_DIST , SLIDESHOW_EXIF_FOCUS_DIST }, + { LISTITEM_PICTURE_EXP_MODE , SLIDESHOW_EXIF_EXPOSURE_MODE }, + { LISTITEM_PICTURE_EXP_TIME , SLIDESHOW_EXIF_EXPOSURE_TIME }, + { LISTITEM_PICTURE_ISO , SLIDESHOW_EXIF_ISO_EQUIV }, + { LISTITEM_PICTURE_AUTHOR , SLIDESHOW_IPTC_AUTHOR }, + { LISTITEM_PICTURE_BYLINE , SLIDESHOW_IPTC_BYLINE }, + { LISTITEM_PICTURE_BYLINE_TITLE , SLIDESHOW_IPTC_BYLINE_TITLE }, + { LISTITEM_PICTURE_CATEGORY , SLIDESHOW_IPTC_CATEGORY }, + { LISTITEM_PICTURE_CCD_WIDTH , SLIDESHOW_EXIF_CCD_WIDTH }, + { LISTITEM_PICTURE_CITY , SLIDESHOW_IPTC_CITY }, + { LISTITEM_PICTURE_URGENCY , SLIDESHOW_IPTC_URGENCY }, + { LISTITEM_PICTURE_COPYRIGHT_NOTICE , SLIDESHOW_IPTC_COPYRIGHT_NOTICE }, + { LISTITEM_PICTURE_COUNTRY , SLIDESHOW_IPTC_COUNTRY }, + { LISTITEM_PICTURE_COUNTRY_CODE , SLIDESHOW_IPTC_COUNTRY_CODE }, + { LISTITEM_PICTURE_CREDIT , SLIDESHOW_IPTC_CREDIT }, + { LISTITEM_PICTURE_IPTCDATE , SLIDESHOW_IPTC_DATE }, + { LISTITEM_PICTURE_DIGITAL_ZOOM , SLIDESHOW_EXIF_DIGITAL_ZOOM, }, + { LISTITEM_PICTURE_EXPOSURE , SLIDESHOW_EXIF_EXPOSURE }, + { LISTITEM_PICTURE_EXPOSURE_BIAS , SLIDESHOW_EXIF_EXPOSURE_BIAS }, + { LISTITEM_PICTURE_FLASH_USED , SLIDESHOW_EXIF_FLASH_USED }, + { LISTITEM_PICTURE_HEADLINE , SLIDESHOW_IPTC_HEADLINE }, + { LISTITEM_PICTURE_COLOUR , SLIDESHOW_COLOUR }, + { LISTITEM_PICTURE_LIGHT_SOURCE , SLIDESHOW_EXIF_LIGHT_SOURCE }, + { LISTITEM_PICTURE_METERING_MODE , SLIDESHOW_EXIF_METERING_MODE }, + { LISTITEM_PICTURE_OBJECT_NAME , SLIDESHOW_IPTC_OBJECT_NAME }, + { LISTITEM_PICTURE_ORIENTATION , SLIDESHOW_EXIF_ORIENTATION }, + { LISTITEM_PICTURE_PROCESS , SLIDESHOW_PROCESS }, + { LISTITEM_PICTURE_REF_SERVICE , SLIDESHOW_IPTC_REF_SERVICE }, + { LISTITEM_PICTURE_SOURCE , SLIDESHOW_IPTC_SOURCE }, + { LISTITEM_PICTURE_SPEC_INSTR , SLIDESHOW_IPTC_SPEC_INSTR }, + { LISTITEM_PICTURE_STATE , SLIDESHOW_IPTC_STATE }, + { LISTITEM_PICTURE_SUP_CATEGORIES , SLIDESHOW_IPTC_SUP_CATEGORIES }, + { LISTITEM_PICTURE_TX_REFERENCE , SLIDESHOW_IPTC_TX_REFERENCE }, + { LISTITEM_PICTURE_WHITE_BALANCE , SLIDESHOW_EXIF_WHITE_BALANCE }, + { LISTITEM_PICTURE_IMAGETYPE , SLIDESHOW_IPTC_IMAGETYPE }, + { LISTITEM_PICTURE_SUBLOCATION , SLIDESHOW_IPTC_SUBLOCATION }, + { LISTITEM_PICTURE_TIMECREATED , SLIDESHOW_IPTC_TIMECREATED }, + { LISTITEM_PICTURE_GPS_LAT , SLIDESHOW_EXIF_GPS_LATITUDE }, + { LISTITEM_PICTURE_GPS_LON , SLIDESHOW_EXIF_GPS_LONGITUDE }, + { LISTITEM_PICTURE_GPS_ALT , SLIDESHOW_EXIF_GPS_ALTITUDE } +}; + +CPicturesGUIInfo::CPicturesGUIInfo() = default; + +CPicturesGUIInfo::~CPicturesGUIInfo() = default; + +void CPicturesGUIInfo::SetCurrentSlide(CFileItem *item) +{ + if (m_currentSlide && item && m_currentSlide->GetPath() == item->GetPath()) + return; + + if (item) + { + if (item->HasPictureInfoTag()) // Note: item may also be a video + { + CPictureInfoTag* tag = item->GetPictureInfoTag(); + if (!tag->Loaded()) // If picture metadata has not been loaded yet, load it now + tag->Load(item->GetPath()); + } + m_currentSlide.reset(new CFileItem(*item)); + } + else if (m_currentSlide) + { + m_currentSlide.reset(); + } +} + +const CFileItem* CPicturesGUIInfo::GetCurrentSlide() const +{ + return m_currentSlide.get(); +} + +bool CPicturesGUIInfo::InitCurrentItem(CFileItem *item) +{ + return false; +} + +bool CPicturesGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + if (item->IsPicture() && info.m_info >= LISTITEM_PICTURE_START && info.m_info <= LISTITEM_PICTURE_END) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + const auto& it = listitem2slideshow_map.find(info.m_info); + if (it != listitem2slideshow_map.end()) + { + if (item->HasPictureInfoTag()) + { + value = item->GetPictureInfoTag()->GetInfo(it->second); + return true; + } + } + else + { + CLog::Log(LOGERROR, + "CPicturesGUIInfo::GetLabel - cannot map LISTITEM ({}) to SLIDESHOW label!", + info.m_info); + return false; + } + } + else if (m_currentSlide && info.m_info >= SLIDESHOW_LABELS_START && info.m_info <= SLIDESHOW_LABELS_END) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // SLIDESHOW_* + /////////////////////////////////////////////////////////////////////////////////////////////// + switch (info.m_info) + { + case SLIDESHOW_FILE_NAME: + { + value = URIUtils::GetFileName(m_currentSlide->GetPath()); + return true; + } + case SLIDESHOW_FILE_PATH: + { + const std::string path = URIUtils::GetDirectory(m_currentSlide->GetPath()); + value = CURL(path).GetWithoutUserDetails(); + return true; + } + case SLIDESHOW_FILE_SIZE: + { + if (!m_currentSlide->m_bIsFolder || m_currentSlide->m_dwSize) + { + value = StringUtils::SizeToString(m_currentSlide->m_dwSize); + return true; + } + break; + } + case SLIDESHOW_FILE_DATE: + { + if (m_currentSlide->m_dateTime.IsValid()) + { + value = m_currentSlide->m_dateTime.GetAsLocalizedDate(); + return true; + } + break; + } + case SLIDESHOW_INDEX: + { + CGUIWindowSlideShow *slideshow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW); + if (slideshow && slideshow->NumSlides()) + { + value = StringUtils::Format("{}/{}", slideshow->CurrentSlide(), slideshow->NumSlides()); + return true; + } + break; + } + default: + { + value = m_currentSlide->GetPictureInfoTag()->GetInfo(info.m_info); + return true; + } + } + } + + if (item->IsPicture()) + { + ///////////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////////// + switch (info.m_info) + { + case LISTITEM_PICTURE_PATH: + { + if (!(item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR())) + { + value = item->GetPath(); + return true; + } + break; + } + } + } + + return false; +} + +bool CPicturesGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + return false; +} + +bool CPicturesGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // SLIDESHOW_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SLIDESHOW_ISPAUSED: + { + CGUIWindowSlideShow *slideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW); + value = (slideShow && slideShow->IsPaused()); + return true; + } + case SLIDESHOW_ISRANDOM: + { + CGUIWindowSlideShow *slideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW); + value = (slideShow && slideShow->IsShuffled()); + return true; + } + case SLIDESHOW_ISACTIVE: + { + CGUIWindowSlideShow *slideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW); + value = (slideShow && slideShow->InSlideShow()); + return true; + } + case SLIDESHOW_ISVIDEO: + { + CGUIWindowSlideShow *slideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW); + value = (slideShow && slideShow->GetCurrentSlide() && slideShow->GetCurrentSlide()->IsVideo()); + return true; + } + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/PicturesGUIInfo.h b/xbmc/guilib/guiinfo/PicturesGUIInfo.h new file mode 100644 index 0000000..68cdb4c --- /dev/null +++ b/xbmc/guilib/guiinfo/PicturesGUIInfo.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +#include <memory> + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CPicturesGUIInfo : public CGUIInfoProvider +{ +public: + CPicturesGUIInfo(); + ~CPicturesGUIInfo() override; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + + void SetCurrentSlide(CFileItem *item); + const CFileItem* GetCurrentSlide() const; + +private: + std::unique_ptr<CFileItem> m_currentSlide; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp b/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp new file mode 100644 index 0000000..dfb9455 --- /dev/null +++ b/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp @@ -0,0 +1,726 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/PlayerGUIInfo.h" + +#include "FileItem.h" +#include "PlayListPlayer.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "Util.h" +#include "application/Application.h" +#include "application/ApplicationComponents.h" +#include "application/ApplicationPlayer.h" +#include "application/ApplicationVolumeHandling.h" +#include "cores/AudioEngine/Utils/AEUtil.h" +#include "cores/DataCacheCore.h" +#include "cores/EdlEdit.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIDialog.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoHelper.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "utils/Variant.h" +#include "utils/log.h" + +#include <charconv> +#include <cmath> + +using namespace KODI::GUILIB::GUIINFO; + +CPlayerGUIInfo::CPlayerGUIInfo() + : m_appPlayer(CServiceBroker::GetAppComponents().GetComponent<CApplicationPlayer>()), + m_appVolume(CServiceBroker::GetAppComponents().GetComponent<CApplicationVolumeHandling>()) +{ +} + +CPlayerGUIInfo::~CPlayerGUIInfo() = default; + +int CPlayerGUIInfo::GetTotalPlayTime() const +{ + return std::lrint(g_application.GetTotalTime()); +} + +int CPlayerGUIInfo::GetPlayTime() const +{ + return std::lrint(g_application.GetTime()); +} + +int CPlayerGUIInfo::GetPlayTimeRemaining() const +{ + int iReverse = GetTotalPlayTime() - std::lrint(g_application.GetTime()); + return iReverse > 0 ? iReverse : 0; +} + +float CPlayerGUIInfo::GetSeekPercent() const +{ + int iTotal = GetTotalPlayTime(); + if (iTotal == 0) + return 0.0f; + + float fPercentPlayTime = static_cast<float>(GetPlayTime() * 1000) / iTotal * 0.1f; + float fPercentPerSecond = 100.0f / static_cast<float>(iTotal); + float fPercent = + fPercentPlayTime + fPercentPerSecond * m_appPlayer->GetSeekHandler().GetSeekSize(); + fPercent = std::max(0.0f, std::min(fPercent, 100.0f)); + return fPercent; +} + +std::string CPlayerGUIInfo::GetCurrentPlayTime(TIME_FORMAT format) const +{ + if (format == TIME_FORMAT_GUESS && GetTotalPlayTime() >= 3600) + format = TIME_FORMAT_HH_MM_SS; + + return StringUtils::SecondsToTimeString(std::lrint(GetPlayTime()), format); +} + +std::string CPlayerGUIInfo::GetCurrentPlayTimeRemaining(TIME_FORMAT format) const +{ + if (format == TIME_FORMAT_GUESS && GetTotalPlayTime() >= 3600) + format = TIME_FORMAT_HH_MM_SS; + + int iTimeRemaining = GetPlayTimeRemaining(); + if (iTimeRemaining) + return StringUtils::SecondsToTimeString(iTimeRemaining, format); + + return std::string(); +} + +std::string CPlayerGUIInfo::GetDuration(TIME_FORMAT format) const +{ + int iTotal = GetTotalPlayTime(); + if (iTotal > 0) + { + if (format == TIME_FORMAT_GUESS && iTotal >= 3600) + format = TIME_FORMAT_HH_MM_SS; + return StringUtils::SecondsToTimeString(iTotal, format); + } + return std::string(); +} + +std::string CPlayerGUIInfo::GetCurrentSeekTime(TIME_FORMAT format) const +{ + if (format == TIME_FORMAT_GUESS && GetTotalPlayTime() >= 3600) + format = TIME_FORMAT_HH_MM_SS; + + return StringUtils::SecondsToTimeString( + g_application.GetTime() + m_appPlayer->GetSeekHandler().GetSeekSize(), format); +} + +std::string CPlayerGUIInfo::GetSeekTime(TIME_FORMAT format) const +{ + if (!m_appPlayer->GetSeekHandler().HasTimeCode()) + return std::string(); + + int iSeekTimeCode = m_appPlayer->GetSeekHandler().GetTimeCodeSeconds(); + if (format == TIME_FORMAT_GUESS && iSeekTimeCode >= 3600) + format = TIME_FORMAT_HH_MM_SS; + + return StringUtils::SecondsToTimeString(iSeekTimeCode, format); +} + +void CPlayerGUIInfo::SetShowInfo(bool showinfo) +{ + if (showinfo != m_playerShowInfo) + { + m_playerShowInfo = showinfo; + m_events.Publish(PlayerShowInfoChangedEvent(m_playerShowInfo)); + } +} + +bool CPlayerGUIInfo::ToggleShowInfo() +{ + SetShowInfo(!m_playerShowInfo); + return m_playerShowInfo; +} + +bool CPlayerGUIInfo::InitCurrentItem(CFileItem *item) +{ + if (item && m_appPlayer->IsPlaying()) + { + CLog::Log(LOGDEBUG, "CPlayerGUIInfo::InitCurrentItem({})", CURL::GetRedacted(item->GetPath())); + m_currentItem.reset(new CFileItem(*item)); + } + else + { + m_currentItem.reset(); + } + return false; +} + +bool CPlayerGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // PLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case PLAYER_SEEKOFFSET: + { + int lastSeekOffset = CServiceBroker::GetDataCacheCore().GetSeekOffSet(); + std::string seekOffset = StringUtils::SecondsToTimeString( + std::abs(lastSeekOffset / 1000), static_cast<TIME_FORMAT>(info.GetData1())); + if (lastSeekOffset < 0) + value = "-" + seekOffset; + else if (lastSeekOffset > 0) + value = "+" + seekOffset; + return true; + } + case PLAYER_PROGRESS: + value = std::to_string(std::lrintf(g_application.GetPercentage())); + return true; + case PLAYER_PROGRESS_CACHE: + value = std::to_string(std::lrintf(g_application.GetCachePercentage())); + return true; + case PLAYER_VOLUME: + value = + StringUtils::Format("{:2.1f} dB", CAEUtil::PercentToGain(m_appVolume->GetVolumeRatio())); + return true; + case PLAYER_SUBTITLE_DELAY: + value = StringUtils::Format("{:2.3f} s", m_appPlayer->GetVideoSettings().m_SubtitleDelay); + return true; + case PLAYER_AUDIO_DELAY: + value = StringUtils::Format("{:2.3f} s", m_appPlayer->GetVideoSettings().m_AudioDelay); + return true; + case PLAYER_CHAPTER: + value = StringUtils::Format("{:02}", m_appPlayer->GetChapter()); + return true; + case PLAYER_CHAPTERCOUNT: + value = StringUtils::Format("{:02}", m_appPlayer->GetChapterCount()); + return true; + case PLAYER_CHAPTERNAME: + m_appPlayer->GetChapterName(value); + return true; + case PLAYER_PATH: + case PLAYER_FILENAME: + case PLAYER_FILEPATH: + value = GUIINFO::GetFileInfoLabelValueFromPath(info.m_info, item->GetPath()); + return true; + case PLAYER_TITLE: + // use label or drop down to title from path + value = item->GetLabel(); + if (value.empty()) + value = CUtil::GetTitleFromPath(item->GetPath()); + return true; + case PLAYER_PLAYSPEED: + { + float speed = m_appPlayer->GetPlaySpeed(); + if (speed == 1.0f) + speed = m_appPlayer->GetPlayTempo(); + value = StringUtils::Format("{:.2f}", speed); + return true; + } + case PLAYER_TIME: + value = GetCurrentPlayTime(static_cast<TIME_FORMAT>(info.GetData1())); + return true; + case PLAYER_START_TIME: + { + const CDateTime time(m_appPlayer->GetStartTime()); + value = time.GetAsLocalizedTime(static_cast<TIME_FORMAT>(info.GetData1())); + return true; + } + case PLAYER_DURATION: + value = GetDuration(static_cast<TIME_FORMAT>(info.GetData1())); + return true; + case PLAYER_TIME_REMAINING: + value = GetCurrentPlayTimeRemaining(static_cast<TIME_FORMAT>(info.GetData1())); + return true; + case PLAYER_FINISH_TIME: + { + CDateTime time(CDateTime::GetCurrentDateTime()); + int playTimeRemaining = GetPlayTimeRemaining(); + float speed = m_appPlayer->GetPlaySpeed(); + float tempo = m_appPlayer->GetPlayTempo(); + if (speed == 1.0f) + playTimeRemaining /= tempo; + time += CDateTimeSpan(0, 0, 0, playTimeRemaining); + value = time.GetAsLocalizedTime(static_cast<TIME_FORMAT>(info.GetData1())); + return true; + } + case PLAYER_TIME_SPEED: + { + float speed = m_appPlayer->GetPlaySpeed(); + if (speed != 1.0f) + value = StringUtils::Format("{} ({}x)", + GetCurrentPlayTime(static_cast<TIME_FORMAT>(info.GetData1())), + static_cast<int>(speed)); + else + value = GetCurrentPlayTime(TIME_FORMAT_GUESS); + return true; + } + case PLAYER_SEEKTIME: + value = GetCurrentSeekTime(static_cast<TIME_FORMAT>(info.GetData1())); + return true; + case PLAYER_SEEKSTEPSIZE: + { + int seekSize = m_appPlayer->GetSeekHandler().GetSeekSize(); + std::string strSeekSize = StringUtils::SecondsToTimeString(abs(seekSize), static_cast<TIME_FORMAT>(info.GetData1())); + if (seekSize < 0) + value = "-" + strSeekSize; + if (seekSize > 0) + value = "+" + strSeekSize; + return true; + } + case PLAYER_SEEKNUMERIC: + value = GetSeekTime(static_cast<TIME_FORMAT>(info.GetData1())); + return !value.empty(); + case PLAYER_CACHELEVEL: + { + int iLevel = m_appPlayer->GetCacheLevel(); + if (iLevel >= 0) + { + value = std::to_string(iLevel); + return true; + } + break; + } + case PLAYER_ITEM_ART: + value = item->GetArt(info.GetData3()); + return true; + case PLAYER_ICON: + value = item->GetArt("thumb"); + if (value.empty()) + value = item->GetArt("icon"); + if (fallback) + *fallback = item->GetArt("icon"); + return true; + case PLAYER_EDITLIST: + case PLAYER_CUTS: + case PLAYER_SCENE_MARKERS: + case PLAYER_CUTLIST: + case PLAYER_CHAPTERS: + value = GetContentRanges(info.m_info); + return true; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // PLAYER_PROCESS_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case PLAYER_PROCESS_VIDEODECODER: + value = CServiceBroker::GetDataCacheCore().GetVideoDecoderName(); + return true; + case PLAYER_PROCESS_DEINTMETHOD: + value = CServiceBroker::GetDataCacheCore().GetVideoDeintMethod(); + return true; + case PLAYER_PROCESS_PIXELFORMAT: + value = CServiceBroker::GetDataCacheCore().GetVideoPixelFormat(); + return true; + case PLAYER_PROCESS_VIDEOFPS: + value = StringUtils::Format("{:.3f}", CServiceBroker::GetDataCacheCore().GetVideoFps()); + return true; + case PLAYER_PROCESS_VIDEODAR: + value = StringUtils::Format("{:.2f}", CServiceBroker::GetDataCacheCore().GetVideoDAR()); + return true; + case PLAYER_PROCESS_VIDEOWIDTH: + value = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetVideoWidth()); + return true; + case PLAYER_PROCESS_VIDEOHEIGHT: + value = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetVideoHeight()); + return true; + case PLAYER_PROCESS_VIDEOSCANTYPE: + value = CServiceBroker::GetDataCacheCore().IsVideoInterlaced() ? "i" : "p"; + return true; + case PLAYER_PROCESS_AUDIODECODER: + value = CServiceBroker::GetDataCacheCore().GetAudioDecoderName(); + return true; + case PLAYER_PROCESS_AUDIOCHANNELS: + value = CServiceBroker::GetDataCacheCore().GetAudioChannels(); + return true; + case PLAYER_PROCESS_AUDIOSAMPLERATE: + value = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetAudioSampleRate()); + return true; + case PLAYER_PROCESS_AUDIOBITSPERSAMPLE: + value = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetAudioBitsPerSample()); + return true; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // PLAYLIST_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case PLAYLIST_LENGTH: + case PLAYLIST_POSITION: + case PLAYLIST_RANDOM: + case PLAYLIST_REPEAT: + value = GUIINFO::GetPlaylistLabel(info.m_info, info.GetData1()); + return true; + } + + return false; +} + +bool CPlayerGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // PLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case PLAYER_VOLUME: + value = static_cast<int>(m_appVolume->GetVolumePercent()); + return true; + case PLAYER_PROGRESS: + value = std::lrintf(g_application.GetPercentage()); + return true; + case PLAYER_PROGRESS_CACHE: + value = std::lrintf(g_application.GetCachePercentage()); + return true; + case PLAYER_SEEKBAR: + value = std::lrintf(GetSeekPercent()); + return true; + case PLAYER_CACHELEVEL: + value = m_appPlayer->GetCacheLevel(); + return true; + case PLAYER_CHAPTER: + value = m_appPlayer->GetChapter(); + return true; + case PLAYER_CHAPTERCOUNT: + value = m_appPlayer->GetChapterCount(); + return true; + case PLAYER_SUBTITLE_DELAY: + value = m_appPlayer->GetSubtitleDelay(); + return true; + case PLAYER_AUDIO_DELAY: + value = m_appPlayer->GetAudioDelay(); + return true; + } + + return false; +} + +bool CPlayerGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + const CFileItem *item = nullptr; + if (gitem->IsFileItem()) + item = static_cast<const CFileItem*>(gitem); + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // PLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case PLAYER_SHOWINFO: + value = m_playerShowInfo; + return true; + case PLAYER_SHOWTIME: + value = m_playerShowTime; + return true; + case PLAYER_MUTED: + value = (m_appVolume->IsMuted() || + m_appVolume->GetVolumeRatio() <= CApplicationVolumeHandling::VOLUME_MINIMUM); + return true; + case PLAYER_HAS_MEDIA: + value = m_appPlayer->IsPlaying(); + return true; + case PLAYER_HAS_AUDIO: + value = m_appPlayer->IsPlayingAudio(); + return true; + case PLAYER_HAS_VIDEO: + value = m_appPlayer->IsPlayingVideo(); + return true; + case PLAYER_HAS_GAME: + value = m_appPlayer->IsPlayingGame(); + return true; + case PLAYER_PLAYING: + value = m_appPlayer->GetPlaySpeed() == 1.0f; + return true; + case PLAYER_PAUSED: + value = m_appPlayer->IsPausedPlayback(); + return true; + case PLAYER_REWINDING: + value = m_appPlayer->GetPlaySpeed() < 0.0f; + return true; + case PLAYER_FORWARDING: + value = m_appPlayer->GetPlaySpeed() > 1.5f; + return true; + case PLAYER_REWINDING_2x: + value = m_appPlayer->GetPlaySpeed() == -2; + return true; + case PLAYER_REWINDING_4x: + value = m_appPlayer->GetPlaySpeed() == -4; + return true; + case PLAYER_REWINDING_8x: + value = m_appPlayer->GetPlaySpeed() == -8; + return true; + case PLAYER_REWINDING_16x: + value = m_appPlayer->GetPlaySpeed() == -16; + return true; + case PLAYER_REWINDING_32x: + value = m_appPlayer->GetPlaySpeed() == -32; + return true; + case PLAYER_FORWARDING_2x: + value = m_appPlayer->GetPlaySpeed() == 2; + return true; + case PLAYER_FORWARDING_4x: + value = m_appPlayer->GetPlaySpeed() == 4; + return true; + case PLAYER_FORWARDING_8x: + value = m_appPlayer->GetPlaySpeed() == 8; + return true; + case PLAYER_FORWARDING_16x: + value = m_appPlayer->GetPlaySpeed() == 16; + return true; + case PLAYER_FORWARDING_32x: + value = m_appPlayer->GetPlaySpeed() == 32; + return true; + case PLAYER_CAN_PAUSE: + value = m_appPlayer->CanPause(); + return true; + case PLAYER_CAN_SEEK: + value = m_appPlayer->CanSeek(); + return true; + case PLAYER_SUPPORTS_TEMPO: + value = m_appPlayer->SupportsTempo(); + return true; + case PLAYER_IS_TEMPO: + value = (m_appPlayer->GetPlayTempo() != 1.0f && m_appPlayer->GetPlaySpeed() == 1.0f); + return true; + case PLAYER_CACHING: + value = m_appPlayer->IsCaching(); + return true; + case PLAYER_SEEKBAR: + { + CGUIDialog *seekBar = CServiceBroker::GetGUI()->GetWindowManager().GetDialog(WINDOW_DIALOG_SEEK_BAR); + value = seekBar ? seekBar->IsDialogRunning() : false; + return true; + } + case PLAYER_SEEKING: + value = m_appPlayer->GetSeekHandler().InProgress(); + return true; + case PLAYER_HASPERFORMEDSEEK: + { + int requestedLastSecondInterval{0}; + std::from_chars_result result = + std::from_chars(info.GetData3().data(), info.GetData3().data() + info.GetData3().size(), + requestedLastSecondInterval); + if (result.ec == std::errc::invalid_argument) + { + value = false; + return false; + } + + value = CServiceBroker::GetDataCacheCore().HasPerformedSeek(requestedLastSecondInterval); + return true; + } + case PLAYER_PASSTHROUGH: + value = m_appPlayer->IsPassthrough(); + return true; + case PLAYER_ISINTERNETSTREAM: + if (item) + { + value = URIUtils::IsInternetStream(item->GetDynPath()); + return true; + } + break; + case PLAYER_HAS_PROGRAMS: + value = (m_appPlayer->GetProgramsCount() > 1) ? true : false; + return true; + case PLAYER_HAS_RESOLUTIONS: + value = CServiceBroker::GetWinSystem()->GetGfxContext().IsFullScreenRoot() && + CResolutionUtils::HasWhitelist(); + return true; + case PLAYER_HASDURATION: + value = g_application.GetTotalTime() > 0; + return true; + case PLAYER_FRAMEADVANCE: + value = CServiceBroker::GetDataCacheCore().IsFrameAdvance(); + return true; + case PLAYER_HAS_SCENE_MARKERS: + value = !CServiceBroker::GetDataCacheCore().GetSceneMarkers().empty(); + return true; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // PLAYLIST_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case PLAYLIST_ISRANDOM: + { + PLAYLIST::CPlayListPlayer& player = CServiceBroker::GetPlaylistPlayer(); + PLAYLIST::Id playlistid = info.GetData1(); + if (info.GetData2() > 0 && playlistid != PLAYLIST::TYPE_NONE) + value = player.IsShuffled(playlistid); + else + value = player.IsShuffled(player.GetCurrentPlaylist()); + return true; + } + case PLAYLIST_ISREPEAT: + { + PLAYLIST::CPlayListPlayer& player = CServiceBroker::GetPlaylistPlayer(); + PLAYLIST::Id playlistid = info.GetData1(); + if (info.GetData2() > 0 && playlistid != PLAYLIST::TYPE_NONE) + value = (player.GetRepeat(playlistid) == PLAYLIST::RepeatState::ALL); + else + value = player.GetRepeat(player.GetCurrentPlaylist()) == PLAYLIST::RepeatState::ALL; + return true; + } + case PLAYLIST_ISREPEATONE: + { + PLAYLIST::CPlayListPlayer& player = CServiceBroker::GetPlaylistPlayer(); + PLAYLIST::Id playlistid = info.GetData1(); + if (info.GetData2() > 0 && playlistid != PLAYLIST::TYPE_NONE) + value = (player.GetRepeat(playlistid) == PLAYLIST::RepeatState::ONE); + else + value = player.GetRepeat(player.GetCurrentPlaylist()) == PLAYLIST::RepeatState::ONE; + return true; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // PLAYER_PROCESS_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case PLAYER_PROCESS_VIDEOHWDECODER: + value = CServiceBroker::GetDataCacheCore().IsVideoHwDecoder(); + return true; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_ISPLAYING: + { + if (item) + { + if (item->HasProperty("playlistposition")) + { + value = static_cast<int>(item->GetProperty("playlisttype").asInteger()) == CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() && + static_cast<int>(item->GetProperty("playlistposition").asInteger()) == CServiceBroker::GetPlaylistPlayer().GetCurrentSong(); + return true; + } + else if (m_currentItem && !m_currentItem->GetPath().empty()) + { + if (!g_application.m_strPlayListFile.empty()) + { + //playlist file that is currently playing or the playlistitem that is currently playing. + value = item->IsPath(g_application.m_strPlayListFile) || m_currentItem->IsSamePath(item); + } + else + { + value = m_currentItem->IsSamePath(item); + } + return true; + } + } + break; + } + } + + return false; +} + +std::string CPlayerGUIInfo::GetContentRanges(int iInfo) const +{ + std::string values; + + CDataCacheCore& data = CServiceBroker::GetDataCacheCore(); + std::vector<std::pair<float, float>> ranges; + + std::time_t start; + int64_t current; + int64_t min; + int64_t max; + data.GetPlayTimes(start, current, min, max); + + std::time_t duration = max - start * 1000; + if (duration > 0) + { + switch (iInfo) + { + case PLAYER_EDITLIST: + case PLAYER_CUTLIST: + ranges = GetEditList(data, duration); + break; + case PLAYER_CUTS: + ranges = GetCuts(data, duration); + break; + case PLAYER_SCENE_MARKERS: + ranges = GetSceneMarkers(data, duration); + break; + case PLAYER_CHAPTERS: + ranges = GetChapters(data, duration); + break; + default: + CLog::Log(LOGERROR, "CPlayerGUIInfo::GetContentRanges({}) - unhandled guiinfo", iInfo); + break; + } + + // create csv string from ranges + for (const auto& range : ranges) + values += StringUtils::Format("{:.5f},{:.5f},", range.first, range.second); + + if (!values.empty()) + values.pop_back(); // remove trailing comma + } + + return values; +} + +std::vector<std::pair<float, float>> CPlayerGUIInfo::GetEditList(const CDataCacheCore& data, + std::time_t duration) const +{ + std::vector<std::pair<float, float>> ranges; + + const std::vector<EDL::Edit>& edits = data.GetEditList(); + for (const auto& edit : edits) + { + float editStart = edit.start * 100.0f / duration; + float editEnd = edit.end * 100.0f / duration; + ranges.emplace_back(std::make_pair(editStart, editEnd)); + } + return ranges; +} + +std::vector<std::pair<float, float>> CPlayerGUIInfo::GetCuts(const CDataCacheCore& data, + std::time_t duration) const +{ + std::vector<std::pair<float, float>> ranges; + + const std::vector<int64_t>& cuts = data.GetCuts(); + float lastMarker = 0.0f; + for (const auto& cut : cuts) + { + float marker = cut * 100.0f / duration; + if (marker != 0) + ranges.emplace_back(std::make_pair(lastMarker, marker)); + + lastMarker = marker; + } + return ranges; +} + +std::vector<std::pair<float, float>> CPlayerGUIInfo::GetSceneMarkers(const CDataCacheCore& data, + std::time_t duration) const +{ + std::vector<std::pair<float, float>> ranges; + + const std::vector<int64_t>& scenes = data.GetSceneMarkers(); + float lastMarker = 0.0f; + for (const auto& scene : scenes) + { + float marker = scene * 100.0f / duration; + if (marker != 0) + ranges.emplace_back(std::make_pair(lastMarker, marker)); + + lastMarker = marker; + } + return ranges; +} + +std::vector<std::pair<float, float>> CPlayerGUIInfo::GetChapters(const CDataCacheCore& data, + std::time_t duration) const +{ + std::vector<std::pair<float, float>> ranges; + + const std::vector<std::pair<std::string, int64_t>>& chapters = data.GetChapters(); + float lastMarker = 0.0f; + for (const auto& chapter : chapters) + { + float marker = chapter.second * 1000 * 100.0f / duration; + if (marker != 0) + ranges.emplace_back(std::make_pair(lastMarker, marker)); + + lastMarker = marker; + } + return ranges; +} diff --git a/xbmc/guilib/guiinfo/PlayerGUIInfo.h b/xbmc/guilib/guiinfo/PlayerGUIInfo.h new file mode 100644 index 0000000..e0cb3c8 --- /dev/null +++ b/xbmc/guilib/guiinfo/PlayerGUIInfo.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" +#include "utils/EventStream.h" +#include "utils/TimeFormat.h" + +#include <atomic> +#include <ctime> +#include <memory> +#include <utility> +#include <vector> + +class CApplicationPlayer; +class CApplicationVolumeHandling; +class CDataCacheCore; + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +struct PlayerShowInfoChangedEvent +{ + explicit PlayerShowInfoChangedEvent(bool showInfo) : m_showInfo(showInfo) {} + virtual ~PlayerShowInfoChangedEvent() = default; + + bool m_showInfo{false}; +}; + +class CPlayerGUIInfo : public CGUIInfoProvider +{ +public: + CPlayerGUIInfo(); + ~CPlayerGUIInfo() override; + + CEventStream<PlayerShowInfoChangedEvent>& Events() { return m_events; } + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + + void SetShowTime(bool showtime) { m_playerShowTime = showtime; } + void SetShowInfo(bool showinfo); + bool GetShowInfo() const { return m_playerShowInfo; } + bool ToggleShowInfo(); + +private: + int GetTotalPlayTime() const; + int GetPlayTime() const; + int GetPlayTimeRemaining() const; + float GetSeekPercent() const; + + std::string GetCurrentPlayTime(TIME_FORMAT format) const; + std::string GetCurrentPlayTimeRemaining(TIME_FORMAT format) const; + std::string GetDuration(TIME_FORMAT format) const; + std::string GetCurrentSeekTime(TIME_FORMAT format) const; + std::string GetSeekTime(TIME_FORMAT format) const; + + std::string GetContentRanges(int iInfo) const; + std::vector<std::pair<float, float>> GetEditList(const CDataCacheCore& data, + std::time_t duration) const; + std::vector<std::pair<float, float>> GetCuts(const CDataCacheCore& data, + std::time_t duration) const; + std::vector<std::pair<float, float>> GetSceneMarkers(const CDataCacheCore& data, + std::time_t duration) const; + std::vector<std::pair<float, float>> GetChapters(const CDataCacheCore& data, + std::time_t duration) const; + + std::unique_ptr<CFileItem> m_currentItem; + std::atomic_bool m_playerShowTime{false}; + std::atomic_bool m_playerShowInfo{false}; + const std::shared_ptr<CApplicationPlayer> m_appPlayer; + const std::shared_ptr<CApplicationVolumeHandling> m_appVolume; + CEventSource<PlayerShowInfoChangedEvent> m_events; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/SkinGUIInfo.cpp b/xbmc/guilib/guiinfo/SkinGUIInfo.cpp new file mode 100644 index 0000000..1d51b96 --- /dev/null +++ b/xbmc/guilib/guiinfo/SkinGUIInfo.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/SkinGUIInfo.h" + +#include "ServiceBroker.h" +#include "addons/Skin.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "settings/SkinSettings.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" + +using namespace KODI::GUILIB::GUIINFO; + +bool CSkinGUIInfo::InitCurrentItem(CFileItem *item) +{ + return false; +} + +bool CSkinGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // SKIN_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SKIN_BOOL: + { + bool bInfo = CSkinSettings::GetInstance().GetBool(info.GetData1()); + if (bInfo) + { + value = g_localizeStrings.Get(20122); // True + return true; + } + break; + } + case SKIN_STRING: + { + value = CSkinSettings::GetInstance().GetString(info.GetData1()); + return true; + } + case SKIN_THEME: + { + value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOOKANDFEEL_SKINTHEME); + return true; + } + case SKIN_COLOUR_THEME: + { + value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOOKANDFEEL_SKINCOLORS); + return true; + } + case SKIN_ASPECT_RATIO: + { + if (g_SkinInfo) + { + value = g_SkinInfo->GetCurrentAspect(); + return true; + } + break; + } + case SKIN_FONT: + { + value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOOKANDFEEL_FONT); + return true; + } + case SKIN_TIMER_ELAPSEDSECS: + { + value = std::to_string(g_SkinInfo->GetTimerElapsedSeconds(info.GetData3())); + return true; + } + } + + return false; +} + +bool CSkinGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + case SKIN_INTEGER: + { + value = CSkinSettings::GetInstance().GetInt(info.GetData1()); + return true; + } + case SKIN_TIMER_ELAPSEDSECS: + { + value = g_SkinInfo->GetTimerElapsedSeconds(info.GetData3()); + return true; + } + } + return false; +} + +bool CSkinGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // SKIN_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SKIN_BOOL: + { + value = CSkinSettings::GetInstance().GetBool(info.GetData1()); + return true; + } + case SKIN_STRING_IS_EQUAL: + { + value = StringUtils::EqualsNoCase(CSkinSettings::GetInstance().GetString(info.GetData1()), info.GetData3()); + return true; + } + case SKIN_STRING: + { + value = !CSkinSettings::GetInstance().GetString(info.GetData1()).empty(); + return true; + } + case SKIN_HAS_THEME: + { + std::string theme = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOOKANDFEEL_SKINTHEME); + URIUtils::RemoveExtension(theme); + value = StringUtils::EqualsNoCase(theme, info.GetData3()); + return true; + } + case SKIN_TIMER_IS_RUNNING: + { + value = g_SkinInfo->TimerIsRunning(info.GetData3()); + return true; + } + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/SkinGUIInfo.h b/xbmc/guilib/guiinfo/SkinGUIInfo.h new file mode 100644 index 0000000..7f6c1c4 --- /dev/null +++ b/xbmc/guilib/guiinfo/SkinGUIInfo.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CSkinGUIInfo : public CGUIInfoProvider +{ +public: + CSkinGUIInfo() = default; + ~CSkinGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/SystemGUIInfo.cpp b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp new file mode 100644 index 0000000..bc01047 --- /dev/null +++ b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp @@ -0,0 +1,727 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/SystemGUIInfo.h" + +#include "FileItem.h" +#include "GUIPassword.h" +#include "LangInfo.h" +#include "ServiceBroker.h" +#include "addons/AddonManager.h" +#include "addons/addoninfo/AddonType.h" +#include "application/AppParams.h" +#include "application/ApplicationComponents.h" +#include "application/ApplicationPowerHandling.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "network/Network.h" +#if defined(TARGET_DARWIN_OSX) +#include "platform/darwin/osx/smc.h" +#endif +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoHelper.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "powermanagement/PowerManager.h" +#include "profiles/ProfileManager.h" +#include "settings/AdvancedSettings.h" +#include "settings/MediaSettings.h" +#include "settings/SettingUtils.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "storage/MediaManager.h" +#include "storage/discs/IDiscDriveHandler.h" +#include "utils/AlarmClock.h" +#include "utils/CPUInfo.h" +#include "utils/HDRCapabilities.h" +#include "utils/MemUtils.h" +#include "utils/StringUtils.h" +#include "utils/SystemInfo.h" +#include "utils/TimeUtils.h" +#include "windowing/WinSystem.h" +#include "windows/GUIMediaWindow.h" + +using namespace KODI::GUILIB; +using namespace KODI::GUILIB::GUIINFO; + +CSystemGUIInfo::CSystemGUIInfo() +: m_lastSysHeatInfoTime(-SYSTEM_HEAT_UPDATE_INTERVAL) +{ +} + +std::string CSystemGUIInfo::GetSystemHeatInfo(int info) const +{ + if (CTimeUtils::GetFrameTime() - m_lastSysHeatInfoTime >= SYSTEM_HEAT_UPDATE_INTERVAL) + { + m_lastSysHeatInfoTime = CTimeUtils::GetFrameTime(); +#if defined(TARGET_POSIX) + CServiceBroker::GetCPUInfo()->GetTemperature(m_cpuTemp); + m_gpuTemp = GetGPUTemperature(); +#endif + } + + std::string text; + switch(info) + { + case SYSTEM_CPU_TEMPERATURE: + return m_cpuTemp.IsValid() ? g_langInfo.GetTemperatureAsString(m_cpuTemp) : g_localizeStrings.Get(10005); // Not available + case SYSTEM_GPU_TEMPERATURE: + return m_gpuTemp.IsValid() ? g_langInfo.GetTemperatureAsString(m_gpuTemp) : g_localizeStrings.Get(10005); + case SYSTEM_FAN_SPEED: + text = StringUtils::Format("{}%", m_fanSpeed * 2); + break; + case SYSTEM_CPU_USAGE: + if (CServiceBroker::GetCPUInfo()->SupportsCPUUsage()) +#if defined(TARGET_DARWIN) || defined(TARGET_WINDOWS) + text = StringUtils::Format("{}%", CServiceBroker::GetCPUInfo()->GetUsedPercentage()); +#else + text = CServiceBroker::GetCPUInfo()->GetCoresUsageString(); +#endif + else + text = g_localizeStrings.Get(10005); // Not available + break; + } + return text; +} + +CTemperature CSystemGUIInfo::GetGPUTemperature() const +{ + int value = 0; + char scale = 0; + +#if defined(TARGET_DARWIN_OSX) + value = SMCGetTemperature(SMC_KEY_GPU_TEMP); + return CTemperature::CreateFromCelsius(value); +#elif defined(TARGET_WINDOWS_STORE) + return CTemperature::CreateFromCelsius(0); +#else + std::string cmd = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_gpuTempCmd; + int ret = 0; + FILE* p = NULL; + + if (cmd.empty() || !(p = popen(cmd.c_str(), "r"))) + return CTemperature(); + + ret = fscanf(p, "%d %c", &value, &scale); + pclose(p); + + if (ret != 2) + return CTemperature(); +#endif + + if (scale == 'C' || scale == 'c') + return CTemperature::CreateFromCelsius(value); + if (scale == 'F' || scale == 'f') + return CTemperature::CreateFromFahrenheit(value); + return CTemperature(); +} + +void CSystemGUIInfo::UpdateFPS() +{ + m_frameCounter++; + unsigned int curTime = CTimeUtils::GetFrameTime(); + + float fTimeSpan = static_cast<float>(curTime - m_lastFPSTime); + if (fTimeSpan >= 1000.0f) + { + fTimeSpan /= 1000.0f; + m_fps = m_frameCounter / fTimeSpan; + m_lastFPSTime = curTime; + m_frameCounter = 0; + } +} + +bool CSystemGUIInfo::InitCurrentItem(CFileItem *item) +{ + return false; +} + +bool CSystemGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // SYSTEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SYSTEM_TIME: + value = CDateTime::GetCurrentDateTime().GetAsLocalizedTime(static_cast<TIME_FORMAT>(info.GetData1())); + return true; + case SYSTEM_DATE: + if (info.GetData3().empty()) + value = CDateTime::GetCurrentDateTime().GetAsLocalizedDate(true); + else + value = CDateTime::GetCurrentDateTime().GetAsLocalizedDate(info.GetData3()); + return true; + case SYSTEM_FREE_SPACE: + case SYSTEM_USED_SPACE: + case SYSTEM_TOTAL_SPACE: + case SYSTEM_FREE_SPACE_PERCENT: + case SYSTEM_USED_SPACE_PERCENT: + value = g_sysinfo.GetHddSpaceInfo(info.m_info); + return true; + case SYSTEM_CPU_TEMPERATURE: + case SYSTEM_GPU_TEMPERATURE: + case SYSTEM_FAN_SPEED: + case SYSTEM_CPU_USAGE: + value = GetSystemHeatInfo(info.m_info); + return true; + case SYSTEM_VIDEO_ENCODER_INFO: + case NETWORK_MAC_ADDRESS: + case SYSTEM_OS_VERSION_INFO: + case SYSTEM_CPUFREQUENCY: + case SYSTEM_INTERNET_STATE: + case SYSTEM_UPTIME: + case SYSTEM_TOTALUPTIME: + case SYSTEM_BATTERY_LEVEL: + value = g_sysinfo.GetInfo(info.m_info); + return true; + case SYSTEM_PRIVACY_POLICY: + value = g_sysinfo.GetPrivacyPolicy(); + return true; + case SYSTEM_SCREEN_RESOLUTION: + { + const auto winSystem = CServiceBroker::GetWinSystem(); + if (winSystem) + { + const RESOLUTION_INFO& resInfo = winSystem->GetGfxContext().GetResInfo(); + + if (winSystem->IsFullScreen()) + value = StringUtils::Format("{}x{} @ {:.2f} Hz - {}", resInfo.iScreenWidth, + resInfo.iScreenHeight, resInfo.fRefreshRate, + g_localizeStrings.Get(244)); + else + value = StringUtils::Format("{}x{} - {}", resInfo.iScreenWidth, resInfo.iScreenHeight, + g_localizeStrings.Get(242)); + } + else + { + value = ""; + } + return true; + } + case SYSTEM_BUILD_VERSION_SHORT: + value = CSysInfo::GetVersionShort(); + return true; + case SYSTEM_BUILD_VERSION: + value = CSysInfo::GetVersion(); + return true; + case SYSTEM_BUILD_DATE: + value = CSysInfo::GetBuildDate(); + return true; + case SYSTEM_BUILD_VERSION_CODE: + value = CSysInfo::GetVersionCode(); + return true; + case SYSTEM_BUILD_VERSION_GIT: + value = CSysInfo::GetVersionGit(); + return true; + case SYSTEM_FREE_MEMORY: + case SYSTEM_FREE_MEMORY_PERCENT: + case SYSTEM_USED_MEMORY: + case SYSTEM_USED_MEMORY_PERCENT: + case SYSTEM_TOTAL_MEMORY: + { + KODI::MEMORY::MemoryStatus stat; + KODI::MEMORY::GetMemoryStatus(&stat); + int iMemPercentFree = 100 - static_cast<int>(100.0f * (stat.totalPhys - stat.availPhys) / stat.totalPhys + 0.5f); + int iMemPercentUsed = 100 - iMemPercentFree; + + if (info.m_info == SYSTEM_FREE_MEMORY) + value = StringUtils::Format("{}MB", static_cast<unsigned int>(stat.availPhys / MB)); + else if (info.m_info == SYSTEM_FREE_MEMORY_PERCENT) + value = StringUtils::Format("{}%", iMemPercentFree); + else if (info.m_info == SYSTEM_USED_MEMORY) + value = StringUtils::Format( + "{}MB", static_cast<unsigned int>((stat.totalPhys - stat.availPhys) / MB)); + else if (info.m_info == SYSTEM_USED_MEMORY_PERCENT) + value = StringUtils::Format("{}%", iMemPercentUsed); + else if (info.m_info == SYSTEM_TOTAL_MEMORY) + value = StringUtils::Format("{}MB", static_cast<unsigned int>(stat.totalPhys / MB)); + return true; + } + case SYSTEM_SCREEN_MODE: + value = CServiceBroker::GetWinSystem()->GetGfxContext().GetResInfo().strMode; + return true; + case SYSTEM_SCREEN_WIDTH: + value = StringUtils::Format( + "{}", CServiceBroker::GetWinSystem()->GetGfxContext().GetResInfo().iScreenWidth); + return true; + case SYSTEM_SCREEN_HEIGHT: + value = StringUtils::Format( + "{}", CServiceBroker::GetWinSystem()->GetGfxContext().GetResInfo().iScreenHeight); + return true; + case SYSTEM_FPS: + value = StringUtils::Format("{:02.2f}", m_fps); + return true; +#ifdef HAS_DVD_DRIVE + case SYSTEM_DVD_LABEL: + value = CServiceBroker::GetMediaManager().GetDiskLabel(); + return true; +#endif + case SYSTEM_ALARM_POS: + if (g_alarmClock.GetRemaining("shutdowntimer") == 0.0) + value.clear(); + else + { + double fTime = g_alarmClock.GetRemaining("shutdowntimer"); + if (fTime > 60.0) + value = StringUtils::Format(g_localizeStrings.Get(13213), + g_alarmClock.GetRemaining("shutdowntimer") / 60.0); + else + value = StringUtils::Format(g_localizeStrings.Get(13214), + g_alarmClock.GetRemaining("shutdowntimer")); + } + return true; + case SYSTEM_PROFILENAME: + value = CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetCurrentProfile().getName(); + return true; + case SYSTEM_PROFILECOUNT: + value = StringUtils::Format("{0}", CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetNumberOfProfiles()); + return true; + case SYSTEM_PROFILEAUTOLOGIN: + { + const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager(); + int iProfileId = profileManager->GetAutoLoginProfileId(); + if ((iProfileId < 0) || !profileManager->GetProfileName(iProfileId, value)) + value = g_localizeStrings.Get(37014); // Last used profile + return true; + } + case SYSTEM_PROFILETHUMB: + { + const std::string& thumb = CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetCurrentProfile().getThumb(); + value = thumb.empty() ? "DefaultUser.png" : thumb; + return true; + } + case SYSTEM_LANGUAGE: + value = g_langInfo.GetEnglishLanguageName(); + return true; + case SYSTEM_TEMPERATURE_UNITS: + value = g_langInfo.GetTemperatureUnitString(); + return true; + case SYSTEM_FRIENDLY_NAME: + value = CSysInfo::GetDeviceName(); + return true; + case SYSTEM_STEREOSCOPIC_MODE: + { + int iStereoMode = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_VIDEOSCREEN_STEREOSCOPICMODE); + value = std::to_string(iStereoMode); + return true; + } + case SYSTEM_GET_CORE_USAGE: + value = StringUtils::Format( + "{:4.2f}", + CServiceBroker::GetCPUInfo()->GetCoreInfo(std::stoi(info.GetData3())).m_usagePercent); + return true; + case SYSTEM_RENDER_VENDOR: + value = CServiceBroker::GetRenderSystem()->GetRenderVendor(); + return true; + case SYSTEM_RENDER_RENDERER: + value = CServiceBroker::GetRenderSystem()->GetRenderRenderer(); + return true; + case SYSTEM_RENDER_VERSION: + value = CServiceBroker::GetRenderSystem()->GetRenderVersionString(); + return true; + case SYSTEM_ADDON_UPDATE_COUNT: + value = CServiceBroker::GetAddonMgr().GetLastAvailableUpdatesCountAsString(); + return true; +#if defined(TARGET_LINUX) + case SYSTEM_PLATFORM_WINDOWING: + value = CServiceBroker::GetWinSystem()->GetName(); + StringUtils::ToCapitalize(value); + return true; +#endif + case SYSTEM_SUPPORTED_HDR_TYPES: + { + if (CServiceBroker::GetWinSystem()->IsHDRDisplay()) + { + // Assumes HDR10 minimum requirement for HDR + std::string types = "HDR10"; + + const CHDRCapabilities caps = CServiceBroker::GetWinSystem()->GetDisplayHDRCapabilities(); + + if (caps.SupportsHLG()) + types += ", HLG"; + if (caps.SupportsHDR10Plus()) + types += ", HDR10+"; + if (caps.SupportsDolbyVision()) + types += ", Dolby Vision"; + + value = types; + } + + return true; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // NETWORK_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case NETWORK_IP_ADDRESS: + { + CNetworkInterface* iface = CServiceBroker::GetNetwork().GetFirstConnectedInterface(); + if (iface) + { + value = iface->GetCurrentIPAddress(); + return true; + } + break; + } + case NETWORK_SUBNET_MASK: + { + CNetworkInterface* iface = CServiceBroker::GetNetwork().GetFirstConnectedInterface(); + if (iface) + { + value = iface->GetCurrentNetmask(); + return true; + } + break; + } + case NETWORK_GATEWAY_ADDRESS: + { + CNetworkInterface* iface = CServiceBroker::GetNetwork().GetFirstConnectedInterface(); + if (iface) + { + value = iface->GetCurrentDefaultGateway(); + return true; + } + break; + } + case NETWORK_DNS1_ADDRESS: + { + const std::vector<std::string> nss = CServiceBroker::GetNetwork().GetNameServers(); + if (nss.size() >= 1) + { + value = nss[0]; + return true; + } + break; + } + case NETWORK_DNS2_ADDRESS: + { + const std::vector<std::string> nss = CServiceBroker::GetNetwork().GetNameServers(); + if (nss.size() >= 2) + { + value = nss[1]; + return true; + } + break; + } + case NETWORK_DHCP_ADDRESS: + { + // wtf? + std::string dhcpserver; + value = dhcpserver; + return true; + } + case NETWORK_LINK_STATE: + { + std::string linkStatus = g_localizeStrings.Get(151); + linkStatus += " "; + CNetworkInterface* iface = CServiceBroker::GetNetwork().GetFirstConnectedInterface(); + if (iface && iface->IsConnected()) + linkStatus += g_localizeStrings.Get(15207); + else + linkStatus += g_localizeStrings.Get(15208); + value = linkStatus; + return true; + } + } + + return false; +} + +bool CSystemGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // SYSTEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SYSTEM_FREE_MEMORY: + case SYSTEM_USED_MEMORY: + { + KODI::MEMORY::MemoryStatus stat; + KODI::MEMORY::GetMemoryStatus(&stat); + int memPercentUsed = static_cast<int>(100.0f * (stat.totalPhys - stat.availPhys) / stat.totalPhys + 0.5f); + if (info.m_info == SYSTEM_FREE_MEMORY) + value = 100 - memPercentUsed; + else + value = memPercentUsed; + return true; + } + case SYSTEM_FREE_SPACE: + case SYSTEM_USED_SPACE: + { + g_sysinfo.GetHddSpaceInfo(value, info.m_info, true); + return true; + } + case SYSTEM_CPU_USAGE: + value = CServiceBroker::GetCPUInfo()->GetUsedPercentage(); + return true; + case SYSTEM_BATTERY_LEVEL: + value = CServiceBroker::GetPowerManager().BatteryLevel(); + return true; + } + + return false; +} + +bool CSystemGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // SYSTEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case SYSTEM_ALWAYS_TRUE: + value = true; + return true; + case SYSTEM_ALWAYS_FALSE: + value = false; + return true; + case SYSTEM_ETHERNET_LINK_ACTIVE: + // wtf: not implemented - always returns true?! + value = true; + return true; + case SYSTEM_PLATFORM_LINUX: +#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_PLATFORM_WINDOWS: +#ifdef TARGET_WINDOWS + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_PLATFORM_UWP: +#ifdef TARGET_WINDOWS_STORE + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_PLATFORM_DARWIN: +#ifdef TARGET_DARWIN + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_PLATFORM_DARWIN_OSX: +#ifdef TARGET_DARWIN_OSX + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_PLATFORM_DARWIN_IOS: +#ifdef TARGET_DARWIN_IOS + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_PLATFORM_DARWIN_TVOS: +#ifdef TARGET_DARWIN_TVOS + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_PLATFORM_ANDROID: +#if defined(TARGET_ANDROID) + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_MEDIA_DVD: + value = CServiceBroker::GetMediaManager().IsDiscInDrive(); + return true; + case SYSTEM_MEDIA_AUDIO_CD: + #ifdef HAS_DVD_DRIVE + if (CServiceBroker::GetMediaManager().IsDiscInDrive()) + { + MEDIA_DETECT::CCdInfo* pCdInfo = CServiceBroker::GetMediaManager().GetCdInfo(); + value = pCdInfo && (pCdInfo->IsAudio(1) || pCdInfo->IsCDExtra(1) || pCdInfo->IsMixedMode(1)); + } + else + #endif + { + value = false; + } + return true; +#ifdef HAS_DVD_DRIVE + case SYSTEM_DVDREADY: + value = CServiceBroker::GetMediaManager().GetDriveStatus() != DriveState::NOT_READY; + return true; + case SYSTEM_TRAYOPEN: + value = CServiceBroker::GetMediaManager().GetDriveStatus() == DriveState::OPEN; + return true; +#endif + case SYSTEM_CAN_POWERDOWN: + value = CServiceBroker::GetPowerManager().CanPowerdown(); + return true; + case SYSTEM_CAN_SUSPEND: + value = CServiceBroker::GetPowerManager().CanSuspend(); + return true; + case SYSTEM_CAN_HIBERNATE: + value = CServiceBroker::GetPowerManager().CanHibernate(); + return true; + case SYSTEM_CAN_REBOOT: + value = CServiceBroker::GetPowerManager().CanReboot(); + return true; + case SYSTEM_SCREENSAVER_ACTIVE: + case SYSTEM_IS_SCREENSAVER_INHIBITED: + case SYSTEM_DPMS_ACTIVE: + case SYSTEM_IDLE_SHUTDOWN_INHIBITED: + case SYSTEM_IDLE_TIME: + { + auto& components = CServiceBroker::GetAppComponents(); + const auto appPower = components.GetComponent<CApplicationPowerHandling>(); + switch (info.m_info) + { + case SYSTEM_SCREENSAVER_ACTIVE: + value = appPower->IsInScreenSaver(); + return true; + case SYSTEM_IS_SCREENSAVER_INHIBITED: + value = appPower->IsScreenSaverInhibited(); + return true; + case SYSTEM_DPMS_ACTIVE: + value = appPower->IsDPMSActive(); + return true; + case SYSTEM_IDLE_SHUTDOWN_INHIBITED: + value = appPower->IsIdleShutdownInhibited(); + return true; + case SYSTEM_IDLE_TIME: + value = appPower->GlobalIdleTime() >= static_cast<int>(info.GetData1()); + return true; + default: + return false; + } + } + case SYSTEM_HASLOCKS: + value = CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE; + return true; + case SYSTEM_HAS_PVR: + value = true; + return true; + case SYSTEM_HAS_PVR_ADDON: + value = CServiceBroker::GetAddonMgr().HasAddons(ADDON::AddonType::PVRDLL); + return true; + case SYSTEM_HAS_CMS: +#if defined(HAS_GL) || defined(HAS_DX) + value = true; +#else + value = false; +#endif + return true; + case SYSTEM_ISMASTER: + value = CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && g_passwordManager.bMasterUser; + return true; + case SYSTEM_ISFULLSCREEN: + value = CServiceBroker::GetWinSystem()->IsFullScreen(); + return true; + case SYSTEM_ISSTANDALONE: + value = CServiceBroker::GetAppParams()->IsStandAlone(); + return true; + case SYSTEM_HAS_SHUTDOWN: + value = (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNTIME) > 0); + return true; + case SYSTEM_LOGGEDON: + value = !(CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_LOGIN_SCREEN); + return true; + case SYSTEM_SHOW_EXIT_BUTTON: + value = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_showExitButton; + return true; + case SYSTEM_HAS_LOGINSCREEN: + value = CServiceBroker::GetSettingsComponent()->GetProfileManager()->UsingLoginScreen(); + return true; + case SYSTEM_INTERNET_STATE: + { + g_sysinfo.GetInfo(info.m_info); + value = g_sysinfo.HasInternet(); + return true; + } + case SYSTEM_HAS_CORE_ID: + value = CServiceBroker::GetCPUInfo()->HasCoreId(info.GetData1()); + return true; + case SYSTEM_DATE: + { + if (info.GetData2() == -1) // info doesn't contain valid startDate + return false; + const CDateTime date = CDateTime::GetCurrentDateTime(); + int currentDate = date.GetMonth() * 100 + date.GetDay(); + int startDate = info.GetData1(); + int stopDate = info.GetData2(); + + if (stopDate < startDate) + value = currentDate >= startDate || currentDate < stopDate; + else + value = currentDate >= startDate && currentDate < stopDate; + return true; + } + case SYSTEM_TIME: + { + int currentTime = CDateTime::GetCurrentDateTime().GetMinuteOfDay(); + int startTime = info.GetData1(); + int stopTime = info.GetData2(); + + if (stopTime < startTime) + value = currentTime >= startTime || currentTime < stopTime; + else + value = currentTime >= startTime && currentTime < stopTime; + return true; + } + case SYSTEM_ALARM_LESS_OR_EQUAL: + { + int time = std::lrint(g_alarmClock.GetRemaining(info.GetData3())); + int timeCompare = info.GetData2(); + if (time > 0) + value = timeCompare >= time; + else + value = false; + return true; + } + case SYSTEM_HAS_ALARM: + value = g_alarmClock.HasAlarm(info.GetData3()); + return true; + case SYSTEM_SUPPORTS_CPU_USAGE: + value = CServiceBroker::GetCPUInfo()->SupportsCPUUsage(); + return true; + case SYSTEM_GET_BOOL: + value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(info.GetData3()); + return true; + case SYSTEM_SETTING: + { + if (StringUtils::EqualsNoCase(info.GetData3(), "hidewatched")) + { + CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); + if (window) + { + value = CMediaSettings::GetInstance().GetWatchedMode(window->CurrentDirectory().GetContent()) == WatchedModeUnwatched; + return true; + } + } + else if (StringUtils::EqualsNoCase(info.GetData3(), "hideunwatchedepisodethumbs")) + { + const std::shared_ptr<CSettingList> setting(std::dynamic_pointer_cast<CSettingList>( + CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting( + CSettings::SETTING_VIDEOLIBRARY_SHOWUNWATCHEDPLOTS))); + value = setting && !CSettingUtils::FindIntInList( + setting, CSettings::VIDEOLIBRARY_THUMB_SHOW_UNWATCHED_EPISODE); + return true; + } + break; + } + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/SystemGUIInfo.h b/xbmc/guilib/guiinfo/SystemGUIInfo.h new file mode 100644 index 0000000..ed2ea03 --- /dev/null +++ b/xbmc/guilib/guiinfo/SystemGUIInfo.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" +#include "utils/Temperature.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CSystemGUIInfo : public CGUIInfoProvider +{ +public: + CSystemGUIInfo(); + ~CSystemGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + + float GetFPS() const { return m_fps; } + void UpdateFPS(); + +private: + std::string GetSystemHeatInfo(int info) const; + CTemperature GetGPUTemperature() const; + + static const int SYSTEM_HEAT_UPDATE_INTERVAL = 60000; + + mutable unsigned int m_lastSysHeatInfoTime; + mutable CTemperature m_gpuTemp; + mutable CTemperature m_cpuTemp; + int m_fanSpeed = 0; + float m_fps = 0.0; + unsigned int m_frameCounter = 0; + unsigned int m_lastFPSTime = 0; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/VideoGUIInfo.cpp b/xbmc/guilib/guiinfo/VideoGUIInfo.cpp new file mode 100644 index 0000000..794434f --- /dev/null +++ b/xbmc/guilib/guiinfo/VideoGUIInfo.cpp @@ -0,0 +1,818 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/VideoGUIInfo.h" + +#include "FileItem.h" +#include "PlayListPlayer.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "Util.h" +#include "application/Application.h" +#include "application/ApplicationComponents.h" +#include "application/ApplicationPlayer.h" +#include "cores/DataCacheCore.h" +#include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/StereoscopicsManager.h" +#include "guilib/WindowIDs.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoHelper.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "playlists/PlayList.h" +#include "settings/AdvancedSettings.h" +#include "settings/SettingUtils.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "settings/lib/Setting.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "utils/log.h" +#include "video/VideoInfoTag.h" +#include "video/VideoThumbLoader.h" + +#include <math.h> + +using namespace KODI::GUILIB; +using namespace KODI::GUILIB::GUIINFO; + +CVideoGUIInfo::CVideoGUIInfo() + : m_appPlayer(CServiceBroker::GetAppComponents().GetComponent<CApplicationPlayer>()) +{ +} + +int CVideoGUIInfo::GetPercentPlayed(const CVideoInfoTag* tag) const +{ + CBookmark bookmark = tag->GetResumePoint(); + if (bookmark.IsPartWay()) + return std::lrintf(static_cast<float>(bookmark.timeInSeconds) / + static_cast<float>(bookmark.totalTimeInSeconds) * 100.0f); + else + return 0; +} + +bool CVideoGUIInfo::InitCurrentItem(CFileItem *item) +{ + if (item && item->IsVideo()) + { + // special case where .strm is used to start an audio stream + if (item->IsInternetStream() && m_appPlayer->IsPlayingAudio()) + return false; + + CLog::Log(LOGDEBUG, "CVideoGUIInfo::InitCurrentItem({})", CURL::GetRedacted(item->GetPath())); + + // Find a thumb for this file. + if (!item->HasArt("thumb")) + { + CVideoThumbLoader loader; + loader.LoadItem(item); + } + + // find a thumb for this stream + if (item->IsInternetStream()) + { + if (!g_application.m_strPlayListFile.empty()) + { + CLog::Log(LOGDEBUG, "Streaming media detected... using {} to find a thumb", + g_application.m_strPlayListFile); + CFileItem thumbItem(g_application.m_strPlayListFile,false); + + CVideoThumbLoader loader; + if (loader.FillThumb(thumbItem)) + item->SetArt("thumb", thumbItem.GetArt("thumb")); + } + } + return true; + } + return false; +} + +bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + // For videoplayer "offset" and "position" info labels check playlist + if (info.GetData1() && ((info.m_info >= VIDEOPLAYER_OFFSET_POSITION_FIRST && + info.m_info <= VIDEOPLAYER_OFFSET_POSITION_LAST) || + (info.m_info >= PLAYER_OFFSET_POSITION_FIRST && info.m_info <= PLAYER_OFFSET_POSITION_LAST))) + return GetPlaylistInfo(value, info); + + const CVideoInfoTag* tag = item->GetVideoInfoTag(); + if (tag) + { + switch (info.m_info) + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // PLAYER_* / VIDEOPLAYER_* / LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case VIDEOPLAYER_ART: + value = item->GetArt(info.GetData3()); + return true; + case PLAYER_PATH: + case PLAYER_FILENAME: + case PLAYER_FILEPATH: + if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + + value = tag->m_strFileNameAndPath; + if (value.empty()) + value = item->GetPath(); + value = GUIINFO::GetFileInfoLabelValueFromPath(info.m_info, value); + return true; + case PLAYER_TITLE: + value = tag->m_strTitle; + return !value.empty(); + case VIDEOPLAYER_TITLE: + value = tag->m_strTitle; + return !value.empty(); + case LISTITEM_TITLE: + value = tag->m_strTitle; + return true; + case VIDEOPLAYER_ORIGINALTITLE: + case LISTITEM_ORIGINALTITLE: + value = tag->m_strOriginalTitle; + return true; + case VIDEOPLAYER_GENRE: + case LISTITEM_GENRE: + value = StringUtils::Join(tag->m_genre, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); + return true; + case VIDEOPLAYER_DIRECTOR: + case LISTITEM_DIRECTOR: + value = StringUtils::Join(tag->m_director, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); + return true; + case VIDEOPLAYER_IMDBNUMBER: + case LISTITEM_IMDBNUMBER: + value = tag->GetUniqueID(); + return true; + case VIDEOPLAYER_DBID: + case LISTITEM_DBID: + if (tag->m_iDbId > -1) + { + value = std::to_string(tag->m_iDbId); + return true; + } + break; + case VIDEOPLAYER_TVSHOWDBID: + case LISTITEM_TVSHOWDBID: + if (tag->m_iIdShow > -1) + { + value = std::to_string(tag->m_iIdShow); + return true; + } + break; + case VIDEOPLAYER_UNIQUEID: + case LISTITEM_UNIQUEID: + if (!info.GetData3().empty()) + value = tag->GetUniqueID(info.GetData3()); + return true; + case VIDEOPLAYER_RATING: + case LISTITEM_RATING: + { + float rating = tag->GetRating(info.GetData3()).rating; + if (rating > 0.f) + { + value = StringUtils::FormatNumber(rating); + return true; + } + break; + } + case VIDEOPLAYER_RATING_AND_VOTES: + case LISTITEM_RATING_AND_VOTES: + { + CRating rating = tag->GetRating(info.GetData3()); + if (rating.rating >= 0.f) + { + if (rating.rating > 0.f && rating.votes == 0) + value = StringUtils::FormatNumber(rating.rating); + else if (rating.votes > 0) + value = StringUtils::Format(g_localizeStrings.Get(20350), + StringUtils::FormatNumber(rating.rating), + StringUtils::FormatNumber(rating.votes)); + else + break; + return true; + } + break; + } + case VIDEOPLAYER_USER_RATING: + case LISTITEM_USER_RATING: + if (tag->m_iUserRating > 0) + { + value = std::to_string(tag->m_iUserRating); + return true; + } + break; + case VIDEOPLAYER_VOTES: + case LISTITEM_VOTES: + value = StringUtils::FormatNumber(tag->GetRating(info.GetData3()).votes); + return true; + case VIDEOPLAYER_YEAR: + case LISTITEM_YEAR: + if (tag->HasYear()) + { + value = std::to_string(tag->GetYear()); + return true; + } + break; + case VIDEOPLAYER_PREMIERED: + case LISTITEM_PREMIERED: + { + CDateTime dateTime; + if (tag->m_firstAired.IsValid()) + dateTime = tag->m_firstAired; + else if (tag->HasPremiered()) + dateTime = tag->GetPremiered(); + + if (dateTime.IsValid()) + { + value = dateTime.GetAsLocalizedDate(); + return true; + } + break; + } + case VIDEOPLAYER_PLOT: + value = tag->m_strPlot; + return true; + case VIDEOPLAYER_TRAILER: + case LISTITEM_TRAILER: + value = tag->m_strTrailer; + return true; + case VIDEOPLAYER_PLOT_OUTLINE: + case LISTITEM_PLOT_OUTLINE: + value = tag->m_strPlotOutline; + return true; + case VIDEOPLAYER_EPISODE: + case LISTITEM_EPISODE: + { + int iEpisode = -1; + if (tag->m_iEpisode > 0) + { + iEpisode = tag->m_iEpisode; + } + + if (iEpisode >= 0) + { + value = std::to_string(iEpisode); + return true; + } + break; + } + case VIDEOPLAYER_SEASON: + case LISTITEM_SEASON: + if (tag->m_iSeason >= 0) + { + value = std::to_string(tag->m_iSeason); + return true; + } + break; + case VIDEOPLAYER_TVSHOW: + case LISTITEM_TVSHOW: + value = tag->m_strShowTitle; + return true; + case VIDEOPLAYER_STUDIO: + case LISTITEM_STUDIO: + value = StringUtils::Join(tag->m_studio, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); + return true; + case VIDEOPLAYER_COUNTRY: + case LISTITEM_COUNTRY: + value = StringUtils::Join(tag->m_country, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); + return true; + case VIDEOPLAYER_MPAA: + case LISTITEM_MPAA: + value = tag->m_strMPAARating; + return true; + case VIDEOPLAYER_TOP250: + case LISTITEM_TOP250: + if (tag->m_iTop250 > 0) + { + value = std::to_string(tag->m_iTop250); + return true; + } + break; + case VIDEOPLAYER_CAST: + case LISTITEM_CAST: + value = tag->GetCast(); + return true; + case VIDEOPLAYER_CAST_AND_ROLE: + case LISTITEM_CAST_AND_ROLE: + value = tag->GetCast(true); + return true; + case VIDEOPLAYER_ARTIST: + case LISTITEM_ARTIST: + value = StringUtils::Join(tag->m_artist, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); + return true; + case VIDEOPLAYER_ALBUM: + case LISTITEM_ALBUM: + value = tag->m_strAlbum; + return true; + case VIDEOPLAYER_WRITER: + case LISTITEM_WRITER: + value = StringUtils::Join(tag->m_writingCredits, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); + return true; + case VIDEOPLAYER_TAGLINE: + case LISTITEM_TAGLINE: + value = tag->m_strTagLine; + return true; + case VIDEOPLAYER_LASTPLAYED: + case LISTITEM_LASTPLAYED: + { + const CDateTime dateTime = tag->m_lastPlayed; + if (dateTime.IsValid()) + { + value = dateTime.GetAsLocalizedDate(); + return true; + } + break; + } + case VIDEOPLAYER_PLAYCOUNT: + case LISTITEM_PLAYCOUNT: + if (tag->GetPlayCount() > 0) + { + value = std::to_string(tag->GetPlayCount()); + return true; + } + break; + + ///////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_DURATION: + { + int iDuration = tag->GetDuration(); + if (iDuration > 0) + { + value = StringUtils::SecondsToTimeString(iDuration, static_cast<TIME_FORMAT>(info.GetData4())); + return true; + } + break; + } + case LISTITEM_TRACKNUMBER: + if (tag->m_iTrack > -1 ) + { + value = std::to_string(tag->m_iTrack); + return true; + } + break; + case LISTITEM_PLOT: + { + std::shared_ptr<CSettingList> setting(std::dynamic_pointer_cast<CSettingList>( + CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting( + CSettings::SETTING_VIDEOLIBRARY_SHOWUNWATCHEDPLOTS))); + if (tag->m_type != MediaTypeTvShow && tag->m_type != MediaTypeVideoCollection && + tag->GetPlayCount() == 0 && setting && + ((tag->m_type == MediaTypeMovie && + !CSettingUtils::FindIntInList( + setting, CSettings::VIDEOLIBRARY_PLOTS_SHOW_UNWATCHED_MOVIES)) || + (tag->m_type == MediaTypeEpisode && + !CSettingUtils::FindIntInList( + setting, CSettings::VIDEOLIBRARY_PLOTS_SHOW_UNWATCHED_TVSHOWEPISODES)))) + { + value = g_localizeStrings.Get(20370); + } + else + { + value = tag->m_strPlot; + } + return true; + } + case LISTITEM_STATUS: + value = tag->m_strStatus; + return true; + case LISTITEM_TAG: + value = StringUtils::Join(tag->m_tags, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); + return true; + case LISTITEM_SET: + value = tag->m_set.title; + return true; + case LISTITEM_SETID: + if (tag->m_set.id > 0) + { + value = std::to_string(tag->m_set.id); + return true; + } + break; + case LISTITEM_ENDTIME_RESUME: + { + const CDateTimeSpan duration(0, 0, 0, tag->GetDuration() - tag->GetResumePoint().timeInSeconds); + value = (CDateTime::GetCurrentDateTime() + duration).GetAsLocalizedTime("", false); + return true; + } + case LISTITEM_ENDTIME: + { + const CDateTimeSpan duration(0, 0, 0, tag->GetDuration()); + value = (CDateTime::GetCurrentDateTime() + duration).GetAsLocalizedTime("", false); + return true; + } + case LISTITEM_DATE_ADDED: + if (tag->m_dateAdded.IsValid()) + { + value = tag->m_dateAdded.GetAsLocalizedDate(); + return true; + } + break; + case LISTITEM_DBTYPE: + value = tag->m_type; + return true; + case LISTITEM_APPEARANCES: + if (tag->m_relevance > -1) + { + value = std::to_string(tag->m_relevance); + return true; + } + break; + case LISTITEM_PERCENT_PLAYED: + value = std::to_string(GetPercentPlayed(tag)); + return true; + case LISTITEM_VIDEO_CODEC: + value = tag->m_streamDetails.GetVideoCodec(); + return true; + case LISTITEM_VIDEO_RESOLUTION: + value = CStreamDetails::VideoDimsToResolutionDescription(tag->m_streamDetails.GetVideoWidth(), tag->m_streamDetails.GetVideoHeight()); + return true; + case LISTITEM_VIDEO_ASPECT: + value = CStreamDetails::VideoAspectToAspectDescription(tag->m_streamDetails.GetVideoAspect()); + return true; + case LISTITEM_AUDIO_CODEC: + value = tag->m_streamDetails.GetAudioCodec(); + return true; + case LISTITEM_AUDIO_CHANNELS: + { + int iChannels = tag->m_streamDetails.GetAudioChannels(); + if (iChannels > 0) + { + value = std::to_string(iChannels); + return true; + } + break; + } + case LISTITEM_AUDIO_LANGUAGE: + value = tag->m_streamDetails.GetAudioLanguage(); + return true; + case LISTITEM_SUBTITLE_LANGUAGE: + value = tag->m_streamDetails.GetSubtitleLanguage(); + return true; + case LISTITEM_FILENAME: + case LISTITEM_FILE_EXTENSION: + if (item->IsVideoDb()) + value = URIUtils::GetFileName(tag->m_strFileNameAndPath); + else if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + value = URIUtils::GetFileName(item->GetPath()); + + if (info.m_info == LISTITEM_FILE_EXTENSION) + { + std::string strExtension = URIUtils::GetExtension(value); + value = StringUtils::TrimLeft(strExtension, "."); + } + return true; + case LISTITEM_FOLDERNAME: + case LISTITEM_PATH: + if (item->IsVideoDb()) + { + if (item->m_bIsFolder) + value = tag->m_strPath; + else + URIUtils::GetParentPath(tag->m_strFileNameAndPath, value); + } + else if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + URIUtils::GetParentPath(item->GetPath(), value); + + value = CURL(value).GetWithoutUserDetails(); + + if (info.m_info == LISTITEM_FOLDERNAME) + { + URIUtils::RemoveSlashAtEnd(value); + value = URIUtils::GetFileName(value); + } + return true; + case LISTITEM_FILENAME_AND_PATH: + if (item->IsVideoDb()) + value = tag->m_strFileNameAndPath; + else if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + value = item->GetPath(); + + value = CURL(value).GetWithoutUserDetails(); + return true; + case LISTITEM_VIDEO_HDR_TYPE: + value = tag->m_streamDetails.GetVideoHdrType(); + return true; + } + } + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // VIDEOPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case VIDEOPLAYER_PLAYLISTLEN: + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_VIDEO) + { + value = GUIINFO::GetPlaylistLabel(PLAYLIST_LENGTH); + return true; + } + break; + case VIDEOPLAYER_PLAYLISTPOS: + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_VIDEO) + { + value = GUIINFO::GetPlaylistLabel(PLAYLIST_POSITION); + return true; + } + break; + case VIDEOPLAYER_VIDEO_ASPECT: + value = CStreamDetails::VideoAspectToAspectDescription(CServiceBroker::GetDataCacheCore().GetVideoDAR()); + return true; + case VIDEOPLAYER_STEREOSCOPIC_MODE: + value = CServiceBroker::GetDataCacheCore().GetVideoStereoMode(); + return true; + case VIDEOPLAYER_SUBTITLES_LANG: + value = m_subtitleInfo.language; + return true; + break; + case VIDEOPLAYER_COVER: + if (m_appPlayer->IsPlayingVideo()) + { + if (fallback) + *fallback = "DefaultVideoCover.png"; + + value = item->HasArt("thumb") ? item->GetArt("thumb") : "DefaultVideoCover.png"; + return true; + } + break; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_STEREOSCOPIC_MODE: + value = item->GetProperty("stereomode").asString(); + if (value.empty() && tag) + value = CStereoscopicsManager::NormalizeStereoMode(tag->m_streamDetails.GetStereoMode()); + return true; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // VIDEOPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case VIDEOPLAYER_VIDEO_CODEC: + value = m_videoInfo.codecName; + return true; + case VIDEOPLAYER_VIDEO_RESOLUTION: + value = CStreamDetails::VideoDimsToResolutionDescription(m_videoInfo.width, m_videoInfo.height); + return true; + case VIDEOPLAYER_HDR_TYPE: + value = CStreamDetails::HdrTypeToString(m_videoInfo.hdrType); + return true; + case VIDEOPLAYER_AUDIO_CODEC: + value = m_audioInfo.codecName; + return true; + case VIDEOPLAYER_AUDIO_CHANNELS: + { + int iChannels = m_audioInfo.channels; + if (iChannels > 0) + { + value = std::to_string(iChannels); + return true; + } + break; + } + case VIDEOPLAYER_AUDIO_BITRATE: + { + int iBitrate = m_audioInfo.bitrate; + if (iBitrate > 0) + { + value = std::to_string(std::lrint(static_cast<double>(iBitrate) / 1000.0)); + return true; + } + break; + } + case VIDEOPLAYER_VIDEO_BITRATE: + { + int iBitrate = m_videoInfo.bitrate; + if (iBitrate > 0) + { + value = std::to_string(std::lrint(static_cast<double>(iBitrate) / 1000.0)); + return true; + } + break; + } + case VIDEOPLAYER_AUDIO_LANG: + value = m_audioInfo.language; + return true; + } + + return false; +} + +bool CVideoGUIInfo::GetPlaylistInfo(std::string& value, const CGUIInfo& info) const +{ + const PLAYLIST::CPlayList& playlist = + CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::TYPE_VIDEO); + if (playlist.size() < 1) + return false; + + int index = info.GetData2(); + if (info.GetData1() == 1) + { // relative index (requires current playlist is TYPE_VIDEO) + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() != PLAYLIST::TYPE_VIDEO) + return false; + + index = CServiceBroker::GetPlaylistPlayer().GetNextSong(index); + } + + if (index < 0 || index >= playlist.size()) + return false; + + const CFileItemPtr playlistItem = playlist[index]; + // try to set a thumbnail + if (!playlistItem->HasArt("thumb")) + { + CVideoThumbLoader loader; + loader.LoadItem(playlistItem.get()); + // still no thumb? then just the set the default cover + if (!playlistItem->HasArt("thumb")) + playlistItem->SetArt("thumb", "DefaultVideoCover.png"); + } + if (info.m_info == VIDEOPLAYER_PLAYLISTPOS) + { + value = std::to_string(index + 1); + return true; + } + else if (info.m_info == VIDEOPLAYER_COVER) + { + value = playlistItem->GetArt("thumb"); + return true; + } + else if (info.m_info == VIDEOPLAYER_ART) + { + value = playlistItem->GetArt(info.GetData3()); + return true; + } + + return GetLabel(value, playlistItem.get(), 0, CGUIInfo(info.m_info), nullptr); +} + +bool CVideoGUIInfo::GetFallbackLabel(std::string& value, + const CFileItem* item, + int contextWindow, + const CGUIInfo& info, + std::string* fallback) +{ + // No fallback for videoplayer "offset" and "position" info labels + if (info.GetData1() && ((info.m_info >= VIDEOPLAYER_OFFSET_POSITION_FIRST && + info.m_info <= VIDEOPLAYER_OFFSET_POSITION_LAST) || + (info.m_info >= PLAYER_OFFSET_POSITION_FIRST && info.m_info <= PLAYER_OFFSET_POSITION_LAST))) + return false; + + const CVideoInfoTag* tag = item->GetVideoInfoTag(); + if (tag) + { + switch (info.m_info) + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // VIDEOPLAYER_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case VIDEOPLAYER_TITLE: + value = item->GetLabel(); + if (value.empty()) + value = CUtil::GetTitleFromPath(item->GetPath()); + return true; + default: + break; + } + } + return false; +} + +bool CVideoGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + if (!gitem->IsFileItem()) + return false; + + const CFileItem *item = static_cast<const CFileItem*>(gitem); + const CVideoInfoTag* tag = item->GetVideoInfoTag(); + if (tag) + { + switch (info.m_info) + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_PERCENT_PLAYED: + value = GetPercentPlayed(tag); + return true; + } + } + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // VIDEOPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case VIDEOPLAYER_AUDIOSTREAMCOUNT: + value = m_appPlayer->GetAudioStreamCount(); + return true; + + default: + break; + } + + return false; +} + +bool CVideoGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + if (!gitem->IsFileItem()) + return false; + + const CFileItem *item = static_cast<const CFileItem*>(gitem); + const CVideoInfoTag* tag = item->GetVideoInfoTag(); + if (tag) + { + switch (info.m_info) + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // VIDEOPLAYER_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case VIDEOPLAYER_HAS_INFO: + value = !tag->IsEmpty(); + return true; + + ///////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_IS_RESUMABLE: + value = tag->GetResumePoint().timeInSeconds > 0; + return true; + case LISTITEM_IS_COLLECTION: + value = tag->m_type == MediaTypeVideoCollection; + return true; + } + } + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // VIDEOPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case VIDEOPLAYER_CONTENT: + { + std::string strContent = "files"; + if (tag) + { + if (tag->m_type == MediaTypeMovie) + strContent = "movies"; + else if (tag->m_type == MediaTypeEpisode) + strContent = "episodes"; + else if (tag->m_type == MediaTypeMusicVideo) + strContent = "musicvideos"; + } + value = StringUtils::EqualsNoCase(info.GetData3(), strContent); + return value; // if no match for this provider, other providers shall be asked. + } + case VIDEOPLAYER_USING_OVERLAYS: + value = (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_VIDEOPLAYER_RENDERMETHOD) == RENDER_OVERLAYS); + return true; + case VIDEOPLAYER_ISFULLSCREEN: + value = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO || + CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_FULLSCREEN_GAME; + return true; + case VIDEOPLAYER_HASMENU: + value = m_appPlayer->GetSupportedMenuType() != MenuType::NONE; + return true; + case VIDEOPLAYER_HASTELETEXT: + value = m_appPlayer->HasTeletextCache(); + return true; + case VIDEOPLAYER_HASSUBTITLES: + value = m_appPlayer->GetSubtitleCount() > 0; + return true; + case VIDEOPLAYER_SUBTITLESENABLED: + value = m_appPlayer->GetSubtitleVisible(); + return true; + case VIDEOPLAYER_IS_STEREOSCOPIC: + value = !CServiceBroker::GetDataCacheCore().GetVideoStereoMode().empty(); + return true; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_IS_STEREOSCOPIC: + { + std::string stereoMode = item->GetProperty("stereomode").asString(); + if (stereoMode.empty() && tag) + stereoMode = CStereoscopicsManager::NormalizeStereoMode(tag->m_streamDetails.GetStereoMode()); + if (!stereoMode.empty() && stereoMode != "mono") + value = true; + return true; + } + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/VideoGUIInfo.h b/xbmc/guilib/guiinfo/VideoGUIInfo.h new file mode 100644 index 0000000..55202b2 --- /dev/null +++ b/xbmc/guilib/guiinfo/VideoGUIInfo.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +#include <memory> + +class CApplicationPlayer; +class CVideoInfoTag; + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CVideoGUIInfo : public CGUIInfoProvider +{ +public: + CVideoGUIInfo(); + ~CVideoGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetFallbackLabel(std::string& value, + const CFileItem* item, + int contextWindow, + const CGUIInfo& info, + std::string* fallback) override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + +private: + int GetPercentPlayed(const CVideoInfoTag* tag) const; + bool GetPlaylistInfo(std::string& value, const CGUIInfo& info) const; + + const std::shared_ptr<CApplicationPlayer> m_appPlayer; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/VisualisationGUIInfo.cpp b/xbmc/guilib/guiinfo/VisualisationGUIInfo.cpp new file mode 100644 index 0000000..27a892f --- /dev/null +++ b/xbmc/guilib/guiinfo/VisualisationGUIInfo.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/VisualisationGUIInfo.h" + +#include "GUIUserMessages.h" +#include "ServiceBroker.h" +#include "addons/Addon.h" +#include "addons/AddonManager.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIVisualisationControl.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/URIUtils.h" + +using namespace KODI::GUILIB::GUIINFO; + +bool CVisualisationGUIInfo::InitCurrentItem(CFileItem *item) +{ + return false; +} + +bool CVisualisationGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // VISUALISATION_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case VISUALISATION_PRESET: + { + CGUIMessage msg(GUI_MSG_GET_VISUALISATION, 0, 0); + CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); + if (msg.GetPointer()) + { + CGUIVisualisationControl* viz = static_cast<CGUIVisualisationControl*>(msg.GetPointer()); + if (viz) + { + value = viz->GetActivePresetName(); + URIUtils::RemoveExtension(value); + return true; + } + } + break; + } + case VISUALISATION_NAME: + { + ADDON::AddonPtr addon; + value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_MUSICPLAYER_VISUALISATION); + if (CServiceBroker::GetAddonMgr().GetAddon(value, addon, ADDON::OnlyEnabled::CHOICE_YES) && + addon) + { + value = addon->Name(); + return true; + } + break; + } + } + + return false; +} + +bool CVisualisationGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + return false; +} + +bool CVisualisationGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // VISUALISATION_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case VISUALISATION_LOCKED: + { + CGUIMessage msg(GUI_MSG_GET_VISUALISATION, 0, 0); + CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); + if (msg.GetPointer()) + { + CGUIVisualisationControl *pVis = static_cast<CGUIVisualisationControl*>(msg.GetPointer()); + value = pVis->IsLocked(); + return true; + } + break; + } + case VISUALISATION_ENABLED: + { + value = !CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_MUSICPLAYER_VISUALISATION).empty(); + return true; + } + case VISUALISATION_HAS_PRESETS: + { + CGUIMessage msg(GUI_MSG_GET_VISUALISATION, 0, 0); + CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); + if (msg.GetPointer()) + { + CGUIVisualisationControl* viz = static_cast<CGUIVisualisationControl*>(msg.GetPointer()); + value = (viz && viz->HasPresets()); + return true; + } + break; + } + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/VisualisationGUIInfo.h b/xbmc/guilib/guiinfo/VisualisationGUIInfo.h new file mode 100644 index 0000000..d3cb05d --- /dev/null +++ b/xbmc/guilib/guiinfo/VisualisationGUIInfo.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CVisualisationGUIInfo : public CGUIInfoProvider +{ +public: + CVisualisationGUIInfo() = default; + ~CVisualisationGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI diff --git a/xbmc/guilib/guiinfo/WeatherGUIInfo.cpp b/xbmc/guilib/guiinfo/WeatherGUIInfo.cpp new file mode 100644 index 0000000..3aa2044 --- /dev/null +++ b/xbmc/guilib/guiinfo/WeatherGUIInfo.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012-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 "guilib/guiinfo/WeatherGUIInfo.h" + +#include "FileItem.h" +#include "LangInfo.h" +#include "ServiceBroker.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "weather/WeatherManager.h" + +using namespace KODI::GUILIB::GUIINFO; + +bool CWeatherGUIInfo::InitCurrentItem(CFileItem *item) +{ + return false; +} + +bool CWeatherGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // WEATHER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case WEATHER_CONDITIONS_TEXT: + value = CServiceBroker::GetWeatherManager().GetInfo(WEATHER_LABEL_CURRENT_COND); + StringUtils::Trim(value); + return true; + case WEATHER_CONDITIONS_ICON: + value = CServiceBroker::GetWeatherManager().GetInfo(WEATHER_IMAGE_CURRENT_ICON); + return true; + case WEATHER_TEMPERATURE: + value = StringUtils::Format( + "{}{}", CServiceBroker::GetWeatherManager().GetInfo(WEATHER_LABEL_CURRENT_TEMP), + g_langInfo.GetTemperatureUnitString()); + return true; + case WEATHER_LOCATION: + value = CServiceBroker::GetWeatherManager().GetInfo(WEATHER_LABEL_LOCATION); + return true; + case WEATHER_FANART_CODE: + value = URIUtils::GetFileName(CServiceBroker::GetWeatherManager().GetInfo(WEATHER_IMAGE_CURRENT_ICON)); + URIUtils::RemoveExtension(value); + return true; + case WEATHER_PLUGIN: + value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_WEATHER_ADDON); + return true; + } + + return false; +} + +bool CWeatherGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + return false; +} + +bool CWeatherGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // WEATHER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case WEATHER_IS_FETCHED: + value = CServiceBroker::GetWeatherManager().IsFetched(); + return true;; + } + + return false; +} diff --git a/xbmc/guilib/guiinfo/WeatherGUIInfo.h b/xbmc/guilib/guiinfo/WeatherGUIInfo.h new file mode 100644 index 0000000..560d025 --- /dev/null +++ b/xbmc/guilib/guiinfo/WeatherGUIInfo.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012-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. + */ + +#pragma once + +#include "guilib/guiinfo/GUIInfoProvider.h" + +namespace KODI +{ +namespace GUILIB +{ +namespace GUIINFO +{ + +class CGUIInfo; + +class CWeatherGUIInfo : public CGUIInfoProvider +{ +public: + CWeatherGUIInfo() = default; + ~CWeatherGUIInfo() override = default; + + // KODI::GUILIB::GUIINFO::IGUIInfoProvider implementation + bool InitCurrentItem(CFileItem *item) override; + bool GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const override; + bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; + bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const CGUIInfo &info) const override; +}; + +} // namespace GUIINFO +} // namespace GUILIB +} // namespace KODI |