forked from osmc/osmc
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PATCH] [Binary Addon] provide API versions to addon for better
downgrade handling
- Loading branch information
1 parent
a3d9ba1
commit cd84d5f
Showing
1 changed file
with
287 additions
and
0 deletions.
There are no files selected for viewing
287 changes: 287 additions & 0 deletions
287
package/mediacenter-next-osmc/patches/rbp-010-pull-api.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,287 @@ | ||
From 64a933b29acd42e094815b95b088336dbc540056 Mon Sep 17 00:00:00 2001 | ||
From: peak3d <pfau@peak3d.de> | ||
Date: Mon, 4 Feb 2019 09:01:46 +0100 | ||
Subject: [PATCH] [Binary Addon] provide API versions to addon for better | ||
downgrade handling | ||
|
||
--- | ||
xbmc/DynamicDll.h | 6 ++- | ||
xbmc/addons/binary-addons/AddonDll.cpp | 38 ++++++++++++----- | ||
xbmc/addons/binary-addons/DllAddon.h | 8 ++++ | ||
.../include/kodi/AddonBase.h | 41 ++++++++++++++++--- | ||
.../include/kodi/xbmc_addon_dll.h | 5 +++ | ||
5 files changed, 82 insertions(+), 16 deletions(-) | ||
|
||
diff --git a/xbmc/DynamicDll.h b/xbmc/DynamicDll.h | ||
index 4f51a99b7e28..3a7c535a3b81 100644 | ||
--- a/xbmc/DynamicDll.h | ||
+++ b/xbmc/DynamicDll.h | ||
@@ -125,7 +125,7 @@ public: \ | ||
public: \ | ||
virtual result name args override \ | ||
{ \ | ||
- return m_##name args2; \ | ||
+ return m_##name ? m_##name args2 : (result) 0; \ | ||
} | ||
|
||
#define DEFINE_METHOD_LINKAGE0(result, linkage, name) \ | ||
@@ -403,6 +403,10 @@ public: \ | ||
if (!m_dll->ResolveExport( #dllmethod , & m_##method##_ptr )) \ | ||
return false; | ||
|
||
+#define RESOLVE_METHOD_RENAME_OPTIONAL(dllmethod, method) \ | ||
+ m_##method##_ptr = nullptr; \ | ||
+ m_dll->ResolveExport( #dllmethod , & m_##method##_ptr ); | ||
+ | ||
#define RESOLVE_METHOD_RENAME_FP(dllmethod, method) \ | ||
if (!m_dll->ResolveExport( #dllmethod , & method##_ptr )) \ | ||
return false; | ||
diff --git a/xbmc/addons/binary-addons/AddonDll.cpp b/xbmc/addons/binary-addons/AddonDll.cpp | ||
index 0562cc157043..2fb2c2cd843f 100644 | ||
--- a/xbmc/addons/binary-addons/AddonDll.cpp | ||
+++ b/xbmc/addons/binary-addons/AddonDll.cpp | ||
@@ -215,7 +215,10 @@ ADDON_STATUS CAddonDll::Create(ADDON_TYPE type, void* funcTable, void* info) | ||
|
||
/* Call Create to make connections, initializing data or whatever is | ||
needed to become the AddOn running */ | ||
- ADDON_STATUS status = m_pDll->Create(m_pHelpers->GetCallbacks(), info); | ||
+ ADDON_STATUS status = m_pDll->CreateEx_available() | ||
+ ? m_pDll->CreateEx(m_pHelpers->GetCallbacks(), kodi::addon::GetTypeVersion(ADDON_GLOBAL_MAIN), info) | ||
+ : m_pDll->Create(m_pHelpers->GetCallbacks(), info); | ||
+ | ||
if (status == ADDON_STATUS_OK) | ||
{ | ||
m_initialized = true; | ||
@@ -263,7 +266,10 @@ ADDON_STATUS CAddonDll::Create(KODI_HANDLE firstKodiInstance) | ||
|
||
/* Call Create to make connections, initializing data or whatever is | ||
needed to become the AddOn running */ | ||
- ADDON_STATUS status = m_pDll->Create(&m_interface, nullptr); | ||
+ ADDON_STATUS status = m_pDll->CreateEx_available() | ||
+ ? m_pDll->CreateEx(&m_interface, kodi::addon::GetTypeVersion(ADDON_GLOBAL_MAIN), nullptr) | ||
+ : m_pDll->Create(&m_interface, nullptr); | ||
+ | ||
if (status == ADDON_STATUS_OK) | ||
{ | ||
m_initialized = true; | ||
@@ -323,7 +329,11 @@ ADDON_STATUS CAddonDll::CreateInstance(ADDON_TYPE instanceType, const std::strin | ||
return ADDON_STATUS_PERMANENT_FAILURE; | ||
|
||
KODI_HANDLE addonInstance; | ||
- status = m_interface.toAddon->create_instance(instanceType, instanceID.c_str(), instance, &addonInstance, parentInstance); | ||
+ if (!m_interface.toAddon->create_instance_ex) | ||
+ status = m_interface.toAddon->create_instance(instanceType, instanceID.c_str(), instance, &addonInstance, parentInstance); | ||
+ else | ||
+ status = m_interface.toAddon->create_instance_ex(instanceType, instanceID.c_str(), instance, &addonInstance, parentInstance, kodi::addon::GetTypeVersion(instanceType)); | ||
+ | ||
if (status == ADDON_STATUS_OK) | ||
{ | ||
m_usedInstances[instanceID] = std::make_pair(instanceType, addonInstance); | ||
@@ -334,6 +344,9 @@ ADDON_STATUS CAddonDll::CreateInstance(ADDON_TYPE instanceType, const std::strin | ||
|
||
void CAddonDll::DestroyInstance(const std::string& instanceID) | ||
{ | ||
+ if (m_usedInstances.empty()) | ||
+ return; | ||
+ | ||
auto it = m_usedInstances.find(instanceID); | ||
if (it != m_usedInstances.end()) | ||
{ | ||
@@ -450,6 +463,9 @@ bool CAddonDll::CheckAPIVersion(int type) | ||
/* check the API version */ | ||
AddonVersion kodiMinVersion(kodi::addon::GetTypeMinVersion(type)); | ||
AddonVersion addonVersion(m_pDll->GetAddonTypeVersion(type)); | ||
+ AddonVersion addonMinVersion = m_pDll->GetAddonTypeMinVersion_available() | ||
+ ? AddonVersion(m_pDll->GetAddonTypeMinVersion(type)) | ||
+ : addonVersion; | ||
|
||
/* Check the global usage from addon | ||
* if not used from addon becomes "0.0.0" returned | ||
@@ -461,13 +477,15 @@ bool CAddonDll::CheckAPIVersion(int type) | ||
* present. | ||
*/ | ||
if (kodiMinVersion > addonVersion || | ||
- addonVersion > AddonVersion(kodi::addon::GetTypeVersion(type))) | ||
- { | ||
- CLog::Log(LOGERROR, "Add-on '%s' is using an incompatible API version for type '%s'. Kodi API min version = '%s', add-on API version '%s'", | ||
- Name().c_str(), | ||
- kodi::addon::GetTypeName(type), | ||
- kodiMinVersion.asString().c_str(), | ||
- addonVersion.asString().c_str()); | ||
+ addonMinVersion > AddonVersion(kodi::addon::GetTypeVersion(type))) | ||
+ { | ||
+ CLog::Log(LOGERROR, "Add-on '{}' is using an incompatible API version for type '{}'. Kodi API min version = '{}/{}', add-on API version '{}/{}'", | ||
+ Name(), | ||
+ kodi::addon::GetTypeName(type), | ||
+ kodi::addon::GetTypeVersion(type), | ||
+ kodiMinVersion.asString(), | ||
+ addonMinVersion.asString(), | ||
+ addonVersion.asString()); | ||
|
||
CEventLog &eventLog = CServiceBroker::GetEventLog(); | ||
eventLog.AddWithNotification(EventPtr(new CNotificationEvent(Name(), 24152, EventLevel::Error))); | ||
diff --git a/xbmc/addons/binary-addons/DllAddon.h b/xbmc/addons/binary-addons/DllAddon.h | ||
index 7350b2ee2ff6..806c0f49a876 100644 | ||
--- a/xbmc/addons/binary-addons/DllAddon.h | ||
+++ b/xbmc/addons/binary-addons/DllAddon.h | ||
@@ -17,10 +17,12 @@ class DllAddonInterface | ||
virtual ~DllAddonInterface() = default; | ||
virtual void GetAddon(void* pAddon) =0; | ||
virtual ADDON_STATUS Create(void *cb, void *info) =0; | ||
+ virtual ADDON_STATUS CreateEx(void *cb, const char* globalApiVersion, void *info) = 0; | ||
virtual void Destroy() =0; | ||
virtual ADDON_STATUS GetStatus() =0; | ||
virtual ADDON_STATUS SetSetting(const char *settingName, const void *settingValue) =0; | ||
virtual const char* GetAddonTypeVersion(int type)=0; | ||
+ virtual const char* GetAddonTypeMinVersion(int type) = 0; | ||
}; | ||
|
||
class DllAddon : public DllDynamic, public DllAddonInterface | ||
@@ -28,18 +30,24 @@ class DllAddon : public DllDynamic, public DllAddonInterface | ||
public: | ||
DECLARE_DLL_WRAPPER_TEMPLATE(DllAddon) | ||
DEFINE_METHOD2(ADDON_STATUS, Create, (void* p1, void* p2)) | ||
+ DEFINE_METHOD3(ADDON_STATUS, CreateEx, (void* p1, const char* p2, void* p3)) | ||
+ bool CreateEx_available() { return m_CreateEx != nullptr; } | ||
DEFINE_METHOD0(void, Destroy) | ||
DEFINE_METHOD0(ADDON_STATUS, GetStatus) | ||
DEFINE_METHOD2(ADDON_STATUS, SetSetting, (const char *p1, const void *p2)) | ||
DEFINE_METHOD1(void, GetAddon, (void* p1)) | ||
DEFINE_METHOD1(const char*, GetAddonTypeVersion, (int p1)) | ||
+ DEFINE_METHOD1(const char*, GetAddonTypeMinVersion, (int p1)) | ||
+ bool GetAddonTypeMinVersion_available() { return m_GetAddonTypeMinVersion != nullptr; } | ||
BEGIN_METHOD_RESOLVE() | ||
RESOLVE_METHOD_RENAME(get_addon,GetAddon) | ||
RESOLVE_METHOD_RENAME(ADDON_Create, Create) | ||
+ RESOLVE_METHOD_RENAME_OPTIONAL(ADDON_CreateEx, CreateEx) | ||
RESOLVE_METHOD_RENAME(ADDON_Destroy, Destroy) | ||
RESOLVE_METHOD_RENAME(ADDON_GetStatus, GetStatus) | ||
RESOLVE_METHOD_RENAME(ADDON_SetSetting, SetSetting) | ||
RESOLVE_METHOD_RENAME(ADDON_GetTypeVersion, GetAddonTypeVersion) | ||
+ RESOLVE_METHOD_RENAME_OPTIONAL(ADDON_GetTypeMinVersion, GetAddonTypeMinVersion) | ||
END_METHOD_RESOLVE() | ||
}; | ||
|
||
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h | ||
index 8e45693a16b6..5325ebfea2ad 100644 | ||
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h | ||
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/AddonBase.h | ||
@@ -193,6 +193,7 @@ typedef struct KodiToAddonFuncTable_Addon | ||
ADDON_STATUS (*create_instance)(int instanceType, const char* instanceID, KODI_HANDLE instance, KODI_HANDLE* addonInstance, KODI_HANDLE parent); | ||
void (*destroy_instance)(int instanceType, KODI_HANDLE instance); | ||
ADDON_STATUS (*set_setting)(const char *settingName, const void *settingValue); | ||
+ ADDON_STATUS(*create_instance_ex)(int instanceType, const char* instanceID, KODI_HANDLE instance, KODI_HANDLE* addonInstance, KODI_HANDLE parent, const char* version); | ||
} KodiToAddonFuncTable_Addon; | ||
|
||
/* | ||
@@ -251,6 +252,11 @@ class IAddonInstance | ||
return ADDON_STATUS_NOT_IMPLEMENTED; | ||
} | ||
|
||
+ virtual ADDON_STATUS CreateInstanceEx(int instanceType, std::string instanceID, KODI_HANDLE instance, KODI_HANDLE& addonInstance, const std::string &version) | ||
+ { | ||
+ return CreateInstance(instanceType, instanceID, instance, addonInstance); | ||
+ } | ||
+ | ||
const ADDON_TYPE m_type; | ||
}; | ||
} /* namespace addon */ | ||
@@ -292,6 +298,9 @@ class ATTRIBUTE_HIDDEN CAddonBase | ||
CAddonBase::m_interface->toAddon->create_instance = ADDONBASE_CreateInstance; | ||
CAddonBase::m_interface->toAddon->destroy_instance = ADDONBASE_DestroyInstance; | ||
CAddonBase::m_interface->toAddon->set_setting = ADDONBASE_SetSetting; | ||
+ // If version is present, we know that kodi has create_instance_ex implemented | ||
+ if (!CAddonBase::m_strGlobalApiVersion.empty()) | ||
+ CAddonBase::m_interface->toAddon->create_instance_ex = ADDONBASE_CreateInstanceEx; | ||
} | ||
|
||
virtual ~CAddonBase() = default; | ||
@@ -320,8 +329,14 @@ class ATTRIBUTE_HIDDEN CAddonBase | ||
return ADDON_STATUS_UNKNOWN; | ||
} | ||
|
||
+ virtual ADDON_STATUS CreateInstanceEx(int instanceType, std::string instanceID, KODI_HANDLE instance, KODI_HANDLE& addonInstance, const std::string &version) | ||
+ { | ||
+ return CreateInstance(instanceType, instanceID, instance, addonInstance); | ||
+ } | ||
+ | ||
/* Global variables of class */ | ||
static AddonGlobalInterface* m_interface; // Interface function table to hold addresses on add-on and from kodi | ||
+ static std::string m_strGlobalApiVersion; | ||
|
||
/*private:*/ /* Needed public as long the old call functions becomes used! */ | ||
static inline void ADDONBASE_Destroy() | ||
@@ -338,17 +353,22 @@ class ATTRIBUTE_HIDDEN CAddonBase | ||
} | ||
|
||
static inline ADDON_STATUS ADDONBASE_CreateInstance(int instanceType, const char* instanceID, KODI_HANDLE instance, KODI_HANDLE* addonInstance, KODI_HANDLE parent) | ||
+ { | ||
+ return ADDONBASE_CreateInstanceEx(instanceType, instanceID, instance, addonInstance, parent, nullptr); | ||
+ } | ||
+ | ||
+ static inline ADDON_STATUS ADDONBASE_CreateInstanceEx(int instanceType, const char* instanceID, KODI_HANDLE instance, KODI_HANDLE* addonInstance, KODI_HANDLE parent, const char* version) | ||
{ | ||
ADDON_STATUS status = ADDON_STATUS_NOT_IMPLEMENTED; | ||
if (parent != nullptr) | ||
- status = static_cast<IAddonInstance*>(parent)->CreateInstance(instanceType, instanceID, instance, *addonInstance); | ||
+ status = static_cast<IAddonInstance*>(parent)->CreateInstanceEx(instanceType, instanceID, instance, *addonInstance, version); | ||
if (status == ADDON_STATUS_NOT_IMPLEMENTED) | ||
- status = CAddonBase::m_interface->addonBase->CreateInstance(instanceType, instanceID, instance, *addonInstance); | ||
+ status = CAddonBase::m_interface->addonBase->CreateInstanceEx(instanceType, instanceID, instance, *addonInstance, version); | ||
if (*addonInstance == nullptr) | ||
- throw std::logic_error("kodi::addon::CAddonBase CreateInstance returns a empty instance pointer!"); | ||
+ throw std::logic_error("kodi::addon::CAddonBase CreateInstanceEx returns a empty instance pointer!"); | ||
|
||
if (static_cast<::kodi::addon::IAddonInstance*>(*addonInstance)->m_type != instanceType) | ||
- throw std::logic_error("kodi::addon::CAddonBase CreateInstance with difference on given and returned instance type!"); | ||
+ throw std::logic_error("kodi::addon::CAddonBase CreateInstanceEx with difference on given and returned instance type!"); | ||
|
||
return status; | ||
} | ||
@@ -650,6 +670,11 @@ inline void* GetInterface(const std::string &name, const std::string &version) | ||
kodi::addon::CAddonBase::m_interface->addonBase = new AddonClass; \ | ||
return kodi::addon::CAddonBase::m_interface->addonBase->Create(); \ | ||
} \ | ||
+ extern "C" __declspec(dllexport) ADDON_STATUS ADDON_CreateEx(KODI_HANDLE addonInterface, const char* globalApiVersion, void *unused) \ | ||
+ { \ | ||
+ kodi::addon::CAddonBase::m_strGlobalApiVersion = globalApiVersion; \ | ||
+ return ADDON_Create(addonInterface, unused); \ | ||
+ } \ | ||
extern "C" __declspec(dllexport) void ADDON_Destroy() \ | ||
{ \ | ||
kodi::addon::CAddonBase::ADDONBASE_Destroy(); \ | ||
@@ -666,4 +691,10 @@ inline void* GetInterface(const std::string &name, const std::string &version) | ||
{ \ | ||
return kodi::addon::GetTypeVersion(type); \ | ||
} \ | ||
- AddonGlobalInterface* kodi::addon::CAddonBase::m_interface = nullptr; | ||
+ extern "C" __declspec(dllexport) const char* ADDON_GetTypeMinVersion(int type) \ | ||
+ { \ | ||
+ return kodi::addon::GetTypeMinVersion(type); \ | ||
+ } \ | ||
+ AddonGlobalInterface* kodi::addon::CAddonBase::m_interface = nullptr; \ | ||
+ std::string kodi::addon::CAddonBase::m_strGlobalApiVersion; | ||
+ | ||
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_dll.h | ||
index e9e7d9ac871c..ce2bc9801ec0 100644 | ||
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_dll.h | ||
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_dll.h | ||
@@ -15,6 +15,7 @@ extern "C" { | ||
#endif | ||
|
||
ADDON_STATUS __declspec(dllexport) ADDON_Create(void *callbacks, void* props); | ||
+ ADDON_STATUS __declspec(dllexport) ADDON_CreateEx(void *callbacks, const char* globalApiVersion, void* props); | ||
void __declspec(dllexport) ADDON_Destroy(); | ||
ADDON_STATUS __declspec(dllexport) ADDON_GetStatus(); | ||
ADDON_STATUS __declspec(dllexport) ADDON_SetSetting(const char *settingName, const void *settingValue); | ||
@@ -22,6 +23,10 @@ extern "C" { | ||
{ | ||
return kodi::addon::GetTypeVersion(type); | ||
} | ||
+ __declspec(dllexport) const char* ADDON_GetTypeMinVersion(int type) | ||
+ { | ||
+ return kodi::addon::GetTypeMinVersion(type); | ||
+ } | ||
|
||
#ifdef __cplusplus | ||
}; |