aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kodi.xcodeproj/project.pbxproj8
-rw-r--r--addons/resource.language.en_gb/resources/strings.po55
-rw-r--r--addons/skin.estuary/1080i/MyPVRGuide.xml13
-rw-r--r--project/cmake/cpack/deb/packages/kodi-peripheral-dev.txt.in24
-rw-r--r--project/cmake/scripts/linux/Install.cmake9
-rw-r--r--system/settings/settings.xml5
-rw-r--r--xbmc/Application.cpp83
-rw-r--r--xbmc/Application.h12
-rw-r--r--xbmc/GUIInfoManager.cpp4
-rw-r--r--xbmc/NfoFile.cpp3
-rw-r--r--xbmc/Util.cpp17
-rw-r--r--xbmc/XBApplicationEx.cpp18
-rw-r--r--xbmc/XBApplicationEx.h2
-rw-r--r--xbmc/addons/Addon.cpp38
-rw-r--r--xbmc/addons/AddonInstaller.cpp28
-rw-r--r--xbmc/addons/AddonInstaller.h4
-rw-r--r--xbmc/addons/AddonManager.cpp119
-rw-r--r--xbmc/addons/AddonManager.h8
-rw-r--r--xbmc/addons/AddonSystemSettings.cpp106
-rw-r--r--xbmc/addons/AddonSystemSettings.h18
-rw-r--r--xbmc/addons/GUIDialogAddonInfo.cpp2
-rw-r--r--xbmc/addons/GUIWindowAddonBrowser.cpp3
-rw-r--r--xbmc/addons/Repository.cpp60
-rw-r--r--xbmc/addons/RepositoryUpdater.cpp11
-rw-r--r--xbmc/addons/Skin.cpp16
-rw-r--r--xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp18
-rw-r--r--xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h1
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp2
-rw-r--r--xbmc/cores/IPlayer.h4
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp2
-rw-r--r--xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp27
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp11
-rw-r--r--xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp3
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp14
-rw-r--r--xbmc/epg/GUIEPGGridContainer.cpp41
-rw-r--r--xbmc/epg/GUIEPGGridContainer.h4
-rw-r--r--xbmc/filesystem/AddonsDirectory.cpp2
-rw-r--r--xbmc/guilib/GUIControlFactory.cpp10
-rw-r--r--xbmc/guilib/GUIVisualisationControl.cpp3
-rw-r--r--xbmc/interfaces/builtins/AddonBuiltins.cpp5
-rw-r--r--xbmc/music/MusicDatabase.cpp5
-rw-r--r--xbmc/music/infoscanner/MusicInfoScanner.cpp5
-rw-r--r--xbmc/music/windows/GUIWindowMusicNav.cpp4
-rw-r--r--xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp3
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRBase.cpp11
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRChannels.cpp5
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRChannels.h1
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRGuide.cpp5
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRGuide.h1
-rw-r--r--xbmc/settings/MediaSettings.cpp2
-rw-r--r--xbmc/settings/dialogs/GUIDialogContentSettings.cpp11
-rw-r--r--xbmc/video/CMakeLists.txt3
-rw-r--r--xbmc/video/Makefile1
-rw-r--r--xbmc/video/ViewModeSettings.cpp111
-rw-r--r--xbmc/video/ViewModeSettings.h55
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoSettings.cpp7
-rw-r--r--xbmc/video/windows/GUIWindowFullScreen.cpp5
57 files changed, 731 insertions, 317 deletions
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj
index ae7bd4db5c..c6cdb0e8a9 100644
--- a/Kodi.xcodeproj/project.pbxproj
+++ b/Kodi.xcodeproj/project.pbxproj
@@ -393,6 +393,8 @@
7C5608C70F1754930056433A /* ExternalPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C5608C40F1754930056433A /* ExternalPlayer.cpp */; };
7C62F24210505BC7002AD2C1 /* Bookmark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C62F24010505BC7002AD2C1 /* Bookmark.cpp */; };
7C62F45E1057A62D002AD2C1 /* DirectoryNodeSingles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C62F45C1057A62D002AD2C1 /* DirectoryNodeSingles.cpp */; };
+ 7C68401B1D87C6D400C55360 /* ViewModeSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C6840191D87C6D400C55360 /* ViewModeSettings.cpp */; };
+ 7C68401C1D87C6D400C55360 /* ViewModeSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C6840191D87C6D400C55360 /* ViewModeSettings.cpp */; };
7C6EB330155BD1D40080368A /* ImageFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C6EB32E155BD1D40080368A /* ImageFile.cpp */; };
7C6EB6FA155F32C30080368A /* HTTPImageHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C6EB6F8155F32C30080368A /* HTTPImageHandler.cpp */; };
7C779E3A104A57E500F444C4 /* RenderSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C779E1F104A57E500F444C4 /* RenderSystem.cpp */; };
@@ -2941,6 +2943,8 @@
7C62F24110505BC7002AD2C1 /* Bookmark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bookmark.h; sourceTree = "<group>"; };
7C62F45C1057A62D002AD2C1 /* DirectoryNodeSingles.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryNodeSingles.cpp; sourceTree = "<group>"; };
7C62F45D1057A62D002AD2C1 /* DirectoryNodeSingles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryNodeSingles.h; sourceTree = "<group>"; };
+ 7C6840191D87C6D400C55360 /* ViewModeSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewModeSettings.cpp; sourceTree = "<group>"; };
+ 7C68401A1D87C6D400C55360 /* ViewModeSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewModeSettings.h; sourceTree = "<group>"; };
7C6EB32E155BD1D40080368A /* ImageFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFile.cpp; sourceTree = "<group>"; };
7C6EB32F155BD1D40080368A /* ImageFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFile.h; sourceTree = "<group>"; };
7C6EB6F8155F32C30080368A /* HTTPImageHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTTPImageHandler.cpp; sourceTree = "<group>"; };
@@ -6031,6 +6035,8 @@
F59876BE0FBA351D008EF4FB /* VideoReferenceClock.h */,
7CC30DBE16291C2C003E7579 /* VideoThumbLoader.cpp */,
7CC30DBF16291C2C003E7579 /* VideoThumbLoader.h */,
+ 7C6840191D87C6D400C55360 /* ViewModeSettings.cpp */,
+ 7C68401A1D87C6D400C55360 /* ViewModeSettings.h */,
);
path = video;
sourceTree = "<group>";
@@ -10113,6 +10119,7 @@
E38A06CE0D95AA5500FF8227 /* GUIDialogKaiToast.cpp in Sources */,
7C8E023D1BA35D0B0072E8B2 /* ProfileBuiltins.cpp in Sources */,
E3B53E7C0D97B08100021A96 /* DVDSubtitleParserMicroDVD.cpp in Sources */,
+ 7C68401B1D87C6D400C55360 /* ViewModeSettings.cpp in Sources */,
E36C29DF0DA72429001F0C9D /* Artist.cpp in Sources */,
E36C29E00DA72429001F0C9D /* Album.cpp in Sources */,
E36C29E60DA72442001F0C9D /* DVDSubtitleParserSami.cpp in Sources */,
@@ -11451,6 +11458,7 @@
E49913AE174E5F3300741B6D /* UPnPPlayer.cpp in Sources */,
E49913AF174E5F3300741B6D /* UPnPRenderer.cpp in Sources */,
E49913B0174E5F3300741B6D /* UPnPServer.cpp in Sources */,
+ 7C68401C1D87C6D400C55360 /* ViewModeSettings.cpp in Sources */,
E49913B1174E5F3300741B6D /* UPnPSettings.cpp in Sources */,
E49913B2174E5F3700741B6D /* WebSocket.cpp in Sources */,
E49913B3174E5F3700741B6D /* WebSocketManager.cpp in Sources */,
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 3de62d4e54..7a3854a464 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -10354,7 +10354,13 @@ msgctxt "#19295"
msgid "Delete timer rule"
msgstr ""
-#empty strings from id 19296 to 19498
+#. Label if no pvr addons are enabled
+#: xbmc/pvr/windows/GUIWindowPVRBase.cpp
+msgctxt "#19296"
+msgid "No PVR add-on enabled"
+msgstr ""
+
+#empty strings from id 19297 to 19498
#: xbmc/epg/Epg.cpp
msgctxt "#19499"
@@ -13448,10 +13454,14 @@ msgctxt "#21844"
msgid "XP comment"
msgstr ""
+#. Used in context menu
+#: xbmc/video/windows/GUIWindowVideoNav.cpp
msgctxt "#21845"
msgid "Scan to library"
msgstr ""
+#empty strings from id 21846 to 21856
+
msgctxt "#21857"
msgid "Sub-location"
msgstr ""
@@ -14089,11 +14099,7 @@ msgctxt "#24043"
msgid "Available updates"
msgstr ""
-#: xbmc/addons/AddonInstaller.cpp
-#: xbmc/addons/AddonsDatabase.cpp
-msgctxt "#24044"
-msgid "Dependencies not met. Please contact add-on author."
-msgstr ""
+# empty string 24043
#. Used as an event log description for add-ons failed to install from zip
#: xbmc/addons/AddonInstaller.cpp
@@ -14116,10 +14122,7 @@ msgctxt "#24048"
msgid "VideoPlayer InputStream"
msgstr ""
-#: xbmc/filesystem/AddonsDirectory.cpp
-msgctxt "#24049"
-msgid "Incompatible"
-msgstr ""
+# empty string 24049
#: unknown
msgctxt "#24050"
@@ -14638,7 +14641,15 @@ msgctxt "#24147"
msgid "Failed to scan %s: %s"
msgstr ""
-#empty strings from id 24148 to 24990
+msgctxt "#24148"
+msgid "Incompatible add-ons"
+msgstr ""
+
+msgctxt "#24149"
+msgid "The following add-ons are incompatible with this version of Kodi and have been automatically disabled: %s."
+msgstr ""
+
+#empty strings from id 24150 to 24990
#. Used as error message in add-on browser when add-on repository data could not be downloaded
#: xbmc/filesystem/AddonsDirectory.cpp
@@ -15248,18 +15259,6 @@ msgctxt "#29985"
msgid "If traffic advisory is send from RDS, volume is increased"
msgstr ""
-#. Boolean value on settings
-#: system/settings/settings.xml
-msgctxt "#29986"
-msgid "Publicate traffic messages"
-msgstr ""
-
-#. Help text of boolean on/off value
-#: system/settings/settings.xml
-msgctxt "#29987"
-msgid "Send present traffic messages around and can be handled from add-ons (nothing inside Kodi)"
-msgstr ""
-
#. Music role category
#: system/library/music/musicroles/Arrangers.xml
msgctxt "#29988"
@@ -19584,3 +19583,13 @@ msgstr ""
msgctxt "#39007"
msgid "This provides access to where picture sources can be added and otherwise managed."
msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#39008"
+msgid "Zoom - 120% width"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#39009"
+msgid "Zoom - 110% width"
+msgstr ""
diff --git a/addons/skin.estuary/1080i/MyPVRGuide.xml b/addons/skin.estuary/1080i/MyPVRGuide.xml
index 6f9f118aae..6a1cd6a225 100644
--- a/addons/skin.estuary/1080i/MyPVRGuide.xml
+++ b/addons/skin.estuary/1080i/MyPVRGuide.xml
@@ -27,11 +27,12 @@
<top>0</top>
<width>1700</width>
<height>510</height>
- <pagecontrol>10</pagecontrol>
+ <pagecontrol>60</pagecontrol>
<scrolltime tween="quadratic" easing="out">200</scrolltime>
<timeblocks>36</timeblocks>
<rulerunit>6</rulerunit>
<onleft>9000</onleft>
+ <onright>60</onright>
<onup>10</onup>
<ondown>10</ondown>
<viewtype label="19032">list</viewtype>
@@ -154,6 +155,16 @@
</control>
</focusedlayout>
</control>
+ <control type="scrollbar" id="60">
+ <right>85</right>
+ <top>45</top>
+ <width>13</width>
+ <height>465</height>
+ <onleft>10</onleft>
+ <onright>10</onright>
+ <orientation>vertical</orientation>
+ <texturesliderbackground colordiffuse="22FFFFFF">colors/white.png</texturesliderbackground>
+ </control>
<control type="group">
<top>540</top>
<left>-120</left>
diff --git a/project/cmake/cpack/deb/packages/kodi-peripheral-dev.txt.in b/project/cmake/cpack/deb/packages/kodi-peripheral-dev.txt.in
new file mode 100644
index 0000000000..1c41c5f5d2
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-peripheral-dev.txt.in
@@ -0,0 +1,24 @@
+# kodi-peripheral-dev debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC@-peripheral-dev
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION libdevel
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC@-addon-dev
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (peripheral add-ons dev package)
+PACKAGE_DESCRIPTION_FOOTER This is the development package for @APP_NAME@'s peripheral add-ons.
diff --git a/project/cmake/scripts/linux/Install.cmake b/project/cmake/scripts/linux/Install.cmake
index ba90de4a35..fac75eddf2 100644
--- a/project/cmake/scripts/linux/Install.cmake
+++ b/project/cmake/scripts/linux/Install.cmake
@@ -139,6 +139,7 @@ install(PROGRAMS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/texturepacker/TexturePack
# Install kodi-addon-dev headers
install(FILES ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_vfs_types.h
+ ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_vfs_utils.hpp
${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_adsp.h
${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_audioengine.h
${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h
@@ -297,6 +298,14 @@ install(FILES ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbm
DESTINATION ${includedir}/${APP_NAME_LC}
COMPONENT kodi-visualization-dev)
+# Install kodi-peripheral-dev
+install(FILES ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_callbacks.h
+ ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h
+ ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h
+ ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_utils.hpp
+ DESTINATION ${includedir}/${APP_NAME_LC}
+ COMPONENT kodi-peripheral-dev)
+
# Install XBT skin files
foreach(texture ${XBT_FILES})
string(REPLACE "${CMAKE_BINARY_DIR}/" "" dir ${texture})
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index ca912cd996..8d20a7ae8f 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -1477,11 +1477,6 @@
<dependency type="enable" setting="pvrplayback.trafficadvisory">true</dependency>
</dependencies>
</setting>
- <setting id="pvrplayback.sendrdstrafficmsg" type="boolean" label="29986" help="29987">
- <level>2</level>
- <default>false</default>
- <control type="toggle" />
- </setting>
</group>
</category>
<category id="pvrrecord" label="19043" help="36233">
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index 775063a7a9..45cc633fcd 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -280,7 +280,7 @@ CApplication::CApplication(void)
m_nextPlaylistItem = -1;
m_bPlaybackStarting = false;
m_ePlayState = PLAY_STATE_NONE;
- m_skinReverting = false;
+ m_confirmSkinChange = true;
#ifdef HAS_GLX
XInitThreads();
@@ -1164,12 +1164,19 @@ bool CApplication::Initialize()
if (g_advancedSettings.m_splashImage)
g_windowManager.ActivateWindow(WINDOW_SPLASH);
- // Make sure we have at least the default skin
+ m_confirmSkinChange = false;
+ m_incompatibleAddons = CAddonSystemSettings::GetInstance().MigrateAddons();
+ m_confirmSkinChange = true;
+
std::string defaultSkin = ((const CSettingString*)CSettings::GetInstance().GetSetting(CSettings::SETTING_LOOKANDFEEL_SKIN))->GetDefault();
- if (!LoadSkin(CSettings::GetInstance().GetString(CSettings::SETTING_LOOKANDFEEL_SKIN)) && !LoadSkin(defaultSkin))
+ if (!LoadSkin(CSettings::GetInstance().GetString(CSettings::SETTING_LOOKANDFEEL_SKIN)))
{
- CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
- return false;
+ CLog::Log(LOGERROR, "Failed to load skin '%s'", CSettings::GetInstance().GetString(CSettings::SETTING_LOOKANDFEEL_SKIN).c_str());
+ if (!LoadSkin(defaultSkin))
+ {
+ CLog::Log(LOGFATAL, "Default skin '%s' could not be loaded! Terminating..", defaultSkin.c_str());
+ return false;
+ }
}
if (CSettings::GetInstance().GetBool(CSettings::SETTING_MASTERLOCK_STARTUPLOCK) &&
@@ -1249,8 +1256,6 @@ bool CApplication::Initialize()
CLog::Log(LOGNOTICE, "initialize done");
- m_bInitializing = false;
-
// reset our screensaver (starts timers etc.)
ResetScreenSaver();
@@ -1406,11 +1411,14 @@ void CApplication::OnSettingChanged(const CSetting *setting)
// reset the settings to ignore during changing skins
m_skinReloadSettingIgnore.clear();
- // now we can finally reload skins
- std::string builtin("ReloadSkin");
- if (settingId == CSettings::SETTING_LOOKANDFEEL_SKIN && !m_skinReverting)
- builtin += "(confirm)";
- CApplicationMessenger::GetInstance().PostMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, builtin);
+ if (g_SkinInfo)
+ {
+ // now we can finally reload skins
+ std::string builtin("ReloadSkin");
+ if (settingId == CSettings::SETTING_LOOKANDFEEL_SKIN && m_confirmSkinChange)
+ builtin += "(confirm)";
+ CApplicationMessenger::GetInstance().PostMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, builtin);
+ }
}
else if (settingId == CSettings::SETTING_LOOKANDFEEL_SKINZOOM)
{
@@ -1549,7 +1557,10 @@ bool CApplication::OnSettingsSaving() const
void CApplication::ReloadSkin(bool confirm/*=false*/)
{
- std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
+ if (!g_SkinInfo || m_bInitializing)
+ return; // Don't allow reload before skin is loaded by system
+
+ std::string oldSkin = g_SkinInfo->ID();
CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
g_windowManager.SendMessage(msg);
@@ -1557,18 +1568,15 @@ void CApplication::ReloadSkin(bool confirm/*=false*/)
std::string newSkin = CSettings::GetInstance().GetString(CSettings::SETTING_LOOKANDFEEL_SKIN);
if (LoadSkin(newSkin))
{
- /* The Reset() or SetString() below will cause recursion, so the m_skinReverting boolean is set so as to not prompt the
+ /* The Reset() or SetString() below will cause recursion, so the m_confirmSkinChange boolean is set so as to not prompt the
user as to whether they want to keep the current skin. */
- if (confirm && !m_skinReverting)
+ if (confirm && m_confirmSkinChange)
{
if (HELPERS::ShowYesNoDialogText(CVariant{13123}, CVariant{13111}, CVariant{""}, CVariant{""}, 10000) !=
DialogResponse::YES)
{
- m_skinReverting = true;
- if (oldSkin.empty())
- CSettings::GetInstance().GetSetting(CSettings::SETTING_LOOKANDFEEL_SKIN)->Reset();
- else
- CSettings::GetInstance().SetString(CSettings::SETTING_LOOKANDFEEL_SKIN, oldSkin);
+ m_confirmSkinChange = false;
+ CSettings::GetInstance().SetString(CSettings::SETTING_LOOKANDFEEL_SKIN, oldSkin);
}
}
}
@@ -1578,12 +1586,12 @@ void CApplication::ReloadSkin(bool confirm/*=false*/)
std::string defaultSkin = ((CSettingString*)CSettings::GetInstance().GetSetting(CSettings::SETTING_LOOKANDFEEL_SKIN))->GetDefault();
if (newSkin != defaultSkin)
{
- m_skinReverting = true;
+ m_confirmSkinChange = false;
CSettings::GetInstance().GetSetting(CSettings::SETTING_LOOKANDFEEL_SKIN)->Reset();
CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
}
}
- m_skinReverting = false;
+ m_confirmSkinChange = true;
}
bool CApplication::Load(const TiXmlNode *settings)
@@ -1620,20 +1628,13 @@ bool CApplication::Save(TiXmlNode *settings) const
bool CApplication::LoadSkin(const std::string& skinID)
{
- AddonPtr addon;
- if (CAddonMgr::GetInstance().GetAddon(skinID, addon, ADDON_SKIN))
+ SkinPtr skin;
{
- if (LoadSkin(std::dynamic_pointer_cast<ADDON::CSkinInfo>(addon)))
- return true;
+ AddonPtr addon;
+ if (!CAddonMgr::GetInstance().GetAddon(skinID, addon, ADDON_SKIN))
+ return false;
+ skin = std::static_pointer_cast<ADDON::CSkinInfo>(addon);
}
- CLog::Log(LOGERROR, "failed to load requested skin '%s'", skinID.c_str());
- return false;
-}
-
-bool CApplication::LoadSkin(const SkinPtr& skin)
-{
- if (!skin)
- return false;
// start/prepare the skin
skin->Start();
@@ -1643,7 +1644,10 @@ bool CApplication::LoadSkin(const SkinPtr& skin)
// check if the skin has been properly loaded and if it has a Home.xml
if (!skin->HasSkinFile("Home.xml"))
+ {
+ CLog::Log(LOGERROR, "failed to load requested skin '%s'", skin->ID().c_str());
return false;
+ }
bool bPreviousPlayingState=false;
bool bPreviousRenderingState=false;
@@ -1675,7 +1679,6 @@ bool CApplication::LoadSkin(const SkinPtr& skin)
CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().asString().c_str());
g_SkinInfo = skin;
- g_SkinInfo->Start();
CLog::Log(LOGINFO, " load fonts for skin...");
g_graphicsContext.SetMediaDir(skin->Path());
@@ -4159,8 +4162,18 @@ bool CApplication::OnMessage(CGUIMessage& message)
if (m_fallbackLanguageLoaded)
CGUIDialogOK::ShowAndGetInput(CVariant{24133}, CVariant{24134});
+ if (!m_incompatibleAddons.empty())
+ {
+ auto addonList = StringUtils::Join(m_incompatibleAddons, ", ");
+ auto msg = StringUtils::Format(g_localizeStrings.Get(24149).c_str(), addonList.c_str());
+ CGUIDialogOK::ShowAndGetInput(CVariant{24148}, CVariant{std::move(msg)});
+ m_incompatibleAddons.clear();
+ }
+
// show info dialog about moved configuration files if needed
ShowAppMigrationMessage();
+
+ m_bInitializing = false;
}
}
break;
diff --git a/xbmc/Application.h b/xbmc/Application.h
index c14f62d54f..d20b7725e2 100644
--- a/xbmc/Application.h
+++ b/xbmc/Application.h
@@ -23,6 +23,7 @@
#include "system.h" // for HAS_DVD_DRIVE et. al.
#include "XBApplicationEx.h"
+#include "addons/AddonSystemSettings.h"
#include "guilib/IMsgTargetCallback.h"
#include "guilib/Resolution.h"
#include "utils/GlobalsHandling.h"
@@ -145,7 +146,7 @@ public:
virtual void FrameMove(bool processEvents, bool processGUI = true) override;
virtual void Render() override;
virtual void Preflight();
- virtual bool Create() override;
+ bool Create();
virtual bool Cleanup() override;
bool CreateGUI();
@@ -416,8 +417,7 @@ protected:
virtual bool OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode) override;
bool LoadSkin(const std::string& skinID);
- bool LoadSkin(const std::shared_ptr<ADDON::CSkinInfo>& skin);
-
+
/*!
\brief Delegates the action to all registered action handlers.
\param action The action
@@ -425,7 +425,7 @@ protected:
*/
bool NotifyActionListeners(const CAction &action) const;
- bool m_skinReverting;
+ bool m_confirmSkinChange;
std::string m_skinReloadSettingIgnore;
bool m_saveSkinOnUnloading;
@@ -522,7 +522,9 @@ protected:
std::vector<IActionListener *> m_actionListeners;
bool m_fallbackLanguageLoaded;
-
+
+ std::vector<std::string> m_incompatibleAddons; /*!< Result of addon migration */
+
private:
CCriticalSection m_critSection; /*!< critical section for all changes to this class, except for changes to triggers */
diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp
index 6648fb8d64..0115337916 100644
--- a/xbmc/GUIInfoManager.cpp
+++ b/xbmc/GUIInfoManager.cpp
@@ -10561,11 +10561,7 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std::
break;
case LISTITEM_ADDON_BROKEN:
if (item->HasAddonInfo())
- {
- if (item->GetAddonInfo()->Broken() == "DEPSNOTMET")
- return g_localizeStrings.Get(24044);
return item->GetAddonInfo()->Broken();
- }
break;
case LISTITEM_ADDON_TYPE:
if (item->HasAddonInfo())
diff --git a/xbmc/NfoFile.cpp b/xbmc/NfoFile.cpp
index 02228e108e..2f871e778e 100644
--- a/xbmc/NfoFile.cpp
+++ b/xbmc/NfoFile.cpp
@@ -24,6 +24,7 @@
#include "NfoFile.h"
#include "video/VideoInfoDownloader.h"
#include "addons/AddonManager.h"
+#include "addons/AddonSystemSettings.h"
#include "filesystem/File.h"
#include "FileItem.h"
#include "music/Album.h"
@@ -46,7 +47,7 @@ CNfoFile::NFOResult CNfoFile::Create(const std::string& strPath, const ScraperPt
AddonPtr addon;
ScraperPtr defaultScraper;
- if (CAddonMgr::GetInstance().GetDefault(m_type, addon))
+ if (CAddonSystemSettings::GetInstance().GetActive(m_type, addon))
defaultScraper = std::dynamic_pointer_cast<CScraper>(addon);
if (m_type == ADDON_SCRAPER_ALBUMS)
diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp
index 618e7dc98b..9fb278691e 100644
--- a/xbmc/Util.cpp
+++ b/xbmc/Util.cpp
@@ -145,9 +145,12 @@ std::string GetHomePath(const std::string& strTarget, std::string strPath)
{
strPathW = buf.get();
CWIN32Util::RemoveExtraLongPathPrefix(strPathW);
- g_charsetConverter.wToUTF8(strPathW, strPath);
+
if (IsDirectoryValidRoot(strPathW))
+ {
+ g_charsetConverter.wToUTF8(strPathW, strPath);
return strPath;
+ }
}
}
}
@@ -172,16 +175,18 @@ std::string GetHomePath(const std::string& strTarget, std::string strPath)
auto bufSize = GetCurrentDirectoryW(0, nullptr);
if (bufSize > 0)
{
- auto buf = new wchar_t[bufSize];
- if (0 != GetCurrentDirectoryW(bufSize, buf))
+ auto buf = std::make_unique<wchar_t[]>(bufSize);
+ if (0 != GetCurrentDirectoryW(bufSize, buf.get()))
{
std::string currentDirectory;
- std::wstring currentDirectoryW(buf);
+ std::wstring currentDirectoryW(buf.get());
CWIN32Util::RemoveExtraLongPathPrefix(currentDirectoryW);
- g_charsetConverter.wToUTF8(currentDirectoryW, currentDirectory);
-
+
if (IsDirectoryValidRoot(currentDirectoryW))
+ {
+ g_charsetConverter.wToUTF8(currentDirectoryW, currentDirectory);
return currentDirectory;
+ }
}
}
diff --git a/xbmc/XBApplicationEx.cpp b/xbmc/XBApplicationEx.cpp
index f6fffd8f6e..473a973df0 100644
--- a/xbmc/XBApplicationEx.cpp
+++ b/xbmc/XBApplicationEx.cpp
@@ -50,24 +50,6 @@ CXBApplicationEx::~CXBApplicationEx()
{
}
-/* Create the app */
-bool CXBApplicationEx::Create()
-{
- // Variables to perform app timing
- m_bStop = false;
- m_AppFocused = true;
- m_ExitCode = EXITCODE_QUIT;
-
- // Initialize the app's device-dependent objects
- if (!Initialize())
- {
- CLog::Log(LOGERROR, "XBAppEx: Call to Initialize() failed!" );
- return false;
- }
-
- return true;
-}
-
/* Destroy the app */
VOID CXBApplicationEx::Destroy()
{
diff --git a/xbmc/XBApplicationEx.h b/xbmc/XBApplicationEx.h
index c46cba15b1..f8b8c6deb0 100644
--- a/xbmc/XBApplicationEx.h
+++ b/xbmc/XBApplicationEx.h
@@ -49,8 +49,6 @@ public:
virtual void SetRenderGUI(bool renderGUI) {};
public:
- // Functions to create, run, and clean up the application
- virtual bool Create();
INT Run();
VOID Destroy();
diff --git a/xbmc/addons/Addon.cpp b/xbmc/addons/Addon.cpp
index a2551d6ff5..476ab29741 100644
--- a/xbmc/addons/Addon.cpp
+++ b/xbmc/addons/Addon.cpp
@@ -348,8 +348,11 @@ void OnEnabled(const std::string& id)
CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_ADSPDLL))
return addon->OnEnabled();
- if (CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_SERVICE))
- std::static_pointer_cast<CService>(addon)->Start();
+ if (CAddonMgr::GetInstance().ServicesHasStarted())
+ {
+ if (CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_SERVICE))
+ std::static_pointer_cast<CService>(addon)->Start();
+ }
if (CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_REPOSITORY))
CRepositoryUpdater::GetInstance().ScheduleUpdate(); //notify updater there is a new addon
@@ -357,13 +360,17 @@ void OnEnabled(const std::string& id)
void OnDisabled(const std::string& id)
{
+
AddonPtr addon;
if (CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_PVRDLL, false) ||
CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_ADSPDLL, false))
return addon->OnDisabled();
- if (CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_SERVICE, false))
- std::static_pointer_cast<CService>(addon)->Stop();
+ if (CAddonMgr::GetInstance().ServicesHasStarted())
+ {
+ if (CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_SERVICE, false))
+ std::static_pointer_cast<CService>(addon)->Stop();
+ }
if (CAddonMgr::GetInstance().GetAddon(id, addon, ADDON_CONTEXT_ITEM, false))
CContextMenuManager::GetInstance().Unload(*std::static_pointer_cast<CContextMenuAddon>(addon));
@@ -374,8 +381,12 @@ void OnPreInstall(const AddonPtr& addon)
//Before installing we need to stop/unregister any local addon
//that have this id, regardless of what the 'new' addon is.
AddonPtr localAddon;
- if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_SERVICE))
- std::static_pointer_cast<CService>(localAddon)->Stop();
+
+ if (CAddonMgr::GetInstance().ServicesHasStarted())
+ {
+ if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_SERVICE))
+ std::static_pointer_cast<CService>(localAddon)->Stop();
+ }
if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_CONTEXT_ITEM))
CContextMenuManager::GetInstance().Unload(*std::static_pointer_cast<CContextMenuAddon>(localAddon));
@@ -388,8 +399,11 @@ void OnPreInstall(const AddonPtr& addon)
void OnPostInstall(const AddonPtr& addon, bool update, bool modal)
{
AddonPtr localAddon;
- if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_SERVICE))
- std::static_pointer_cast<CService>(localAddon)->Start();
+ if (CAddonMgr::GetInstance().ServicesHasStarted())
+ {
+ if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_SERVICE))
+ std::static_pointer_cast<CService>(localAddon)->Start();
+ }
if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_REPOSITORY))
CRepositoryUpdater::GetInstance().ScheduleUpdate(); //notify updater there is a new addon or version
@@ -400,8 +414,12 @@ void OnPostInstall(const AddonPtr& addon, bool update, bool modal)
void OnPreUnInstall(const AddonPtr& addon)
{
AddonPtr localAddon;
- if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_SERVICE))
- std::static_pointer_cast<CService>(localAddon)->Stop();
+
+ if (CAddonMgr::GetInstance().ServicesHasStarted())
+ {
+ if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_SERVICE))
+ std::static_pointer_cast<CService>(localAddon)->Stop();
+ }
if (CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon, ADDON_CONTEXT_ITEM))
CContextMenuManager::GetInstance().Unload(*std::static_pointer_cast<CContextMenuAddon>(localAddon));
diff --git a/xbmc/addons/AddonInstaller.cpp b/xbmc/addons/AddonInstaller.cpp
index 5fb65055a0..d252b94084 100644
--- a/xbmc/addons/AddonInstaller.cpp
+++ b/xbmc/addons/AddonInstaller.cpp
@@ -63,7 +63,7 @@ struct find_map : public std::binary_function<CAddonInstaller::JobMap::value_typ
}
};
-CAddonInstaller::CAddonInstaller()
+CAddonInstaller::CAddonInstaller() : m_idle(true)
{ }
CAddonInstaller::~CAddonInstaller()
@@ -81,6 +81,8 @@ void CAddonInstaller::OnJobComplete(unsigned int jobID, bool success, CJob* job)
JobMap::iterator i = find_if(m_downloadJobs.begin(), m_downloadJobs.end(), bind2nd(find_map(), jobID));
if (i != m_downloadJobs.end())
m_downloadJobs.erase(i);
+ if (m_downloadJobs.empty())
+ m_idle.Set();
lock.Leave();
PrunePackageCache();
@@ -150,6 +152,8 @@ bool CAddonInstaller::Cancel(const std::string &addonID)
{
CJobManager::GetInstance().CancelJob(i->second.jobID);
m_downloadJobs.erase(i);
+ if (m_downloadJobs.empty())
+ m_idle.Set();
return true;
}
@@ -188,6 +192,7 @@ bool CAddonInstaller::InstallModal(const std::string &addonID, ADDON::AddonPtr &
return CAddonMgr::GetInstance().GetAddon(addonID, addon);
}
+
bool CAddonInstaller::InstallOrUpdate(const std::string &addonID, bool background /* = true */, bool modal /* = false */)
{
AddonPtr addon;
@@ -239,10 +244,12 @@ bool CAddonInstaller::DoInstall(const AddonPtr &addon, const RepositoryPtr& repo
{
unsigned int jobID = CJobManager::GetInstance().AddJob(installJob, this);
m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(jobID)));
+ m_idle.Reset();
return true;
}
m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(0)));
+ m_idle.Reset();
lock.Leave();
bool result = false;
@@ -255,6 +262,8 @@ bool CAddonInstaller::DoInstall(const AddonPtr &addon, const RepositoryPtr& repo
lock.Enter();
JobMap::iterator i = m_downloadJobs.find(addon->ID());
m_downloadJobs.erase(i);
+ if (m_downloadJobs.empty())
+ m_idle.Set();
return result;
}
@@ -345,10 +354,10 @@ bool CAddonInstaller::CheckDependencies(const AddonPtr &addon,
//! @todo should we assume that installed deps are OK?
if (dep && std::find(preDeps.begin(), preDeps.end(), dep->ID()) == preDeps.end())
{
+ preDeps.push_back(dep->ID());
if (!CheckDependencies(dep, preDeps, database, failedDep))
{
database.Close();
- preDeps.push_back(dep->ID());
return false;
}
}
@@ -418,13 +427,22 @@ void CAddonInstaller::PrunePackageCache()
delete it->second;
}
-void CAddonInstaller::InstallUpdates(bool includeBlacklisted /* = false */)
+void CAddonInstaller::InstallUpdates()
{
- for (const auto& addon : CAddonMgr::GetInstance().GetAvailableUpdates())
+ auto updates = CAddonMgr::GetInstance().GetAvailableUpdates();
+ for (const auto& addon : updates)
{
- if (includeBlacklisted || !CAddonMgr::GetInstance().IsBlacklisted(addon->ID()))
+ if (!CAddonMgr::GetInstance().IsBlacklisted(addon->ID()))
CAddonInstaller::GetInstance().InstallOrUpdate(addon->ID());
}
+
+ CSingleLock lock(m_critSection);
+ if (!m_downloadJobs.empty())
+ {
+ m_idle.Reset();
+ lock.Leave();
+ m_idle.Wait();
+ }
}
bool CAddonInstaller::GetRepoForAddon(const std::string& addonId, RepositoryPtr& repoPtr)
diff --git a/xbmc/addons/AddonInstaller.h b/xbmc/addons/AddonInstaller.h
index 02c71855d4..61d13ffea1 100644
--- a/xbmc/addons/AddonInstaller.h
+++ b/xbmc/addons/AddonInstaller.h
@@ -94,7 +94,8 @@ public:
*/
bool HasJob(const std::string& ID) const;
- void InstallUpdates(bool includeBlacklisted = false);
+ /*! Install update and block until all updates have installed. */
+ void InstallUpdates();
void OnJobComplete(unsigned int jobID, bool success, CJob* job);
void OnJobProgress(unsigned int jobID, unsigned int progress, unsigned int total, const CJob *job);
@@ -152,6 +153,7 @@ private:
CCriticalSection m_critSection;
JobMap m_downloadJobs;
+ CEvent m_idle;
};
class CAddonInstallJob : public CFileOperationJob
diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp
index 9a4225c050..8dec0bbd38 100644
--- a/xbmc/addons/AddonManager.cpp
+++ b/xbmc/addons/AddonManager.cpp
@@ -257,7 +257,8 @@ static bool LoadManifest(std::set<std::string>& system, std::set<std::string>& o
CAddonMgr::CAddonMgr()
: m_cp_context(nullptr),
- m_cpluff(nullptr)
+ m_cpluff(nullptr),
+ m_serviceSystemStarted(false)
{ }
CAddonMgr::~CAddonMgr()
@@ -610,89 +611,6 @@ bool CAddonMgr::GetAddon(const std::string &str, AddonPtr &addon, const TYPE &ty
return false;
}
-//! @todo handle all 'default' cases here, not just scrapers & vizs
-bool CAddonMgr::GetDefault(const TYPE &type, AddonPtr &addon)
-{
- std::string setting;
- switch (type)
- {
- case ADDON_VIZ:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_MUSICPLAYER_VISUALISATION);
- break;
- case ADDON_SCREENSAVER:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_SCREENSAVER_MODE);
- break;
- case ADDON_SCRAPER_ALBUMS:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_MUSICLIBRARY_ALBUMSSCRAPER);
- break;
- case ADDON_SCRAPER_ARTISTS:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_MUSICLIBRARY_ARTISTSSCRAPER);
- break;
- case ADDON_SCRAPER_MOVIES:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_SCRAPERS_MOVIESDEFAULT);
- break;
- case ADDON_SCRAPER_MUSICVIDEOS:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_SCRAPERS_MUSICVIDEOSDEFAULT);
- break;
- case ADDON_SCRAPER_TVSHOWS:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_SCRAPERS_TVSHOWSDEFAULT);
- break;
- case ADDON_WEB_INTERFACE:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_SERVICES_WEBSKIN);
- break;
- case ADDON_RESOURCE_LANGUAGE:
- setting = CSettings::GetInstance().GetString(CSettings::SETTING_LOCALE_LANGUAGE);
- break;
- default:
- return false;
- }
- return GetAddon(setting, addon, type);
-}
-
-bool CAddonMgr::SetDefault(const TYPE &type, const std::string &addonID)
-{
- switch (type)
- {
- case ADDON_VIZ:
- CSettings::GetInstance().SetString(CSettings::SETTING_MUSICPLAYER_VISUALISATION, addonID);
- break;
- case ADDON_SCREENSAVER:
- CSettings::GetInstance().SetString(CSettings::SETTING_SCREENSAVER_MODE, addonID);
- break;
- case ADDON_SCRAPER_ALBUMS:
- CSettings::GetInstance().SetString(CSettings::SETTING_MUSICLIBRARY_ALBUMSSCRAPER, addonID);
- break;
- case ADDON_SCRAPER_ARTISTS:
- CSettings::GetInstance().SetString(CSettings::SETTING_MUSICLIBRARY_ARTISTSSCRAPER, addonID);
- break;
- case ADDON_SCRAPER_MOVIES:
- CSettings::GetInstance().SetString(CSettings::SETTING_SCRAPERS_MOVIESDEFAULT, addonID);
- break;
- case ADDON_SCRAPER_MUSICVIDEOS:
- CSettings::GetInstance().SetString(CSettings::SETTING_SCRAPERS_MUSICVIDEOSDEFAULT, addonID);
- break;
- case ADDON_SCRAPER_TVSHOWS:
- CSettings::GetInstance().SetString(CSettings::SETTING_SCRAPERS_TVSHOWSDEFAULT, addonID);
- break;
- case ADDON_RESOURCE_LANGUAGE:
- CSettings::GetInstance().SetString(CSettings::SETTING_LOCALE_LANGUAGE, addonID);
- break;
- case ADDON_SCRIPT_WEATHER:
- CSettings::GetInstance().SetString(CSettings::SETTING_WEATHER_ADDON, addonID);
- break;
- case ADDON_SKIN:
- CSettings::GetInstance().SetString(CSettings::SETTING_LOOKANDFEEL_SKIN, addonID);
- break;
- case ADDON_RESOURCE_UISOUNDS:
- CSettings::GetInstance().SetString(CSettings::SETTING_LOOKANDFEEL_SOUNDSKIN, addonID);
- break;
- default:
- return false;
- }
-
- return true;
-}
-
bool CAddonMgr::FindAddons()
{
bool result = false;
@@ -1204,6 +1122,11 @@ bool CAddonMgr::AddonsFromRepoXML(const CRepository::DirInfo& repo, const std::s
return true;
}
+bool CAddonMgr::ServicesHasStarted() const
+{
+ CSingleLock lock(m_critSection);
+ return m_serviceSystemStarted;
+}
bool CAddonMgr::StartServices(const bool beforelogin)
{
@@ -1225,6 +1148,9 @@ bool CAddonMgr::StartServices(const bool beforelogin)
}
}
+ CSingleLock lock(m_critSection);
+ m_serviceSystemStarted = true;
+
return ret;
}
@@ -1248,6 +1174,31 @@ void CAddonMgr::StopServices(const bool onlylogin)
}
}
+bool CAddonMgr::IsCompatible(const IAddon& addon)
+{
+ for (const auto& dependencyInfo : addon.GetDeps())
+ {
+ const auto& optional = dependencyInfo.second.second;
+ if (!optional)
+ {
+ const auto& dependencyId = dependencyInfo.first;
+ const auto& version = dependencyInfo.second.first;
+
+ // Intentionally only check the xbmc.* and kodi.* magic dependencies. Everything else will
+ // not be missing anyway, unless addon was installed in an unsupported way.
+ if (StringUtils::StartsWith(dependencyId, "xbmc.") ||
+ StringUtils::StartsWith(dependencyId, "kodi."))
+ {
+ AddonPtr dependency;
+ bool haveAddon = GetAddon(dependencyId, dependency);
+ if (!haveAddon || !dependency->MeetsVersion(version))
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
int cp_to_clog(cp_log_severity_t lvl)
{
if (lvl >= CP_LOG_ERROR)
diff --git a/xbmc/addons/AddonManager.h b/xbmc/addons/AddonManager.h
index 7a2835cc56..3eb857631f 100644
--- a/xbmc/addons/AddonManager.h
+++ b/xbmc/addons/AddonManager.h
@@ -83,9 +83,6 @@ namespace ADDON
bool RegisterAddonMgrCallback(TYPE type, IAddonMgrCallback* cb);
void UnregisterAddonMgrCallback(TYPE type);
- /* Addon access */
- bool GetDefault(const TYPE &type, AddonPtr &addon);
- bool SetDefault(const TYPE &type, const std::string &addonID);
/*! \brief Retrieve a specific addon (of a specific type)
\param id the id of the addon to retrieve.
\param addon [out] the retrieved addon pointer - only use if the function returns true.
@@ -245,6 +242,10 @@ namespace ADDON
*/
void StopServices(const bool onlylogin);
+ bool ServicesHasStarted() const;
+
+ bool IsCompatible(const IAddon& addon);
+
static AddonPtr Factory(const cp_plugin_info_t* plugin, TYPE type);
static bool Factory(const cp_plugin_info_t* plugin, TYPE type, CAddonBuilder& builder);
static void FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder& builder);
@@ -273,6 +274,7 @@ namespace ADDON
CEventSource<AddonEvent> m_events;
std::set<std::string> m_systemAddons;
std::set<std::string> m_optionalAddons;
+ bool m_serviceSystemStarted;
};
}; /* namespace ADDON */
diff --git a/xbmc/addons/AddonSystemSettings.cpp b/xbmc/addons/AddonSystemSettings.cpp
index a8dc72d9fe..fccc680bd1 100644
--- a/xbmc/addons/AddonSystemSettings.cpp
+++ b/xbmc/addons/AddonSystemSettings.cpp
@@ -19,11 +19,13 @@
*/
#include "addons/AddonManager.h"
+#include "addons/AddonInstaller.h"
#include "addons/AddonSystemSettings.h"
#include "addons/RepositoryUpdater.h"
#include "guilib/GUIWindowManager.h"
#include "messaging/helpers/DialogHelper.h"
#include "settings/Settings.h"
+#include "utils/log.h"
namespace ADDON
@@ -61,4 +63,108 @@ void CAddonSystemSettings::OnSettingChanged(const CSetting* setting)
}
}
+static const std::map<ADDON::TYPE, std::string> settingMap = {
+ {ADDON_VIZ, CSettings::SETTING_MUSICPLAYER_VISUALISATION},
+ {ADDON_SCREENSAVER, CSettings::SETTING_SCREENSAVER_MODE},
+ {ADDON_SCRAPER_ALBUMS, CSettings::SETTING_MUSICLIBRARY_ALBUMSSCRAPER},
+ {ADDON_SCRAPER_ARTISTS, CSettings::SETTING_MUSICLIBRARY_ARTISTSSCRAPER},
+ {ADDON_SCRAPER_MOVIES, CSettings::SETTING_SCRAPERS_MOVIESDEFAULT},
+ {ADDON_SCRAPER_MUSICVIDEOS, CSettings::SETTING_SCRAPERS_MUSICVIDEOSDEFAULT},
+ {ADDON_SCRAPER_TVSHOWS, CSettings::SETTING_SCRAPERS_TVSHOWSDEFAULT},
+ {ADDON_WEB_INTERFACE, CSettings::SETTING_SERVICES_WEBSKIN},
+ {ADDON_RESOURCE_LANGUAGE, CSettings::SETTING_LOCALE_LANGUAGE},
+ {ADDON_SCRIPT_WEATHER, CSettings::SETTING_WEATHER_ADDON},
+ {ADDON_SKIN, CSettings::SETTING_LOOKANDFEEL_SKIN},
+ {ADDON_RESOURCE_UISOUNDS, CSettings::SETTING_LOOKANDFEEL_SOUNDSKIN},
+};
+
+bool CAddonSystemSettings::GetActive(const TYPE& type, AddonPtr& addon)
+{
+ auto it = settingMap.find(type);
+ if (it != settingMap.end())
+ {
+ auto settingValue = CSettings::GetInstance().GetString(it->second);
+ return CAddonMgr::GetInstance().GetAddon(settingValue, addon, type);
+ }
+ return false;
+}
+
+bool CAddonSystemSettings::SetActive(const TYPE& type, const std::string& addonID)
+{
+ auto it = settingMap.find(type);
+ if (it != settingMap.end())
+ {
+ CSettings::GetInstance().SetString(it->second, addonID);
+ return true;
+ }
+ return false;
+}
+
+bool CAddonSystemSettings::IsActive(const IAddon& addon)
+{
+ AddonPtr active;
+ return GetActive(addon.Type(), active) && active->ID() == addon.ID();
+}
+
+bool CAddonSystemSettings::UnsetActive(const AddonPtr& addon)
+{
+ auto it = settingMap.find(addon->Type());
+ if (it == settingMap.end())
+ return true;
+
+ auto setting = static_cast<CSettingString*>(CSettings::GetInstance().GetSetting(it->second));
+ if (setting->GetValue() != addon->ID())
+ return true;
+
+ if (setting->GetDefault() == addon->ID())
+ return false; // Cant unset defaults
+
+ setting->Reset();
+ return true;
+}
+
+
+std::vector<std::string> CAddonSystemSettings::MigrateAddons()
+{
+ auto getIncompatible = [](){
+ VECADDONS incompatible;
+ CAddonMgr::GetInstance().GetAddons(incompatible);
+ incompatible.erase(std::remove_if(incompatible.begin(), incompatible.end(),
+ [](const AddonPtr a){ return CAddonMgr::GetInstance().IsCompatible(*a); }), incompatible.end());
+ return incompatible;
+ };
+
+ if (getIncompatible().empty())
+ return std::vector<std::string>();
+
+ if (CSettings::GetInstance().GetInt(CSettings::SETTING_ADDONS_AUTOUPDATES) == AUTO_UPDATES_ON)
+ {
+ if (CRepositoryUpdater::GetInstance().CheckForUpdates())
+ CRepositoryUpdater::GetInstance().Await();
+
+ CLog::Log(LOGINFO, "ADDON: waiting for add-ons to update...");
+ CAddonInstaller::GetInstance().InstallUpdates();
+ }
+
+ auto incompatible = getIncompatible();
+ for (const auto& addon : incompatible)
+ CLog::Log(LOGNOTICE, "ADDON: %s version %s is incompatible", addon->ID().c_str(), addon->Version().asString().c_str());
+
+ std::vector<std::string> changed;
+ for (const auto& addon : incompatible)
+ {
+ if (!UnsetActive(addon))
+ {
+ CLog::Log(LOGWARNING, "ADDON: failed to unset %s", addon->ID().c_str());
+ continue;
+ }
+ if (!CAddonMgr::GetInstance().DisableAddon(addon->ID()))
+ {
+ CLog::Log(LOGWARNING, "ADDON: failed to disable %s", addon->ID().c_str());
+ }
+ changed.push_back(addon->Name());
+ }
+
+ return changed;
+}
}
diff --git a/xbmc/addons/AddonSystemSettings.h b/xbmc/addons/AddonSystemSettings.h
index af67d8c36f..42a5345aad 100644
--- a/xbmc/addons/AddonSystemSettings.h
+++ b/xbmc/addons/AddonSystemSettings.h
@@ -19,8 +19,9 @@
*
*/
+#include "addons/IAddon.h"
#include "settings/lib/ISettingCallback.h"
-
+#include <string>
namespace ADDON
{
@@ -36,6 +37,21 @@ public:
void OnSettingAction(const CSetting* setting) override;
void OnSettingChanged(const CSetting* setting) override;
+ bool GetActive(const TYPE& type, AddonPtr& addon);
+ bool SetActive(const TYPE& type, const std::string& addonID);
+ bool IsActive(const IAddon& addon);
+
+ /*!
+ * Attempt to unset addon as active. Returns true if addon is no longer active,
+ * false if it could not be unset (e.g. if the addon is the default)
+ */
+ bool UnsetActive(const AddonPtr& addon);
+
+ /*!
+ * Attempt to migrate installed addons. Returns a list of addons that was modified.
+ */
+ std::vector<std::string> MigrateAddons();
+
private:
CAddonSystemSettings() = default;
CAddonSystemSettings(const CAddonSystemSettings&) = default;
diff --git a/xbmc/addons/GUIDialogAddonInfo.cpp b/xbmc/addons/GUIDialogAddonInfo.cpp
index 81f1104a06..167bcf9a2a 100644
--- a/xbmc/addons/GUIDialogAddonInfo.cpp
+++ b/xbmc/addons/GUIDialogAddonInfo.cpp
@@ -367,7 +367,7 @@ void CGUIDialogAddonInfo::OnSelect()
if (CanOpen() || CanRun())
CBuiltins::GetInstance().Execute("RunAddon(" + m_localAddon->ID() + ")");
else if (CanUse())
- CAddonMgr::GetInstance().SetDefault(m_localAddon->Type(), m_localAddon->ID());
+ CAddonSystemSettings::GetInstance().SetActive(m_localAddon->Type(), m_localAddon->ID());
}
bool CGUIDialogAddonInfo::CanOpen() const
diff --git a/xbmc/addons/GUIWindowAddonBrowser.cpp b/xbmc/addons/GUIWindowAddonBrowser.cpp
index b2909d766a..68cb844cf9 100644
--- a/xbmc/addons/GUIWindowAddonBrowser.cpp
+++ b/xbmc/addons/GUIWindowAddonBrowser.cpp
@@ -165,7 +165,8 @@ class UpdateAddons : public IRunnable
{
virtual void Run()
{
- CAddonInstaller::GetInstance().InstallUpdates(true);
+ for (const auto& addon : CAddonMgr::GetInstance().GetAvailableUpdates())
+ CAddonInstaller::GetInstance().InstallOrUpdate(addon->ID());
}
};
diff --git a/xbmc/addons/Repository.cpp b/xbmc/addons/Repository.cpp
index cb6bc19738..e64a3665c1 100644
--- a/xbmc/addons/Repository.cpp
+++ b/xbmc/addons/Repository.cpp
@@ -258,57 +258,47 @@ bool CRepositoryUpdateJob::DoWork()
database.UpdateRepositoryContent(m_repo->ID(), m_repo->Version(), newChecksum, addons);
- //Update broken status
- database.BeginMultipleExecute();
+ //Notify about broken status changes
for (const auto& addon : addons)
{
AddonPtr localAddon;
- CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon);
+ if (!CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon))
+ continue;
if (localAddon && localAddon->Version() > addon->Version())
- //We have a newer verison locally
+ //We have a newer version locally
continue;
+ AddonPtr oldAddon;
+ database.GetAddon(addon->ID(), oldAddon);
+
if (database.GetAddonVersion(addon->ID()).first > addon->Version())
//Newer version in db (ie. in a different repo)
continue;
std::string broken = addon->Broken();
- bool depsMet = CAddonInstaller::GetInstance().CheckDependencies(addon);
- if (!depsMet && broken.empty())
- broken = "DEPSNOTMET";
-
- if (localAddon)
+ bool isBroken = !addon->Broken().empty();
+ bool isBrokenInDb = oldAddon && !oldAddon->Broken().empty();
+ if (isBroken && !isBrokenInDb)
{
- bool brokenInDb = database.IsAddonBroken(addon->ID());
- if (!broken.empty() && !brokenInDb)
- {
- //newly broken
- int line = 24096;
- if (broken == "DEPSNOTMET")
- line = 24104;
- if (HELPERS::ShowYesNoDialogLines(CVariant{addon->Name()}, CVariant{line}, CVariant{24097}, CVariant{""})
- == DialogResponse::YES)
- {
- CAddonMgr::GetInstance().DisableAddon(addon->ID());
- }
-
- CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' marked broken. reason: \"%s\"",
- m_repo->ID().c_str(), addon->ID().c_str(), broken.c_str());
-
- CEventLog::GetInstance().Add(EventPtr(new CAddonManagementEvent(addon, 24096)));
- }
- else if (broken.empty() && brokenInDb)
+ //newly broken
+ if (HELPERS::ShowYesNoDialogLines(CVariant{addon->Name()}, CVariant{24096}, CVariant{24097}, CVariant{""})
+ == DialogResponse::YES)
{
- //Unbroken
- CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' unbroken",
- m_repo->ID().c_str(), addon->ID().c_str());
+ CAddonMgr::GetInstance().DisableAddon(addon->ID());
}
- }
- //Update broken status
- database.BreakAddon(addon->ID(), broken);
+ CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' marked broken. reason: \"%s\"",
+ m_repo->ID().c_str(), addon->ID().c_str(), broken.c_str());
+
+ CEventLog::GetInstance().Add(EventPtr(new CAddonManagementEvent(addon, 24096)));
+ }
+ else if (!isBroken && isBrokenInDb)
+ {
+ //Unbroken
+ CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' unbroken",
+ m_repo->ID().c_str(), addon->ID().c_str());
+ }
}
- database.CommitMultipleExecute();
return true;
}
diff --git a/xbmc/addons/RepositoryUpdater.cpp b/xbmc/addons/RepositoryUpdater.cpp
index 41bc15c496..357f4f8af0 100644
--- a/xbmc/addons/RepositoryUpdater.cpp
+++ b/xbmc/addons/RepositoryUpdater.cpp
@@ -64,9 +64,10 @@ void CRepositoryUpdater::OnJobComplete(unsigned int jobID, bool success, CJob* j
CLog::Log(LOGDEBUG, "CRepositoryUpdater: done.");
m_doneEvent.Set();
+ VECADDONS updates = CAddonMgr::GetInstance().GetAvailableUpdates();
+
if (CSettings::GetInstance().GetInt(CSettings::SETTING_ADDONS_AUTOUPDATES) == AUTO_UPDATES_NOTIFY)
{
- VECADDONS updates = CAddonMgr::GetInstance().GetAvailableUpdates();
if (!updates.empty())
{
if (updates.size() == 1)
@@ -84,7 +85,13 @@ void CRepositoryUpdater::OnJobComplete(unsigned int jobID, bool success, CJob* j
}
if (CSettings::GetInstance().GetInt(CSettings::SETTING_ADDONS_AUTOUPDATES) == AUTO_UPDATES_ON)
- CAddonInstaller::GetInstance().InstallUpdates();
+ {
+ for (const auto& addon : updates)
+ {
+ if (!CAddonMgr::GetInstance().IsBlacklisted(addon->ID()))
+ CAddonInstaller::GetInstance().InstallOrUpdate(addon->ID());
+ }
+ }
ScheduleUpdate();
diff --git a/xbmc/addons/Skin.cpp b/xbmc/addons/Skin.cpp
index fa20233d42..f5b5f1f67b 100644
--- a/xbmc/addons/Skin.cpp
+++ b/xbmc/addons/Skin.cpp
@@ -369,12 +369,13 @@ const INFO::CSkinVariableString* CSkinInfo::CreateSkinVariable(const std::string
void CSkinInfo::OnPreInstall()
{
- if (IsInUse())
- CApplicationMessenger::GetInstance().SendMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, "UnloadSkin");
}
void CSkinInfo::OnPostInstall(bool update, bool modal)
{
+ if (!g_SkinInfo)
+ return;
+
if (IsInUse() || (!update && !modal &&
HELPERS::ShowYesNoDialogText(CVariant{Name()}, CVariant{24099}) == DialogResponse::YES))
{
@@ -385,7 +386,7 @@ void CSkinInfo::OnPostInstall(bool update, bool modal)
toast->Close(true);
}
if (CSettings::GetInstance().GetString(CSettings::SETTING_LOOKANDFEEL_SKIN) == ID())
- CApplicationMessenger::GetInstance().SendMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, "ReloadSkin");
+ CApplicationMessenger::GetInstance().PostMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, "ReloadSkin");
else
CSettings::GetInstance().SetString(CSettings::SETTING_LOOKANDFEEL_SKIN, ID());
}
@@ -393,6 +394,9 @@ void CSkinInfo::OnPostInstall(bool update, bool modal)
void CSkinInfo::SettingOptionsSkinColorsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, void *data)
{
+ if (!g_SkinInfo)
+ return;
+
std::string settingValue = ((const CSettingString*)setting)->GetValue();
// Remove the .xml extension from the Themes
if (URIUtils::HasExtension(settingValue, ".xml"))
@@ -434,6 +438,9 @@ void CSkinInfo::SettingOptionsSkinColorsFiller(const CSetting *setting, std::vec
void CSkinInfo::SettingOptionsSkinFontsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, void *data)
{
+ if (!g_SkinInfo)
+ return;
+
std::string settingValue = ((const CSettingString*)setting)->GetValue();
bool currentValueSet = false;
std::string strPath = g_SkinInfo->GetSkinPath("Font.xml");
@@ -512,6 +519,9 @@ void CSkinInfo::SettingOptionsSkinThemesFiller(const CSetting *setting, std::vec
void CSkinInfo::SettingOptionsStartupWindowsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
{
+ if (!g_SkinInfo)
+ return;
+
int settingValue = ((const CSettingInt *)setting)->GetValue();
current = -1;
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
index c6a7f569a8..af5bf93116 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
@@ -33,7 +33,7 @@ using namespace ActiveAE;
CActiveAEResampleFFMPEG::CActiveAEResampleFFMPEG()
{
m_pContext = NULL;
- m_loaded = true;
+ m_doesResample = false;
}
CActiveAEResampleFFMPEG::~CActiveAEResampleFFMPEG()
@@ -43,9 +43,6 @@ CActiveAEResampleFFMPEG::~CActiveAEResampleFFMPEG()
bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality, bool force_resample)
{
- if (!m_loaded)
- return false;
-
m_dst_chan_layout = dst_chan_layout;
m_dst_channels = dst_channels;
m_dst_rate = dst_rate;
@@ -59,6 +56,9 @@ bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, i
m_src_bits = src_bits;
m_src_dither_bits = src_dither;
+ if (m_src_rate != m_dst_rate)
+ m_doesResample = true;
+
if (m_dst_chan_layout == 0)
m_dst_chan_layout = av_get_default_channel_layout(m_dst_channels);
if (m_src_chan_layout == 0)
@@ -186,12 +186,16 @@ int CActiveAEResampleFFMPEG::Resample(uint8_t **dst_buffer, int dst_samples, uin
{
delta = (dst_samples*ratio-dst_samples)*m_dst_rate/m_src_rate;
distance = dst_samples*m_dst_rate/m_src_rate;
+ m_doesResample = true;
}
- if (swr_set_compensation(m_pContext, delta, distance) < 0)
+ if (m_doesResample)
{
- CLog::Log(LOGERROR, "CActiveAEResampleFFMPEG::Resample - set compensation failed");
- return -1;
+ if (swr_set_compensation(m_pContext, delta, distance) < 0)
+ {
+ CLog::Log(LOGERROR, "CActiveAEResampleFFMPEG::Resample - set compensation failed");
+ return -1;
+ }
}
int ret = swr_convert(m_pContext, dst_buffer, dst_samples, (const uint8_t**)src_buffer, src_samples);
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h
index 372c8eed8a..fa65c7789c 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h
@@ -50,6 +50,7 @@ public:
protected:
bool m_loaded;
+ bool m_doesResample;
uint64_t m_src_chan_layout, m_dst_chan_layout;
int m_src_rate, m_dst_rate;
int m_src_channels, m_dst_channels;
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
index b54a85a0ba..dbba74277a 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
@@ -69,10 +69,10 @@ static const enum AEChannel layoutsList[][16] =
{AE_CH_FL, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, // Quad
{AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BC, AE_CH_NULL}, // Surround
{AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_SL, AE_CH_SR, AE_CH_NULL}, // Standard 5.1
+ {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, // 5.1 wide (obsolete)
{AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_SL, AE_CH_SR, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, // Standard 7.1
/* Less common configurations */
{AE_CH_FL, AE_CH_FR, AE_CH_LFE, AE_CH_NULL}, // 2.1
- {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, // 5.1 wide (obsolete)
{AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BL, AE_CH_BR, AE_CH_FLOC,AE_CH_FROC,AE_CH_NULL}, // 7.1 wide (obsolete)
/* Exotic configurations */
{AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_NULL}, // 3 front speakers
diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h
index 90073afa4a..7bc005bce2 100644
--- a/xbmc/cores/IPlayer.h
+++ b/xbmc/cores/IPlayer.h
@@ -224,7 +224,9 @@ enum ViewMode {
ViewModeStretch16x9,
ViewModeOriginal,
ViewModeCustom,
- ViewModeStretch16x9Nonlin
+ ViewModeStretch16x9Nonlin,
+ ViewModeZoom120Width,
+ ViewModeZoom110Width
};
class IPlayer
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp
index 5dadf82c2a..f9b4138162 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp
@@ -1599,7 +1599,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
am_private->gcodec.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE);
break;
}
- am_private->gcodec.param = (void *)((unsigned int)am_private->gcodec.param | (am_private->video_rotation_degree << 16));
+ am_private->gcodec.param = (void *)((std::uintptr_t)am_private->gcodec.param | (am_private->video_rotation_degree << 16));
// translate from generic to firemware version dependent
m_dll->codec_init_para(&am_private->gcodec, &am_private->vcodec);
diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
index 23bcb080fa..8460e27865 100644
--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
@@ -646,7 +646,8 @@ AVDictionary *CDVDDemuxFFmpeg::GetFFMpegOptionsFromInput()
bool hasCookies = false;
for(std::map<std::string, std::string>::const_iterator it = protocolOptions.begin(); it != protocolOptions.end(); ++it)
{
- std::string name = it->first; StringUtils::ToLower(name);
+ std::string name = it->first;
+ StringUtils::ToLower(name);
const std::string &value = it->second;
if (name == "seekable")
@@ -660,24 +661,30 @@ AVDictionary *CDVDDemuxFFmpeg::GetFFMpegOptionsFromInput()
}
else if (name == "cookie")
{
- av_dict_set(&options, "cookies", value.c_str(), 0);
CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::GetFFMpegOptionsFromInput() adding ffmpeg option 'cookies: %s'", value.c_str());
+ headers.append(it->first).append(": ").append(value).append("\r\n");
hasCookies = true;
}
// other standard headers (see https://en.wikipedia.org/wiki/List_of_HTTP_header_fields) are appended as actual headers
else if (name == "accept" || name == "accept-language" || name == "accept-datetime" ||
- name == "authorization" || name == "cache-control" || name == "connection" || name == "content-md5" ||
- name == "date" || name == "expect" || name == "forwarded" || name == "from" || name == "if-match" ||
- name == "if-modified-since" || name == "if-none-match" || name == "if-range" || name == "if-unmodified-since" || name == "max-forwards" ||
- name == "origin" || name == "pragma" || name == "range" || name == "referer" || name == "te" || name == "upgrade" ||
- name == "via" || name == "warning" || name == "x-requested-with" || name == "dnt" || name == "x-forwarded-for" || name == "x-forwarded-host" ||
- name == "x-forwarded-proto" || name == "front-end-https" || name == "x-http-method-override" || name == "x-att-deviceid" ||
- name == "x-wap-profile" || name == "x-uidh" || name == "x-csrf-token" || name == "x-request-id" || name == "x-correlation-id")
+ name == "authorization" || name == "cache-control" || name == "connection" || name == "content-md5" ||
+ name == "date" || name == "expect" || name == "forwarded" || name == "from" || name == "if-match" ||
+ name == "if-modified-since" || name == "if-none-match" || name == "if-range" || name == "if-unmodified-since" ||
+ name == "max-forwards" || name == "origin" || name == "pragma" || name == "range" || name == "referer" ||
+ name == "te" || name == "upgrade" || name == "via" || name == "warning" || name == "x-requested-with" ||
+ name == "dnt" || name == "x-forwarded-for" || name == "x-forwarded-host" || name == "x-forwarded-proto" ||
+ name == "front-end-https" || name == "x-http-method-override" || name == "x-att-deviceid" ||
+ name == "x-wap-profile" || name == "x-uidh" || name == "x-csrf-token" || name == "x-request-id" ||
+ name == "x-correlation-id")
{
if (name == "authorization")
+ {
CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::GetFFMpegOptionsFromInput() adding custom header option '%s: ***********'", it->first.c_str());
+ }
else
+ {
CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::GetFFMpegOptionsFromInput() adding custom header option '%s: %s'", it->first.c_str(), value.c_str());
+ }
headers.append(it->first).append(": ").append(value).append("\r\n");
}
// we don't add blindly all options to headers anymore
@@ -689,8 +696,10 @@ AVDictionary *CDVDDemuxFFmpeg::GetFFMpegOptionsFromInput()
}
}
if (!hasUserAgent)
+ {
// set default xbmc user-agent.
av_dict_set(&options, "user-agent", g_advancedSettings.m_userAgent.c_str(), 0);
+ }
if (!headers.empty())
av_dict_set(&options, "headers", headers.c_str(), 0);
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
index 276a65fd7b..ba1bc8fcd0 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
@@ -145,15 +145,18 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer
{
if (finalFileitem.ContentLookup())
{
- XFILE::CCurlFile url;
+ CURL origUrl(finalFileitem.GetURL());
+ XFILE::CCurlFile curlFile;
// try opening the url to resolve all redirects if any
try
{
- if (url.Open(finalFileitem.GetURL()))
+ if (curlFile.Open(finalFileitem.GetURL()))
{
- finalFileitem.SetPath(url.GetURL());
+ CURL finalUrl(curlFile.GetURL());
+ finalUrl.SetProtocolOptions(origUrl.GetProtocolOptions());
+ finalFileitem.SetPath(finalUrl.Get());
}
- url.Close();
+ curlFile.Close();
}
catch (XFILE::CRedirectException *pRedirectEx)
{
diff --git a/xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp b/xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp
index 52c6799b5e..dd5082e964 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp
@@ -1730,9 +1730,6 @@ unsigned int CDVDRadioRDSData::DecodeTDC(uint8_t *msgElement, unsigned int len)
void CDVDRadioRDSData::SendTMCSignal(unsigned int flags, uint8_t *data)
{
- if (!CSettings::GetInstance().GetBool("pvrplayback.sendrdstrafficmsg"))
- return;
-
if (!(flags & 0x80) && (memcmp(data, m_TMC_LastData, 5) == 0))
return;
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp
index f18c671d90..f9b3bfb4eb 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp
@@ -428,7 +428,7 @@ void CBaseRenderer::ManageRenderArea()
void CBaseRenderer::SetViewMode(int viewMode)
{
- if (viewMode < ViewModeNormal || viewMode > ViewModeStretch16x9Nonlin)
+ if (viewMode < ViewModeNormal || viewMode > ViewModeZoom110Width)
viewMode = ViewModeNormal;
CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode = viewMode;
@@ -537,6 +537,18 @@ void CBaseRenderer::SetViewMode(int viewMode)
CDisplaySettings::GetInstance().SetNonLinearStretched(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_CustomNonLinStretch);
CDisplaySettings::GetInstance().SetVerticalShift(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_CustomVerticalShift);
}
+ else if (CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode == ViewModeZoom120Width)
+ {
+ float fitHeightZoom = sourceFrameRatio * screenHeight / (info.fPixelRatio * screenWidth);
+ CDisplaySettings::GetInstance().SetPixelRatio(1.0f);
+ CDisplaySettings::GetInstance().SetZoomAmount(fitHeightZoom < 1.0f ? 1.0f : (fitHeightZoom > 1.2f ? 1.2f : fitHeightZoom));
+ }
+ else if (CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode == ViewModeZoom110Width)
+ {
+ float fitHeightZoom = sourceFrameRatio * screenHeight / (info.fPixelRatio * screenWidth);
+ CDisplaySettings::GetInstance().SetPixelRatio(1.0f);
+ CDisplaySettings::GetInstance().SetZoomAmount(fitHeightZoom < 1.0f ? 1.0f : (fitHeightZoom > 1.1f ? 1.1f : fitHeightZoom));
+ }
else // if (CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode == ViewModeNormal)
{
CDisplaySettings::GetInstance().SetPixelRatio(1.0);
diff --git a/xbmc/epg/GUIEPGGridContainer.cpp b/xbmc/epg/GUIEPGGridContainer.cpp
index 96c7bec2da..8cfa281585 100644
--- a/xbmc/epg/GUIEPGGridContainer.cpp
+++ b/xbmc/epg/GUIEPGGridContainer.cpp
@@ -53,6 +53,7 @@ CGUIEPGGridContainer::CGUIEPGGridContainer(int parentID, int controlID, float po
m_programmeLayout(nullptr),
m_focusedProgrammeLayout(nullptr),
m_rulerLayout(nullptr),
+ m_pageControl(0),
m_rulerUnit(rulerUnit),
m_channelsPerPage(0),
m_programmesPerPage(0),
@@ -105,6 +106,7 @@ CGUIEPGGridContainer::CGUIEPGGridContainer(const CGUIEPGGridContainer &other)
m_programmeLayout(other.m_programmeLayout),
m_focusedProgrammeLayout(other.m_focusedProgrammeLayout),
m_rulerLayout(other.m_rulerLayout),
+ m_pageControl(other.m_pageControl),
m_rulerUnit(other.m_rulerUnit),
m_channelsPerPage(other.m_channelsPerPage),
m_programmesPerPage(other.m_programmesPerPage),
@@ -147,19 +149,38 @@ CGUIEPGGridContainer::CGUIEPGGridContainer(const CGUIEPGGridContainer &other)
{
}
+void CGUIEPGGridContainer::SetPageControl(int id)
+{
+ m_pageControl = id;
+}
+
void CGUIEPGGridContainer::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
{
ValidateOffset();
if (m_bInvalidated)
+ {
UpdateLayout();
+ if (m_pageControl && m_gridModel->ChannelItemsSize())
+ {
+ CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), m_pageControl, m_channelsPerPage, m_gridModel->ChannelItemsSize());
+ SendWindowMessage(msg);
+ }
+ }
+
UpdateScrollOffset(currentTime);
ProcessChannels(currentTime, dirtyregions);
ProcessRuler(currentTime, dirtyregions);
ProcessProgrammeGrid(currentTime, dirtyregions);
ProcessProgressIndicator(currentTime, dirtyregions);
+ if (m_pageControl && m_gridModel->ChannelItemsSize())
+ {
+ CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), m_pageControl, MathUtils::round_int(m_channelScrollOffset / m_channelHeight));
+ SendWindowMessage(msg);
+ }
+
CGUIControl::Process(currentTime, dirtyregions);
}
@@ -453,6 +474,14 @@ bool CGUIEPGGridContainer::OnMessage(CGUIMessage& message)
message.SetParam1(GetSelectedItem());
return true;
+ case GUI_MSG_PAGE_CHANGE:
+ if (message.GetSenderId() == m_pageControl && IsVisible())
+ {
+ ScrollToChannelOffset(message.GetParam1());
+ return true;
+ }
+ break;
+
case GUI_MSG_LABEL_BIND:
UpdateItems();
return true;
@@ -1038,10 +1067,16 @@ std::string CGUIEPGGridContainer::GetLabel(int info) const
switch (info)
{
case CONTAINER_NUM_PAGES:
- label = StringUtils::Format("%u", (m_gridModel->ChannelItemsSize() + m_channelsPerPage - 1) / m_channelsPerPage);
+ if (m_channelsPerPage > 0)
+ label = StringUtils::Format("%u", (m_gridModel->ChannelItemsSize() + m_channelsPerPage - 1) / m_channelsPerPage);
+ else
+ label = StringUtils::Format("%u", 0);
break;
case CONTAINER_CURRENT_PAGE:
- label = StringUtils::Format("%u", 1 + (m_channelCursor + m_channelOffset) / m_channelsPerPage );
+ if (m_channelsPerPage > 0)
+ label = StringUtils::Format("%u", 1 + (m_channelCursor + m_channelOffset) / m_channelsPerPage);
+ else
+ label = StringUtils::Format("%u", 1);
break;
case CONTAINER_POSITION:
label = StringUtils::Format("%i", 1 + m_channelCursor + m_channelOffset);
@@ -1330,7 +1365,7 @@ void CGUIEPGGridContainer::GoToEnd()
int blocksEnd = 0; // the end block of the last epg element for the selected channel
int blocksStart = 0; // the start block of the last epg element for the selected channel
int blockOffset = 0; // the block offset to scroll to
- for (int blockIndex = m_gridModel->GetBlockCount(); blockIndex >= 0 && (!blocksEnd || !blocksStart); blockIndex--)
+ for (int blockIndex = m_gridModel->GetBlockCount() - 1; blockIndex >= 0 && (!blocksEnd || !blocksStart); blockIndex--)
{
if (!blocksEnd && m_gridModel->GetGridItem(m_channelCursor + m_channelOffset, blockIndex))
blocksEnd = blockIndex;
diff --git a/xbmc/epg/GUIEPGGridContainer.h b/xbmc/epg/GUIEPGGridContainer.h
index e867f16834..55f3af91c8 100644
--- a/xbmc/epg/GUIEPGGridContainer.h
+++ b/xbmc/epg/GUIEPGGridContainer.h
@@ -43,6 +43,8 @@ namespace EPG
virtual CGUIEPGGridContainer *Clone() const { return new CGUIEPGGridContainer(*this); }
+ void SetPageControl(int id);
+
virtual bool OnAction(const CAction &action);
virtual void OnDown();
virtual void OnUp();
@@ -139,6 +141,8 @@ namespace EPG
CGUIListItemLayout *m_focusedProgrammeLayout;
CGUIListItemLayout *m_rulerLayout;
+ int m_pageControl;
+
void GetChannelCacheOffsets(int &cacheBefore, int &cacheAfter);
void GetProgrammeCacheOffsets(int &cacheBefore, int &cacheAfter);
diff --git a/xbmc/filesystem/AddonsDirectory.cpp b/xbmc/filesystem/AddonsDirectory.cpp
index fc252a406d..63e384fd14 100644
--- a/xbmc/filesystem/AddonsDirectory.cpp
+++ b/xbmc/filesystem/AddonsDirectory.cpp
@@ -623,8 +623,6 @@ void CAddonsDirectory::GenerateAddonListing(const CURL &path,
pItem->SetProperty("Addon.Status", g_localizeStrings.Get(24023));
if (hasUpdate)
pItem->SetProperty("Addon.Status", g_localizeStrings.Get(24068));
- if (addon->Broken() == "DEPSNOTMET")
- pItem->SetProperty("Addon.Status", g_localizeStrings.Get(24049));
else if (!addon->Broken().empty())
pItem->SetProperty("Addon.Status", g_localizeStrings.Get(24098));
diff --git a/xbmc/guilib/GUIControlFactory.cpp b/xbmc/guilib/GUIControlFactory.cpp
index 53f8fe1c2b..91cf5534bb 100644
--- a/xbmc/guilib/GUIControlFactory.cpp
+++ b/xbmc/guilib/GUIControlFactory.cpp
@@ -1338,10 +1338,12 @@ CGUIControl* CGUIControlFactory::Create(int parentID, const CRect &rect, TiXmlEl
break;
case CGUIControl::GUICONTAINER_EPGGRID:
{
- control = new CGUIEPGGridContainer(parentID, id, posX, posY, width, height, scrollTime, preloadItems, timeBlocks, rulerUnit, textureProgressIndicator);
- ((CGUIEPGGridContainer *)control)->LoadLayout(pControlNode);
- ((CGUIEPGGridContainer *)control)->SetRenderOffset(offset);
- ((CGUIEPGGridContainer *)control)->SetType(viewType, viewLabel);
+ CGUIEPGGridContainer *epgGridContainer = new CGUIEPGGridContainer(parentID, id, posX, posY, width, height, scrollTime, preloadItems, timeBlocks, rulerUnit, textureProgressIndicator);
+ control = epgGridContainer;
+ epgGridContainer->LoadLayout(pControlNode);
+ epgGridContainer->SetRenderOffset(offset);
+ epgGridContainer->SetType(viewType, viewLabel);
+ epgGridContainer->SetPageControl(pageControl);
}
break;
case CGUIControl::GUICONTAINER_FIXEDLIST:
diff --git a/xbmc/guilib/GUIVisualisationControl.cpp b/xbmc/guilib/GUIVisualisationControl.cpp
index cde54c17dc..e4d8d5e578 100644
--- a/xbmc/guilib/GUIVisualisationControl.cpp
+++ b/xbmc/guilib/GUIVisualisationControl.cpp
@@ -23,6 +23,7 @@
#include "GUIUserMessages.h"
#include "Application.h"
#include "addons/AddonManager.h"
+#include "addons/AddonSystemSettings.h"
#include "addons/Visualisation.h"
#include "utils/log.h"
#include "input/Key.h"
@@ -100,7 +101,7 @@ void CGUIVisualisationControl::Process(unsigned int currentTime, CDirtyRegionLis
if (!m_addon && !m_bAttemptedLoad)
{
AddonPtr addon;
- if (ADDON::CAddonMgr::GetInstance().GetDefault(ADDON_VIZ, addon))
+ if (ADDON::CAddonSystemSettings::GetInstance().GetActive(ADDON_VIZ, addon))
{
m_addon = std::dynamic_pointer_cast<CVisualisation>(addon);
if (m_addon)
diff --git a/xbmc/interfaces/builtins/AddonBuiltins.cpp b/xbmc/interfaces/builtins/AddonBuiltins.cpp
index 18b112dd2d..5b5eb7ef8c 100644
--- a/xbmc/interfaces/builtins/AddonBuiltins.cpp
+++ b/xbmc/interfaces/builtins/AddonBuiltins.cpp
@@ -24,6 +24,7 @@
#include "addons/AddonManager.h"
#include "addons/AddonInstaller.h"
+#include "addons/AddonSystemSettings.h"
#include "addons/GUIDialogAddonSettings.h"
#include "addons/GUIWindowAddonBrowser.h"
#include "addons/PluginSource.h"
@@ -221,7 +222,7 @@ static int OpenDefaultSettings(const std::vector<std::string>& params)
{
AddonPtr addon;
ADDON::TYPE type = TranslateType(params[0]);
- if (CAddonMgr::GetInstance().GetDefault(type, addon))
+ if (CAddonSystemSettings::GetInstance().GetActive(type, addon))
{
bool changed = CGUIDialogAddonSettings::ShowAndGetInput(addon);
if (type == ADDON_VIZ && changed)
@@ -246,7 +247,7 @@ static int SetDefaultAddon(const std::vector<std::string>& params)
if (type != ADDON_UNKNOWN &&
CGUIWindowAddonBrowser::SelectAddonID(type,addonID,allowNone))
{
- CAddonMgr::GetInstance().SetDefault(type,addonID);
+ CAddonSystemSettings::GetInstance().SetActive(type, addonID);
if (type == ADDON_VIZ)
g_windowManager.SendMessage(GUI_MSG_VISUALISATION_RELOAD, 0, 0);
}
diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp
index b033256b0c..59216fef18 100644
--- a/xbmc/music/MusicDatabase.cpp
+++ b/xbmc/music/MusicDatabase.cpp
@@ -22,6 +22,7 @@
#include "addons/Addon.h"
#include "addons/AddonManager.h"
+#include "addons/AddonSystemSettings.h"
#include "addons/Scraper.h"
#include "Album.h"
#include "Application.h"
@@ -5689,7 +5690,7 @@ bool CMusicDatabase::GetScraperForPath(const std::string& strPath, ADDON::Scrape
else
{ // use default scraper of the requested type
ADDON::AddonPtr defaultScraper;
- if (ADDON::CAddonMgr::GetInstance().GetDefault(type, defaultScraper))
+ if (ADDON::CAddonSystemSettings::GetInstance().GetActive(type, defaultScraper))
{
info = std::dynamic_pointer_cast<ADDON::CScraper>(defaultScraper);
}
@@ -5700,7 +5701,7 @@ bool CMusicDatabase::GetScraperForPath(const std::string& strPath, ADDON::Scrape
if (!info)
{ // use default music scraper instead
ADDON::AddonPtr addon;
- if(ADDON::CAddonMgr::GetInstance().GetDefault(type, addon))
+ if(ADDON::CAddonSystemSettings::GetInstance().GetActive(type, addon))
{
info = std::dynamic_pointer_cast<ADDON::CScraper>(addon);
return info != NULL;
diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp
index 1ebc77e248..e31e12df27 100644
--- a/xbmc/music/infoscanner/MusicInfoScanner.cpp
+++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp
@@ -24,6 +24,7 @@
#include <utility>
#include "addons/AddonManager.h"
+#include "addons/AddonSystemSettings.h"
#include "addons/Scraper.h"
#include "dialogs/GUIDialogExtendedProgressBar.h"
#include "dialogs/GUIDialogProgress.h"
@@ -771,10 +772,10 @@ int CMusicInfoScanner::RetrieveMusicInfo(const std::string& strDirectory, CFileI
ADDON::AddonPtr addon;
ADDON::ScraperPtr albumScraper;
ADDON::ScraperPtr artistScraper;
- if(ADDON::CAddonMgr::GetInstance().GetDefault(ADDON::ADDON_SCRAPER_ALBUMS, addon))
+ if(ADDON::CAddonSystemSettings::GetInstance().GetActive(ADDON::ADDON_SCRAPER_ALBUMS, addon))
albumScraper = std::dynamic_pointer_cast<ADDON::CScraper>(addon);
- if(ADDON::CAddonMgr::GetInstance().GetDefault(ADDON::ADDON_SCRAPER_ARTISTS, addon))
+ if(ADDON::CAddonSystemSettings::GetInstance().GetActive(ADDON::ADDON_SCRAPER_ARTISTS, addon))
artistScraper = std::dynamic_pointer_cast<ADDON::CScraper>(addon);
// Add each album
diff --git a/xbmc/music/windows/GUIWindowMusicNav.cpp b/xbmc/music/windows/GUIWindowMusicNav.cpp
index 341b007574..be63b8e2b6 100644
--- a/xbmc/music/windows/GUIWindowMusicNav.cpp
+++ b/xbmc/music/windows/GUIWindowMusicNav.cpp
@@ -20,6 +20,7 @@
#include "GUIWindowMusicNav.h"
#include "addons/AddonManager.h"
+#include "addons/AddonSystemSettings.h"
#include "utils/FileUtils.h"
#include "utils/URIUtils.h"
#include "PlayListPlayer.h"
@@ -706,7 +707,8 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
if (!m_musicdatabase.GetScraperForPath(path, scraper, ADDON::ScraperTypeFromContent(content)))
{
ADDON::AddonPtr defaultScraper;
- if (ADDON::CAddonMgr::GetInstance().GetDefault(ADDON::ScraperTypeFromContent(content), defaultScraper))
+ if (ADDON::CAddonSystemSettings::GetInstance().GetActive(
+ ADDON::ScraperTypeFromContent(content), defaultScraper))
{
scraper = std::dynamic_pointer_cast<ADDON::CScraper>(defaultScraper);
}
diff --git a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp
index 0f7dcf0b61..872b6f1ab6 100644
--- a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp
+++ b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp
@@ -20,6 +20,7 @@
#include "HTTPWebinterfaceHandler.h"
#include "addons/AddonManager.h"
+#include "addons/AddonSystemSettings.h"
#include "addons/Webinterface.h"
#include "filesystem/Directory.h"
#include "filesystem/File.h"
@@ -108,7 +109,7 @@ bool CHTTPWebinterfaceHandler::ResolveAddon(const std::string &url, ADDON::Addon
// determine the path within the addon
path = StringUtils::Join(components, WEBSERVER_DIRECTORY_SEPARATOR);
}
- else if (!ADDON::CAddonMgr::GetInstance().GetDefault(ADDON::ADDON_WEB_INTERFACE, addon) || addon == NULL)
+ else if (!ADDON::CAddonSystemSettings::GetInstance().GetActive(ADDON::ADDON_WEB_INTERFACE, addon) || addon == NULL)
return false;
// get the path of the addon
diff --git a/xbmc/pvr/windows/GUIWindowPVRBase.cpp b/xbmc/pvr/windows/GUIWindowPVRBase.cpp
index 4a01c99037..04eb81fbb4 100644
--- a/xbmc/pvr/windows/GUIWindowPVRBase.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRBase.cpp
@@ -22,6 +22,7 @@
#include "GUIWindowPVRRecordings.h"
#include "Application.h"
+#include "addons/AddonManager.h"
#include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h"
#include "dialogs/GUIDialogKaiToast.h"
#include "dialogs/GUIDialogNumeric.h"
@@ -339,8 +340,14 @@ void CGUIWindowPVRBase::SetInvalid()
bool CGUIWindowPVRBase::CanBeActivated() const
{
- // No activation if PVR is not (yet) available.
- return g_PVRManager.IsStarted();
+ // check if there is at least one enabled PVR add-on
+ if (!ADDON::CAddonMgr::GetInstance().HasAddons(ADDON::ADDON_PVRDLL))
+ {
+ CGUIDialogOK::ShowAndGetInput(CVariant{19296}, CVariant{19272}); // No PVR add-on enabled, You need a tuner, backend software...
+ return false;
+ }
+
+ return true;
}
bool CGUIWindowPVRBase::OpenChannelGroupSelectionDialog(void)
diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp
index ad70b8491f..610a8d10b3 100644
--- a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp
@@ -70,11 +70,6 @@ void CGUIWindowPVRChannels::UnregisterObservers(void)
g_EpgContainer.UnregisterObserver(this);
}
-bool CGUIWindowPVRChannels::CanBeActivated() const
-{
- return true;
-}
-
void CGUIWindowPVRChannels::GetContextButtons(int itemNumber, CContextButtons &buttons)
{
if (itemNumber < 0 || itemNumber >= m_vecItems->Size())
diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.h b/xbmc/pvr/windows/GUIWindowPVRChannels.h
index a41b891156..88878ce78e 100644
--- a/xbmc/pvr/windows/GUIWindowPVRChannels.h
+++ b/xbmc/pvr/windows/GUIWindowPVRChannels.h
@@ -29,7 +29,6 @@ namespace PVR
CGUIWindowPVRChannels(bool bRadio);
virtual ~CGUIWindowPVRChannels(void) {};
- virtual bool CanBeActivated() const override;
virtual bool OnMessage(CGUIMessage& message) override;
virtual void GetContextButtons(int itemNumber, CContextButtons &buttons) override;
virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button) override;
diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp
index a6b6e22ef5..bc3b0a214b 100644
--- a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp
@@ -58,11 +58,6 @@ CGUIEPGGridContainer* CGUIWindowPVRGuide::GetGridControl()
return dynamic_cast<CGUIEPGGridContainer*>(GetControl(m_viewControl.GetCurrentControl()));
}
-bool CGUIWindowPVRGuide::CanBeActivated() const
-{
- return true;
-}
-
void CGUIWindowPVRGuide::Init()
{
CGUIEPGGridContainer *epgGridContainer = GetGridControl();
diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.h b/xbmc/pvr/windows/GUIWindowPVRGuide.h
index 9cfe186c72..5cf3c5365d 100644
--- a/xbmc/pvr/windows/GUIWindowPVRGuide.h
+++ b/xbmc/pvr/windows/GUIWindowPVRGuide.h
@@ -41,7 +41,6 @@ namespace PVR
CGUIWindowPVRGuide(bool bRadio);
virtual ~CGUIWindowPVRGuide(void);
- virtual bool CanBeActivated() const override;
virtual void OnInitWindow() override;
virtual void OnDeinitWindow(int nextWindowID) override;
virtual bool OnMessage(CGUIMessage& message) override;
diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp
index 2d9358f14d..ff466c4df0 100644
--- a/xbmc/settings/MediaSettings.cpp
+++ b/xbmc/settings/MediaSettings.cpp
@@ -94,7 +94,7 @@ bool CMediaSettings::Load(const TiXmlNode *settings)
scalingMethod = (int)VS_SCALINGMETHOD_LINEAR;
m_defaultVideoSettings.m_ScalingMethod = (ESCALINGMETHOD)scalingMethod;
- XMLUtils::GetInt(pElement, "viewmode", m_defaultVideoSettings.m_ViewMode, ViewModeNormal, ViewModeCustom);
+ XMLUtils::GetInt(pElement, "viewmode", m_defaultVideoSettings.m_ViewMode, ViewModeNormal, ViewModeZoom110Width);
if (!XMLUtils::GetFloat(pElement, "zoomamount", m_defaultVideoSettings.m_CustomZoomAmount, 0.5f, 2.0f))
m_defaultVideoSettings.m_CustomZoomAmount = 1.0f;
if (!XMLUtils::GetFloat(pElement, "pixelratio", m_defaultVideoSettings.m_CustomPixelRatio, 0.5f, 2.0f))
diff --git a/xbmc/settings/dialogs/GUIDialogContentSettings.cpp b/xbmc/settings/dialogs/GUIDialogContentSettings.cpp
index 497c781b64..de3f53c1c8 100644
--- a/xbmc/settings/dialogs/GUIDialogContentSettings.cpp
+++ b/xbmc/settings/dialogs/GUIDialogContentSettings.cpp
@@ -27,6 +27,7 @@
#include <limits.h>
#include "GUIDialogContentSettings.h"
+#include "addons/AddonSystemSettings.h"
#include "addons/GUIDialogAddonSettings.h"
#include "addons/GUIWindowAddonBrowser.h"
#include "filesystem/AddonsDirectory.h"
@@ -239,7 +240,8 @@ void CGUIDialogContentSettings::OnSettingAction(const CSetting *setting)
m_content = static_cast<CONTENT_TYPE>(selected.second);
AddonPtr scraperAddon;
- CAddonMgr::GetInstance().GetDefault(ADDON::ScraperTypeFromContent(m_content), scraperAddon);
+ CAddonSystemSettings::GetInstance().GetActive(ADDON::ScraperTypeFromContent(m_content),
+ scraperAddon);
m_scraper = std::dynamic_pointer_cast<CScraper>(scraperAddon);
SetupView();
@@ -249,10 +251,13 @@ void CGUIDialogContentSettings::OnSettingAction(const CSetting *setting)
else if (settingId == SETTING_SCRAPER_LIST)
{
ADDON::TYPE type = ADDON::ScraperTypeFromContent(m_content);
- std::string selectedAddonId = m_scraper->ID();
+ std::string currentScraperId;
+ if (m_scraper != nullptr)
+ currentScraperId = m_scraper->ID();
+ std::string selectedAddonId = currentScraperId;
if (CGUIWindowAddonBrowser::SelectAddonID(type, selectedAddonId, false) == 1
- && selectedAddonId != m_scraper->ID())
+ && selectedAddonId != currentScraperId)
{
AddonPtr scraperAddon;
CAddonMgr::GetInstance().GetAddon(selectedAddonId, scraperAddon);
diff --git a/xbmc/video/CMakeLists.txt b/xbmc/video/CMakeLists.txt
index 5a1c5c6c2a..9842fce0aa 100644
--- a/xbmc/video/CMakeLists.txt
+++ b/xbmc/video/CMakeLists.txt
@@ -10,7 +10,8 @@ set(SOURCES Bookmark.cpp
VideoInfoTag.cpp
VideoLibraryQueue.cpp
VideoReferenceClock.cpp
- VideoThumbLoader.cpp)
+ VideoThumbLoader.cpp
+ ViewModeSettings.cpp)
set(HEADERS Bookmark.h
ContextMenus.h
diff --git a/xbmc/video/Makefile b/xbmc/video/Makefile
index be03ee1804..c2b31c648a 100644
--- a/xbmc/video/Makefile
+++ b/xbmc/video/Makefile
@@ -11,6 +11,7 @@ SRCS=Bookmark.cpp \
VideoLibraryQueue.cpp \
VideoReferenceClock.cpp \
VideoThumbLoader.cpp \
+ ViewModeSettings.cpp \
LIB=video.a
diff --git a/xbmc/video/ViewModeSettings.cpp b/xbmc/video/ViewModeSettings.cpp
new file mode 100644
index 0000000000..bb885df7bc
--- /dev/null
+++ b/xbmc/video/ViewModeSettings.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ViewModeSettings.h"
+
+#include "cores/IPlayer.h"
+#include "guilib/LocalizeStrings.h"
+#include "settings/VideoSettings.h"
+
+struct ViewModeProperties
+{
+ int stringIndex;
+ int viewMode;
+ bool hideFromQuickCycle;
+ bool hideFromList;
+};
+
+#define HIDE_ITEM true
+
+/** The list of all the view modes along with their properties
+ */
+static const ViewModeProperties viewModes[] =
+{
+ { 630, ViewModeNormal },
+ { 631, ViewModeZoom },
+ { 39008, ViewModeZoom120Width },
+ { 39009, ViewModeZoom110Width },
+ { 632, ViewModeStretch4x3 },
+ { 633, ViewModeWideZoom },
+ { 634, ViewModeStretch16x9 },
+ { 644, ViewModeStretch16x9Nonlin, HIDE_ITEM, HIDE_ITEM },
+ { 635, ViewModeOriginal },
+ { 636, ViewModeCustom, HIDE_ITEM, HIDE_ITEM }
+};
+
+#define NUMBER_OF_VIEW_MODES (sizeof(viewModes) / sizeof(viewModes[0]))
+
+/** Gets the index of a view mode
+ *
+ * @param viewMode The view mode
+ * @return The index of the view mode in the viewModes array
+ */
+static int GetViewModeIndex(int viewMode)
+{
+ size_t i;
+
+ // Find the current view mode
+ for (i = 0; i < NUMBER_OF_VIEW_MODES; i++)
+ {
+ if (viewModes[i].viewMode == viewMode)
+ return i;
+ }
+
+ return 0; // An invalid view mode will always return the first view mode
+}
+
+/** Gets the next view mode for quick cycling through the modes
+ *
+ * @param viewMode The current view mode
+ * @return The next view mode
+ */
+int CViewModeSettings::GetNextQuickCycleViewMode(int viewMode)
+{
+ // Find the next quick cycle view mode
+ for (size_t i = GetViewModeIndex(viewMode) + 1; i < NUMBER_OF_VIEW_MODES; i++)
+ {
+ if (!viewModes[i].hideFromQuickCycle)
+ return viewModes[i].viewMode;
+ }
+
+ return ViewModeNormal;
+}
+
+/** Gets the string index for the view mode
+ *
+ * @param viewMode The current view mode
+ * @return The string index
+ */
+int CViewModeSettings::GetViewModeStringIndex(int viewMode)
+{
+ return viewModes[GetViewModeIndex(viewMode)].stringIndex;
+}
+
+/** Fills the list with all visible view modes
+ */
+void CViewModeSettings::ViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+ // Add all appropriate view modes to the list control
+ for (const auto &item : viewModes)
+ {
+ if (!item.hideFromList)
+ list.push_back(make_pair(g_localizeStrings.Get(item.stringIndex), item.viewMode));
+ }
+}
diff --git a/xbmc/video/ViewModeSettings.h b/xbmc/video/ViewModeSettings.h
new file mode 100644
index 0000000000..a5c182e830
--- /dev/null
+++ b/xbmc/video/ViewModeSettings.h
@@ -0,0 +1,55 @@
+
+#pragma once
+
+/*
+ * Copyright (C) 2016 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "settings/lib/Setting.h"
+
+class CViewModeSettings
+{
+private:
+ CViewModeSettings();
+ ~CViewModeSettings() {};
+
+public:
+ /** Gets the next view mode for quick cycling through the modes
+ *
+ * @param viewMode The current view mode
+ * @return The next view mode
+ */
+ static int GetNextQuickCycleViewMode(int viewMode);
+
+ /** Gets the string index for the view mode
+ *
+ * @param viewMode The current view mode
+ * @return The string index
+ */
+ static int GetViewModeStringIndex(int viewMode);
+
+ /** Fills the list with all visible view modes
+ */
+ static void ViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+
+};
diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
index 480994d976..c9ffc14b33 100644
--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
@@ -38,6 +38,7 @@
#include "Application.h"
#include "utils/LangCodeExpander.h"
#include "utils/StringUtils.h"
+#include "video/ViewModeSettings.h"
#define SETTING_VIDEO_VIEW_MODE "video.viewmode"
#define SETTING_VIDEO_ZOOM "video.zoom"
@@ -332,10 +333,7 @@ void CGUIDialogVideoSettings::InitializeSettings()
if (g_application.m_pPlayer->Supports(RENDERFEATURE_STRETCH) || g_application.m_pPlayer->Supports(RENDERFEATURE_PIXEL_RATIO))
{
- entries.clear();
- for (int i = 0; i < 7; ++i)
- entries.push_back(std::make_pair(630 + i, i));
- AddSpinner(groupVideo, SETTING_VIDEO_VIEW_MODE, 629, 0, videoSettings.m_ViewMode, entries);
+ AddList(groupVideo, SETTING_VIDEO_VIEW_MODE, 629, 0, videoSettings.m_ViewMode, CViewModeSettings::ViewModesFiller, 629);
}
if (g_application.m_pPlayer->Supports(RENDERFEATURE_ZOOM))
AddSlider(groupVideo, SETTING_VIDEO_ZOOM, 216, 0, videoSettings.m_CustomZoomAmount, "%2.2f", 0.5f, 0.01f, 2.0f, 216, usePopup);
@@ -426,4 +424,3 @@ void CGUIDialogVideoSettings::VideoStreamsOptionFiller(const CSetting *setting,
current = -1;
}
}
-
diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp
index ef17efdaef..7263752ea8 100644
--- a/xbmc/video/windows/GUIWindowFullScreen.cpp
+++ b/xbmc/video/windows/GUIWindowFullScreen.cpp
@@ -43,6 +43,7 @@
#include "windowing/WindowingFactory.h"
#include "cores/IPlayer.h"
#include "guiinfo/GUIInfoLabels.h"
+#include "video/ViewModeSettings.h"
#include <stdio.h>
#include <algorithm>
@@ -218,7 +219,7 @@ bool CGUIWindowFullScreen::OnAction(const CAction &action)
if (m_bShowViewModeInfo)
{
#ifdef HAS_VIDEO_PLAYBACK
- g_application.m_pPlayer->SetRenderViewMode(++CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode);
+ g_application.m_pPlayer->SetRenderViewMode(CViewModeSettings::GetNextQuickCycleViewMode(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode));
#endif
}
m_bShowViewModeInfo = true;
@@ -383,7 +384,7 @@ void CGUIWindowFullScreen::FrameMove()
// get the "View Mode" string
std::string strTitle = g_localizeStrings.Get(629);
const auto& settings = CMediaSettings::GetInstance().GetCurrentVideoSettings();
- int sId = settings.m_ViewMode == ViewModeStretch16x9Nonlin ? 644 : 630 + settings.m_ViewMode;
+ int sId = CViewModeSettings::GetViewModeStringIndex(settings.m_ViewMode);
std::string strMode = g_localizeStrings.Get(sId);
std::string strInfo = StringUtils::Format("%s : %s", strTitle.c_str(), strMode.c_str());
CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW1);